authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-08-25 20:00:57-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-08-25 20:00:57-07:00
log4971400bdcc810766da15c63e3e57a59e49499ca
treea083b906cf09fc7e43c4862fcae452c616cc2df3
parent96368b9f39468d727a85f9ce2729d65dd2fe3169
parent3e24e958922806379f9f609e36954a489eb20831

Merge remote-tracking branch 'origin/master' into llvm11


4 files changed, 67 insertions(+), 71 deletions(-)

lib/std/heap/general_purpose_allocator.zig+23-36
...@@ -402,41 +402,6 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type {...@@ -402,41 +402,6 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type {
402 }402 }
403 }403 }
404404
405 fn freeSlot(
406 self: *Self,
407 bucket: *BucketHeader,
408 bucket_index: usize,
409 size_class: usize,
410 slot_index: SlotIndex,
411 used_byte: *u8,
412 used_bit_index: u3,
413 trace_addr: usize,
414 ) void {
415 // Capture stack trace to be the "first free", in case a double free happens.
416 bucket.captureStackTrace(trace_addr, size_class, slot_index, .free);
417
418 used_byte.* &= ~(@as(u8, 1) << used_bit_index);
419 bucket.used_count -= 1;
420 if (bucket.used_count == 0) {
421 if (bucket.next == bucket) {
422 // it's the only bucket and therefore the current one
423 self.buckets[bucket_index] = null;
424 } else {
425 bucket.next.prev = bucket.prev;
426 bucket.prev.next = bucket.next;
427 self.buckets[bucket_index] = bucket.prev;
428 }
429 if (!config.never_unmap) {
430 self.backing_allocator.free(bucket.page[0..page_size]);
431 }
432 const bucket_size = bucketSize(size_class);
433 const bucket_slice = @ptrCast([*]align(@alignOf(BucketHeader)) u8, bucket)[0..bucket_size];
434 self.backing_allocator.free(bucket_slice);
435 } else {
436 @memset(bucket.page + slot_index * size_class, undefined, size_class);
437 }
438 }
439
440 /// This function assumes the object is in the large object storage regardless405 /// This function assumes the object is in the large object storage regardless
441 /// of the parameters.406 /// of the parameters.
442 fn resizeLarge(407 fn resizeLarge(
...@@ -560,7 +525,29 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type {...@@ -560,7 +525,29 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type {
560 }525 }
561 }526 }
562 if (new_size == 0) {527 if (new_size == 0) {
563 self.freeSlot(bucket, bucket_index, size_class, slot_index, used_byte, used_bit_index, ret_addr);528 // Capture stack trace to be the "first free", in case a double free happens.
529 bucket.captureStackTrace(ret_addr, size_class, slot_index, .free);
530
531 used_byte.* &= ~(@as(u8, 1) << used_bit_index);
532 bucket.used_count -= 1;
533 if (bucket.used_count == 0) {
534 if (bucket.next == bucket) {
535 // it's the only bucket and therefore the current one
536 self.buckets[bucket_index] = null;
537 } else {
538 bucket.next.prev = bucket.prev;
539 bucket.prev.next = bucket.next;
540 self.buckets[bucket_index] = bucket.prev;
541 }
542 if (!config.never_unmap) {
543 self.backing_allocator.free(bucket.page[0..page_size]);
544 }
545 const bucket_size = bucketSize(size_class);
546 const bucket_slice = @ptrCast([*]align(@alignOf(BucketHeader)) u8, bucket)[0..bucket_size];
547 self.backing_allocator.free(bucket_slice);
548 } else {
549 @memset(old_mem.ptr, undefined, old_mem.len);
550 }
564 return @as(usize, 0);551 return @as(usize, 0);
565 }552 }
566 const new_aligned_size = math.max(new_size, old_align);553 const new_aligned_size = math.max(new_size, old_align);
lib/std/math/big/int.zig+25-18
...@@ -15,6 +15,8 @@ const maxInt = std.math.maxInt;...@@ -15,6 +15,8 @@ const maxInt = std.math.maxInt;
15const minInt = std.math.minInt;15const minInt = std.math.minInt;
16const assert = std.debug.assert;16const assert = std.debug.assert;
1717
18const debug_safety = false;
19
18/// Returns the number of limbs needed to store `scalar`, which must be a20/// Returns the number of limbs needed to store `scalar`, which must be a
19/// primitive integer value.21/// primitive integer value.
20pub fn calcLimbLen(scalar: anytype) usize {22pub fn calcLimbLen(scalar: anytype) usize {
...@@ -57,7 +59,7 @@ pub fn calcSetStringLimbCount(base: u8, string_len: usize) usize {...@@ -57,7 +59,7 @@ pub fn calcSetStringLimbCount(base: u8, string_len: usize) usize {
5759
58/// a + b * c + *carry, sets carry to the overflow bits60/// a + b * c + *carry, sets carry to the overflow bits
59pub fn addMulLimbWithCarry(a: Limb, b: Limb, c: Limb, carry: *Limb) Limb {61pub fn addMulLimbWithCarry(a: Limb, b: Limb, c: Limb, carry: *Limb) Limb {
60 @setRuntimeSafety(false);62 @setRuntimeSafety(debug_safety);
61 var r1: Limb = undefined;63 var r1: Limb = undefined;
6264
63 // r1 = a + *carry65 // r1 = a + *carry
...@@ -1529,8 +1531,7 @@ pub const Managed = struct {...@@ -1529,8 +1531,7 @@ pub const Managed = struct {
1529 /// self's allocator is used for temporary storage to boost multiplication performance.1531 /// self's allocator is used for temporary storage to boost multiplication performance.
1530 pub fn setString(self: *Managed, base: u8, value: []const u8) !void {1532 pub fn setString(self: *Managed, base: u8, value: []const u8) !void {
1531 if (base < 2 or base > 16) return error.InvalidBase;1533 if (base < 2 or base > 16) return error.InvalidBase;
1532 const den = (@sizeOf(Limb) * 8 / base);1534 try self.ensureCapacity(calcSetStringLimbCount(base, value.len));
1533 try self.ensureCapacity((value.len + (den - 1)) / den);
1534 const limbs_buffer = try self.allocator.alloc(Limb, calcSetStringLimbsBufferLen(base, value.len));1535 const limbs_buffer = try self.allocator.alloc(Limb, calcSetStringLimbsBufferLen(base, value.len));
1535 defer self.allocator.free(limbs_buffer);1536 defer self.allocator.free(limbs_buffer);
1536 var m = self.toMutable();1537 var m = self.toMutable();
...@@ -1646,17 +1647,19 @@ pub const Managed = struct {...@@ -1646,17 +1647,19 @@ pub const Managed = struct {
1646 /// rma = a * b1647 /// rma = a * b
1647 ///1648 ///
1648 /// rma, a and b may be aliases. However, it is more efficient if rma does not alias a or b.1649 /// rma, a and b may be aliases. However, it is more efficient if rma does not alias a or b.
1650 /// If rma aliases a or b, then caller must call `rma.ensureMulCapacity` prior to calling `mul`.
1649 ///1651 ///
1650 /// Returns an error if memory could not be allocated.1652 /// Returns an error if memory could not be allocated.
1651 ///1653 ///
1652 /// rma's allocator is used for temporary storage to speed up the multiplication.1654 /// rma's allocator is used for temporary storage to speed up the multiplication.
1653 pub fn mul(rma: *Managed, a: Const, b: Const) !void {1655 pub fn mul(rma: *Managed, a: Const, b: Const) !void {
1654 try rma.ensureCapacity(a.limbs.len + b.limbs.len + 1);
1655 var alias_count: usize = 0;1656 var alias_count: usize = 0;
1656 if (rma.limbs.ptr == a.limbs.ptr)1657 if (rma.limbs.ptr == a.limbs.ptr)
1657 alias_count += 1;1658 alias_count += 1;
1658 if (rma.limbs.ptr == b.limbs.ptr)1659 if (rma.limbs.ptr == b.limbs.ptr)
1659 alias_count += 1;1660 alias_count += 1;
1661 assert(alias_count == 0 or rma.limbs.len >= a.limbs.len + b.limbs.len + 1);
1662 try rma.ensureMulCapacity(a, b);
1660 var m = rma.toMutable();1663 var m = rma.toMutable();
1661 if (alias_count == 0) {1664 if (alias_count == 0) {
1662 m.mulNoAlias(a, b, rma.allocator);1665 m.mulNoAlias(a, b, rma.allocator);
...@@ -1669,6 +1672,10 @@ pub const Managed = struct {...@@ -1669,6 +1672,10 @@ pub const Managed = struct {
1669 rma.setMetadata(m.positive, m.len);1672 rma.setMetadata(m.positive, m.len);
1670 }1673 }
16711674
1675 pub fn ensureMulCapacity(rma: *Managed, a: Const, b: Const) !void {
1676 try rma.ensureCapacity(a.limbs.len + b.limbs.len + 1);
1677 }
1678
1672 /// q = a / b (rem r)1679 /// q = a / b (rem r)
1673 ///1680 ///
1674 /// a / b are floored (rounded towards 0).1681 /// a / b are floored (rounded towards 0).
...@@ -1773,7 +1780,7 @@ pub const Managed = struct {...@@ -1773,7 +1780,7 @@ pub const Managed = struct {
1773///1780///
1774/// r MUST NOT alias any of a or b.1781/// r MUST NOT alias any of a or b.
1775fn llmulacc(opt_allocator: ?*Allocator, r: []Limb, a: []const Limb, b: []const Limb) void {1782fn llmulacc(opt_allocator: ?*Allocator, r: []Limb, a: []const Limb, b: []const Limb) void {
1776 @setRuntimeSafety(false);1783 @setRuntimeSafety(debug_safety);
17771784
1778 const a_norm = a[0..llnormalize(a)];1785 const a_norm = a[0..llnormalize(a)];
1779 const b_norm = b[0..llnormalize(b)];1786 const b_norm = b[0..llnormalize(b)];
...@@ -1806,7 +1813,7 @@ fn llmulacc(opt_allocator: ?*Allocator, r: []Limb, a: []const Limb, b: []const L...@@ -1806,7 +1813,7 @@ fn llmulacc(opt_allocator: ?*Allocator, r: []Limb, a: []const Limb, b: []const L
1806///1813///
1807/// r MUST NOT alias any of a or b.1814/// r MUST NOT alias any of a or b.
1808fn llmulacc_karatsuba(allocator: *Allocator, r: []Limb, x: []const Limb, y: []const Limb) error{OutOfMemory}!void {1815fn llmulacc_karatsuba(allocator: *Allocator, r: []Limb, x: []const Limb, y: []const Limb) error{OutOfMemory}!void {
1809 @setRuntimeSafety(false);1816 @setRuntimeSafety(debug_safety);
18101817
1811 assert(r.len >= x.len + y.len + 1);1818 assert(r.len >= x.len + y.len + 1);
18121819
...@@ -1873,7 +1880,7 @@ fn llmulacc_karatsuba(allocator: *Allocator, r: []Limb, x: []const Limb, y: []co...@@ -1873,7 +1880,7 @@ fn llmulacc_karatsuba(allocator: *Allocator, r: []Limb, x: []const Limb, y: []co
18731880
1874// r = r + a1881// r = r + a
1875fn llaccum(r: []Limb, a: []const Limb) Limb {1882fn llaccum(r: []Limb, a: []const Limb) Limb {
1876 @setRuntimeSafety(false);1883 @setRuntimeSafety(debug_safety);
1877 assert(r.len != 0 and a.len != 0);1884 assert(r.len != 0 and a.len != 0);
1878 assert(r.len >= a.len);1885 assert(r.len >= a.len);
18791886
...@@ -1896,7 +1903,7 @@ fn llaccum(r: []Limb, a: []const Limb) Limb {...@@ -1896,7 +1903,7 @@ fn llaccum(r: []Limb, a: []const Limb) Limb {
18961903
1897/// Returns -1, 0, 1 if |a| < |b|, |a| == |b| or |a| > |b| respectively for limbs.1904/// Returns -1, 0, 1 if |a| < |b|, |a| == |b| or |a| > |b| respectively for limbs.
1898pub fn llcmp(a: []const Limb, b: []const Limb) i8 {1905pub fn llcmp(a: []const Limb, b: []const Limb) i8 {
1899 @setRuntimeSafety(false);1906 @setRuntimeSafety(debug_safety);
1900 const a_len = llnormalize(a);1907 const a_len = llnormalize(a);
1901 const b_len = llnormalize(b);1908 const b_len = llnormalize(b);
1902 if (a_len < b_len) {1909 if (a_len < b_len) {
...@@ -1923,12 +1930,12 @@ pub fn llcmp(a: []const Limb, b: []const Limb) i8 {...@@ -1923,12 +1930,12 @@ pub fn llcmp(a: []const Limb, b: []const Limb) i8 {
1923}1930}
19241931
1925fn llmulDigit(acc: []Limb, y: []const Limb, xi: Limb) void {1932fn llmulDigit(acc: []Limb, y: []const Limb, xi: Limb) void {
1926 @setRuntimeSafety(false);1933 @setRuntimeSafety(debug_safety);
1927 if (xi == 0) {1934 if (xi == 0) {
1928 return;1935 return;
1929 }1936 }
19301937
1931 var carry: usize = 0;1938 var carry: Limb = 0;
1932 var a_lo = acc[0..y.len];1939 var a_lo = acc[0..y.len];
1933 var a_hi = acc[y.len..];1940 var a_hi = acc[y.len..];
19341941
...@@ -1945,7 +1952,7 @@ fn llmulDigit(acc: []Limb, y: []const Limb, xi: Limb) void {...@@ -1945,7 +1952,7 @@ fn llmulDigit(acc: []Limb, y: []const Limb, xi: Limb) void {
19451952
1946/// returns the min length the limb could be.1953/// returns the min length the limb could be.
1947fn llnormalize(a: []const Limb) usize {1954fn llnormalize(a: []const Limb) usize {
1948 @setRuntimeSafety(false);1955 @setRuntimeSafety(debug_safety);
1949 var j = a.len;1956 var j = a.len;
1950 while (j > 0) : (j -= 1) {1957 while (j > 0) : (j -= 1) {
1951 if (a[j - 1] != 0) {1958 if (a[j - 1] != 0) {
...@@ -1959,7 +1966,7 @@ fn llnormalize(a: []const Limb) usize {...@@ -1959,7 +1966,7 @@ fn llnormalize(a: []const Limb) usize {
19591966
1960/// Knuth 4.3.1, Algorithm S.1967/// Knuth 4.3.1, Algorithm S.
1961fn llsub(r: []Limb, a: []const Limb, b: []const Limb) void {1968fn llsub(r: []Limb, a: []const Limb, b: []const Limb) void {
1962 @setRuntimeSafety(false);1969 @setRuntimeSafety(debug_safety);
1963 assert(a.len != 0 and b.len != 0);1970 assert(a.len != 0 and b.len != 0);
1964 assert(a.len > b.len or (a.len == b.len and a[a.len - 1] >= b[b.len - 1]));1971 assert(a.len > b.len or (a.len == b.len and a[a.len - 1] >= b[b.len - 1]));
1965 assert(r.len >= a.len);1972 assert(r.len >= a.len);
...@@ -1983,7 +1990,7 @@ fn llsub(r: []Limb, a: []const Limb, b: []const Limb) void {...@@ -1983,7 +1990,7 @@ fn llsub(r: []Limb, a: []const Limb, b: []const Limb) void {
19831990
1984/// Knuth 4.3.1, Algorithm A.1991/// Knuth 4.3.1, Algorithm A.
1985fn lladd(r: []Limb, a: []const Limb, b: []const Limb) void {1992fn lladd(r: []Limb, a: []const Limb, b: []const Limb) void {
1986 @setRuntimeSafety(false);1993 @setRuntimeSafety(debug_safety);
1987 assert(a.len != 0 and b.len != 0);1994 assert(a.len != 0 and b.len != 0);
1988 assert(a.len >= b.len);1995 assert(a.len >= b.len);
1989 assert(r.len >= a.len + 1);1996 assert(r.len >= a.len + 1);
...@@ -2007,7 +2014,7 @@ fn lladd(r: []Limb, a: []const Limb, b: []const Limb) void {...@@ -2007,7 +2014,7 @@ fn lladd(r: []Limb, a: []const Limb, b: []const Limb) void {
20072014
2008/// Knuth 4.3.1, Exercise 16.2015/// Knuth 4.3.1, Exercise 16.
2009fn lldiv1(quo: []Limb, rem: *Limb, a: []const Limb, b: Limb) void {2016fn lldiv1(quo: []Limb, rem: *Limb, a: []const Limb, b: Limb) void {
2010 @setRuntimeSafety(false);2017 @setRuntimeSafety(debug_safety);
2011 assert(a.len > 1 or a[0] >= b);2018 assert(a.len > 1 or a[0] >= b);
2012 assert(quo.len >= a.len);2019 assert(quo.len >= a.len);
20132020
...@@ -2033,7 +2040,7 @@ fn lldiv1(quo: []Limb, rem: *Limb, a: []const Limb, b: Limb) void {...@@ -2033,7 +2040,7 @@ fn lldiv1(quo: []Limb, rem: *Limb, a: []const Limb, b: Limb) void {
2033}2040}
20342041
2035fn llshl(r: []Limb, a: []const Limb, shift: usize) void {2042fn llshl(r: []Limb, a: []const Limb, shift: usize) void {
2036 @setRuntimeSafety(false);2043 @setRuntimeSafety(debug_safety);
2037 assert(a.len >= 1);2044 assert(a.len >= 1);
2038 assert(r.len >= a.len + (shift / Limb.bit_count) + 1);2045 assert(r.len >= a.len + (shift / Limb.bit_count) + 1);
20392046
...@@ -2060,7 +2067,7 @@ fn llshl(r: []Limb, a: []const Limb, shift: usize) void {...@@ -2060,7 +2067,7 @@ fn llshl(r: []Limb, a: []const Limb, shift: usize) void {
2060}2067}
20612068
2062fn llshr(r: []Limb, a: []const Limb, shift: usize) void {2069fn llshr(r: []Limb, a: []const Limb, shift: usize) void {
2063 @setRuntimeSafety(false);2070 @setRuntimeSafety(debug_safety);
2064 assert(a.len >= 1);2071 assert(a.len >= 1);
2065 assert(r.len >= a.len - (shift / Limb.bit_count));2072 assert(r.len >= a.len - (shift / Limb.bit_count));
20662073
...@@ -2084,7 +2091,7 @@ fn llshr(r: []Limb, a: []const Limb, shift: usize) void {...@@ -2084,7 +2091,7 @@ fn llshr(r: []Limb, a: []const Limb, shift: usize) void {
2084}2091}
20852092
2086fn llor(r: []Limb, a: []const Limb, b: []const Limb) void {2093fn llor(r: []Limb, a: []const Limb, b: []const Limb) void {
2087 @setRuntimeSafety(false);2094 @setRuntimeSafety(debug_safety);
2088 assert(r.len >= a.len);2095 assert(r.len >= a.len);
2089 assert(a.len >= b.len);2096 assert(a.len >= b.len);
20902097
...@@ -2098,7 +2105,7 @@ fn llor(r: []Limb, a: []const Limb, b: []const Limb) void {...@@ -2098,7 +2105,7 @@ fn llor(r: []Limb, a: []const Limb, b: []const Limb) void {
2098}2105}
20992106
2100fn lland(r: []Limb, a: []const Limb, b: []const Limb) void {2107fn lland(r: []Limb, a: []const Limb, b: []const Limb) void {
2101 @setRuntimeSafety(false);2108 @setRuntimeSafety(debug_safety);
2102 assert(r.len >= b.len);2109 assert(r.len >= b.len);
2103 assert(a.len >= b.len);2110 assert(a.len >= b.len);
21042111
lib/std/math/big/rational.zig+1
...@@ -110,6 +110,7 @@ pub const Rational = struct {...@@ -110,6 +110,7 @@ pub const Rational = struct {
110110
111 var j: usize = start;111 var j: usize = start;
112 while (j < str.len - i - 1) : (j += 1) {112 while (j < str.len - i - 1) : (j += 1) {
113 try self.p.ensureMulCapacity(self.p.toConst(), base);
113 try self.p.mul(self.p.toConst(), base);114 try self.p.mul(self.p.toConst(), base);
114 }115 }
115116
lib/std/rand.zig+18-17
...@@ -3,21 +3,22 @@...@@ -3,21 +3,22 @@
3// This file is part of [zig](https://ziglang.org/), which is MIT licensed.3// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
4// The MIT license requires this copyright notice to be included in all copies4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.5// and substantial portions of the software.
6// The engines provided here should be initialized from an external source. For now, randomBytes6
7// from the crypto package is the most suitable. Be sure to use a CSPRNG when required, otherwise using7//! The engines provided here should be initialized from an external source. For now, randomBytes
8// a normal PRNG will be faster and use substantially less stack space.8//! from the crypto package is the most suitable. Be sure to use a CSPRNG when required, otherwise using
9//9//! a normal PRNG will be faster and use substantially less stack space.
10// ```10//!
11// var buf: [8]u8 = undefined;11//! ```
12// try std.crypto.randomBytes(buf[0..]);12//! var buf: [8]u8 = undefined;
13// const seed = mem.readIntLittle(u64, buf[0..8]);13//! try std.crypto.randomBytes(buf[0..]);
14//14//! const seed = mem.readIntLittle(u64, buf[0..8]);
15// var r = DefaultPrng.init(seed);15//!
16//16//! var r = DefaultPrng.init(seed);
17// const s = r.random.int(u64);17//!
18// ```18//! const s = r.random.int(u64);
19//19//! ```
20// TODO(tiehuis): Benchmark these against other reference implementations.20//!
21//! TODO(tiehuis): Benchmark these against other reference implementations.
2122
22const std = @import("std.zig");23const std = @import("std.zig");
23const builtin = @import("builtin");24const builtin = @import("builtin");
...@@ -29,10 +30,10 @@ const math = std.math;...@@ -29,10 +30,10 @@ const math = std.math;
29const ziggurat = @import("rand/ziggurat.zig");30const ziggurat = @import("rand/ziggurat.zig");
30const maxInt = std.math.maxInt;31const maxInt = std.math.maxInt;
3132
32// When you need fast unbiased random numbers33/// Fast unbiased random numbers.
33pub const DefaultPrng = Xoroshiro128;34pub const DefaultPrng = Xoroshiro128;
3435
35// When you need cryptographically secure random numbers36/// Cryptographically secure random numbers.
36pub const DefaultCsprng = Isaac64;37pub const DefaultCsprng = Isaac64;
3738
38pub const Random = struct {39pub const Random = struct {