• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2016, the R8 project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4 package com.android.tools.r8.dex;
5 
6 import com.android.tools.r8.code.Instruction;
7 import com.android.tools.r8.graph.ObjectToOffsetMapping;
8 import com.android.tools.r8.utils.EncodedValueUtils;
9 import com.android.tools.r8.utils.LebUtils;
10 import java.nio.ByteBuffer;
11 import java.nio.ByteOrder;
12 import java.nio.ShortBuffer;
13 
14 /**
15  * Provides an abstraction around a {@link ByteBuffer} with write operations for
16  * additional DEX specific formats, like Leb128.
17  */
18 public class DexOutputBuffer {
19   private static final int DEFAULT_BUFFER_SIZE = 256 * 1024;
20 
21   private ByteBuffer byteBuffer;
22 
DexOutputBuffer()23   public DexOutputBuffer() {
24     byteBuffer = allocate(DEFAULT_BUFFER_SIZE);
25   }
26 
ensureSpaceFor(int bytes)27   private void ensureSpaceFor(int bytes) {
28     if (byteBuffer.remaining() < bytes) {
29       int newSize = byteBuffer.capacity() + Math.max(byteBuffer.capacity(), bytes * 2);
30       ByteBuffer newBuffer = allocate(newSize);
31       System.arraycopy(byteBuffer.array(), 0, newBuffer.array(), 0, byteBuffer.position());
32       newBuffer.position(byteBuffer.position());
33       byteBuffer = newBuffer;
34     }
35   }
36 
allocate(int size)37   private ByteBuffer allocate(int size) {
38     ByteBuffer buffer = ByteBuffer.allocate(size);
39     buffer.order(ByteOrder.LITTLE_ENDIAN);
40     return buffer;
41   }
42 
putUleb128(int value)43   public void putUleb128(int value) {
44     LebUtils.putUleb128(this, value);
45   }
46 
putSleb128(int value)47   public void putSleb128(int value) {
48     LebUtils.putSleb128(this, value);
49   }
50 
putSignedEncodedValue(long value, int expectedSize)51   public int putSignedEncodedValue(long value, int expectedSize) {
52     return EncodedValueUtils.putSigned(this, value, expectedSize);
53   }
54 
putUnsignedEncodedValue(long value, int expectedSize)55   public int putUnsignedEncodedValue(long value, int expectedSize) {
56     return EncodedValueUtils.putUnsigned(this, value, expectedSize);
57   }
58 
putInstructions(Instruction[] insns, ObjectToOffsetMapping mapping)59   public void putInstructions(Instruction[] insns, ObjectToOffsetMapping mapping) {
60     int size = 0;
61     for (Instruction insn : insns) {
62       size += insn.getSize();
63     }
64     ensureSpaceFor(size * Short.BYTES);
65     assert byteBuffer.position() % 2 == 0;
66     ShortBuffer shortBuffer = byteBuffer.asShortBuffer();
67     for (int i = 0; i < insns.length; i++) {
68       insns[i].write(shortBuffer, mapping);
69     }
70     byteBuffer.position(byteBuffer.position() + shortBuffer.position() * Short.BYTES);
71   }
72 
putByte(byte aByte)73   public void putByte(byte aByte) {
74     ensureSpaceFor(Byte.BYTES);
75     byteBuffer.put(aByte);
76   }
77 
putBytes(byte[] bytes)78   public void putBytes(byte[] bytes) {
79     ensureSpaceFor(bytes.length);
80     byteBuffer.put(bytes);
81   }
82 
putShort(short aShort)83   public void putShort(short aShort) {
84     ensureSpaceFor(Short.BYTES);
85     byteBuffer.putShort(aShort);
86   }
87 
putInt(int anInteger)88   public void putInt(int anInteger) {
89     ensureSpaceFor(Integer.BYTES);
90     byteBuffer.putInt(anInteger);
91   }
92 
93   /**
94    * Moves the position in the bytebuffer forward until it is aligned.
95    *
96    * @param bytes  alignment requirement in bytes
97    * @return       the new position after alignment
98    */
align(int bytes)99   public int align(int bytes) {
100     assert bytes > 0;
101     int mask = bytes - 1;
102     int newPosition = (byteBuffer.position() + mask) & ~mask;
103     ensureSpaceFor(newPosition - position());
104     byteBuffer.position(newPosition);
105     return newPosition;
106   }
107 
position()108   public int position() {
109     return byteBuffer.position();
110   }
111 
forward(int bytes)112   public void forward(int bytes) {
113     ensureSpaceFor(bytes);
114     byteBuffer.position(byteBuffer.position() + bytes);
115   }
116 
rewind(int bytes)117   public void rewind(int bytes) {
118     forward(-bytes);
119   }
120 
moveTo(int position)121   public void moveTo(int position) {
122     ensureSpaceFor(position - byteBuffer.position());
123     byteBuffer.position(position);
124   }
125 
isAligned(int bytes)126   public boolean isAligned(int bytes) {
127     return position() % bytes == 0;
128   }
129 
asArray()130   public byte[] asArray() {
131     return byteBuffer.array();
132   }
133 }
134