Skip to content

Commit f3ce73e

Browse files
committed
Unsigned native int array support for JVM.
Means we can get buf8, utf8, buf16, utf16 types behaving on JVM.
1 parent 9561e47 commit f3ce73e

File tree

5 files changed

+828
-7
lines changed

5 files changed

+828
-7
lines changed

src/vm/jvm/runtime/org/perl6/nqp/runtime/Ops.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@
7878
import org.perl6.nqp.sixmodel.reprs.VMArrayInstance_i16;
7979
import org.perl6.nqp.sixmodel.reprs.VMArrayInstance_i32;
8080
import org.perl6.nqp.sixmodel.reprs.VMArrayInstance_i8;
81+
import org.perl6.nqp.sixmodel.reprs.VMArrayInstance_u8;
8182
import org.perl6.nqp.sixmodel.reprs.VMExceptionInstance;
8283
import org.perl6.nqp.sixmodel.reprs.VMHash;
8384
import org.perl6.nqp.sixmodel.reprs.VMHashInstance;
@@ -3202,13 +3203,20 @@ protected static ByteBuffer decode8(SixModelObject buf, ThreadContext tc) {
32023203
? ByteBuffer.wrap(bufi8.slots, bufi8.start, bufi8.elems)
32033204
: ByteBuffer.allocate(0);
32043205
}
3206+
else if (buf instanceof VMArrayInstance_u8) {
3207+
VMArrayInstance_u8 bufu8 = (VMArrayInstance_u8)buf;
3208+
bb = bufu8.slots != null
3209+
? ByteBuffer.wrap(bufu8.slots, bufu8.start, bufu8.elems)
3210+
: ByteBuffer.allocate(0);
3211+
}
32053212
else {
32063213
int n = (int)buf.elems(tc);
32073214
bb = ByteBuffer.allocate(n);
32083215
for (int i = 0; i < n; i++) {
32093216
buf.at_pos_native(tc, i);
32103217
bb.put((byte)tc.native_i);
32113218
}
3219+
bb.rewind();
32123220
}
32133221
return bb;
32143222
}

src/vm/jvm/runtime/org/perl6/nqp/sixmodel/reprs/VMArray.java

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,18 @@ public SixModelObject allocate(ThreadContext tc, STable st) {
3030
case StorageSpec.BP_INT:
3131
if (ss.bits == 64)
3232
obj = new VMArrayInstance_i();
33-
if (ss.bits == 8)
34-
obj = new VMArrayInstance_i8();
33+
else if (ss.bits == 8)
34+
obj = ss.is_unsigned == 0
35+
? new VMArrayInstance_i8()
36+
: new VMArrayInstance_u8();
3537
else if (ss.bits == 16)
36-
obj = new VMArrayInstance_i16();
38+
obj = ss.is_unsigned == 0
39+
? new VMArrayInstance_i16()
40+
: new VMArrayInstance_u16();
3741
else if (ss.bits == 32)
38-
obj = new VMArrayInstance_i32();
42+
obj = ss.is_unsigned == 0
43+
? new VMArrayInstance_i32()
44+
: new VMArrayInstance_u32();
3945
else
4046
obj = new VMArrayInstance_i();
4147
break;
@@ -84,11 +90,17 @@ public SixModelObject deserialize_stub(ThreadContext tc, STable st) {
8490
switch (ss.boxed_primitive) {
8591
case StorageSpec.BP_INT:
8692
if (ss.bits == 8)
87-
obj = new VMArrayInstance_i8();
93+
obj = ss.is_unsigned == 0
94+
? new VMArrayInstance_i8()
95+
: new VMArrayInstance_u8();
8896
else if (ss.bits == 16)
89-
obj = new VMArrayInstance_i16();
97+
obj = ss.is_unsigned == 0
98+
? new VMArrayInstance_i16()
99+
: new VMArrayInstance_u16();
90100
else if (ss.bits == 32)
91-
obj = new VMArrayInstance_i32();
101+
obj = ss.is_unsigned == 0
102+
? new VMArrayInstance_i32()
103+
: new VMArrayInstance_u32();
92104
else
93105
obj = new VMArrayInstance_i();
94106
break;
Lines changed: 267 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,267 @@
1+
package org.perl6.nqp.sixmodel.reprs;
2+
3+
import java.lang.System;
4+
5+
import org.perl6.nqp.runtime.ExceptionHandling;
6+
import org.perl6.nqp.runtime.ThreadContext;
7+
import org.perl6.nqp.sixmodel.SixModelObject;
8+
9+
public class VMArrayInstance_u16 extends SixModelObject {
10+
public int elems;
11+
public int start;
12+
public short[] slots;
13+
14+
private static long widen(short s) {
15+
return s < 0 ? s + (1 << 16) : s;
16+
}
17+
18+
public void at_pos_native(ThreadContext tc, long index) {
19+
if (index < 0) {
20+
index += elems;
21+
if (index < 0)
22+
throw ExceptionHandling.dieInternal(tc, "VMArray: Index out of bounds");
23+
}
24+
else if (index >= elems) {
25+
tc.native_type = ThreadContext.NATIVE_INT;
26+
tc.native_i = 0;
27+
return;
28+
}
29+
30+
tc.native_type = ThreadContext.NATIVE_INT;
31+
tc.native_i = widen(slots[start + (int)index]);
32+
}
33+
34+
public long exists_pos(ThreadContext tc, long key) {
35+
if (key < 0) {
36+
key += this.elems;
37+
}
38+
if (key >= 0 && key < this.elems) {
39+
return 1;
40+
}
41+
return 0;
42+
}
43+
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;
49+
50+
if (n < 0)
51+
throw ExceptionHandling.dieInternal(tc, "VMArray: Can't resize to negative elements");
52+
53+
if (n == elems)
54+
return;
55+
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) {
59+
if (elems > 0)
60+
memmove(slots, 0, start, elems);
61+
this.start = 0;
62+
/* fill out any unused slots with zeros */
63+
while (elems < ssize) {
64+
slots[(int)elems] = 0;
65+
elems++;
66+
}
67+
}
68+
69+
this.elems = (int)n;
70+
if (n <= ssize) {
71+
/* we already have n slots available, we can just return */
72+
return;
73+
}
74+
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). */
79+
if (ssize < 8192) {
80+
ssize *= 2;
81+
if (n > ssize) ssize = n;
82+
if (ssize < 8) ssize = 8;
83+
}
84+
else {
85+
ssize = (n + 0x1000) & ~0xfff;
86+
}
87+
88+
/* now allocate the new slot buffer */
89+
if (slots == null) {
90+
slots = new short[(int)ssize];
91+
}
92+
else {
93+
short[] new_slots = new short[(int)ssize];
94+
System.arraycopy(slots, 0, new_slots, 0, slots.length);
95+
slots = new_slots;
96+
}
97+
98+
this.slots = slots;
99+
}
100+
101+
public void bind_pos_native(ThreadContext tc, long index) {
102+
if (index < 0) {
103+
index += elems;
104+
if (index < 0)
105+
throw ExceptionHandling.dieInternal(tc, "VMArray: Index out of bounds");
106+
}
107+
else if (index >= elems)
108+
set_size_internal(tc, index + 1);
109+
110+
tc.native_type = ThreadContext.NATIVE_INT;
111+
slots[start + (int)index] = (short)tc.native_i;
112+
}
113+
114+
public long elems(ThreadContext tc) {
115+
return elems;
116+
}
117+
118+
public void set_elems(ThreadContext tc, long count) {
119+
set_size_internal(tc, count);
120+
}
121+
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;
126+
}
127+
128+
public void pop_native(ThreadContext tc) {
129+
if (elems < 1)
130+
throw ExceptionHandling.dieInternal(tc, "VMArray: Can't pop from an empty array");
131+
elems--;
132+
tc.native_type = ThreadContext.NATIVE_INT;
133+
tc.native_i = widen(slots[start + elems]);
134+
}
135+
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 */
139+
if (start < 1) {
140+
int n = 8;
141+
int i;
142+
143+
/* grow the array */
144+
int origElems = elems;
145+
set_size_internal(tc, elems + n);
146+
147+
/* move elements and set start */
148+
memmove(slots, n, 0, origElems);
149+
start = n;
150+
elems = origElems;
151+
152+
/* clear out beginning elements */
153+
for (i = 0; i < n; i++)
154+
slots[i] = 0;
155+
}
156+
157+
/* Now do the unshift */
158+
start--;
159+
tc.native_type = ThreadContext.NATIVE_INT;
160+
slots[start] = (short)tc.native_i;
161+
elems++;
162+
}
163+
164+
public void shift_native(ThreadContext tc) {
165+
if (elems < 1)
166+
throw ExceptionHandling.dieInternal(tc, "VMArray: Can't shift from an empty array");
167+
168+
tc.native_type = ThreadContext.NATIVE_INT;
169+
tc.native_i = widen(slots[start]);
170+
start++;
171+
elems--;
172+
}
173+
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) {
176+
long elems0 = elems;
177+
long elems1 = from.elems(tc);
178+
long start;
179+
long tail;
180+
short[] slots = null;
181+
182+
/* start from end? */
183+
if (offset < 0) {
184+
offset += elems0;
185+
186+
if (offset < 0)
187+
throw ExceptionHandling.dieInternal(tc, "VMArray: Illegal splice offset");
188+
}
189+
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>
194+
* as we can. */
195+
if (offset == 0) {
196+
long n = elems1 - count;
197+
start = this.start;
198+
if (n > start)
199+
n = start;
200+
if (n <= -elems0) {
201+
elems0 = 0;
202+
count = 0;
203+
this.start = 0;
204+
this.elems = (int)elems0;
205+
}
206+
else if (n != 0) {
207+
elems0 += n;
208+
count += n;
209+
this.start = (int)(start - n);
210+
this.elems = (int)elems0;
211+
}
212+
}
213+
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)
217+
return;
218+
219+
/* number of elements to right of splice (the "tail") */
220+
tail = elems0 - offset - count;
221+
if (tail < 0)
222+
tail = 0;
223+
224+
else if (tail > 0 && count > elems1) {
225+
/* We're shrinking the array, so first move the tail left */
226+
slots = this.slots;
227+
start = this.start;
228+
memmove(slots, start + offset + elems1, start + offset + count, tail);
229+
}
230+
231+
/* now resize the array */
232+
set_size_internal(tc, offset + elems1 + tail);
233+
234+
slots = this.slots;
235+
start = this.start;
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);
239+
}
240+
241+
/* now copy C<from>'s elements into SELF */
242+
if (elems1 > 0) {
243+
int i;
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;
248+
}
249+
}
250+
}
251+
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);
254+
}
255+
256+
public SixModelObject clone(ThreadContext tc) {
257+
try {
258+
VMArrayInstance_i16 clone = (VMArrayInstance_i16)this.clone();
259+
clone.sc = null;
260+
if (clone.slots != null)
261+
clone.slots = this.slots.clone();
262+
return clone;
263+
} catch (CloneNotSupportedException e) {
264+
throw new RuntimeException(e);
265+
}
266+
}
267+
}

0 commit comments

Comments
 (0)