Remove thread local code mapping.
Fixes: 181636450
Change-Id: I1b4b7f036756722243e9e23a32cb6164abb5b481
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 8209749..a45e7fb 100644
--- a/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
+++ b/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
@@ -63,13 +63,10 @@
import java.util.ArrayList;
import java.util.Collection;
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.concurrent.Future;
import java.util.function.Predicate;
import java.util.stream.Collectors;
@@ -269,7 +266,6 @@
}
// Generate the dex file contents.
- List<Future<Boolean>> dexDataFutures = new ArrayList<>();
timing.begin("Distribute");
List<VirtualFile> virtualFiles = distribute(executorService);
timing.end();
@@ -380,11 +376,10 @@
virtualFile.computeMapping(appView, graphLens, namingLens, initClassLens, timing);
timing.end();
timing.begin("Rewrite jumbo strings");
- MethodToCodeObjectMapping codeMapping =
- rewriteCodeWithJumboStrings(objectMapping, virtualFile.classes(), appView.appInfo().app());
+ rewriteCodeWithJumboStrings(objectMapping, virtualFile.classes(), appView.appInfo().app());
timing.end();
timing.begin("Write bytes");
- ByteBufferResult result = writeDexFile(objectMapping, codeMapping, byteBufferProvider);
+ ByteBufferResult result = writeDexFile(objectMapping, byteBufferProvider);
ByteDataView data =
new ByteDataView(result.buffer.array(), result.buffer.arrayOffset(), result.length);
timing.end();
@@ -652,7 +647,7 @@
* <p>If run multiple times on a class, the lowest index that is required to be a JumboString will
* be used.
*/
- private MethodToCodeObjectMapping rewriteCodeWithJumboStrings(
+ private void rewriteCodeWithJumboStrings(
ObjectToOffsetMapping mapping,
Collection<DexProgramClass> classes,
DexApplication application) {
@@ -660,19 +655,14 @@
if (!options.testing.forceJumboStringProcessing) {
// If there are no strings with jumbo indices at all this is a no-op.
if (!mapping.hasJumboStrings()) {
- return MethodToCodeObjectMapping.fromMethodBacking();
+ return;
}
// If the globally highest sorting string is not a jumbo string this is also a no-op.
if (application.highestSortingString != null
&& application.highestSortingString.compareTo(mapping.getFirstJumboString()) < 0) {
- return MethodToCodeObjectMapping.fromMethodBacking();
+ return;
}
}
- // At least one method needs a jumbo string in which case we construct a thread local mapping
- // for all code objects and write the processed results into that map.
- // TODO(b/181636450): Reconsider the code mapping setup now that synthetics are never duplicated
- // in outputs.
- Map<DexEncodedMethod, DexWritableCode> codeMapping = new IdentityHashMap<>();
for (DexProgramClass clazz : classes) {
clazz.forEachProgramMethodMatching(
DexEncodedMethod::hasCode,
@@ -684,25 +674,18 @@
mapping,
application.dexItemFactory,
options.testing.forceJumboStringProcessing);
- codeMapping.put(method.getDefinition(), rewrittenCode);
- // The mapping now has ownership of the methods code object. This ensures freeing of
- // code resources once the map entry is cleared and also ensures that we don't end up
- // using the incorrect code pointer again later!
- method.getDefinition().unsetCode();
+ method.getDefinition().setCode(rewrittenCode.asCode(), appView);
});
}
- return MethodToCodeObjectMapping.fromMapBacking(codeMapping);
}
private ByteBufferResult writeDexFile(
ObjectToOffsetMapping objectMapping,
- MethodToCodeObjectMapping codeMapping,
ByteBufferProvider provider) {
FileWriter fileWriter =
new FileWriter(
provider,
objectMapping,
- codeMapping,
appView.appInfo(),
options,
namingLens,
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 c937839..84b245c 100644
--- a/src/main/java/com/android/tools/r8/dex/FileWriter.java
+++ b/src/main/java/com/android/tools/r8/dex/FileWriter.java
@@ -98,8 +98,6 @@
}
private final ObjectToOffsetMapping mapping;
- private final MethodToCodeObjectMapping codeMapping;
- private final AppInfo appInfo;
private final DexApplication application;
private final InternalOptions options;
private final GraphLens graphLens;
@@ -112,20 +110,17 @@
public FileWriter(
ByteBufferProvider provider,
ObjectToOffsetMapping mapping,
- MethodToCodeObjectMapping codeMapping,
AppInfo appInfo,
InternalOptions options,
NamingLens namingLens,
CodeToKeep desugaredLibraryCodeToKeep) {
this.mapping = mapping;
- this.codeMapping = codeMapping;
- this.appInfo = appInfo;
this.application = appInfo.app();
this.options = options;
this.graphLens = mapping.getGraphLens();
this.namingLens = namingLens;
this.dest = new DexOutputBuffer(provider);
- this.mixedSectionOffsets = new MixedSectionOffsets(options, codeMapping);
+ this.mixedSectionOffsets = new MixedSectionOffsets(options);
this.desugaredLibraryCodeToKeep = desugaredLibraryCodeToKeep;
}
@@ -179,9 +174,6 @@
Layout layout = Layout.from(mapping);
layout.setCodesOffset(layout.dataSectionOffset);
- // Check code objects in the code-mapping are consistent with the collected code objects.
- assert codeMapping.verifyCodeObjects(mixedSectionOffsets.getCodes());
-
// Sort the codes first, as their order might impact size due to alignment constraints.
List<ProgramDexCode> codes = sortDexCodesByClassName();
@@ -340,7 +332,7 @@
for (DexProgramClass clazz : mapping.getClasses()) {
clazz.forEachProgramMethod(
method -> {
- DexWritableCode code = codeMapping.getCode(method.getDefinition());
+ DexWritableCode code = method.getDefinition().getDexWritableCodeOrNull();
assert code != null || method.getDefinition().shouldNotHaveCode();
if (code != null) {
ProgramDexCode programCode = new ProgramDexCode(code, method);
@@ -661,7 +653,7 @@
dest.putUleb128(nextOffset - currentOffset);
currentOffset = nextOffset;
dest.putUleb128(method.accessFlags.getAsDexAccessFlags());
- DexWritableCode code = codeMapping.getCode(method);
+ DexWritableCode code = method.getDexWritableCodeOrNull();
desugaredLibraryCodeToKeep.recordMethod(method.getReference());
if (code == null) {
assert method.shouldNotHaveCode();
@@ -670,7 +662,7 @@
dest.putUleb128(mixedSectionOffsets.getOffsetFor(method, code));
// Writing the methods starts to take up memory so we are going to flush the
// code objects since they are no longer necessary after this.
- codeMapping.clearCode(method);
+ method.unsetCode();
}
}
}
@@ -1077,8 +1069,6 @@
private static final int NOT_SET = -1;
private static final int NOT_KNOWN = -2;
- private final MethodToCodeObjectMapping codeMapping;
-
private final Reference2IntMap<DexEncodedMethod> codes = createReference2IntMap();
private final Object2IntMap<DexDebugInfo> debugInfos = createObject2IntMap();
private final Object2IntMap<DexTypeList> typeLists = createObject2IntMap();
@@ -1108,9 +1098,8 @@
return result;
}
- private MixedSectionOffsets(InternalOptions options, MethodToCodeObjectMapping codeMapping) {
+ private MixedSectionOffsets(InternalOptions options) {
this.minApiLevel = options.getMinApiLevel();
- this.codeMapping = codeMapping;
}
private <T> boolean add(Object2IntMap<T> map, T item) {
@@ -1151,7 +1140,7 @@
@Override
public void visit(DexEncodedMethod method) {
- method.collectMixedSectionItemsWithCodeMapping(this, codeMapping);
+ method.collectMixedSectionItemsWithCodeMapping(this);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/dex/MethodToCodeObjectMapping.java b/src/main/java/com/android/tools/r8/dex/MethodToCodeObjectMapping.java
deleted file mode 100644
index dfdb07a..0000000
--- a/src/main/java/com/android/tools/r8/dex/MethodToCodeObjectMapping.java
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright (c) 2019, 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.Code;
-import com.android.tools.r8.graph.DexEncodedMethod;
-import com.android.tools.r8.graph.DexWritableCode;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
-
-public abstract class MethodToCodeObjectMapping {
-
- public abstract DexWritableCode getCode(DexEncodedMethod method);
-
- public abstract void clearCode(DexEncodedMethod method);
-
- public abstract boolean verifyCodeObjects(Collection<DexEncodedMethod> codes);
-
- public static MethodToCodeObjectMapping fromMethodBacking() {
- return MethodBacking.INSTANCE;
- }
-
- public static MethodToCodeObjectMapping fromMapBacking(
- Map<DexEncodedMethod, DexWritableCode> map) {
- return new MapBacking(map);
- }
-
- private static class MethodBacking extends MethodToCodeObjectMapping {
-
- private static final MethodBacking INSTANCE = new MethodBacking();
-
- @Override
- public DexWritableCode getCode(DexEncodedMethod method) {
- Code code = method.getCode();
- assert code == null || code.isDexWritableCode();
- return code == null ? null : code.asDexWritableCode();
- }
-
- @Override
- public void clearCode(DexEncodedMethod method) {
- method.unsetCode();
- }
-
- @Override
- public boolean verifyCodeObjects(Collection<DexEncodedMethod> codes) {
- return true;
- }
- }
-
- private static class MapBacking extends MethodToCodeObjectMapping {
-
- private final Map<DexEncodedMethod, DexWritableCode> codes;
-
- public MapBacking(Map<DexEncodedMethod, DexWritableCode> codes) {
- this.codes = codes;
- }
-
- @Override
- public DexWritableCode getCode(DexEncodedMethod method) {
- return codes.get(method);
- }
-
- @Override
- public void clearCode(DexEncodedMethod method) {
- // We can safely clear the thread local pointer to even shared methods.
- codes.put(method, null);
- }
-
- @Override
- public boolean verifyCodeObjects(Collection<DexEncodedMethod> methods) {
- // TODO(b/204056443): Convert to a Set<DexWritableCode> when DexCode#hashCode() works.
- List<DexWritableCode> codes =
- methods.stream().map(this::getCode).collect(Collectors.toList());
- assert this.codes.values().containsAll(codes);
- return true;
- }
- }
-}
diff --git a/src/main/java/com/android/tools/r8/dex/MixedSectionCollection.java b/src/main/java/com/android/tools/r8/dex/MixedSectionCollection.java
index 0ca695e..e082a31 100644
--- a/src/main/java/com/android/tools/r8/dex/MixedSectionCollection.java
+++ b/src/main/java/com/android/tools/r8/dex/MixedSectionCollection.java
@@ -59,8 +59,7 @@
* <p>Allows overriding the behavior when dex-file writing.
*/
public void visit(DexEncodedMethod dexEncodedMethod) {
- dexEncodedMethod.collectMixedSectionItemsWithCodeMapping(
- this, MethodToCodeObjectMapping.fromMethodBacking());
+ dexEncodedMethod.collectMixedSectionItemsWithCodeMapping(this);
}
/**
diff --git a/src/main/java/com/android/tools/r8/graph/DefaultInstanceInitializerCode.java b/src/main/java/com/android/tools/r8/graph/DefaultInstanceInitializerCode.java
index f336d89..e25cb47 100644
--- a/src/main/java/com/android/tools/r8/graph/DefaultInstanceInitializerCode.java
+++ b/src/main/java/com/android/tools/r8/graph/DefaultInstanceInitializerCode.java
@@ -123,6 +123,11 @@
}
@Override
+ public Code asCode() {
+ return this;
+ }
+
+ @Override
public void acceptHashing(HashingVisitor visitor) {
visitor.visitInt(getCfWritableCodeKind().hashCode());
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexCode.java b/src/main/java/com/android/tools/r8/graph/DexCode.java
index d49c43f..703977e 100644
--- a/src/main/java/com/android/tools/r8/graph/DexCode.java
+++ b/src/main/java/com/android/tools/r8/graph/DexCode.java
@@ -351,6 +351,11 @@
}
@Override
+ public Code asCode() {
+ return this;
+ }
+
+ @Override
public IRCode buildIR(ProgramMethod method, AppView<?> appView, Origin origin) {
DexSourceCode source =
new DexSourceCode(
diff --git a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
index a68f038..e89b2ac 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
@@ -38,7 +38,6 @@
import com.android.tools.r8.code.Return;
import com.android.tools.r8.code.Throw;
import com.android.tools.r8.code.XorIntLit8;
-import com.android.tools.r8.dex.MethodToCodeObjectMapping;
import com.android.tools.r8.dex.MixedSectionCollection;
import com.android.tools.r8.errors.InternalCompilerError;
import com.android.tools.r8.errors.Unreachable;
@@ -768,9 +767,8 @@
mixedItems.visit(this);
}
- public void collectMixedSectionItemsWithCodeMapping(
- MixedSectionCollection mixedItems, MethodToCodeObjectMapping mapping) {
- DexWritableCode code = mapping.getCode(this);
+ public void collectMixedSectionItemsWithCodeMapping(MixedSectionCollection mixedItems) {
+ DexWritableCode code = getDexWritableCodeOrNull();
if (code != null && mixedItems.add(this, code)) {
code.collectMixedSectionItems(mixedItems);
}
@@ -1315,6 +1313,12 @@
this.genericSignature = MethodTypeSignature.noSignature();
}
+ public DexWritableCode getDexWritableCodeOrNull() {
+ Code code = getCode();
+ assert code == null || code.isDexWritableCode();
+ return code == null ? null : code.asDexWritableCode();
+ }
+
public static Builder syntheticBuilder() {
return new Builder(true);
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexWritableCode.java b/src/main/java/com/android/tools/r8/graph/DexWritableCode.java
index 664b4e8..fffff66 100644
--- a/src/main/java/com/android/tools/r8/graph/DexWritableCode.java
+++ b/src/main/java/com/android/tools/r8/graph/DexWritableCode.java
@@ -71,6 +71,8 @@
int getOutgoingRegisterSize();
+ Code asCode();
+
default boolean isDexCode() {
return false;
}
diff --git a/src/main/java/com/android/tools/r8/graph/ThrowNullCode.java b/src/main/java/com/android/tools/r8/graph/ThrowNullCode.java
index eb7728c..c573130 100644
--- a/src/main/java/com/android/tools/r8/graph/ThrowNullCode.java
+++ b/src/main/java/com/android/tools/r8/graph/ThrowNullCode.java
@@ -41,6 +41,11 @@
}
@Override
+ public Code asCode() {
+ return this;
+ }
+
+ @Override
public void acceptHashing(HashingVisitor visitor) {
visitor.visitInt(getCfWritableCodeKind().hashCode());
}