1
package org.perl6.nqp.sixmodel.reprs;
3
import java.lang.System;
5
import org.perl6.nqp.runtime.ExceptionHandling;
6
import org.perl6.nqp.runtime.ThreadContext;
7
import org.perl6.nqp.sixmodel.SixModelObject;
9
public class VMArrayInstance_u16 extends SixModelObject {
14
private static long widen(short s) {
15
return s < 0 ? s + (1 << 16) : s;
18
public void at_pos_native(ThreadContext tc, long index) {
22
throw ExceptionHandling.dieInternal(tc, "VMArray: Index out of bounds");
24
else if (index >= elems) {
25
tc.native_type = ThreadContext.NATIVE_INT;
30
tc.native_type = ThreadContext.NATIVE_INT;
31
tc.native_i = widen(slots[start + (int)index]);
34
public long exists_pos(ThreadContext tc, long key) {
38
if (key >= 0 && key < this.elems) {
44
private void set_size_internal(ThreadContext tc, long n) {
45
long elems = this.elems;
46
long start = this.start;
47
long ssize = this.slots == null ? 0 : this.slots.length;
48
short[] slots = this.slots;
51
throw ExceptionHandling.dieInternal(tc, "VMArray: Can't resize to negative elements");
56
/* if there aren't enough slots at the end, shift off empty slots
57
* from the beginning first */
58
if (start > 0 && n + start > ssize) {
60
memmove(slots, 0, start, elems);
62
/* fill out any unused slots with zeros */
63
while (elems < ssize) {
64
slots[(int)elems] = 0;
71
/* we already have n slots available, we can just return */
75
/* We need more slots. If the current slot size is less
76
* than 8K, use the larger of twice the current slot size
77
* or the actual number of elements needed. Otherwise,
78
* grow the slots to the next multiple of 4096 (0x1000). */
81
if (n > ssize) ssize = n;
82
if (ssize < 8) ssize = 8;
85
ssize = (n + 0x1000) & ~0xfff;
88
/* now allocate the new slot buffer */
90
slots = new short[(int)ssize];
93
short[] new_slots = new short[(int)ssize];
94
System.arraycopy(slots, 0, new_slots, 0, slots.length);
101
public void bind_pos_native(ThreadContext tc, long index) {
105
throw ExceptionHandling.dieInternal(tc, "VMArray: Index out of bounds");
107
else if (index >= elems)
108
set_size_internal(tc, index + 1);
110
tc.native_type = ThreadContext.NATIVE_INT;
111
slots[start + (int)index] = (short)tc.native_i;
114
public long elems(ThreadContext tc) {
118
public void set_elems(ThreadContext tc, long count) {
119
set_size_internal(tc, count);
122
public void push_native(ThreadContext tc) {
123
set_size_internal(tc, elems + 1);
124
tc.native_type = ThreadContext.NATIVE_INT;
125
slots[start + elems - 1] = (short)tc.native_i;
128
public void pop_native(ThreadContext tc) {
130
throw ExceptionHandling.dieInternal(tc, "VMArray: Can't pop from an empty array");
132
tc.native_type = ThreadContext.NATIVE_INT;
133
tc.native_i = widen(slots[start + elems]);
136
public void unshift_native(ThreadContext tc) {
137
/* If we don't have room at the beginning of the slots,
138
* make some room (8 slots) for unshifting */
144
int origElems = elems;
145
set_size_internal(tc, elems + n);
147
/* move elements and set start */
148
memmove(slots, n, 0, origElems);
152
/* clear out beginning elements */
153
for (i = 0; i < n; i++)
157
/* Now do the unshift */
159
tc.native_type = ThreadContext.NATIVE_INT;
160
slots[start] = (short)tc.native_i;
164
public void shift_native(ThreadContext tc) {
166
throw ExceptionHandling.dieInternal(tc, "VMArray: Can't shift from an empty array");
168
tc.native_type = ThreadContext.NATIVE_INT;
169
tc.native_i = widen(slots[start]);
174
/* This can be optimized for the case we have two VMArray representation objects. */
175
public void splice(ThreadContext tc, SixModelObject from, long offset, long count) {
177
long elems1 = from.elems(tc);
180
short[] slots = null;
182
/* start from end? */
187
throw ExceptionHandling.dieInternal(tc, "VMArray: Illegal splice offset");
190
/* When offset == 0, then we may be able to reduce the memmove
191
* calls and reallocs by adjusting SELF's start, elems0, and
192
* count to better match the incoming splice. In particular,
193
* we're seeking to adjust C<count> to as close to C<elems1>
196
long n = elems1 - count;
204
this.elems = (int)elems0;
209
this.start = (int)(start - n);
210
this.elems = (int)elems0;
214
/* if count == 0 and elems1 == 0, there's nothing left
215
* to copy or remove, so the splice is done! */
216
if (count == 0 && elems1 == 0)
219
/* number of elements to right of splice (the "tail") */
220
tail = elems0 - offset - count;
224
else if (tail > 0 && count > elems1) {
225
/* We're shrinking the array, so first move the tail left */
228
memmove(slots, start + offset + elems1, start + offset + count, tail);
231
/* now resize the array */
232
set_size_internal(tc, offset + elems1 + tail);
236
if (tail > 0 && count < elems1) {
237
/* The array grew, so move the tail to the right */
238
memmove(slots, start + offset + elems1, start + offset + count, tail);
241
/* now copy C<from>'s elements into SELF */
244
int from_pos = (int)(start + offset);
245
for (i = 0; i < elems1; i++) {
246
from.at_pos_native(tc, i);
247
slots[from_pos + i] = (short)tc.native_i;
252
private void memmove(short[] slots, long dest_start, long src_start, long l_n) {
253
System.arraycopy(slots, (int)src_start, slots, (int)dest_start, (int)l_n);
256
public SixModelObject clone(ThreadContext tc) {
258
VMArrayInstance_i16 clone = (VMArrayInstance_i16)this.clone();
260
if (clone.slots != null)
261
clone.slots = this.slots.clone();
263
} catch (CloneNotSupportedException e) {
264
throw new RuntimeException(e);