diff options
author | Jaewoong Jung <jungjw@google.com> | 2019-07-15 11:59:57 -0700 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2019-07-15 11:59:57 -0700 |
commit | a937690b71d863bd26bb5e797f9de908620727f4 (patch) | |
tree | 368fb885df83bfc67159399a02a8b9e3424656c3 | |
parent | f6608e9344e1b2543389d48c8326c64b413ae096 (diff) | |
parent | a9e6e81858f320fb075a079ba1f44368e873d7cd (diff) | |
download | dalvik-a937690b71d863bd26bb5e797f9de908620727f4.tar.gz |
Merge "Optimize dexdeps code."
am: a9e6e81858
Change-Id: Ieafed53cac0ee8c49baaeb21ad8459b997429812
-rw-r--r-- | tools/dexdeps/src/com/android/dexdeps/DexData.java | 140 |
1 files changed, 72 insertions, 68 deletions
diff --git a/tools/dexdeps/src/com/android/dexdeps/DexData.java b/tools/dexdeps/src/com/android/dexdeps/DexData.java index cc1978c86..1b6cc98ed 100644 --- a/tools/dexdeps/src/com/android/dexdeps/DexData.java +++ b/tools/dexdeps/src/com/android/dexdeps/DexData.java @@ -18,6 +18,8 @@ package com.android.dexdeps; import java.io.IOException; import java.io.RandomAccessFile; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; import java.nio.charset.StandardCharsets; import java.util.Arrays; @@ -35,7 +37,7 @@ public class DexData { private ClassDefItem[] mClassDefs; private byte tmpBuf[] = new byte[4]; - private boolean isBigEndian = false; + private ByteOrder mByteOrder = ByteOrder.LITTLE_ENDIAN; /** * Constructs a new DexData for this file. @@ -99,7 +101,7 @@ public class DexData { /* do nothing */ } else if (mHeaderItem.endianTag == HeaderItem.REVERSE_ENDIAN_CONSTANT){ /* file is big-endian (!), reverse future reads */ - isBigEndian = true; + mByteOrder = ByteOrder.BIG_ENDIAN; } else { System.err.println("Endian constant has unexpected value " + Integer.toHexString(mHeaderItem.endianTag)); @@ -107,26 +109,27 @@ public class DexData { } seek(8+4+20); // magic, checksum, signature - mHeaderItem.fileSize = readInt(); - mHeaderItem.headerSize = readInt(); - /*mHeaderItem.endianTag =*/ readInt(); - /*mHeaderItem.linkSize =*/ readInt(); - /*mHeaderItem.linkOff =*/ readInt(); - /*mHeaderItem.mapOff =*/ readInt(); - mHeaderItem.stringIdsSize = readInt(); - mHeaderItem.stringIdsOff = readInt(); - mHeaderItem.typeIdsSize = readInt(); - mHeaderItem.typeIdsOff = readInt(); - mHeaderItem.protoIdsSize = readInt(); - mHeaderItem.protoIdsOff = readInt(); - mHeaderItem.fieldIdsSize = readInt(); - mHeaderItem.fieldIdsOff = readInt(); - mHeaderItem.methodIdsSize = readInt(); - mHeaderItem.methodIdsOff = readInt(); - mHeaderItem.classDefsSize = readInt(); - mHeaderItem.classDefsOff = readInt(); - /*mHeaderItem.dataSize =*/ readInt(); - /*mHeaderItem.dataOff =*/ readInt(); + ByteBuffer buffer = readByteBuffer(Integer.BYTES * 20); + mHeaderItem.fileSize = buffer.getInt(); + mHeaderItem.headerSize = buffer.getInt(); + /*mHeaderItem.endianTag =*/ buffer.getInt(); + /*mHeaderItem.linkSize =*/ buffer.getInt(); + /*mHeaderItem.linkOff =*/ buffer.getInt(); + /*mHeaderItem.mapOff =*/ buffer.getInt(); + mHeaderItem.stringIdsSize = buffer.getInt(); + mHeaderItem.stringIdsOff = buffer.getInt(); + mHeaderItem.typeIdsSize = buffer.getInt(); + mHeaderItem.typeIdsOff = buffer.getInt(); + mHeaderItem.protoIdsSize = buffer.getInt(); + mHeaderItem.protoIdsOff = buffer.getInt(); + mHeaderItem.fieldIdsSize = buffer.getInt(); + mHeaderItem.fieldIdsOff = buffer.getInt(); + mHeaderItem.methodIdsSize = buffer.getInt(); + mHeaderItem.methodIdsOff = buffer.getInt(); + mHeaderItem.classDefsSize = buffer.getInt(); + mHeaderItem.classDefsOff = buffer.getInt(); + /*mHeaderItem.dataSize =*/ buffer.getInt(); + /*mHeaderItem.dataOff =*/ buffer.getInt(); } /** @@ -143,9 +146,7 @@ public class DexData { //System.out.println("reading " + count + " strings"); seek(mHeaderItem.stringIdsOff); - for (int i = 0; i < count; i++) { - stringOffsets[i] = readInt(); - } + readByteBuffer(Integer.BYTES * count).asIntBuffer().get(stringOffsets); mStrings = new String[count]; @@ -166,9 +167,10 @@ public class DexData { //System.out.println("reading " + count + " typeIds"); seek(mHeaderItem.typeIdsOff); + ByteBuffer buffer = readByteBuffer(Integer.BYTES * count); for (int i = 0; i < count; i++) { mTypeIds[i] = new TypeIdItem(); - mTypeIds[i].descriptorIdx = readInt(); + mTypeIds[i].descriptorIdx = buffer.getInt(); //System.out.println(i + ": " + mTypeIds[i].descriptorIdx + // " " + mStrings[mTypeIds[i].descriptorIdx]); @@ -184,15 +186,16 @@ public class DexData { //System.out.println("reading " + count + " protoIds"); seek(mHeaderItem.protoIdsOff); + ByteBuffer buffer = readByteBuffer(Integer.BYTES * 3 * count); /* * Read the proto ID items. */ for (int i = 0; i < count; i++) { mProtoIds[i] = new ProtoIdItem(); - mProtoIds[i].shortyIdx = readInt(); - mProtoIds[i].returnTypeIdx = readInt(); - mProtoIds[i].parametersOff = readInt(); + mProtoIds[i].shortyIdx = buffer.getInt(); + mProtoIds[i].returnTypeIdx = buffer.getInt(); + mProtoIds[i].parametersOff = buffer.getInt(); //System.out.println(i + ": " + mProtoIds[i].shortyIdx + // " " + mStrings[mProtoIds[i].shortyIdx]); @@ -212,10 +215,11 @@ public class DexData { } else { seek(offset); int size = readInt(); // #of entries in list + buffer = readByteBuffer(Short.BYTES * size); protoId.types = new int[size]; for (int j = 0; j < size; j++) { - protoId.types[j] = readShort() & 0xffff; + protoId.types[j] = buffer.getShort() & 0xffff; } } } @@ -230,11 +234,12 @@ public class DexData { //System.out.println("reading " + count + " fieldIds"); seek(mHeaderItem.fieldIdsOff); + ByteBuffer buffer = readByteBuffer((Integer.BYTES + Short.BYTES * 2) * count); for (int i = 0; i < count; i++) { mFieldIds[i] = new FieldIdItem(); - mFieldIds[i].classIdx = readShort() & 0xffff; - mFieldIds[i].typeIdx = readShort() & 0xffff; - mFieldIds[i].nameIdx = readInt(); + mFieldIds[i].classIdx = buffer.getShort() & 0xffff; + mFieldIds[i].typeIdx = buffer.getShort() & 0xffff; + mFieldIds[i].nameIdx = buffer.getInt(); //System.out.println(i + ": " + mFieldIds[i].nameIdx + // " " + mStrings[mFieldIds[i].nameIdx]); @@ -250,11 +255,12 @@ public class DexData { //System.out.println("reading " + count + " methodIds"); seek(mHeaderItem.methodIdsOff); + ByteBuffer buffer = readByteBuffer((Integer.BYTES + Short.BYTES * 2) * count); for (int i = 0; i < count; i++) { mMethodIds[i] = new MethodIdItem(); - mMethodIds[i].classIdx = readShort() & 0xffff; - mMethodIds[i].protoIdx = readShort() & 0xffff; - mMethodIds[i].nameIdx = readInt(); + mMethodIds[i].classIdx = buffer.getShort() & 0xffff; + mMethodIds[i].protoIdx = buffer.getShort() & 0xffff; + mMethodIds[i].nameIdx = buffer.getInt(); //System.out.println(i + ": " + mMethodIds[i].nameIdx + // " " + mStrings[mMethodIds[i].nameIdx]); @@ -270,17 +276,18 @@ public class DexData { //System.out.println("reading " + count + " classDefs"); seek(mHeaderItem.classDefsOff); + ByteBuffer buffer = readByteBuffer(Integer.BYTES * 8 * count); for (int i = 0; i < count; i++) { mClassDefs[i] = new ClassDefItem(); - mClassDefs[i].classIdx = readInt(); + mClassDefs[i].classIdx = buffer.getInt(); - /* access_flags = */ readInt(); - /* superclass_idx = */ readInt(); - /* interfaces_off = */ readInt(); - /* source_file_idx = */ readInt(); - /* annotations_off = */ readInt(); - /* class_data_off = */ readInt(); - /* static_values_off = */ readInt(); + /* access_flags = */ buffer.getInt(); + /* superclass_idx = */ buffer.getInt(); + /* interfaces_off = */ buffer.getInt(); + /* source_file_idx = */ buffer.getInt(); + /* annotations_off = */ buffer.getInt(); + /* class_data_off = */ buffer.getInt(); + /* static_values_off = */ buffer.getInt(); //System.out.println(i + ": " + mClassDefs[i].classIdx + " " + // mStrings[mTypeIds[mClassDefs[i].classIdx].descriptorIdx]); @@ -452,24 +459,12 @@ public class DexData { } /** - * Reads a signed 16-bit integer, byte-swapping if necessary. - */ - short readShort() throws IOException { - mDexFile.readFully(tmpBuf, 0, 2); - if (isBigEndian) { - return (short) ((tmpBuf[1] & 0xff) | ((tmpBuf[0] & 0xff) << 8)); - } else { - return (short) ((tmpBuf[0] & 0xff) | ((tmpBuf[1] & 0xff) << 8)); - } - } - - /** * Reads a signed 32-bit integer, byte-swapping if necessary. */ int readInt() throws IOException { mDexFile.readFully(tmpBuf, 0, 4); - if (isBigEndian) { + if (mByteOrder == ByteOrder.BIG_ENDIAN) { return (tmpBuf[3] & 0xff) | ((tmpBuf[2] & 0xff) << 8) | ((tmpBuf[1] & 0xff) << 16) | ((tmpBuf[0] & 0xff) << 24); } else { @@ -497,29 +492,38 @@ public class DexData { } /** + * Reads bytes and transforms them into a ByteBuffer with the desired byte order set, from which + * primitive values can be read. + */ + ByteBuffer readByteBuffer(int size) throws IOException { + byte bytes[] = new byte[size]; + mDexFile.read(bytes); + return ByteBuffer.wrap(bytes).order(mByteOrder); + } + + /** * Reads a UTF-8 string. * - * We don't know how long the UTF-8 string is, so we have to read one - * byte at a time. We could make an educated guess based on the - * utf16_size and seek back if we get it wrong, but seeking backward - * may cause the underlying implementation to reload I/O buffers. + * We don't know how long the UTF-8 string is, so we try to read the worst case amount of bytes. + * + * Note that the dex file pointer will likely be at a wrong location after this operation, which + * means it can't be used in the middle of sequential reads. */ String readString() throws IOException { int utf16len = readUnsignedLeb128(); byte inBuf[] = new byte[utf16len * 3]; // worst case - int idx; - for (idx = 0; idx < inBuf.length; idx++) { - byte val = readByte(); - if (val == 0) + int bytesRead = mDexFile.read(inBuf); + for (int i = 0; i < bytesRead; i++) { + if (inBuf[i] == 0) { + bytesRead = i; break; - inBuf[idx] = val; + } } - return new String(inBuf, 0, idx, "UTF-8"); + return new String(inBuf, 0, bytesRead, "UTF-8"); } - /* * ======================================================================= * Internal "structure" declarations |