Buffer.java revision 12968:4d8a004e5c6d
1/*
2 * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23package org.graalvm.compiler.asm;
24
25import org.graalvm.compiler.core.common.NumUtil;
26
27import java.nio.ByteBuffer;
28import java.nio.ByteOrder;
29import java.util.Arrays;
30
31/**
32 * Code buffer management for the assembler.
33 */
34final class Buffer {
35
36    protected ByteBuffer data;
37
38    Buffer(ByteOrder order) {
39        data = ByteBuffer.allocate(AsmOptions.InitialCodeBufferSize);
40        data.order(order);
41    }
42
43    public int position() {
44        return data.position();
45    }
46
47    public void setPosition(int position) {
48        assert position >= 0 && position <= data.limit();
49        data.position(position);
50    }
51
52    /**
53     * Closes this buffer. Any further operations on a closed buffer will result in a
54     * {@link NullPointerException}.
55     *
56     * @param trimmedCopy if {@code true}, then a copy of the underlying byte array up to (but not
57     *            including) {@code position()} is returned
58     * @return the data in this buffer or a trimmed copy if {@code trimmedCopy} is {@code true}
59     */
60    public byte[] close(boolean trimmedCopy) {
61        byte[] result = data.array();
62        if (trimmedCopy) {
63            // Make a copy even if result.length == data.position() since
64            // the API for trimmedCopy states a copy is always made
65            result = Arrays.copyOf(result, data.position());
66        }
67        data = null;
68        return result;
69    }
70
71    public byte[] copyData(int start, int end) {
72        if (data == null) {
73            return null;
74        }
75        return Arrays.copyOfRange(data.array(), start, end);
76    }
77
78    /**
79     * Copies the data from this buffer into a given array.
80     *
81     * @param dst the destination array
82     * @param off starting position in {@code dst}
83     * @param len number of bytes to copy
84     */
85    public void copyInto(byte[] dst, int off, int len) {
86        System.arraycopy(data.array(), 0, dst, off, len);
87    }
88
89    protected void ensureSize(int length) {
90        if (length >= data.limit()) {
91            byte[] newBuf = Arrays.copyOf(data.array(), length * 4);
92            ByteBuffer newData = ByteBuffer.wrap(newBuf);
93            newData.order(data.order());
94            newData.position(data.position());
95            data = newData;
96        }
97    }
98
99    public void emitBytes(byte[] arr, int off, int len) {
100        ensureSize(data.position() + len);
101        data.put(arr, off, len);
102    }
103
104    public void emitByte(int b) {
105        assert NumUtil.isUByte(b) || NumUtil.isByte(b);
106        ensureSize(data.position() + 1);
107        data.put((byte) (b & 0xFF));
108    }
109
110    public void emitShort(int b) {
111        assert NumUtil.isUShort(b) || NumUtil.isShort(b);
112        ensureSize(data.position() + 2);
113        data.putShort((short) b);
114    }
115
116    public void emitInt(int b) {
117        ensureSize(data.position() + 4);
118        data.putInt(b);
119    }
120
121    public void emitLong(long b) {
122        ensureSize(data.position() + 8);
123        data.putLong(b);
124    }
125
126    public void emitBytes(byte[] arr, int pos) {
127        final int len = arr.length;
128        ensureSize(pos + len);
129        // Write directly into the underlying array so as to not
130        // change the ByteBuffer's position
131        System.arraycopy(arr, 0, data.array(), pos, len);
132    }
133
134    public void emitByte(int b, int pos) {
135        assert NumUtil.isUByte(b) || NumUtil.isByte(b);
136        ensureSize(pos + 1);
137        data.put(pos, (byte) (b & 0xFF));
138    }
139
140    public void emitShort(int b, int pos) {
141        assert NumUtil.isUShort(b) || NumUtil.isShort(b);
142        ensureSize(pos + 2);
143        data.putShort(pos, (short) b).position();
144    }
145
146    public void emitInt(int b, int pos) {
147        ensureSize(pos + 4);
148        data.putInt(pos, b).position();
149    }
150
151    public void emitLong(long b, int pos) {
152        ensureSize(pos + 8);
153        data.putLong(pos, b).position();
154    }
155
156    public int getByte(int pos) {
157        int b = data.get(pos);
158        return b & 0xff;
159    }
160
161    public int getShort(int pos) {
162        short s = data.getShort(pos);
163        return s & 0xffff;
164    }
165
166    public int getInt(int pos) {
167        return data.getInt(pos);
168    }
169
170    public void reset() {
171        data.clear();
172    }
173}
174