1 /* 2 * Copyright (c) 2009, 2018, 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 */ 23 24 25 package org.graalvm.compiler.asm; 26 27 import org.graalvm.compiler.core.common.NumUtil; 28 29 import java.nio.ByteBuffer; 30 import java.nio.ByteOrder; 31 import java.util.Arrays; 32 33 /** 34 * Code buffer management for the assembler. 35 */ 36 final class Buffer { 37 38 protected ByteBuffer data; 39 Buffer(ByteOrder order)40 Buffer(ByteOrder order) { 41 data = ByteBuffer.allocate(AsmOptions.InitialCodeBufferSize); 42 data.order(order); 43 } 44 position()45 public int position() { 46 return data.position(); 47 } 48 setPosition(int position)49 public void setPosition(int position) { 50 assert position >= 0 && position <= data.limit(); 51 data.position(position); 52 } 53 54 /** 55 * Closes this buffer. Any further operations on a closed buffer will result in a 56 * {@link NullPointerException}. 57 * 58 * @param trimmedCopy if {@code true}, then a copy of the underlying byte array up to (but not 59 * including) {@code position()} is returned 60 * @return the data in this buffer or a trimmed copy if {@code trimmedCopy} is {@code true} 61 */ close(boolean trimmedCopy)62 public byte[] close(boolean trimmedCopy) { 63 byte[] result = data.array(); 64 if (trimmedCopy) { 65 // Make a copy even if result.length == data.position() since 66 // the API for trimmedCopy states a copy is always made 67 result = Arrays.copyOf(result, data.position()); 68 } 69 data = null; 70 return result; 71 } 72 copyData(int start, int end)73 public byte[] copyData(int start, int end) { 74 if (data == null) { 75 return null; 76 } 77 return Arrays.copyOfRange(data.array(), start, end); 78 } 79 80 /** 81 * Copies the data from this buffer into a given array. 82 * 83 * @param dst the destination array 84 * @param off starting position in {@code dst} 85 * @param len number of bytes to copy 86 */ copyInto(byte[] dst, int off, int len)87 public void copyInto(byte[] dst, int off, int len) { 88 System.arraycopy(data.array(), 0, dst, off, len); 89 } 90 ensureSize(int length)91 protected void ensureSize(int length) { 92 if (length >= data.limit()) { 93 byte[] newBuf = Arrays.copyOf(data.array(), length * 4); 94 ByteBuffer newData = ByteBuffer.wrap(newBuf); 95 newData.order(data.order()); 96 newData.position(data.position()); 97 data = newData; 98 } 99 } 100 emitBytes(byte[] arr, int off, int len)101 public void emitBytes(byte[] arr, int off, int len) { 102 ensureSize(data.position() + len); 103 data.put(arr, off, len); 104 } 105 emitByte(int b)106 public void emitByte(int b) { 107 assert NumUtil.isUByte(b) || NumUtil.isByte(b); 108 ensureSize(data.position() + 1); 109 data.put((byte) (b & 0xFF)); 110 } 111 emitShort(int b)112 public void emitShort(int b) { 113 assert NumUtil.isUShort(b) || NumUtil.isShort(b); 114 ensureSize(data.position() + 2); 115 data.putShort((short) b); 116 } 117 emitInt(int b)118 public void emitInt(int b) { 119 ensureSize(data.position() + 4); 120 data.putInt(b); 121 } 122 emitLong(long b)123 public void emitLong(long b) { 124 ensureSize(data.position() + 8); 125 data.putLong(b); 126 } 127 emitBytes(byte[] arr, int pos)128 public void emitBytes(byte[] arr, int pos) { 129 final int len = arr.length; 130 ensureSize(pos + len); 131 // Write directly into the underlying array so as to not 132 // change the ByteBuffer's position 133 System.arraycopy(arr, 0, data.array(), pos, len); 134 } 135 emitByte(int b, int pos)136 public void emitByte(int b, int pos) { 137 assert NumUtil.isUByte(b) || NumUtil.isByte(b); 138 ensureSize(pos + 1); 139 data.put(pos, (byte) (b & 0xFF)); 140 } 141 emitShort(int b, int pos)142 public void emitShort(int b, int pos) { 143 assert NumUtil.isUShort(b) || NumUtil.isShort(b); 144 ensureSize(pos + 2); 145 data.putShort(pos, (short) b).position(); 146 } 147 emitInt(int b, int pos)148 public void emitInt(int b, int pos) { 149 ensureSize(pos + 4); 150 data.putInt(pos, b).position(); 151 } 152 emitLong(long b, int pos)153 public void emitLong(long b, int pos) { 154 ensureSize(pos + 8); 155 data.putLong(pos, b).position(); 156 } 157 getByte(int pos)158 public int getByte(int pos) { 159 int b = data.get(pos); 160 return b & 0xff; 161 } 162 getShort(int pos)163 public int getShort(int pos) { 164 short s = data.getShort(pos); 165 return s & 0xffff; 166 } 167 getInt(int pos)168 public int getInt(int pos) { 169 return data.getInt(pos); 170 } 171 reset()172 public void reset() { 173 data.clear(); 174 } 175 } 176