@@ -18,18 +18,24 @@ import java.lang.Utils._
18
18
import java .util .ScalaOps ._
19
19
20
20
import scala .scalajs .js
21
+ import scala .scalajs .LinkingInfo
21
22
22
23
class ArrayDeque [E ] private (initialCapacity : Int )
23
24
extends AbstractCollection [E ] with Deque [E ] with Cloneable with Serializable {
24
25
self =>
25
26
26
- private val inner : js.Array [E ] = new js.Array [E ](Math .max(initialCapacity, 16 ))
27
+ /* This class has two different implementations for the internal storage.
28
+ * depending on whether we are on Wasm or JS.
29
+ * On JS, we utilize `js.Array`. On Wasm, for performance reasons,
30
+ * we use a scala.Array to avoid JS interop.
31
+ */
27
32
28
- fillNulls( 0 , inner.length )
33
+ private var inner : Array [ AnyRef ] = new Array [ AnyRef ]( Math .max(initialCapacity, 16 ) )
29
34
30
35
private var status = 0
31
36
private var startIndex = 0 // inclusive, 0 <= startIndex < inner.length
32
- private var endIndex = inner.length // exclusive, 0 < endIndex <= inner.length
37
+ private var endIndex = // exclusive, 0 < endIndex <= inner.length
38
+ inner.length
33
39
private var empty = true
34
40
35
41
def this () = this (16 )
@@ -55,8 +61,8 @@ class ArrayDeque[E] private (initialCapacity: Int)
55
61
ensureCapacityForAdd()
56
62
startIndex -= 1
57
63
if (startIndex < 0 )
58
- startIndex = inner. length - 1
59
- inner(startIndex) = e
64
+ startIndex = length() - 1
65
+ inner(startIndex) = e. asInstanceOf [ AnyRef ]
60
66
status += 1
61
67
empty = false
62
68
true
@@ -69,9 +75,9 @@ class ArrayDeque[E] private (initialCapacity: Int)
69
75
} else {
70
76
ensureCapacityForAdd()
71
77
endIndex += 1
72
- if (endIndex > inner. length)
78
+ if (endIndex > length() )
73
79
endIndex = 1
74
- inner(endIndex - 1 ) = e
80
+ inner(endIndex - 1 ) = e. asInstanceOf [ AnyRef ]
75
81
status += 1
76
82
empty = false
77
83
true
@@ -95,12 +101,12 @@ class ArrayDeque[E] private (initialCapacity: Int)
95
101
def pollFirst (): E = {
96
102
if (isEmpty()) null .asInstanceOf [E ]
97
103
else {
98
- val res = inner(startIndex)
99
- inner(startIndex) = null . asInstanceOf [ E ] // free reference for GC
104
+ val res = inner(startIndex). asInstanceOf [ E ]
105
+ inner(startIndex) = null // free reference for GC
100
106
startIndex += 1
101
107
if (startIndex == endIndex)
102
108
empty = true
103
- if (startIndex >= inner. length)
109
+ if (startIndex >= length() )
104
110
startIndex = 0
105
111
status += 1
106
112
res
@@ -111,13 +117,13 @@ class ArrayDeque[E] private (initialCapacity: Int)
111
117
if (isEmpty()) {
112
118
null .asInstanceOf [E ]
113
119
} else {
114
- val res = inner(endIndex - 1 )
115
- inner(endIndex - 1 ) = null . asInstanceOf [ E ] // free reference for GC
120
+ val res = inner(endIndex - 1 ). asInstanceOf [ E ]
121
+ inner(endIndex - 1 ) = null // free reference for GC
116
122
endIndex -= 1
117
123
if (startIndex == endIndex)
118
124
empty = true
119
125
if (endIndex <= 0 )
120
- endIndex = inner. length
126
+ endIndex = length()
121
127
status += 1
122
128
res
123
129
}
@@ -138,13 +144,19 @@ class ArrayDeque[E] private (initialCapacity: Int)
138
144
}
139
145
140
146
def peekFirst (): E = {
141
- if (isEmpty()) null .asInstanceOf [E ]
142
- else inner(startIndex)
147
+ if (isEmpty()) {
148
+ null .asInstanceOf [E ]
149
+ } else {
150
+ inner(startIndex).asInstanceOf [E ]
151
+ }
143
152
}
144
153
145
154
def peekLast (): E = {
146
- if (isEmpty()) null .asInstanceOf [E ]
147
- else inner(endIndex - 1 )
155
+ if (isEmpty()) {
156
+ null .asInstanceOf [E ]
157
+ } else {
158
+ inner(endIndex - 1 ).asInstanceOf [E ]
159
+ }
148
160
}
149
161
150
162
def removeFirstOccurrence (o : Any ): Boolean = {
@@ -189,7 +201,7 @@ class ArrayDeque[E] private (initialCapacity: Int)
189
201
def size (): Int = {
190
202
if (isEmpty()) 0
191
203
else if (endIndex > startIndex) endIndex - startIndex
192
- else (endIndex + inner. length) - startIndex
204
+ else (endIndex + length() ) - startIndex
193
205
}
194
206
195
207
def iterator (): Iterator [E ] = new Iterator [E ] {
@@ -219,10 +231,10 @@ class ArrayDeque[E] private (initialCapacity: Int)
219
231
nextIndex += 1
220
232
if (nextIndex == endIndex)
221
233
nextIndex = - 1
222
- else if (nextIndex >= inner. length)
234
+ else if (nextIndex >= length() )
223
235
nextIndex = 0
224
236
225
- inner(lastIndex)
237
+ inner(lastIndex). asInstanceOf [ E ]
226
238
}
227
239
228
240
override def remove (): Unit = {
@@ -275,10 +287,10 @@ class ArrayDeque[E] private (initialCapacity: Int)
275
287
} else {
276
288
nextIndex -= 1
277
289
if (nextIndex < 0 )
278
- nextIndex = inner. length - 1
290
+ nextIndex = length() - 1
279
291
}
280
292
281
- inner(lastIndex)
293
+ inner(lastIndex). asInstanceOf [ E ]
282
294
}
283
295
284
296
override def remove (): Unit = {
@@ -313,21 +325,22 @@ class ArrayDeque[E] private (initialCapacity: Int)
313
325
status += 1
314
326
empty = true
315
327
startIndex = 0
316
- endIndex = inner. length
328
+ endIndex = length()
317
329
}
318
330
319
331
private def firstIndexOf (o : Any ): Int = {
320
332
// scalastyle:off return
321
333
if (isEmpty())
322
334
return - 1
323
335
val inner = this .inner // local copy
324
- val capacity = inner. length // local copy
336
+ val capacity = length() // local copy
325
337
val endIndex = this .endIndex // local copy
326
338
var i = startIndex
327
339
do {
328
340
if (i >= capacity)
329
341
i = 0
330
- if (Objects .equals(inner(i), o))
342
+ val obj = inner(i).asInstanceOf [E ]
343
+ if (Objects .equals(obj, o))
331
344
return i
332
345
i += 1 // let i overrun so we catch endIndex == capacity
333
346
} while (i != endIndex)
@@ -345,8 +358,9 @@ class ArrayDeque[E] private (initialCapacity: Int)
345
358
do {
346
359
i -= 1
347
360
if (i < 0 )
348
- i = inner.length - 1
349
- if (Objects .equals(inner(i), o))
361
+ i = length() - 1
362
+ val obj = inner(i).asInstanceOf [E ]
363
+ if (Objects .equals(obj, o))
350
364
return i
351
365
} while (i != startIndex)
352
366
- 1
@@ -356,22 +370,14 @@ class ArrayDeque[E] private (initialCapacity: Int)
356
370
private def ensureCapacityForAdd (): Unit = {
357
371
if (isEmpty()) {
358
372
// Nothing to do (constructor ensures capacity is always non-zero).
359
- } else if (startIndex == 0 && endIndex == inner.length) {
360
- val oldCapacity = inner.length
361
- inner.length *= 2
362
- // no copying required: We just keep adding to the end.
363
- // However, ensure array is dense.
364
- fillNulls(oldCapacity, inner.length)
373
+ } else if (startIndex == 0 && endIndex == length()) {
374
+ val oldCapacity = length()
375
+ inner = Arrays .copyOf(inner, oldCapacity * 2 )
365
376
} else if (startIndex == endIndex) {
366
- val oldCapacity = inner.length
367
- inner.length *= 2
368
- // move beginning of array to end
369
- for (i <- 0 until endIndex) {
370
- inner(i + oldCapacity) = inner(i)
371
- inner(i) = null .asInstanceOf [E ] // free old reference for GC
372
- }
373
- // ensure rest of array is dense
374
- fillNulls(endIndex + oldCapacity, inner.length)
377
+ val oldCapacity = length()
378
+ val newArr = new Array [AnyRef ](oldCapacity * 2 )
379
+ System .arraycopy(inner, 0 , newArr, oldCapacity, endIndex)
380
+ inner= newArr
375
381
endIndex += oldCapacity
376
382
}
377
383
}
@@ -397,10 +403,8 @@ class ArrayDeque[E] private (initialCapacity: Int)
397
403
pollLast()
398
404
true
399
405
} else if (target < endIndex) {
400
- // Shift elements from endIndex towards target
401
- for (i <- target until endIndex - 1 )
402
- inner(i) = inner(i + 1 )
403
- inner(endIndex - 1 ) = null .asInstanceOf [E ] // free reference for GC
406
+ System .arraycopy(inner, target + 1 , inner, target, endIndex - target)
407
+ inner(endIndex - 1 ) = null // free reference for GC
404
408
status += 1
405
409
406
410
/* Note that endIndex >= 2:
@@ -429,13 +433,8 @@ class ArrayDeque[E] private (initialCapacity: Int)
429
433
* ==> contradiction.
430
434
*/
431
435
432
- // for (i <- target until startIndex by -1)
433
- var i = target
434
- while (i != startIndex) {
435
- inner(i) = inner(i - 1 )
436
- i -= 1
437
- }
438
- inner(startIndex) = null .asInstanceOf [E ] // free reference for GC
436
+ System .arraycopy(inner, startIndex, inner, startIndex + 1 , target - startIndex)
437
+ inner(startIndex) = null // free reference for GC
439
438
440
439
status += 1
441
440
@@ -452,8 +451,7 @@ class ArrayDeque[E] private (initialCapacity: Int)
452
451
}
453
452
}
454
453
455
- private def fillNulls (from : Int , until : Int ): Unit = {
456
- for (i <- from until until)
457
- inner(i) = null .asInstanceOf [E ]
458
- }
454
+ @ inline
455
+ private def length (): Int =
456
+ inner.length
459
457
}
0 commit comments