~ubuntu-branches/ubuntu/vivid/nqp/vivid-proposed

« back to all changes in this revision

Viewing changes to src/vm/jvm/runtime/org/perl6/nqp/sixmodel/reprs/VMArrayInstance_u16.java

  • Committer: Package Import Robot
  • Author(s): Alessandro Ghedini
  • Date: 2013-11-01 12:09:18 UTC
  • mfrom: (1.1.4)
  • Revision ID: package-import@ubuntu.com-20131101120918-kx51sl0sxl3exsxi
Tags: 2013.10-1
* New upstream release
* Bump versioned (Build-)Depends on parrot
* Update patches
* Install new README.pod
* Fix vcs-field-not-canonical
* Do not install rubyish examples
* Do not Depends on parrot-devel anymore
* Add 07_disable-serialization-tests.patch

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
}