@@ -1066,6 +1066,41 @@ end
1066
1066
1067
1067
array_new_memory (mem:: Memory , newlen:: Int ) = typeof (mem)(undef, newlen) # when implemented, this should attempt to first expand mem
1068
1068
1069
+ function _growbeg_internal! (a:: Vector , delta:: Int , len:: Int )
1070
+ @_terminates_locally_meta
1071
+ ref = a. ref
1072
+ mem = ref. mem
1073
+ offset = memoryrefoffset (ref)
1074
+ newlen = len + delta
1075
+ memlen = length (mem)
1076
+ if offset + len - 1 > memlen || offset < 1
1077
+ throw (ConcurrencyViolationError (" Vector has invalid state. Don't modify internal fields incorrectly, or resize without correct locks" ))
1078
+ end
1079
+ # since we will allocate the array in the middle of the memory we need at least 2*delta extra space
1080
+ # the +1 is because I didn't want to have an off by 1 error.
1081
+ newmemlen = max (overallocation (len), len + 2 * delta + 1 )
1082
+ newoffset = div (newmemlen - newlen, 2 ) + 1
1083
+ # If there is extra data after the end of the array we can use that space so long as there is enough
1084
+ # space at the end that there won't be quadratic behavior with a mix of growth from both ends.
1085
+ # Specifically, we want to ensure that we will only do this operation once before
1086
+ # increasing the size of the array, and that we leave enough space at both the beginning and the end.
1087
+ if newoffset + newlen < memlen
1088
+ newoffset = div (memlen - newlen, 2 ) + 1
1089
+ newmem = mem
1090
+ unsafe_copyto! (newmem, newoffset + delta, mem, offset, len)
1091
+ for j in offset: newoffset+ delta- 1
1092
+ @inbounds _unsetindex! (mem, j)
1093
+ end
1094
+ else
1095
+ newmem = array_new_memory (mem, newmemlen)
1096
+ unsafe_copyto! (newmem, newoffset + delta, mem, offset, len)
1097
+ end
1098
+ if ref != = a. ref
1099
+ throw (ConcurrencyViolationError (" Vector can not be resized concurrently" ))
1100
+ end
1101
+ setfield! (a, :ref , @inbounds memoryref (newmem, newoffset))
1102
+ end
1103
+
1069
1104
function _growbeg! (a:: Vector , delta:: Integer )
1070
1105
@_noub_meta
1071
1106
delta = Int (delta)
@@ -1081,40 +1116,46 @@ function _growbeg!(a::Vector, delta::Integer)
1081
1116
if delta <= offset - 1
1082
1117
setfield! (a, :ref , @inbounds memoryref (ref, 1 - delta))
1083
1118
else
1084
- @noinline (function ()
1085
- @_terminates_locally_meta
1086
- memlen = length (mem)
1087
- if offset + len - 1 > memlen || offset < 1
1088
- throw (ConcurrencyViolationError (" Vector has invalid state. Don't modify internal fields incorrectly, or resize without correct locks" ))
1089
- end
1090
- # since we will allocate the array in the middle of the memory we need at least 2*delta extra space
1091
- # the +1 is because I didn't want to have an off by 1 error.
1092
- newmemlen = max (overallocation (len), len + 2 * delta + 1 )
1093
- newoffset = div (newmemlen - newlen, 2 ) + 1
1094
- # If there is extra data after the end of the array we can use that space so long as there is enough
1095
- # space at the end that there won't be quadratic behavior with a mix of growth from both ends.
1096
- # Specifically, we want to ensure that we will only do this operation once before
1097
- # increasing the size of the array, and that we leave enough space at both the beginning and the end.
1098
- if newoffset + newlen < memlen
1099
- newoffset = div (memlen - newlen, 2 ) + 1
1100
- newmem = mem
1101
- unsafe_copyto! (newmem, newoffset + delta, mem, offset, len)
1102
- for j in offset: newoffset+ delta- 1
1103
- @inbounds _unsetindex! (mem, j)
1104
- end
1105
- else
1106
- newmem = array_new_memory (mem, newmemlen)
1107
- unsafe_copyto! (newmem, newoffset + delta, mem, offset, len)
1108
- end
1109
- if ref != = a. ref
1110
- @noinline throw (ConcurrencyViolationError (" Vector can not be resized concurrently" ))
1111
- end
1112
- setfield! (a, :ref , @inbounds memoryref (newmem, newoffset))
1113
- end )()
1119
+ @noinline _growbeg_internal! (a, delta, len)
1114
1120
end
1115
1121
return
1116
1122
end
1117
1123
1124
+ function _growend_internal! (a:: Vector , delta:: Int , len:: Int )
1125
+ ref = a. ref
1126
+ mem = ref. mem
1127
+ memlen = length (mem)
1128
+ newlen = len + delta
1129
+ offset = memoryrefoffset (ref)
1130
+ newmemlen = offset + newlen - 1
1131
+ if offset + len - 1 > memlen || offset < 1
1132
+ throw (ConcurrencyViolationError (" Vector has invalid state. Don't modify internal fields incorrectly, or resize without correct locks" ))
1133
+ end
1134
+
1135
+ if offset - 1 > div (5 * newlen, 4 )
1136
+ # If the offset is far enough that we can copy without resizing
1137
+ # while maintaining proportional spacing on both ends of the array
1138
+ # note that this branch prevents infinite growth when doing combinations
1139
+ # of push! and popfirst! (i.e. when using a Vector as a queue)
1140
+ newmem = mem
1141
+ newoffset = div (newlen, 8 ) + 1
1142
+ else
1143
+ # grow either by our computed overallocation factor
1144
+ # or exactly the requested size, whichever is larger
1145
+ # TODO we should possibly increase the offset if the current offset is nonzero.
1146
+ newmemlen2 = max (overallocation (memlen), newmemlen)
1147
+ newmem = array_new_memory (mem, newmemlen2)
1148
+ newoffset = offset
1149
+ end
1150
+ newref = @inbounds memoryref (newmem, newoffset)
1151
+ unsafe_copyto! (newref, ref, len)
1152
+ if ref != = a. ref
1153
+ @noinline throw (ConcurrencyViolationError (" Vector can not be resized concurrently" ))
1154
+ end
1155
+ setfield! (a, :ref , newref)
1156
+ return
1157
+ end
1158
+
1118
1159
function _growend! (a:: Vector , delta:: Integer )
1119
1160
@_noub_meta
1120
1161
delta = Int (delta)
@@ -1128,33 +1169,7 @@ function _growend!(a::Vector, delta::Integer)
1128
1169
setfield! (a, :size , (newlen,))
1129
1170
newmemlen = offset + newlen - 1
1130
1171
if memlen < newmemlen
1131
- @noinline (function ()
1132
- if offset + len - 1 > memlen || offset < 1
1133
- throw (ConcurrencyViolationError (" Vector has invalid state. Don't modify internal fields incorrectly, or resize without correct locks" ))
1134
- end
1135
-
1136
- if offset - 1 > div (5 * newlen, 4 )
1137
- # If the offset is far enough that we can copy without resizing
1138
- # while maintaining proportional spacing on both ends of the array
1139
- # note that this branch prevents infinite growth when doing combinations
1140
- # of push! and popfirst! (i.e. when using a Vector as a queue)
1141
- newmem = mem
1142
- newoffset = div (newlen, 8 ) + 1
1143
- else
1144
- # grow either by our computed overallocation factor
1145
- # or exactly the requested size, whichever is larger
1146
- # TODO we should possibly increase the offset if the current offset is nonzero.
1147
- newmemlen2 = max (overallocation (memlen), newmemlen)
1148
- newmem = array_new_memory (mem, newmemlen2)
1149
- newoffset = offset
1150
- end
1151
- newref = @inbounds memoryref (newmem, newoffset)
1152
- unsafe_copyto! (newref, ref, len)
1153
- if ref != = a. ref
1154
- @noinline throw (ConcurrencyViolationError (" Vector can not be resized concurrently" ))
1155
- end
1156
- setfield! (a, :ref , newref)
1157
- end )()
1172
+ @noinline _growend_internal! (a, delta, len)
1158
1173
end
1159
1174
return
1160
1175
end
0 commit comments