blob: 2c3e18a619c8c0b252696cd6e7e6fc0912ec5a9d [file] [log] [blame]
// Copyright (c) 2016, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.dex;
import com.android.tools.r8.graph.DexDebugEvent;
import com.android.tools.r8.graph.DexDebugInfo;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.ObjectToOffsetMapping;
import com.android.tools.r8.utils.LebUtils;
import java.nio.ByteBuffer;
import java.util.Arrays;
public class DebugBytecodeWriter {
private final ObjectToOffsetMapping mapping;
private final GraphLens graphLens;
private final DexDebugInfo info;
private ByteBuffer buffer;
public DebugBytecodeWriter(
DexDebugInfo info, ObjectToOffsetMapping mapping, GraphLens graphLens) {
this.info = info;
this.mapping = mapping;
this.graphLens = graphLens;
// Never allocate a zero-sized buffer, as we need to write the header, and the growth policy
// requires it to have a positive capacity.
this.buffer = ByteBuffer.allocate(info.events.length * 5 + 4);
}
public byte[] generate() {
// Header.
putUleb128(info.startLine); // line_start
putUleb128(info.parameters.length);
for (DexString name : info.parameters) {
putString(name);
}
// Body.
for (DexDebugEvent event : info.events) {
event.writeOn(this, mapping, graphLens);
}
// Tail.
putByte(Constants.DBG_END_SEQUENCE);
return Arrays.copyOf(buffer.array(), buffer.position());
}
private void maybeGrow(int size) {
if (buffer.remaining() < size) {
ByteBuffer newBuffer = ByteBuffer.allocate(buffer.capacity() * 2);
newBuffer.put(buffer.array(), 0, buffer.position());
buffer = newBuffer;
}
}
public void putByte(int item) {
maybeGrow(1);
buffer.put((byte) item);
}
public void putSleb128(int item) {
byte[] encoded = LebUtils.encodeSleb128(item);
maybeGrow(encoded.length);
buffer.put(encoded, 0, encoded.length);
}
public void putUleb128(int item) {
byte[] encoded = LebUtils.encodeUleb128(item);
maybeGrow(encoded.length);
buffer.put(encoded, 0, encoded.length);
}
private void putUleb128p1(int item) {
putUleb128(item + 1);
}
private void putNoIndex() {
putUleb128(0);
}
public void putType(DexType type) {
if (type == null) {
putNoIndex();
} else {
int index = mapping.getOffsetFor(type);
putUleb128p1(index);
}
}
public void putString(DexString string) {
if (string == null) {
putNoIndex();
} else {
int index = mapping.getOffsetFor(string);
putUleb128p1(index);
}
}
}