Revert "Paralleize jumbo string rewriting"
This reverts commit dd45b8cad6d33bc950e9146f50c789642a3be996.
Revert "Paralleize writing of DEX code bytes"
This reverts commit c24b330022279a51611e3c85fee0c4583f2306ab.
Revert "Temporalily fix test"
This reverts commit efd46c721c987a4db5f949a680f65aee34edd2ad.
Bug: b/422947619
Bug: b/444353673
Change-Id: I7af8ae3134de02e9f6aa2849be0a9119e16bbd1d
diff --git a/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java b/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
index 46011da..bb8d845 100644
--- a/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
+++ b/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
@@ -291,7 +291,7 @@
virtualFile -> {
Timing fileTiming =
timing.createThreadTiming("VirtualFile " + virtualFile.getId(), options);
- writeVirtualFile(virtualFile, fileTiming, forcedStrings, executorService);
+ writeVirtualFile(virtualFile, fileTiming, forcedStrings);
fileTiming.end();
return fileTiming;
},
@@ -530,11 +530,7 @@
}
protected void writeVirtualFile(
- VirtualFile virtualFile,
- Timing timing,
- List<DexString> forcedStrings,
- ExecutorService executorService)
- throws ExecutionException {
+ VirtualFile virtualFile, Timing timing, List<DexString> forcedStrings) {
if (virtualFile.isEmpty()) {
return;
}
@@ -571,8 +567,7 @@
timing.end();
timing.begin("Write bytes");
- ByteBufferResult result =
- writeDexFile(objectMapping, byteBufferProvider, virtualFile, timing, executorService);
+ ByteBufferResult result = writeDexFile(objectMapping, byteBufferProvider, virtualFile, timing);
ByteDataView data =
new ByteDataView(result.buffer.array(), result.buffer.arrayOffset(), result.length);
timing.end();
@@ -897,14 +892,12 @@
ObjectToOffsetMapping objectMapping,
ByteBufferProvider provider,
VirtualFile virtualFile,
- Timing timing,
- ExecutorService executorService)
- throws ExecutionException {
+ Timing timing) {
FileWriter fileWriter = new FileWriter(appView, provider, objectMapping, virtualFile);
// Collect the non-fixed sections.
timing.time("collect", fileWriter::collect);
// Generate and write the bytes.
- return timing.time("generate", () -> fileWriter.generate(timing, executorService));
+ return timing.time("generate", () -> fileWriter.generate(timing));
}
private static String mapMainDexListName(DexType type, NamingLens namingLens) {
diff --git a/src/main/java/com/android/tools/r8/dex/ApplicationWriterContainer.java b/src/main/java/com/android/tools/r8/dex/ApplicationWriterContainer.java
index d0a4602..cce512c 100644
--- a/src/main/java/com/android/tools/r8/dex/ApplicationWriterContainer.java
+++ b/src/main/java/com/android/tools/r8/dex/ApplicationWriterContainer.java
@@ -27,7 +27,6 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
class ApplicationWriterContainer extends ApplicationWriter {
@@ -41,8 +40,7 @@
ExecutorService executorService,
List<VirtualFile> virtualFiles,
List<DexString> forcedStrings,
- Timing timing)
- throws ExecutionException {
+ Timing timing) {
Map<FeatureSplit, List<VirtualFile>> virtualFilesForContainers = new HashMap<>();
List<VirtualFile> virtualFilesOutsideContainer = new ArrayList<>();
virtualFiles.forEach(
@@ -62,7 +60,7 @@
timing.begin("Write non container virtual files");
for (VirtualFile virtualFile : virtualFilesOutsideContainer) {
timing.begin("VirtualFile " + virtualFile.getId());
- writeVirtualFile(virtualFile, timing, forcedStrings, executorService);
+ writeVirtualFile(virtualFile, timing, forcedStrings);
timing.end();
}
timing.end();
@@ -70,17 +68,13 @@
// Write container virtual files.
timing.begin("Write container virtual files");
for (List<VirtualFile> virtualFilesForContainer : virtualFilesForContainers.values()) {
- writeContainer(forcedStrings, timing, virtualFilesForContainer, executorService);
+ writeContainer(forcedStrings, timing, virtualFilesForContainer);
}
timing.end();
}
private void writeContainer(
- List<DexString> forcedStrings,
- Timing timing,
- List<VirtualFile> virtualFiles,
- ExecutorService executorService)
- throws ExecutionException {
+ List<DexString> forcedStrings, Timing timing, List<VirtualFile> virtualFiles) {
ProgramConsumer consumer;
ByteBufferProvider byteBufferProvider;
if (programConsumer != null) {
@@ -115,8 +109,7 @@
forcedStrings,
offset,
dexOutputBuffer,
- i == virtualFiles.size() - 1,
- executorService);
+ i == virtualFiles.size() - 1);
if (InternalOptions.assertionsEnabled()) {
// Check that writing did not modify already written sections.
@@ -232,9 +225,7 @@
List<DexString> forcedStrings,
int offset,
DexOutputBuffer outputBuffer,
- boolean last,
- ExecutorService executorService)
- throws ExecutionException {
+ boolean last) {
assert !virtualFile.isEmpty();
assert BitUtils.isAligned(4, offset);
printItemUseInfo(virtualFile);
@@ -246,8 +237,7 @@
timing.begin("Write bytes");
DexContainerSection section =
- writeDexFile(
- objectMapping, outputBuffer, virtualFile, timing, offset, last, executorService);
+ writeDexFile(objectMapping, outputBuffer, virtualFile, timing, offset, last);
timing.end();
return section;
}
@@ -258,9 +248,7 @@
VirtualFile virtualFile,
Timing timing,
int offset,
- boolean includeStringData,
- ExecutorService executorService)
- throws ExecutionException {
+ boolean includeStringData) {
FileWriter fileWriter =
new FileWriter(
appView,
@@ -271,7 +259,6 @@
// Collect the non-fixed sections.
timing.time("collect", fileWriter::collect);
// Generate and write the bytes.
- return timing.time(
- "generate", () -> fileWriter.generate(timing, executorService, offset, CONTAINER_DEX));
+ return timing.time("generate", () -> fileWriter.generate(timing, offset, CONTAINER_DEX));
}
}
diff --git a/src/main/java/com/android/tools/r8/dex/DexOutputBuffer.java b/src/main/java/com/android/tools/r8/dex/DexOutputBuffer.java
index 66322ac..0bb99c4 100644
--- a/src/main/java/com/android/tools/r8/dex/DexOutputBuffer.java
+++ b/src/main/java/com/android/tools/r8/dex/DexOutputBuffer.java
@@ -31,35 +31,6 @@
this(new ByteBufferProvider() {});
}
- /**
- * Internal constructor to create a DexOutputBuffer wrapping an existing ByteBuffer disallowing
- * the buffer to grow thereby ensuring the backing array never changes.
- */
- private DexOutputBuffer(CompatByteBuffer byteBuffer) {
- this.byteBuffer = CompatByteBuffer.wrap(byteBuffer.array());
- this.byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
- byteBufferProvider =
- new ByteBufferProvider() {
- @Override
- public ByteBuffer acquireByteBuffer(int capacity) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void releaseByteBuffer(ByteBuffer buffer) {
- throw new UnsupportedOperationException();
- }
- };
- }
-
- /**
- * Creates a DexOutputBuffer wrapping an existing DexOutputBuffer disallowing the buffer to grow
- * thereby ensuring the backing array never changes.
- */
- public DexOutputBuffer nonExpandableWrapper() {
- return new DexOutputBuffer(byteBuffer);
- }
-
public DexOutputBuffer(ByteBufferProvider byteBufferProvider) {
this.byteBufferProvider = byteBufferProvider;
byteBuffer = allocateByteBuffer(DEFAULT_BUFFER_SIZE);
@@ -160,10 +131,6 @@
byteBuffer.putInt(anInteger);
}
- public byte get() {
- return byteBuffer.get();
- }
-
public short getShort() {
return byteBuffer.getShort();
}
diff --git a/src/main/java/com/android/tools/r8/dex/FileWriter.java b/src/main/java/com/android/tools/r8/dex/FileWriter.java
index fd50c92..7cdd5cc 100644
--- a/src/main/java/com/android/tools/r8/dex/FileWriter.java
+++ b/src/main/java/com/android/tools/r8/dex/FileWriter.java
@@ -5,7 +5,6 @@
import static com.android.tools.r8.utils.DexVersion.Layout.SINGLE_DEX;
import static com.android.tools.r8.utils.LebUtils.sizeAsUleb128;
-import static com.google.common.base.Predicates.alwaysTrue;
import com.android.tools.r8.ByteBufferProvider;
import com.android.tools.r8.errors.CompilationError;
@@ -58,7 +57,6 @@
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.IterableUtils;
import com.android.tools.r8.utils.LebUtils;
-import com.android.tools.r8.utils.ThreadUtils;
import com.android.tools.r8.utils.timing.Timing;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
@@ -66,20 +64,18 @@
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Reference2IntLinkedOpenHashMap;
import it.unimi.dsi.fastutil.objects.Reference2IntMap;
-import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
import java.util.function.Consumer;
import java.util.function.ToIntFunction;
import java.util.zip.Adler32;
@@ -205,70 +201,12 @@
}
}
- public ByteBufferResult generate(Timing timing, ExecutorService executorService)
- throws ExecutionException {
- DexContainerSection res = generate(timing, executorService, 0, SINGLE_DEX);
+ public ByteBufferResult generate(Timing timing) {
+ DexContainerSection res = generate(timing, 0, SINGLE_DEX);
return new ByteBufferResult(res.getBuffer().stealByteBuffer(), res.getLayout().getEndOfFile());
}
- // Class for collecting the codes to write. As the content is populated the codes to write is
- // split into equally sized buckets for writing on multiple threads.
- private static class CodesToWrite {
-
- public static class CodeToWrite {
- public final ProgramMethod method;
- public final int offset;
-
- public CodeToWrite(ProgramMethod method, int offset) {
- this.method = method;
- this.offset = offset;
- }
-
- private void write(DexOutputBuffer buffer, FileWriter writer) {
- DexWritableCode dexWritableCode = method.getDefinition().getCode().asDexWritableCode();
- buffer.moveTo(offset);
- writer.writeCodeItem(method, dexWritableCode, buffer);
- }
- }
-
- // Minimul number of bytes to include in each bucket.
- private final int bucketSize;
- // Mapping of method to the codes offset to write it to. For methods sharing the same code
- // this only contains one method entry, i.e. the codes offsets are unique. The offsets are
- // sorted by construction.
- private final List<List<CodeToWrite>> codesToWrite = new ArrayList<>();
- private List<CodeToWrite> current = new ArrayList<>();
- private int currentSize = 0;
- private int previousOffset = -1;
-
- private CodesToWrite(int bucketSize) {
- this.bucketSize = bucketSize;
- }
-
- private void add(ProgramMethod method, int codeOffset, int codeSize) {
- assert previousOffset == -1 || previousOffset < codeOffset;
- previousOffset = codeOffset;
- current.add(new CodeToWrite(method, codeOffset));
- currentSize += codeSize;
- if (currentSize > bucketSize) {
- codesToWrite.add(current);
- current = new ArrayList<>();
- currentSize = 0;
- }
- }
-
- private List<List<CodeToWrite>> get() {
- if (!current.isEmpty()) {
- codesToWrite.add(current);
- current = Collections.emptyList();
- }
- return codesToWrite;
- }
- }
-
- public DexContainerSection generate(
- Timing timing, ExecutorService executorService, int offset, DexVersion.Layout layoutType)
- throws ExecutionException {
+ public DexContainerSection generate(Timing timing, int offset, DexVersion.Layout layoutType) {
// Check restrictions on interface methods.
checkInterfaceMethods();
@@ -280,37 +218,26 @@
try (Timing t0 = timing.begin("Write codes")) {
layout.setCodesOffset(layout.dataSectionOffset);
- try (Timing t1 = timing.begin("Sort codes")) {
- // Sort the codes first, as their order might impact size due to alignment constraints.
- mixedSectionLayoutStrategy =
- MixedSectionLayoutStrategy.create(appView, mixedSectionOffsets, virtualFile);
- }
+ // Sort the codes first, as their order might impact size due to alignment constraints.
+ mixedSectionLayoutStrategy =
+ MixedSectionLayoutStrategy.create(appView, mixedSectionOffsets, virtualFile);
+ Collection<ProgramMethod> codes = mixedSectionLayoutStrategy.getCodeLayout();
// Output the debug_info_items first, as they have no dependencies.
- Collection<ProgramMethod> codes;
- try (Timing t1 = timing.begin("Get code layout")) {
- codes = mixedSectionLayoutStrategy.getCodeLayout();
- }
- MethodsCodeSizeAndCount methodsCodeSizeAndCount;
- try (Timing t1 = timing.begin("Methods code size and count")) {
- methodsCodeSizeAndCount = methodsCodeSizeAndCount(codes);
- }
- try (Timing t1 = timing.begin("Write debug info")) {
- dest.moveTo(layout.getCodesOffset() + methodsCodeSizeAndCount.getSize());
- if (mixedSectionOffsets.getDebugInfos().isEmpty()) {
- layout.setDebugInfosOffset(0);
- } else {
- // Ensure deterministic ordering of debug info by sorting consistent with the code
- // objects.
- layout.setDebugInfosOffset(dest.align(1));
- Set<DexDebugInfoForWriting> seen =
- new HashSet<>(mixedSectionOffsets.getDebugInfos().size());
- for (ProgramMethod method : codes) {
- DexWritableCode code = method.getDefinition().getCode().asDexWritableCode();
- DexDebugInfoForWriting info = code.getDebugInfoForWriting();
- if (info != null && seen.add(info)) {
- writeDebugItem(code, info);
- }
+ SizeAndCount sizeAndCountOfCodeItems = sizeAndCountOfCodeItems(codes);
+ dest.moveTo(layout.getCodesOffset() + sizeAndCountOfCodeItems.size);
+ if (mixedSectionOffsets.getDebugInfos().isEmpty()) {
+ layout.setDebugInfosOffset(0);
+ } else {
+ // Ensure deterministic ordering of debug info by sorting consistent with the code objects.
+ layout.setDebugInfosOffset(dest.align(1));
+ Set<DexDebugInfoForWriting> seen =
+ new HashSet<>(mixedSectionOffsets.getDebugInfos().size());
+ for (ProgramMethod method : codes) {
+ DexWritableCode code = method.getDefinition().getCode().asDexWritableCode();
+ DexDebugInfoForWriting info = code.getDebugInfoForWriting();
+ if (info != null && seen.add(info)) {
+ writeDebugItem(code, info);
}
}
}
@@ -318,81 +245,29 @@
// Remember the typelist offset for later.
layout.setTypeListsOffset(dest.align(4)); // type_list are aligned.
- // Output the code.
- try (Timing t1 = timing.begin("Write codes bytes")) {
- dest.moveTo(layout.getCodesOffset());
- assert dest.isAligned(4);
- final int codeStart = dest.position();
- // TODO(b/422947619): Adjust this based on available threads. On SystemUI benchmark 100000
- // gives approximately code for 1000 methods per task.
- CodesToWrite codesToWrite = new CodesToWrite(100000);
- int codeOffset = codeStart;
- Object2IntMap<DexWritableCacheKey> offsetCache = new Object2IntLinkedOpenHashMap<>();
- offsetCache.defaultReturnValue(-1);
- for (ProgramMethod method : codes) {
- if (!options.canUseCanonicalizedCodeObjects()) {
- int codeSize = methodsCodeSizeAndCount.getCodeSize(method);
- codeOffset = alignSize(4, codeOffset);
- codesToWrite.add(method, codeOffset, codeSize);
- mixedSectionOffsets.setOffsetFor(method.getDefinition(), codeOffset);
- codeOffset += codeSize;
+ // Now output the code.
+ dest.moveTo(layout.getCodesOffset());
+ assert dest.isAligned(4);
+ Map<DexWritableCacheKey, Integer> offsetCache = new HashMap<>();
+ for (ProgramMethod method : codes) {
+ DexWritableCode dexWritableCode = method.getDefinition().getCode().asDexWritableCode();
+ if (!options.canUseCanonicalizedCodeObjects()) {
+ writeCodeItem(method, dexWritableCode);
+ } else {
+ DexWritableCacheKey cacheLookupKey =
+ dexWritableCode.getCacheLookupKey(method, appView.dexItemFactory());
+ Integer offsetOrNull = offsetCache.get(cacheLookupKey);
+ if (offsetOrNull != null) {
+ mixedSectionOffsets.setOffsetFor(method.getDefinition(), offsetOrNull);
} else {
- DexWritableCode dexWritableCode = method.getDefinition().getCode().asDexWritableCode();
- DexWritableCacheKey cacheLookupKey =
- dexWritableCode.getCacheLookupKey(method, appView.dexItemFactory());
- int canonicalOffset = offsetCache.getInt(cacheLookupKey);
- if (canonicalOffset > 0) {
- mixedSectionOffsets.setOffsetFor(method.getDefinition(), canonicalOffset);
- assert methodsCodeSizeAndCount.getCodeSize(method) == 0;
- } else {
- int codeSize = methodsCodeSizeAndCount.getCodeSize(method);
- codeOffset = alignSize(4, codeOffset);
- codesToWrite.add(method, codeOffset, codeSize);
- offsetCache.put(cacheLookupKey, codeOffset);
- mixedSectionOffsets.setOffsetFor(method.getDefinition(), codeOffset);
- codeOffset += codeSize;
- }
+ offsetCache.put(cacheLookupKey, writeCodeItem(method, dexWritableCode));
}
}
- // Move to end of codes section to ensure backing array has been allocated for all codes.
- int codeSize = codeOffset - codeStart;
- dest.moveTo(codeStart + codeSize);
- dest.moveTo(codeStart);
-
- // Write code into code section.
- List<List<CodesToWrite.CodeToWrite>> toWrite = codesToWrite.get();
- int buckets = toWrite.size();
- ThreadUtils.processItemsThatMatches(
- toWrite,
- alwaysTrue(),
- (list, threadTiming) -> {
- DexOutputBuffer buffer = dest.nonExpandableWrapper();
- for (CodesToWrite.CodeToWrite codeToWrite : list) {
- codeToWrite.write(buffer, this);
- }
- },
- options,
- executorService,
- timing,
- timing.beginMerger("Write codes bytes", executorService),
- (i, list) ->
- "Writing "
- + list.size()
- + " codes for VirtualFile "
- + virtualFile.getId()
- + " ("
- + i
- + "/"
- + buckets
- + ")");
- // Move position to just after the written code section.
- dest.moveTo(codeStart + codeSize);
-
- assert methodsCodeSizeAndCount.getCount()
- == ImmutableSet.copyOf(mixedSectionOffsets.codes.values()).size();
- layout.setCodeCount(methodsCodeSizeAndCount.getCount());
- assert layout.getDebugInfosOffset() == 0 || dest.position() == layout.getDebugInfosOffset();
}
+ assert sizeAndCountOfCodeItems.getCount()
+ == ImmutableSet.copyOf(mixedSectionOffsets.codes.values()).size();
+ layout.setCodeCount(sizeAndCountOfCodeItems.getCount());
+ assert layout.getDebugInfosOffset() == 0 || dest.position() == layout.getDebugInfosOffset();
}
// Now the type lists and rest.
@@ -585,15 +460,10 @@
}
}
- private static class MethodsCodeSizeAndCount {
+ static class SizeAndCount {
private int size = 0;
private int count = 0;
- private final Reference2IntMap<DexMethod> sizes = new Reference2IntOpenHashMap<>();
-
- private MethodsCodeSizeAndCount() {
- sizes.defaultReturnValue(0);
- }
public int getCount() {
return count;
@@ -602,26 +472,20 @@
public int getSize() {
return size;
}
-
- public int getCodeSize(ProgramMethod method) {
- return sizes.getInt(method.getReference());
- }
}
- private MethodsCodeSizeAndCount methodsCodeSizeAndCount(Iterable<ProgramMethod> methods) {
- MethodsCodeSizeAndCount methodsCodeSizeAndCount = new MethodsCodeSizeAndCount();
+ private SizeAndCount sizeAndCountOfCodeItems(Iterable<ProgramMethod> methods) {
+ SizeAndCount sizeAndCount = new SizeAndCount();
Set<DexWritableCacheKey> cache = new HashSet<>();
for (ProgramMethod method : methods) {
DexWritableCode code = method.getDefinition().getCode().asDexWritableCode();
if (!options.canUseCanonicalizedCodeObjects()
|| cache.add(code.getCacheLookupKey(method, appView.dexItemFactory()))) {
- int codeSize = sizeOfCodeItem(code);
- methodsCodeSizeAndCount.count++;
- methodsCodeSizeAndCount.size = alignSize(4, methodsCodeSizeAndCount.size) + codeSize;
- methodsCodeSizeAndCount.sizes.put(method.getReference(), codeSize);
+ sizeAndCount.count++;
+ sizeAndCount.size = alignSize(4, sizeAndCount.size) + sizeOfCodeItem(code);
}
}
- return methodsCodeSizeAndCount;
+ return sizeAndCount;
}
private int sizeOfCodeItem(DexWritableCode code) {
@@ -708,21 +572,10 @@
dest.putBytes(new DebugBytecodeWriter(debugInfo, mapping, graphLens, codeLens).generate());
}
- private int writeCodeItem(ProgramMethod method, DexWritableCode code, DexOutputBuffer dest) {
- return writeCodeItem(method, code, dest, appView, mixedSectionOffsets, mapping, graphLens);
- }
-
- private static int writeCodeItem(
- ProgramMethod method,
- DexWritableCode code,
- DexOutputBuffer dest,
- AppView<?> appView,
- MixedSectionOffsets mixedSectionOffsets,
- ObjectToOffsetMapping mapping,
- GraphLens graphLens) {
- assert dest.isAligned(4);
- int codeOffset = dest.position();
+ private int writeCodeItem(ProgramMethod method, DexWritableCode code) {
GraphLens codeLens = code.getCodeLens(appView);
+ int codeOffset = dest.align(4);
+ mixedSectionOffsets.setOffsetFor(method.getDefinition(), codeOffset);
// Fixed size header information.
dest.putShort((short) code.getRegisterSize(method));
dest.putShort((short) code.getIncomingRegisterSize(method));
diff --git a/src/main/java/com/android/tools/r8/dex/jumbostrings/ContainerJumboStringRewriter.java b/src/main/java/com/android/tools/r8/dex/jumbostrings/ContainerJumboStringRewriter.java
index dc287f8..4cf0940 100644
--- a/src/main/java/com/android/tools/r8/dex/jumbostrings/ContainerJumboStringRewriter.java
+++ b/src/main/java/com/android/tools/r8/dex/jumbostrings/ContainerJumboStringRewriter.java
@@ -37,7 +37,7 @@
}
// Compute string layout and handle jumbo strings for the last DEX section.
timing.begin("Process last virtual file");
- processVirtualFile(lastFile, timing, executorService);
+ processVirtualFile(lastFile, timing);
timing.end();
// Handle jumbo strings for the remaining DEX sections using the string ids in the last DEX
// section.
@@ -46,7 +46,7 @@
alwaysTrue(),
(virtualFile, threadTiming) ->
rewriteJumboStringsAndComputeDebugRepresentationWithExternalStringIds(
- virtualFile, lastFile.getObjectMapping(), threadTiming, executorService),
+ virtualFile, lastFile.getObjectMapping(), threadTiming),
appView.options(),
executorService,
timing,
@@ -54,22 +54,13 @@
}
private void rewriteJumboStringsAndComputeDebugRepresentationWithExternalStringIds(
- VirtualFile virtualFile,
- ObjectToOffsetMapping mapping,
- Timing timing,
- ExecutorService executorService)
- throws ExecutionException {
- computeOffsetMappingAndRewriteJumboStringsWithExternalStringIds(
- virtualFile, timing, mapping, executorService);
+ VirtualFile virtualFile, ObjectToOffsetMapping mapping, Timing timing) {
+ computeOffsetMappingAndRewriteJumboStringsWithExternalStringIds(virtualFile, timing, mapping);
DebugRepresentation.computeForFile(appView, virtualFile);
}
private void computeOffsetMappingAndRewriteJumboStringsWithExternalStringIds(
- VirtualFile virtualFile,
- Timing timing,
- ObjectToOffsetMapping mapping,
- ExecutorService executorService)
- throws ExecutionException {
+ VirtualFile virtualFile, Timing timing, ObjectToOffsetMapping mapping) {
if (virtualFile.isEmpty()) {
return;
}
@@ -77,8 +68,7 @@
virtualFile.computeMapping(appView, lazyDexStrings.size(), timing, mapping);
timing.end();
timing.begin("Rewrite jumbo strings");
- rewriteCodeWithJumboStrings(
- virtualFile.getObjectMapping(), virtualFile.classes(), executorService);
+ rewriteCodeWithJumboStrings(virtualFile.getObjectMapping(), virtualFile.classes());
timing.end();
}
}
diff --git a/src/main/java/com/android/tools/r8/dex/jumbostrings/JumboStringRewriter.java b/src/main/java/com/android/tools/r8/dex/jumbostrings/JumboStringRewriter.java
index 342b881..22aef00 100644
--- a/src/main/java/com/android/tools/r8/dex/jumbostrings/JumboStringRewriter.java
+++ b/src/main/java/com/android/tools/r8/dex/jumbostrings/JumboStringRewriter.java
@@ -53,23 +53,19 @@
ThreadUtils.processItemsThatMatches(
virtualFiles,
alwaysTrue(),
- (virtualFile, timing0) -> processVirtualFile(virtualFile, timing0, executorService),
+ this::processVirtualFile,
options,
executorService,
timing,
timing.beginMerger("Pre-write phase", executorService));
}
- protected final void processVirtualFile(
- VirtualFile virtualFile, Timing timing, ExecutorService executorService)
- throws ExecutionException {
- computeOffsetMappingAndRewriteJumboStrings(virtualFile, timing, executorService);
+ protected final void processVirtualFile(VirtualFile virtualFile, Timing timing) {
+ computeOffsetMappingAndRewriteJumboStrings(virtualFile, timing);
DebugRepresentation.computeForFile(appView, virtualFile);
}
- private void computeOffsetMappingAndRewriteJumboStrings(
- VirtualFile virtualFile, Timing timing, ExecutorService executorService)
- throws ExecutionException {
+ private void computeOffsetMappingAndRewriteJumboStrings(VirtualFile virtualFile, Timing timing) {
if (virtualFile.isEmpty()) {
return;
}
@@ -77,8 +73,7 @@
virtualFile.computeMapping(appView, lazyDexStrings.size(), timing);
timing.end();
timing.begin("Rewrite jumbo strings");
- rewriteCodeWithJumboStrings(
- virtualFile.getObjectMapping(), virtualFile.classes(), executorService);
+ rewriteCodeWithJumboStrings(virtualFile.getObjectMapping(), virtualFile.classes());
timing.end();
}
@@ -90,10 +85,7 @@
* be used.
*/
protected final void rewriteCodeWithJumboStrings(
- ObjectToOffsetMapping mapping,
- Collection<DexProgramClass> classes,
- ExecutorService executorService)
- throws ExecutionException {
+ ObjectToOffsetMapping mapping, Collection<DexProgramClass> classes) {
// Do not bail out early if forcing jumbo string processing.
if (!options.getTestingOptions().forceJumboStringProcessing) {
// If there are no strings with jumbo indices at all this is a no-op.
@@ -101,23 +93,19 @@
return;
}
}
-
- ThreadUtils.processItems(
- classes,
- clazz ->
- clazz.forEachProgramMethodMatching(
- DexEncodedMethod::hasCode,
- method -> {
- DexWritableCode code = method.getDefinition().getCode().asDexWritableCode();
- DexWritableCode rewrittenCode =
- code.rewriteCodeWithJumboStrings(
- method,
- mapping,
- appView,
- options.getTestingOptions().forceJumboStringProcessing);
- method.setCode(rewrittenCode.asCode(), appView);
- }),
- options.getThreadingModule(),
- executorService);
+ for (DexProgramClass clazz : classes) {
+ clazz.forEachProgramMethodMatching(
+ DexEncodedMethod::hasCode,
+ method -> {
+ DexWritableCode code = method.getDefinition().getCode().asDexWritableCode();
+ DexWritableCode rewrittenCode =
+ code.rewriteCodeWithJumboStrings(
+ method,
+ mapping,
+ appView,
+ options.getTestingOptions().forceJumboStringProcessing);
+ method.setCode(rewrittenCode.asCode(), appView);
+ });
+ }
}
}
diff --git a/src/test/java/com/android/tools/r8/dex/DexOutputBufferTest.java b/src/test/java/com/android/tools/r8/dex/DexOutputBufferTest.java
deleted file mode 100644
index 30c9413..0000000
--- a/src/test/java/com/android/tools/r8/dex/DexOutputBufferTest.java
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright (c) 2025, 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 static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-
-import com.android.tools.r8.ByteBufferProvider;
-import com.android.tools.r8.TestBase;
-import com.android.tools.r8.TestParameters;
-import com.android.tools.r8.TestParametersCollection;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-
-@RunWith(Parameterized.class)
-public class DexOutputBufferTest extends TestBase {
-
- private final TestParameters parameters;
-
- @Parameters(name = "{0}")
- public static TestParametersCollection data() {
- return getTestParameters().withNoneRuntime().build();
- }
-
- public DexOutputBufferTest(TestParameters parameters) {
- this.parameters = parameters;
- }
-
- @Test
- public void testNonExpandableWrapperByte() {
- DexOutputBuffer buffer = new DexOutputBuffer(new ByteBufferProvider() {});
- DexOutputBuffer wrapper1 = buffer.nonExpandableWrapper();
- DexOutputBuffer wrapper2 = buffer.nonExpandableWrapper();
- int defaultBufferSize = 256 * 1024; // private DEFAULT_BUFFER_SIZE in DexOutputBuffer.
- for (int i = 0; i < defaultBufferSize; i++) {
- wrapper1.putByte((byte) 1);
- assertEquals(1, wrapper2.get());
- }
- try {
- wrapper1.putByte((byte) 1);
- fail("Unexpected successful operation.");
- } catch (UnsupportedOperationException e) {
- // Expected.
- }
- try {
- wrapper2.putByte((byte) 1);
- fail("Unexpected successful operation.");
- } catch (UnsupportedOperationException e) {
- // Expected.
- }
- }
-
- @Test
- public void testNonExpandableWrapperShort() {
- DexOutputBuffer buffer = new DexOutputBuffer(new ByteBufferProvider() {});
- DexOutputBuffer wrapper1 = buffer.nonExpandableWrapper();
- DexOutputBuffer wrapper2 = buffer.nonExpandableWrapper();
- int defaultBufferSize = 256 * 1024; // private DEFAULT_BUFFER_SIZE in DexOutputBuffer.
- for (int i = 0; i < defaultBufferSize; i += 2 * 2) {
- wrapper1.putShort(Short.MAX_VALUE);
- assertEquals(Short.MAX_VALUE, wrapper2.getShort());
- wrapper1.putShort(Short.MIN_VALUE);
- assertEquals(Short.MIN_VALUE, wrapper2.getShort());
- }
- try {
- wrapper1.putShort((short) 1);
- fail("Unexpected successful operation.");
- } catch (UnsupportedOperationException e) {
- // Expected.
- }
- try {
- wrapper2.putShort((short) 1);
- fail("Unexpected successful operation.");
- } catch (UnsupportedOperationException e) {
- // Expected.
- }
- }
-}
diff --git a/src/test/testbase/java/com/android/tools/r8/ToolHelper.java b/src/test/testbase/java/com/android/tools/r8/ToolHelper.java
index 2d30a5e..7ecd693 100644
--- a/src/test/testbase/java/com/android/tools/r8/ToolHelper.java
+++ b/src/test/testbase/java/com/android/tools/r8/ToolHelper.java
@@ -2700,7 +2700,7 @@
public static void writeApplication(AppView<?> appView) throws ExecutionException {
appView.options().tool = Tool.R8;
- R8.writeApplication(appView, null, Executors.newFixedThreadPool(2));
+ R8.writeApplication(appView, null, Executors.newSingleThreadExecutor());
}
public static void disassemble(AndroidApp app, PrintStream ps) throws IOException {