diff options
author | Ian Zerny <zerny@google.com> | 2017-10-26 13:36:14 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2017-10-26 13:36:14 +0000 |
commit | bc8be4d8a8438ebd0be73fe655e160e22da3be9d (patch) | |
tree | bf673bdf67ec542a3a59977056ae396b172e7443 | |
parent | 4d22d2d18bab390754a423972ffc2a7b47fbde79 (diff) | |
parent | f76614b69a9a5cdf865087797546add35401ab07 (diff) | |
download | r8-bc8be4d8a8438ebd0be73fe655e160e22da3be9d.tar.gz |
Merge "Define distinct access-flag types for classes, methods and fields."
47 files changed, 1017 insertions, 590 deletions
diff --git a/src/main/java/com/android/tools/r8/dex/Constants.java b/src/main/java/com/android/tools/r8/dex/Constants.java index 50af413c7..12ae77ff8 100644 --- a/src/main/java/com/android/tools/r8/dex/Constants.java +++ b/src/main/java/com/android/tools/r8/dex/Constants.java @@ -115,6 +115,7 @@ public class Constants { public static final int ACC_PROTECTED = 0x4; public static final int ACC_STATIC = 0x8; public static final int ACC_FINAL = 0x10; + public static final int ACC_SUPER = 0x20; public static final int ACC_SYNCHRONIZED = 0x20; public static final int ACC_VOLATILE = 0x40; public static final int ACC_BRIDGE = 0x40; diff --git a/src/main/java/com/android/tools/r8/dex/DexFileReader.java b/src/main/java/com/android/tools/r8/dex/DexFileReader.java index 64909cc3a..4b0d6e2fc 100644 --- a/src/main/java/com/android/tools/r8/dex/DexFileReader.java +++ b/src/main/java/com/android/tools/r8/dex/DexFileReader.java @@ -12,9 +12,9 @@ import com.android.tools.r8.Resource.Origin; import com.android.tools.r8.Resource.PathOrigin; import com.android.tools.r8.code.Instruction; import com.android.tools.r8.code.InstructionFactory; +import com.android.tools.r8.graph.ClassAccessFlags; import com.android.tools.r8.graph.ClassKind; import com.android.tools.r8.graph.Descriptor; -import com.android.tools.r8.graph.DexAccessFlags; import com.android.tools.r8.graph.DexAnnotation; import com.android.tools.r8.graph.DexAnnotationElement; import com.android.tools.r8.graph.DexAnnotationSet; @@ -50,6 +50,8 @@ import com.android.tools.r8.graph.DexValue.DexValueMethodHandle; import com.android.tools.r8.graph.DexValue.DexValueMethodType; import com.android.tools.r8.graph.DexValue.DexValueNull; import com.android.tools.r8.graph.DexValue.DexValueString; +import com.android.tools.r8.graph.FieldAccessFlags; +import com.android.tools.r8.graph.MethodAccessFlags; import com.android.tools.r8.graph.OffsetToObjectMapping; import com.android.tools.r8.logging.Log; import com.android.tools.r8.utils.ProgramResource.Kind; @@ -555,7 +557,7 @@ public class DexFileReader { for (int i = 0; i < size; i++) { fieldIndex += file.getUleb128(); DexField field = indexedItems.getField(fieldIndex); - DexAccessFlags accessFlags = new DexAccessFlags(file.getUleb128()); + FieldAccessFlags accessFlags = FieldAccessFlags.fromDexAccessFlags(file.getUleb128()); DexAnnotationSet fieldAnnotations = annotationIterator.getNextFor(field); DexValue staticValue = null; if (accessFlags.isStatic()) { @@ -580,7 +582,7 @@ public class DexFileReader { new MemberAnnotationIterator<>(parameters, DexAnnotationSetRefList::empty); for (int i = 0; i < size; i++) { methodIndex += file.getUleb128(); - DexAccessFlags accessFlags = new DexAccessFlags(file.getUleb128()); + MethodAccessFlags accessFlags = MethodAccessFlags.fromDexAccessFlags(file.getUleb128()); int codeOff = file.getUleb128(); DexCode code = null; if (!skipCodes) { @@ -633,7 +635,7 @@ public class DexFileReader { DexString source = srcIdx == NO_INDEX ? null : indexedItems.getString(srcIdx); // fix annotations. DexType type = indexedItems.getType(classIndices[i]); - DexAccessFlags flags = new DexAccessFlags(accessFlags[i]); + ClassAccessFlags flags = ClassAccessFlags.fromDexAccessFlags(accessFlags[i]); DexClass clazz; DexEncodedField[] staticFields = DexEncodedField.EMPTY_ARRAY; DexEncodedField[] instanceFields = DexEncodedField.EMPTY_ARRAY; 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 dccf88711..27dedb195 100644 --- a/src/main/java/com/android/tools/r8/dex/FileWriter.java +++ b/src/main/java/com/android/tools/r8/dex/FileWriter.java @@ -405,7 +405,7 @@ public class FileWriter { private void writeClassDefItem(DexProgramClass clazz) { dest.putInt(mapping.getOffsetFor(clazz.type)); - dest.putInt(clazz.accessFlags.get()); + dest.putInt(clazz.accessFlags.getAsDexAccessFlags()); dest.putInt( clazz.superType == null ? Constants.NO_INDEX : mapping.getOffsetFor(clazz.superType)); dest.putInt(mixedSectionOffsets.getOffsetFor(clazz.interfaces)); @@ -553,7 +553,7 @@ public class FileWriter { assert nextOffset - currentOffset >= 0; dest.putUleb128(nextOffset - currentOffset); currentOffset = nextOffset; - dest.putUleb128(field.accessFlags.get()); + dest.putUleb128(field.accessFlags.getAsDexAccessFlags()); } } @@ -565,7 +565,7 @@ public class FileWriter { assert nextOffset - currentOffset >= 0; dest.putUleb128(nextOffset - currentOffset); currentOffset = nextOffset; - dest.putUleb128(method.accessFlags.get()); + dest.putUleb128(method.accessFlags.getAsDexAccessFlags()); if (method.getCode() == null) { assert method.accessFlags.isAbstract() || method.accessFlags.isNative(); dest.putUleb128(0); diff --git a/src/main/java/com/android/tools/r8/graph/AccessFlags.java b/src/main/java/com/android/tools/r8/graph/AccessFlags.java new file mode 100644 index 000000000..9f0471e6a --- /dev/null +++ b/src/main/java/com/android/tools/r8/graph/AccessFlags.java @@ -0,0 +1,187 @@ +// Copyright (c) 2017, 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.graph; + +import com.android.tools.r8.dex.Constants; +import com.google.common.collect.ImmutableList; +import java.util.List; +import java.util.function.BooleanSupplier; + +/** Access flags common to classes, methods and fields. */ +public abstract class AccessFlags { + + protected static final int BASE_FLAGS + = Constants.ACC_PUBLIC + | Constants.ACC_PRIVATE + | Constants.ACC_PROTECTED + | Constants.ACC_STATIC + | Constants.ACC_FINAL + | Constants.ACC_SYNTHETIC; + + // Ordered list of flag names. Must be consistent with getPredicates. + private static final List<String> NAMES = ImmutableList.of( + "public", + "private", + "protected", + "static", + "final", + "synthetic" + ); + + // Get ordered list of flag predicates. Must be consistent with getNames. + protected List<BooleanSupplier> getPredicates() { + return ImmutableList.of( + this::isPublic, + this::isPrivate, + this::isProtected, + this::isStatic, + this::isFinal, + this::isSynthetic); + } + + // Get ordered list of flag names. Must be consistent with getPredicates. + protected List<String> getNames() { + return NAMES; + } + + protected int flags; + + protected AccessFlags(int flags) { + this.flags = flags; + } + + public abstract int getAsCfAccessFlags(); + + public abstract int getAsDexAccessFlags(); + + @Override + public boolean equals(Object other) { + if (other instanceof AccessFlags) { + return flags == ((AccessFlags) other).flags; + } + return false; + } + + @Override + public int hashCode() { + return flags; + } + + public boolean isPublic() { + return isSet(Constants.ACC_PUBLIC); + } + + public void setPublic() { + assert !isPrivate() && !isProtected(); + set(Constants.ACC_PUBLIC); + } + + public void unsetPublic() { + unset(Constants.ACC_PUBLIC); + } + + public boolean isPrivate() { + return isSet(Constants.ACC_PRIVATE); + } + + public void setPrivate() { + assert !isPublic() && !isProtected(); + set(Constants.ACC_PRIVATE); + } + + public void unsetPrivate() { + unset(Constants.ACC_PRIVATE); + } + + public boolean isProtected() { + return isSet(Constants.ACC_PROTECTED); + } + + public void setProtected() { + assert !isPublic() && !isPrivate(); + set(Constants.ACC_PROTECTED); + } + + public void unsetProtected() { + unset(Constants.ACC_PROTECTED); + } + + public boolean isStatic() { + return isSet(Constants.ACC_STATIC); + } + + public void setStatic() { + set(Constants.ACC_STATIC); + } + + public boolean isFinal() { + return isSet(Constants.ACC_FINAL); + } + + public void setFinal() { + set(Constants.ACC_FINAL); + } + + public void unsetFinal() { + unset(Constants.ACC_FINAL); + } + + public boolean isSynthetic() { + return isSet(Constants.ACC_SYNTHETIC); + } + + public void setSynthetic() { + set(Constants.ACC_SYNTHETIC); + } + + public void unsetSynthetic() { + unset(Constants.ACC_SYNTHETIC); + } + + public void promoteNonPrivateToPublic() { + if (!isPrivate()) { + unsetProtected(); + setPublic(); + } + } + + public void promoteToPublic() { + unsetProtected(); + unsetPrivate(); + setPublic(); + } + + protected boolean isSet(int flag) { + return (flags & flag) != 0; + } + + protected void set(int flag) { + flags |= flag; + } + + protected void unset(int flag) { + flags &= ~flag; + } + + + public String toSmaliString() { + return toString(); + } + + @Override + public String toString() { + List<String> names = getNames(); + List<BooleanSupplier> predicates = getPredicates(); + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < names.size(); i++) { + if (predicates.get(i).getAsBoolean()) { + if (builder.length() > 0) { + builder.append(' '); + } + builder.append(names.get(i)); + } + } + return builder.toString(); + } +} diff --git a/src/main/java/com/android/tools/r8/graph/ClassAccessFlags.java b/src/main/java/com/android/tools/r8/graph/ClassAccessFlags.java new file mode 100644 index 000000000..64309244e --- /dev/null +++ b/src/main/java/com/android/tools/r8/graph/ClassAccessFlags.java @@ -0,0 +1,134 @@ +// Copyright (c) 2017, 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.graph; + +import com.android.tools.r8.dex.Constants; +import com.google.common.collect.ImmutableList; +import java.util.List; +import java.util.function.BooleanSupplier; + +public class ClassAccessFlags extends AccessFlags { + + // List of valid flags for both DEX and Java. + private static final int SHARED_FLAGS + = AccessFlags.BASE_FLAGS + | Constants.ACC_INTERFACE + | Constants.ACC_ABSTRACT + | Constants.ACC_ANNOTATION + | Constants.ACC_ENUM; + + private static final int DEX_FLAGS + = SHARED_FLAGS; + + private static final int CF_FLAGS + = SHARED_FLAGS + | Constants.ACC_SUPER; + + @Override + protected List<String> getNames() { + return new ImmutableList.Builder<String>() + .addAll(super.getNames()) + .add("interface") + .add("abstract") + .add("annotation") + .add("enum") + .build(); + } + + @Override + protected List<BooleanSupplier> getPredicates() { + return new ImmutableList.Builder<BooleanSupplier>() + .addAll(super.getPredicates()) + .add(this::isInterface) + .add(this::isAbstract) + .add(this::isAnnotation) + .add(this::isEnum) + .build(); + } + + private ClassAccessFlags(int flags) { + super(flags); + } + + public static ClassAccessFlags fromSharedAccessFlags(int access) { + assert (access & SHARED_FLAGS) == access; + assert SHARED_FLAGS == DEX_FLAGS; + return fromDexAccessFlags(access); + } + + public static ClassAccessFlags fromDexAccessFlags(int access) { + // Assume that the SUPER flag should be set (behaviour for Java versions > 1.1). + return new ClassAccessFlags((access & DEX_FLAGS) | Constants.ACC_SUPER); + } + + public static ClassAccessFlags fromCfAccessFlags(int access) { + return new ClassAccessFlags(access & CF_FLAGS); + } + + public ClassAccessFlags copy() { + return new ClassAccessFlags(flags); + } + + @Override + public int getAsDexAccessFlags() { + return flags & ~Constants.ACC_SUPER; + } + + @Override + public int getAsCfAccessFlags() { + return flags; + } + + public boolean isInterface() { + return isSet(Constants.ACC_INTERFACE); + } + + public void setInterface() { + set(Constants.ACC_INTERFACE); + } + + public void unsetInterface() { + unset(Constants.ACC_INTERFACE); + } + + public boolean isAbstract() { + return isSet(Constants.ACC_ABSTRACT); + } + + public void setAbstract() { + set(Constants.ACC_ABSTRACT); + } + + public void unsetAbstract() { + unset(Constants.ACC_ABSTRACT); + } + + public boolean isAnnotation() { + return isSet(Constants.ACC_ANNOTATION); + } + + public void setAnnotation() { + set(Constants.ACC_ANNOTATION); + } + + public boolean isEnum() { + return isSet(Constants.ACC_ENUM); + } + + public void setEnum() { + set(Constants.ACC_ENUM); + } + + public boolean isSuper() { + return isSet(Constants.ACC_SUPER); + } + + public void setSuper() { + set(Constants.ACC_SUPER); + } + + public void unsetSuper() { + unset(Constants.ACC_SUPER); + } +} diff --git a/src/main/java/com/android/tools/r8/graph/ClassKind.java b/src/main/java/com/android/tools/r8/graph/ClassKind.java index 90644e5ad..f8c4cbde5 100644 --- a/src/main/java/com/android/tools/r8/graph/ClassKind.java +++ b/src/main/java/com/android/tools/r8/graph/ClassKind.java @@ -16,7 +16,7 @@ public enum ClassKind { DexType type, ProgramResource.Kind kind, Origin origin, - DexAccessFlags accessFlags, + ClassAccessFlags accessFlags, DexType superType, DexTypeList interfaces, DexString sourceFile, @@ -39,7 +39,7 @@ public enum ClassKind { DexType type, ProgramResource.Kind kind, Origin origin, - DexAccessFlags accessFlags, + ClassAccessFlags accessFlags, DexType superType, DexTypeList interfaces, DexString sourceFile, diff --git a/src/main/java/com/android/tools/r8/graph/DexAccessFlags.java b/src/main/java/com/android/tools/r8/graph/DexAccessFlags.java deleted file mode 100644 index a8f9526cb..000000000 --- a/src/main/java/com/android/tools/r8/graph/DexAccessFlags.java +++ /dev/null @@ -1,310 +0,0 @@ -// 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.graph; - -import com.android.tools.r8.dex.Constants; - -public class DexAccessFlags { - - private static final String[] ACC_NAMES = { - "public", - "private", - "protected", - "static", - "final", - "synchronized", - "volatile(bridge)", - "transient(varargs)", - "native", - "interface", - "abstract", - "strictfp", - "synthetic", - "annotation", - "enum", - "<unused>", - "<init>", - "synchronized", - }; - - private int flags; - - public DexAccessFlags(int flags) { - this.flags = flags; - } - - public DexAccessFlags(int... flags) { - this(combineFlags(flags)); - } - - private static int combineFlags(int[] flags) { - int combined = 0; - for (int flag : flags) { - combined |= flag; - } - return combined; - } - - @Override - public boolean equals(Object other) { - if (other instanceof DexAccessFlags) { - return flags == ((DexAccessFlags) other).flags; - } - return false; - } - - @Override - public int hashCode() { - return get(); - } - - public int get() { - return flags; - } - - public boolean containsAllOf(DexAccessFlags other) { - return (flags & other.get()) == other.get(); - } - - public boolean containsNoneOf(DexAccessFlags other) { - return (flags & other.get()) == 0; - } - - public boolean isPublic() { - return isSet(Constants.ACC_PUBLIC); - } - - public void setPublic() { - set(Constants.ACC_PUBLIC); - } - - public void unsetPublic() { - unset(Constants.ACC_PUBLIC); - } - - public boolean isPrivate() { - return isSet(Constants.ACC_PRIVATE); - } - - public void setPrivate() { - set(Constants.ACC_PRIVATE); - } - - public void unsetPrivate() { - unset(Constants.ACC_PRIVATE); - } - - public boolean isProtected() { - return isSet(Constants.ACC_PROTECTED); - } - - public void setProtected() { - set(Constants.ACC_PROTECTED); - } - - public void unsetProtected() { - unset(Constants.ACC_PROTECTED); - } - - public boolean isStatic() { - return isSet(Constants.ACC_STATIC); - } - - public void setStatic() { - set(Constants.ACC_STATIC); - } - - public boolean isFinal() { - return isSet(Constants.ACC_FINAL); - } - - public void setFinal() { - set(Constants.ACC_FINAL); - } - - public void unsetFinal() { - unset(Constants.ACC_FINAL); - } - - public boolean isSynchronized() { - return isSet(Constants.ACC_SYNCHRONIZED); - } - - public void setSynchronized() { - set(Constants.ACC_SYNCHRONIZED); - } - - public void unsetSynchronized() { - unset(Constants.ACC_SYNCHRONIZED); - } - - public boolean isVolatile() { - return isSet(Constants.ACC_VOLATILE); - } - - public void setVolatile() { - set(Constants.ACC_VOLATILE); - } - - public boolean isBridge() { - return isSet(Constants.ACC_BRIDGE); - } - - public void setBridge() { - set(Constants.ACC_BRIDGE); - } - - public void unsetBridge() { - unset(Constants.ACC_BRIDGE); - } - - public boolean isTransient() { - return isSet(Constants.ACC_TRANSIENT); - } - - public void setTransient() { - set(Constants.ACC_TRANSIENT); - } - - public boolean isVarargs() { - return isSet(Constants.ACC_VARARGS); - } - - public void setVarargs() { - set(Constants.ACC_VARARGS); - } - - public boolean isNative() { - return isSet(Constants.ACC_NATIVE); - } - - public void setNative() { - set(Constants.ACC_NATIVE); - } - - public boolean isInterface() { - return isSet(Constants.ACC_INTERFACE); - } - - public void setInterface() { - set(Constants.ACC_INTERFACE); - } - - public void unsetInterface() { - unset(Constants.ACC_INTERFACE); - } - - public boolean isAbstract() { - return isSet(Constants.ACC_ABSTRACT); - } - - public void setAbstract() { - set(Constants.ACC_ABSTRACT); - } - - public void unsetAbstract() { - unset(Constants.ACC_ABSTRACT); - } - - public boolean isStrict() { - return isSet(Constants.ACC_STRICT); - } - - public void setStrict() { - set(Constants.ACC_STRICT); - } - - public boolean isSynthetic() { - return isSet(Constants.ACC_SYNTHETIC); - } - - public void setSynthetic() { - set(Constants.ACC_SYNTHETIC); - } - - public void unsetSynthetic() { - unset(Constants.ACC_SYNTHETIC); - } - - public boolean isAnnotation() { - return isSet(Constants.ACC_ANNOTATION); - } - - public void setAnnotation() { - set(Constants.ACC_ANNOTATION); - } - - public boolean isEnum() { - return isSet(Constants.ACC_ENUM); - } - - public void setEnum() { - set(Constants.ACC_ENUM); - } - - public boolean isConstructor() { - return isSet(Constants.ACC_CONSTRUCTOR); - } - - public void setConstructor() { - set(Constants.ACC_CONSTRUCTOR); - } - - public void unsetConstructor() { - unset(Constants.ACC_CONSTRUCTOR); - } - - public boolean isDeclaredSynchronized() { - return isSet(Constants.ACC_DECLARED_SYNCHRONIZED); - } - - public void setDeclaredSynchronized() { - set(Constants.ACC_DECLARED_SYNCHRONIZED); - } - - public void promoteNonPrivateToPublic() { - if (!isPrivate()) { - flags &= ~Constants.ACC_PROTECTED; - flags |= Constants.ACC_PUBLIC; - } - } - - public void promoteToPublic() { - flags &= ~Constants.ACC_PROTECTED & ~Constants.ACC_PRIVATE; - flags |= Constants.ACC_PUBLIC; - } - - private boolean isSet(int flag) { - return (flags & flag) != 0; - } - - private void set(int flag) { - flags |= flag; - } - - private void unset(int flag) { - flags &= ~flag; - } - - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - int flags = this.flags; - flags &= ~Constants.ACC_CONSTRUCTOR; // Don't include the constructor flag in the string. - for (int i = 0; i < ACC_NAMES.length && flags != 0; i++, flags >>= 1) { - if ((flags & 0x1) != 0) { - if (builder.length() > 0) { - builder.append(' '); - } - builder.append(ACC_NAMES[i]); - } - } - assert flags == 0; - return builder.toString(); - } - - public String toSmaliString() { - return toString(); - } -} diff --git a/src/main/java/com/android/tools/r8/graph/DexClass.java b/src/main/java/com/android/tools/r8/graph/DexClass.java index 505071166..2aba23b97 100644 --- a/src/main/java/com/android/tools/r8/graph/DexClass.java +++ b/src/main/java/com/android/tools/r8/graph/DexClass.java @@ -19,7 +19,7 @@ public abstract class DexClass extends DexItem { public final Origin origin; public final DexType type; - public final DexAccessFlags accessFlags; + public final ClassAccessFlags accessFlags; public DexType superType; public DexTypeList interfaces; public DexString sourceFile; @@ -45,7 +45,7 @@ public abstract class DexClass extends DexItem { public DexClass( DexString sourceFile, DexTypeList interfaces, - DexAccessFlags accessFlags, + ClassAccessFlags accessFlags, DexType superType, DexType type, DexEncodedField[] staticFields, diff --git a/src/main/java/com/android/tools/r8/graph/DexClasspathClass.java b/src/main/java/com/android/tools/r8/graph/DexClasspathClass.java index d39763e5d..292b368eb 100644 --- a/src/main/java/com/android/tools/r8/graph/DexClasspathClass.java +++ b/src/main/java/com/android/tools/r8/graph/DexClasspathClass.java @@ -17,7 +17,7 @@ public class DexClasspathClass extends DexClass implements Supplier<DexClasspath DexType type, ProgramResource.Kind kind, Origin origin, - DexAccessFlags accessFlags, + ClassAccessFlags accessFlags, DexType superType, DexTypeList interfaces, DexString sourceFile, diff --git a/src/main/java/com/android/tools/r8/graph/DexEncodedField.java b/src/main/java/com/android/tools/r8/graph/DexEncodedField.java index 1ba7755ab..bdfadfc8f 100644 --- a/src/main/java/com/android/tools/r8/graph/DexEncodedField.java +++ b/src/main/java/com/android/tools/r8/graph/DexEncodedField.java @@ -13,11 +13,14 @@ public class DexEncodedField extends KeyedDexItem<DexField> { public static final DexEncodedField[] EMPTY_ARRAY = new DexEncodedField[]{}; public final DexField field; - public final DexAccessFlags accessFlags; + public final FieldAccessFlags accessFlags; public DexAnnotationSet annotations; public DexValue staticValue; - public DexEncodedField(DexField field, DexAccessFlags accessFlags, DexAnnotationSet annotations, + public DexEncodedField( + DexField field, + FieldAccessFlags accessFlags, + DexAnnotationSet annotations, DexValue staticValue) { assert !accessFlags.isStatic() || staticValue != null; this.field = field; 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 19743978f..9c0c39cb2 100644 --- a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java +++ b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java @@ -85,7 +85,7 @@ public class DexEncodedMethod extends KeyedDexItem<DexMethod> { new DexEncodedMethod(null, null, null, null, null); public final DexMethod method; - public final DexAccessFlags accessFlags; + public final MethodAccessFlags accessFlags; public DexAnnotationSet annotations; public DexAnnotationSetRefList parameterAnnotations; private Code code; @@ -186,8 +186,12 @@ public class DexEncodedMethod extends KeyedDexItem<DexMethod> { public List<DebugPositionRange> debugPositionRangeList = null; - public DexEncodedMethod(DexMethod method, DexAccessFlags accessFlags, - DexAnnotationSet annotations, DexAnnotationSetRefList parameterAnnotations, Code code) { + public DexEncodedMethod( + DexMethod method, + MethodAccessFlags accessFlags, + DexAnnotationSet annotations, + DexAnnotationSetRefList parameterAnnotations, + Code code) { this.method = method; this.accessFlags = accessFlags; this.annotations = annotations; @@ -667,7 +671,7 @@ public class DexEncodedMethod extends KeyedDexItem<DexMethod> { private static class Builder { private DexMethod method; - private DexAccessFlags accessFlags; + private MethodAccessFlags accessFlags; private DexAnnotationSet annotations; private DexAnnotationSetRefList parameterAnnotations; private Code code; @@ -677,7 +681,7 @@ public class DexEncodedMethod extends KeyedDexItem<DexMethod> { private Builder(DexEncodedMethod from) { // Copy all the mutable state of a DexEncodedMethod here. method = from.method; - accessFlags = new DexAccessFlags(from.accessFlags.get()); + accessFlags = from.accessFlags.copy(); annotations = from.annotations; parameterAnnotations = from.parameterAnnotations; code = from.code; diff --git a/src/main/java/com/android/tools/r8/graph/DexLibraryClass.java b/src/main/java/com/android/tools/r8/graph/DexLibraryClass.java index 3c9cbdd2b..f2e262b1d 100644 --- a/src/main/java/com/android/tools/r8/graph/DexLibraryClass.java +++ b/src/main/java/com/android/tools/r8/graph/DexLibraryClass.java @@ -17,7 +17,7 @@ public class DexLibraryClass extends DexClass implements Supplier<DexLibraryClas DexType type, ProgramResource.Kind kind, Origin origin, - DexAccessFlags accessFlags, + ClassAccessFlags accessFlags, DexType superType, DexTypeList interfaces, DexString sourceFile, diff --git a/src/main/java/com/android/tools/r8/graph/DexProgramClass.java b/src/main/java/com/android/tools/r8/graph/DexProgramClass.java index ad1af107f..4d1654859 100644 --- a/src/main/java/com/android/tools/r8/graph/DexProgramClass.java +++ b/src/main/java/com/android/tools/r8/graph/DexProgramClass.java @@ -31,7 +31,7 @@ public class DexProgramClass extends DexClass implements Supplier<DexProgramClas DexType type, ProgramResource.Kind originKind, Origin origin, - DexAccessFlags accessFlags, + ClassAccessFlags accessFlags, DexType superType, DexTypeList interfaces, DexString sourceFile, @@ -60,7 +60,7 @@ public class DexProgramClass extends DexClass implements Supplier<DexProgramClas DexType type, ProgramResource.Kind originKind, Origin origin, - DexAccessFlags accessFlags, + ClassAccessFlags accessFlags, DexType superType, DexTypeList interfaces, DexString sourceFile, diff --git a/src/main/java/com/android/tools/r8/graph/FieldAccessFlags.java b/src/main/java/com/android/tools/r8/graph/FieldAccessFlags.java new file mode 100644 index 000000000..b56e60fb3 --- /dev/null +++ b/src/main/java/com/android/tools/r8/graph/FieldAccessFlags.java @@ -0,0 +1,93 @@ +// Copyright (c) 2017, 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.graph; + +import com.android.tools.r8.dex.Constants; +import com.google.common.collect.ImmutableList; +import java.util.List; +import java.util.function.BooleanSupplier; + +public class FieldAccessFlags extends AccessFlags { + + private static final int FLAGS + = AccessFlags.BASE_FLAGS + | Constants.ACC_VOLATILE + | Constants.ACC_TRANSIENT + | Constants.ACC_ENUM; + + @Override + protected List<String> getNames() { + return new ImmutableList.Builder<String>() + .addAll(super.getNames()) + .add("volatile") + .add("transient") + .add("enum") + .build(); + } + + @Override + protected List<BooleanSupplier> getPredicates() { + return new ImmutableList.Builder<BooleanSupplier>() + .addAll(super.getPredicates()) + .add(this::isVolatile) + .add(this::isTransient) + .add(this::isEnum) + .build(); + } + + private FieldAccessFlags(int flags) { + super(flags); + } + + public FieldAccessFlags copy() { + return new FieldAccessFlags(flags); + } + + public static FieldAccessFlags fromSharedAccessFlags(int access) { + assert (access & FLAGS) == access; + return new FieldAccessFlags(access & FLAGS); + } + + public static FieldAccessFlags fromDexAccessFlags(int access) { + return new FieldAccessFlags(access & FLAGS); + } + + public static FieldAccessFlags fromCfAccessFlags(int access) { + return new FieldAccessFlags(access & FLAGS); + } + + @Override + public int getAsCfAccessFlags() { + return flags; + } + + @Override + public int getAsDexAccessFlags() { + return flags; + } + + public boolean isVolatile() { + return isSet(Constants.ACC_VOLATILE); + } + + public void setVolatile() { + set(Constants.ACC_VOLATILE); + } + + public boolean isTransient() { + return isSet(Constants.ACC_TRANSIENT); + } + + public void setTransient() { + set(Constants.ACC_TRANSIENT); + } + + public boolean isEnum() { + return isSet(Constants.ACC_ENUM); + } + + public void setEnum() { + set(Constants.ACC_ENUM); + } +} diff --git a/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java b/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java index 9742df7d3..46f796686 100644 --- a/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java +++ b/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java @@ -40,7 +40,6 @@ import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.FieldVisitor; import org.objectweb.asm.Label; import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; import org.objectweb.asm.TypePath; @@ -67,9 +66,9 @@ public class JarClassFileReader { origin, classKind, reader.b, application, classConsumer), SKIP_FRAMES); } - private static DexAccessFlags createAccessFlags(int access) { - // Clear the "synthetic attribute" and "deprecated" flags if preset. - return new DexAccessFlags(access & ~ACC_SYNTHETIC_ATTRIBUTE & ~ACC_DEPRECATED); + private static int cleanAccessFlags(int access) { + // Clear the "synthetic attribute" and "deprecated" attribute-flags if present. + return access & ~ACC_SYNTHETIC_ATTRIBUTE & ~ACC_DEPRECATED; } private static AnnotationVisitor createAnnotationVisitor(String desc, boolean visible, @@ -103,7 +102,7 @@ public class JarClassFileReader { // DexClass data. private int version; private DexType type; - private DexAccessFlags accessFlags; + private ClassAccessFlags accessFlags; private DexType superType; private DexTypeList interfaces; private DexString sourceFile; @@ -176,10 +175,7 @@ public class JarClassFileReader { public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { this.version = version; - accessFlags = createAccessFlags(access); - // Unset the (in dex) non-existent ACC_SUPER flag on the class. - assert Constants.ACC_SYNCHRONIZED == Opcodes.ACC_SUPER; - accessFlags.unsetSynchronized(); + accessFlags = ClassAccessFlags.fromCfAccessFlags(cleanAccessFlags(access)); type = application.getTypeFromName(name); assert superName != null || name.equals(Constants.JAVA_LANG_OBJECT_NAME); superType = superName == null ? null : application.getTypeFromName(superName); @@ -332,7 +328,7 @@ public class JarClassFileReader { @Override public void visitEnd() { - DexAccessFlags flags = createAccessFlags(access); + FieldAccessFlags flags = FieldAccessFlags.fromCfAccessFlags(cleanAccessFlags(access)); DexField dexField = parent.application.getField(parent.type, name, desc); DexAnnotationSet annotationSet = createAnnotationSet(annotations); DexValue staticValue = flags.isStatic() ? getStaticValue(value, dexField.type) : null; @@ -514,7 +510,7 @@ public class JarClassFileReader { @Override public void visitEnd() { DexMethod method = parent.application.getMethod(parent.type, name, desc); - DexAccessFlags flags = createMethodAccessFlags(access); + MethodAccessFlags flags = createMethodAccessFlags(access); Code code = null; if (!flags.isAbstract() && !flags.isNative() @@ -567,20 +563,11 @@ public class JarClassFileReader { getAnnotations().add(annotation); } - private DexAccessFlags createMethodAccessFlags(int access) { - DexAccessFlags flags = createAccessFlags(access); - // Set just the dex specific declared-synchronized flag if the method is synchronized. - // TODO(zerny): Should declared sync also be set if it is native? - if (flags.isSynchronized() && !flags.isNative()) { - flags.unsetSynchronized(); - flags.setDeclaredSynchronized(); - } - // Set the constructor bit on instance and class initializers. - if (name.equals(Constants.INSTANCE_INITIALIZER_NAME) || name.equals( - Constants.CLASS_INITIALIZER_NAME)) { - flags.setConstructor(); - } - return flags; + private MethodAccessFlags createMethodAccessFlags(int access) { + boolean isConstructor = + name.equals(Constants.INSTANCE_INITIALIZER_NAME) + || name.equals(Constants.CLASS_INITIALIZER_NAME); + return MethodAccessFlags.fromCfAccessFlags(cleanAccessFlags(access), isConstructor); } } diff --git a/src/main/java/com/android/tools/r8/graph/MethodAccessFlags.java b/src/main/java/com/android/tools/r8/graph/MethodAccessFlags.java new file mode 100644 index 000000000..37a6facf3 --- /dev/null +++ b/src/main/java/com/android/tools/r8/graph/MethodAccessFlags.java @@ -0,0 +1,184 @@ +// Copyright (c) 2017, 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.graph; + +import com.android.tools.r8.dex.Constants; +import com.google.common.collect.ImmutableList; +import java.util.List; +import java.util.function.BooleanSupplier; + +public class MethodAccessFlags extends AccessFlags { + + private static final int SHARED_FLAGS + = AccessFlags.BASE_FLAGS + | Constants.ACC_SYNCHRONIZED + | Constants.ACC_BRIDGE + | Constants.ACC_VARARGS + | Constants.ACC_NATIVE + | Constants.ACC_ABSTRACT + | Constants.ACC_STRICT; + + private static final int CF_FLAGS + = SHARED_FLAGS; + + private static final int DEX_FLAGS + = SHARED_FLAGS + | Constants.ACC_CONSTRUCTOR + | Constants.ACC_DECLARED_SYNCHRONIZED; + + @Override + protected List<String> getNames() { + return new ImmutableList.Builder<String>() + .addAll(super.getNames()) + .add("synchronized") + .add("bridge") + .add("varargs") + .add("native") + .add("abstract") + .add("strictfp") + .build(); + } + + @Override + protected List<BooleanSupplier> getPredicates() { + return new ImmutableList.Builder<BooleanSupplier>() + .addAll(super.getPredicates()) + .add(this::isSynchronized) + .add(this::isBridge) + .add(this::isVarargs) + .add(this::isNative) + .add(this::isAbstract) + .add(this::isStrict) + .build(); + } + + private MethodAccessFlags(int flags) { + super(flags); + } + + public MethodAccessFlags copy() { + return new MethodAccessFlags(flags); + } + + public static MethodAccessFlags fromSharedAccessFlags(int access, boolean isConstructor) { + assert (access & SHARED_FLAGS) == access; + assert CF_FLAGS == SHARED_FLAGS; + return fromCfAccessFlags(access, isConstructor); + } + + public static MethodAccessFlags fromCfAccessFlags(int access, boolean isConstructor) { + return new MethodAccessFlags( + (access & CF_FLAGS) | (isConstructor ? Constants.ACC_CONSTRUCTOR : 0)); + } + + public static MethodAccessFlags fromDexAccessFlags(int access) { + MethodAccessFlags flags = new MethodAccessFlags(access & DEX_FLAGS); + if (flags.isDeclaredSynchronized()) { + flags.setSynchronized(); + flags.unsetDeclaredSynchronized(); + } + return flags; + } + + @Override + public int getAsDexAccessFlags() { + MethodAccessFlags copy = copy(); + if (copy.isSynchronized() && !copy.isNative()) { + copy.unsetSynchronized(); + copy.setDeclaredSynchronized(); + } + return copy.flags; + } + + @Override + public int getAsCfAccessFlags() { + return flags & ~Constants.ACC_CONSTRUCTOR; + } + + public boolean isSynchronized() { + return isSet(Constants.ACC_SYNCHRONIZED); + } + + public void setSynchronized() { + set(Constants.ACC_SYNCHRONIZED); + } + + public void unsetSynchronized() { + unset(Constants.ACC_SYNCHRONIZED); + } + + public boolean isBridge() { + return isSet(Constants.ACC_BRIDGE); + } + + public void setBridge() { + set(Constants.ACC_BRIDGE); + } + + public void unsetBridge() { + unset(Constants.ACC_BRIDGE); + } + + public boolean isVarargs() { + return isSet(Constants.ACC_VARARGS); + } + + public void setVarargs() { + set(Constants.ACC_VARARGS); + } + + public boolean isNative() { + return isSet(Constants.ACC_NATIVE); + } + + public void setNative() { + set(Constants.ACC_NATIVE); + } + + public boolean isAbstract() { + return isSet(Constants.ACC_ABSTRACT); + } + + public void setAbstract() { + set(Constants.ACC_ABSTRACT); + } + + public void unsetAbstract() { + unset(Constants.ACC_ABSTRACT); + } + + public boolean isStrict() { + return isSet(Constants.ACC_STRICT); + } + + public void setStrict() { + set(Constants.ACC_STRICT); + } + + public boolean isConstructor() { + return isSet(Constants.ACC_CONSTRUCTOR); + } + + public void setConstructor() { + set(Constants.ACC_CONSTRUCTOR); + } + + public void unsetConstructor() { + unset(Constants.ACC_CONSTRUCTOR); + } + + // DEX only declared-synchronized flag. + + private boolean isDeclaredSynchronized() { + return isSet(Constants.ACC_DECLARED_SYNCHRONIZED); + } + + private void setDeclaredSynchronized() { + set(Constants.ACC_DECLARED_SYNCHRONIZED); + } + + private void unsetDeclaredSynchronized() { + unset(Constants.ACC_DECLARED_SYNCHRONIZED); + } +} diff --git a/src/main/java/com/android/tools/r8/ir/conversion/DexSourceCode.java b/src/main/java/com/android/tools/r8/ir/conversion/DexSourceCode.java index a71f32605..4bafe6211 100644 --- a/src/main/java/com/android/tools/r8/ir/conversion/DexSourceCode.java +++ b/src/main/java/com/android/tools/r8/ir/conversion/DexSourceCode.java @@ -29,7 +29,6 @@ import com.android.tools.r8.code.SwitchPayload; import com.android.tools.r8.code.Throw; import com.android.tools.r8.errors.Unreachable; import com.android.tools.r8.graph.DebugLocalInfo; -import com.android.tools.r8.graph.DexAccessFlags; import com.android.tools.r8.graph.DexCode; import com.android.tools.r8.graph.DexCode.Try; import com.android.tools.r8.graph.DexCode.TryHandler; @@ -40,6 +39,7 @@ import com.android.tools.r8.graph.DexEncodedMethod; import com.android.tools.r8.graph.DexItemFactory; import com.android.tools.r8.graph.DexProto; import com.android.tools.r8.graph.DexType; +import com.android.tools.r8.graph.MethodAccessFlags; import com.android.tools.r8.ir.code.CatchHandlers; import com.android.tools.r8.ir.code.MoveType; import com.android.tools.r8.ir.code.Position; @@ -53,7 +53,7 @@ import java.util.Set; public class DexSourceCode implements SourceCode { private final DexCode code; - private final DexAccessFlags accessFlags; + private final MethodAccessFlags accessFlags; private final DexProto proto; // Mapping from instruction offset to instruction index in the DexCode instruction array. diff --git a/src/main/java/com/android/tools/r8/ir/desugar/AccessorMethodSourceCode.java b/src/main/java/com/android/tools/r8/ir/desugar/AccessorMethodSourceCode.java index 1cf64fd2b..246079899 100644 --- a/src/main/java/com/android/tools/r8/ir/desugar/AccessorMethodSourceCode.java +++ b/src/main/java/com/android/tools/r8/ir/desugar/AccessorMethodSourceCode.java @@ -5,11 +5,11 @@ package com.android.tools.r8.ir.desugar; import com.android.tools.r8.errors.Unreachable; -import com.android.tools.r8.graph.DexAccessFlags; import com.android.tools.r8.graph.DexMethod; import com.android.tools.r8.graph.DexMethodHandle; import com.android.tools.r8.graph.DexProto; import com.android.tools.r8.graph.DexType; +import com.android.tools.r8.graph.MethodAccessFlags; import com.android.tools.r8.ir.code.Invoke; import com.android.tools.r8.ir.code.MoveType; import com.android.tools.r8.ir.conversion.IRBuilder; @@ -57,7 +57,7 @@ final class AccessorMethodSourceCode extends SynthesizedLambdaSourceCode { private boolean isPrivateMethod() { // We should be able to find targets for all private impl-methods, so // we can rely on knowing accessibility flags for them. - DexAccessFlags flags = descriptor().getAccessibility(); + MethodAccessFlags flags = descriptor().getAccessibility(); return flags != null && flags.isPrivate(); } diff --git a/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java b/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java index 09371f774..fa0958bfc 100644 --- a/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java +++ b/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java @@ -5,11 +5,11 @@ package com.android.tools.r8.ir.desugar; import com.android.tools.r8.errors.CompilationError; -import com.android.tools.r8.graph.DexAccessFlags; import com.android.tools.r8.graph.DexClass; import com.android.tools.r8.graph.DexEncodedMethod; import com.android.tools.r8.graph.DexMethod; import com.android.tools.r8.graph.DexType; +import com.android.tools.r8.graph.MethodAccessFlags; import com.android.tools.r8.ir.code.Invoke; import com.android.tools.r8.ir.synthetic.ForwardMethodSourceCode; import com.android.tools.r8.ir.synthetic.SynthesizedCode; @@ -109,7 +109,7 @@ final class ClassProcessor { // New method will have the same name, proto, and also all the flags of the // default method, including bridge flag. DexMethod newMethod = rewriter.factory.createMethod(clazz.type, method.proto, method.name); - DexAccessFlags newFlags = new DexAccessFlags(defaultMethod.accessFlags.get()); + MethodAccessFlags newFlags = defaultMethod.accessFlags.copy(); return new DexEncodedMethod(newMethod, newFlags, defaultMethod.annotations, defaultMethod.parameterAnnotations, new SynthesizedCode(new ForwardMethodSourceCode( diff --git a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java index fb3507be6..1714b9308 100644 --- a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java +++ b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java @@ -6,8 +6,8 @@ package com.android.tools.r8.ir.desugar; import com.android.tools.r8.errors.CompilationError; import com.android.tools.r8.errors.Unimplemented; +import com.android.tools.r8.graph.ClassAccessFlags; import com.android.tools.r8.graph.Code; -import com.android.tools.r8.graph.DexAccessFlags; import com.android.tools.r8.graph.DexAnnotationSet; import com.android.tools.r8.graph.DexCode; import com.android.tools.r8.graph.DexEncodedField; @@ -16,6 +16,7 @@ import com.android.tools.r8.graph.DexMethod; import com.android.tools.r8.graph.DexProgramClass; import com.android.tools.r8.graph.DexType; import com.android.tools.r8.graph.DexTypeList; +import com.android.tools.r8.graph.MethodAccessFlags; import java.util.ArrayList; import java.util.Collections; import java.util.IdentityHashMap; @@ -56,7 +57,7 @@ final class InterfaceProcessor { + "interface method: " + virtual.method.toSourceString()); } - DexAccessFlags newFlags = new DexAccessFlags(virtual.accessFlags.get()); + MethodAccessFlags newFlags = virtual.accessFlags.copy(); newFlags.unsetBridge(); newFlags.setStatic(); DexCode dexCode = code.asDexCode(); @@ -115,7 +116,7 @@ final class InterfaceProcessor { return; // No methods to create, companion class not needed. } - DexAccessFlags companionClassFlags = new DexAccessFlags(iface.accessFlags.get()); + ClassAccessFlags companionClassFlags = iface.accessFlags.copy(); companionClassFlags.unsetAbstract(); companionClassFlags.unsetInterface(); companionClassFlags.setFinal(); diff --git a/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java b/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java index 569d088a7..43548c2b5 100644 --- a/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java +++ b/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java @@ -8,7 +8,7 @@ import com.android.tools.r8.ApiLevelException; import com.android.tools.r8.dex.Constants; import com.android.tools.r8.errors.Unimplemented; import com.android.tools.r8.errors.Unreachable; -import com.android.tools.r8.graph.DexAccessFlags; +import com.android.tools.r8.graph.ClassAccessFlags; import com.android.tools.r8.graph.DexAnnotationSet; import com.android.tools.r8.graph.DexAnnotationSetRefList; import com.android.tools.r8.graph.DexClass; @@ -25,6 +25,8 @@ import com.android.tools.r8.graph.DexString; import com.android.tools.r8.graph.DexType; import com.android.tools.r8.graph.DexTypeList; import com.android.tools.r8.graph.DexValue.DexValueNull; +import com.android.tools.r8.graph.FieldAccessFlags; +import com.android.tools.r8.graph.MethodAccessFlags; import com.android.tools.r8.ir.code.Invoke; import com.android.tools.r8.ir.synthetic.SynthesizedCode; import java.util.ArrayList; @@ -121,7 +123,7 @@ final class LambdaClass { type, null, null, - new DexAccessFlags(Constants.ACC_FINAL | Constants.ACC_SYNTHETIC), + ClassAccessFlags.fromDexAccessFlags(Constants.ACC_FINAL | Constants.ACC_SYNTHETIC), rewriter.factory.objectType, buildInterfaces(), rewriter.factory.createString("lambda"), @@ -155,24 +157,31 @@ final class LambdaClass { // Synthesize main method. DexMethod mainMethod = rewriter.factory .createMethod(type, descriptor.erasedProto, descriptor.name); - methods[index++] = new DexEncodedMethod( - mainMethod, - new DexAccessFlags(Constants.ACC_PUBLIC | Constants.ACC_FINAL), - DexAnnotationSet.empty(), - DexAnnotationSetRefList.empty(), - new SynthesizedCode(new LambdaMainMethodSourceCode(this, mainMethod))); + methods[index++] = + new DexEncodedMethod( + mainMethod, + MethodAccessFlags.fromSharedAccessFlags( + Constants.ACC_PUBLIC | Constants.ACC_FINAL, false), + DexAnnotationSet.empty(), + DexAnnotationSetRefList.empty(), + new SynthesizedCode(new LambdaMainMethodSourceCode(this, mainMethod))); // Synthesize bridge methods. for (DexProto bridgeProto : descriptor.bridges) { DexMethod bridgeMethod = rewriter.factory.createMethod(type, bridgeProto, descriptor.name); - methods[index++] = new DexEncodedMethod( - bridgeMethod, - new DexAccessFlags(Constants.ACC_PUBLIC | Constants.ACC_FINAL - | Constants.ACC_SYNTHETIC | Constants.ACC_BRIDGE), - DexAnnotationSet.empty(), - DexAnnotationSetRefList.empty(), - new SynthesizedCode( - new LambdaBridgeMethodSourceCode(this, mainMethod, bridgeMethod))); + methods[index++] = + new DexEncodedMethod( + bridgeMethod, + MethodAccessFlags.fromSharedAccessFlags( + Constants.ACC_PUBLIC + | Constants.ACC_FINAL + | Constants.ACC_SYNTHETIC + | Constants.ACC_BRIDGE, + false), + DexAnnotationSet.empty(), + DexAnnotationSetRefList.empty(), + new SynthesizedCode( + new LambdaBridgeMethodSourceCode(this, mainMethod, bridgeMethod))); } return methods; } @@ -183,23 +192,27 @@ final class LambdaClass { DexEncodedMethod[] methods = new DexEncodedMethod[stateless ? 2 : 1]; // Constructor. - methods[0] = new DexEncodedMethod( - constructor, - new DexAccessFlags((stateless ? Constants.ACC_PRIVATE : Constants.ACC_PUBLIC) | - Constants.ACC_SYNTHETIC | Constants.ACC_CONSTRUCTOR), - DexAnnotationSet.empty(), - DexAnnotationSetRefList.empty(), - new SynthesizedCode(new LambdaConstructorSourceCode(this))); + methods[0] = + new DexEncodedMethod( + constructor, + MethodAccessFlags.fromSharedAccessFlags( + (stateless ? Constants.ACC_PRIVATE : Constants.ACC_PUBLIC) + | Constants.ACC_SYNTHETIC, + true), + DexAnnotationSet.empty(), + DexAnnotationSetRefList.empty(), + new SynthesizedCode(new LambdaConstructorSourceCode(this))); // Class constructor for stateless lambda classes. if (stateless) { - methods[1] = new DexEncodedMethod( - classConstructor, - new DexAccessFlags( - Constants.ACC_SYNTHETIC | Constants.ACC_CONSTRUCTOR | Constants.ACC_STATIC), - DexAnnotationSet.empty(), - DexAnnotationSetRefList.empty(), - new SynthesizedCode(new LambdaClassConstructorSourceCode(this))); + methods[1] = + new DexEncodedMethod( + classConstructor, + MethodAccessFlags.fromSharedAccessFlags( + Constants.ACC_SYNTHETIC | Constants.ACC_STATIC, true), + DexAnnotationSet.empty(), + DexAnnotationSetRefList.empty(), + new SynthesizedCode(new LambdaClassConstructorSourceCode(this))); } return methods; } @@ -210,8 +223,9 @@ final class LambdaClass { int fieldCount = fieldTypes.length; DexEncodedField[] fields = new DexEncodedField[fieldCount]; for (int i = 0; i < fieldCount; i++) { - DexAccessFlags accessFlags = new DexAccessFlags( - Constants.ACC_FINAL | Constants.ACC_SYNTHETIC | Constants.ACC_PRIVATE); + FieldAccessFlags accessFlags = + FieldAccessFlags.fromSharedAccessFlags( + Constants.ACC_FINAL | Constants.ACC_SYNTHETIC | Constants.ACC_PRIVATE); fields[i] = new DexEncodedField( getCaptureField(i), accessFlags, DexAnnotationSet.empty(), null); } @@ -227,12 +241,16 @@ final class LambdaClass { // Create instance field for stateless lambda. assert this.instanceField != null; DexEncodedField[] fields = new DexEncodedField[1]; - fields[0] = new DexEncodedField( - this.instanceField, - new DexAccessFlags(Constants.ACC_PUBLIC | Constants.ACC_FINAL - | Constants.ACC_SYNTHETIC | Constants.ACC_STATIC), - DexAnnotationSet.empty(), - DexValueNull.NULL); + fields[0] = + new DexEncodedField( + this.instanceField, + FieldAccessFlags.fromSharedAccessFlags( + Constants.ACC_PUBLIC + | Constants.ACC_FINAL + | Constants.ACC_SYNTHETIC + | Constants.ACC_STATIC), + DexAnnotationSet.empty(), + DexValueNull.NULL); return fields; } @@ -497,9 +515,12 @@ final class LambdaClass { DexProgramClass accessorClass = programDefinitionFor(callTarget.holder); assert accessorClass != null; - DexAccessFlags accessorFlags = new DexAccessFlags( - Constants.ACC_SYNTHETIC | Constants.ACC_STATIC | - (accessorClass.isInterface() ? Constants.ACC_PUBLIC : 0)); + MethodAccessFlags accessorFlags = + MethodAccessFlags.fromSharedAccessFlags( + Constants.ACC_SYNTHETIC + | Constants.ACC_STATIC + | (accessorClass.isInterface() ? Constants.ACC_PUBLIC : 0), + false); DexEncodedMethod accessorEncodedMethod = new DexEncodedMethod( callTarget, accessorFlags, DexAnnotationSet.empty(), DexAnnotationSetRefList.empty(), new SynthesizedCode(new AccessorMethodSourceCode(LambdaClass.this))); diff --git a/src/main/java/com/android/tools/r8/ir/desugar/LambdaDescriptor.java b/src/main/java/com/android/tools/r8/ir/desugar/LambdaDescriptor.java index bba7b23f0..5d5252300 100644 --- a/src/main/java/com/android/tools/r8/ir/desugar/LambdaDescriptor.java +++ b/src/main/java/com/android/tools/r8/ir/desugar/LambdaDescriptor.java @@ -6,7 +6,6 @@ package com.android.tools.r8.ir.desugar; import com.android.tools.r8.errors.Unreachable; import com.android.tools.r8.graph.AppInfo; -import com.android.tools.r8.graph.DexAccessFlags; import com.android.tools.r8.graph.DexCallSite; import com.android.tools.r8.graph.DexEncodedMethod; import com.android.tools.r8.graph.DexItemFactory; @@ -17,6 +16,7 @@ import com.android.tools.r8.graph.DexString; import com.android.tools.r8.graph.DexType; import com.android.tools.r8.graph.DexTypeList; import com.android.tools.r8.graph.DexValue; +import com.android.tools.r8.graph.MethodAccessFlags; import com.google.common.collect.Sets; import java.util.ArrayList; import java.util.List; @@ -140,7 +140,7 @@ final class LambdaDescriptor { return encodedMethod.accessFlags.isPrivate() && isInstanceMethod(encodedMethod); } - final DexAccessFlags getAccessibility() { + final MethodAccessFlags getAccessibility() { return targetMethod == null ? null : targetMethod.accessFlags; } @@ -198,7 +198,7 @@ final class LambdaDescriptor { return true; } - DexAccessFlags flags = targetMethod.accessFlags; + MethodAccessFlags flags = targetMethod.accessFlags; // Private methods always need accessors. if (flags.isPrivate()) { diff --git a/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java b/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java index ad4639e7f..b15d254c2 100644 --- a/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java +++ b/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java @@ -4,8 +4,8 @@ package com.android.tools.r8.ir.optimize; import com.android.tools.r8.ApiLevelException; +import com.android.tools.r8.graph.AccessFlags; import com.android.tools.r8.graph.AppInfoWithSubtyping; -import com.android.tools.r8.graph.DexAccessFlags; import com.android.tools.r8.graph.DexClass; import com.android.tools.r8.graph.DexEncodedField; import com.android.tools.r8.graph.DexEncodedMethod; @@ -91,7 +91,7 @@ public class Inliner { return isVisibleWithFlags(target.method.holder, method.method.holder, targetClass.accessFlags); } - private boolean isVisibleWithFlags(DexType target, DexType context, DexAccessFlags flags) { + private boolean isVisibleWithFlags(DexType target, DexType context, AccessFlags flags) { if (flags.isPublic()) { return true; } @@ -166,8 +166,11 @@ public class Inliner { assert SUBCLASS.ordinal() < ALWAYS.ordinal(); } - public static Constraint deriveConstraint(DexType contextHolder, DexType targetHolder, - DexAccessFlags flags, AppInfoWithSubtyping appInfo) { + public static Constraint deriveConstraint( + DexType contextHolder, + DexType targetHolder, + AccessFlags flags, + AppInfoWithSubtyping appInfo) { if (flags.isPublic()) { return ALWAYS; } else if (flags.isPrivate()) { diff --git a/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java b/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java index 74afdcd14..d799e7d79 100644 --- a/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java +++ b/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java @@ -8,9 +8,9 @@ import com.android.tools.r8.ApiLevelException; import com.android.tools.r8.dex.Constants; import com.android.tools.r8.errors.Unreachable; import com.android.tools.r8.graph.AppInfo; +import com.android.tools.r8.graph.ClassAccessFlags; import com.android.tools.r8.graph.Code; import com.android.tools.r8.graph.DebugLocalInfo; -import com.android.tools.r8.graph.DexAccessFlags; import com.android.tools.r8.graph.DexAnnotationSet; import com.android.tools.r8.graph.DexAnnotationSetRefList; import com.android.tools.r8.graph.DexClass; @@ -23,6 +23,7 @@ import com.android.tools.r8.graph.DexProto; import com.android.tools.r8.graph.DexString; import com.android.tools.r8.graph.DexType; import com.android.tools.r8.graph.DexTypeList; +import com.android.tools.r8.graph.MethodAccessFlags; import com.android.tools.r8.graph.UseRegistry; import com.android.tools.r8.ir.code.Add; import com.android.tools.r8.ir.code.BasicBlock; @@ -1058,7 +1059,9 @@ public class Outliner { List<Outline> outlines = new ArrayList<>(candidates.keySet()); outlines.sort(Comparator.naturalOrder()); for (Outline outline : outlines) { - DexAccessFlags methodAccess = new DexAccessFlags(Constants.ACC_PUBLIC, Constants.ACC_STATIC); + MethodAccessFlags methodAccess = + MethodAccessFlags.fromSharedAccessFlags( + Constants.ACC_PUBLIC | Constants.ACC_STATIC, false); DexString methodName = dexItemFactory.createString(options.outline.methodPrefix + count); DexMethod method = outline.buildMethod(type, methodName); direct[count] = new DexEncodedMethod(method, methodAccess, DexAnnotationSet.empty(), @@ -1072,7 +1075,7 @@ public class Outliner { DexType superType = dexItemFactory.createType("Ljava/lang/Object;"); DexTypeList interfaces = DexTypeList.empty(); DexString sourceFile = dexItemFactory.createString("outline"); - DexAccessFlags accessFlags = new DexAccessFlags(Constants.ACC_PUBLIC); + ClassAccessFlags accessFlags = ClassAccessFlags.fromSharedAccessFlags(Constants.ACC_PUBLIC); DexProgramClass clazz = new DexProgramClass( type, null, diff --git a/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java b/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java index 83788c7c2..483327b3d 100644 --- a/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java +++ b/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java @@ -3,11 +3,8 @@ // BSD-style license that can be found in the LICENSE file. package com.android.tools.r8.jar; -import static org.objectweb.asm.Opcodes.ACC_SUPER; - import com.android.tools.r8.OutputSink; import com.android.tools.r8.errors.Unimplemented; -import com.android.tools.r8.graph.DexAccessFlags; import com.android.tools.r8.graph.DexApplication; import com.android.tools.r8.graph.DexEncodedMethod; import com.android.tools.r8.graph.DexProgramClass; @@ -53,7 +50,7 @@ public class CfApplicationWriter { ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_FRAMES); writer.visitSource(clazz.sourceFile.toString(), null); int version = clazz.getClassFileVersion(); - int access = classAndInterfaceAccessFlags(clazz.accessFlags); + int access = clazz.accessFlags.getAsCfAccessFlags(); String desc = clazz.type.toDescriptorString(); String name = internalName(clazz.type); String signature = null; // TODO(zerny): Support generic signatures. @@ -72,7 +69,7 @@ public class CfApplicationWriter { } private void writeMethod(DexEncodedMethod method, ClassWriter writer) { - int access = method.accessFlags.get(); + int access = method.accessFlags.getAsCfAccessFlags(); String name = method.method.name.toString(); String desc = method.descriptor(); String signature = null; // TODO(zerny): Support generic signatures. @@ -81,13 +78,6 @@ public class CfApplicationWriter { method.getCode().asJarCode().writeTo(visitor); } - private static int classAndInterfaceAccessFlags(DexAccessFlags accessFlags) { - // TODO(zerny): Refactor access flags to account for the union of both DEX and Java flags. - int access = accessFlags.get(); - access |= ACC_SUPER; - return access; - } - private static String internalName(DexType type) { return Type.getType(type.toDescriptorString()).getInternalName(); } diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardAccessFlags.java b/src/main/java/com/android/tools/r8/shaking/ProguardAccessFlags.java new file mode 100644 index 000000000..749ce835c --- /dev/null +++ b/src/main/java/com/android/tools/r8/shaking/ProguardAccessFlags.java @@ -0,0 +1,176 @@ +// Copyright (c) 2017, 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.shaking; + +import com.android.tools.r8.dex.Constants; +import com.android.tools.r8.graph.AccessFlags; +import com.google.common.collect.ImmutableList; +import java.util.List; +import java.util.function.BooleanSupplier; + +public class ProguardAccessFlags { + + private int flags = 0; + + // Ordered list of flag names. Must be consistent with getPredicates. + private static final List<String> NAMES = ImmutableList.of( + "public", + "private", + "protected", + "static", + "final", + "abstract", + "volatile", + "transient", + "synchronized", + "native", + "strictfp" + ); + + // Get ordered list of flag predicates. Must be consistent with getNames. + private List<BooleanSupplier> getPredicates() { + return ImmutableList.of( + this::isPublic, + this::isPrivate, + this::isProtected, + this::isStatic, + this::isFinal, + this::isAbstract, + this::isVolatile, + this::isTransient, + this::isSynchronized, + this::isNative, + this::isStrict); + } + + private boolean containsAll(int other) { + return (flags & other) == flags; + } + + private boolean containsNone(int other) { + return (flags & other) == 0; + } + + public boolean containsAll(AccessFlags other) { + return containsAll(other.getAsCfAccessFlags()); + } + + public boolean containsNone(AccessFlags other) { + return containsNone(other.getAsCfAccessFlags()); + } + + public void setPublic() { + set(Constants.ACC_PUBLIC); + } + + public boolean isPublic() { + return isSet(Constants.ACC_PUBLIC); + } + + public void setPrivate() { + set(Constants.ACC_PRIVATE); + } + + public boolean isPrivate() { + return isSet(Constants.ACC_PRIVATE); + } + + public void setProtected() { + set(Constants.ACC_PROTECTED); + } + + public boolean isProtected() { + return isSet(Constants.ACC_PROTECTED); + } + + public void setStatic() { + set(Constants.ACC_STATIC); + } + + public boolean isStatic() { + return isSet(Constants.ACC_STATIC); + } + + public void setFinal() { + set(Constants.ACC_FINAL); + } + + public boolean isFinal() { + return isSet(Constants.ACC_FINAL); + } + + public void setAbstract() { + set(Constants.ACC_ABSTRACT); + } + + public boolean isAbstract() { + return isSet(Constants.ACC_ABSTRACT); + } + + public void setVolatile() { + set(Constants.ACC_VOLATILE); + } + + public boolean isVolatile() { + return isSet(Constants.ACC_VOLATILE); + } + + public void setTransient() { + set(Constants.ACC_TRANSIENT); + } + + public boolean isTransient() { + return isSet(Constants.ACC_TRANSIENT); + } + + public void setSynchronized() { + set(Constants.ACC_SYNCHRONIZED); + } + + public boolean isSynchronized() { + return isSet(Constants.ACC_SYNCHRONIZED); + } + + public void setNative() { + set(Constants.ACC_NATIVE); + } + + public boolean isNative() { + return isSet(Constants.ACC_NATIVE); + } + + public void setStrict() { + set(Constants.ACC_STRICT); + } + + public boolean isStrict() { + return isSet(Constants.ACC_STRICT); + } + + private boolean isSet(int flag) { + return (flags & flag) != 0; + } + + private void set(int flag) { + flags |= flag; + } + + @Override + public String toString() { + List<BooleanSupplier> predicates = getPredicates(); + StringBuilder builder = new StringBuilder(); + boolean space = false; + for (int i = 0; i < NAMES.size(); i++) { + if (predicates.get(i).getAsBoolean()) { + if (space) { + builder.append(' '); + } else { + space = true; + } + builder.append(NAMES.get(i)); + } + } + return builder.toString(); + } +} diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardAlwaysInlineRule.java b/src/main/java/com/android/tools/r8/shaking/ProguardAlwaysInlineRule.java index 524afd200..ab8342df6 100644 --- a/src/main/java/com/android/tools/r8/shaking/ProguardAlwaysInlineRule.java +++ b/src/main/java/com/android/tools/r8/shaking/ProguardAlwaysInlineRule.java @@ -3,7 +3,6 @@ // BSD-style license that can be found in the LICENSE file. package com.android.tools.r8.shaking; -import com.android.tools.r8.graph.DexAccessFlags; import java.util.Set; public class ProguardAlwaysInlineRule extends ProguardConfigurationRule { @@ -22,8 +21,8 @@ public class ProguardAlwaysInlineRule extends ProguardConfigurationRule { private ProguardAlwaysInlineRule( ProguardTypeMatcher classAnnotation, - DexAccessFlags classAccessFlags, - DexAccessFlags negatedClassAccessFlags, + ProguardAccessFlags classAccessFlags, + ProguardAccessFlags negatedClassAccessFlags, boolean classTypeNegated, ProguardClassType classType, ProguardClassNameList classNames, diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardAssumeNoSideEffectRule.java b/src/main/java/com/android/tools/r8/shaking/ProguardAssumeNoSideEffectRule.java index a01dd897b..736c7789b 100644 --- a/src/main/java/com/android/tools/r8/shaking/ProguardAssumeNoSideEffectRule.java +++ b/src/main/java/com/android/tools/r8/shaking/ProguardAssumeNoSideEffectRule.java @@ -3,7 +3,6 @@ // BSD-style license that can be found in the LICENSE file. package com.android.tools.r8.shaking; -import com.android.tools.r8.graph.DexAccessFlags; import java.util.Set; public class ProguardAssumeNoSideEffectRule extends ProguardConfigurationRule { @@ -21,8 +20,8 @@ public class ProguardAssumeNoSideEffectRule extends ProguardConfigurationRule { private ProguardAssumeNoSideEffectRule( ProguardTypeMatcher classAnnotation, - DexAccessFlags classAccessFlags, - DexAccessFlags negatedClassAccessFlags, + ProguardAccessFlags classAccessFlags, + ProguardAccessFlags negatedClassAccessFlags, boolean classTypeNegated, ProguardClassType classType, ProguardClassNameList classNames, diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardAssumeValuesRule.java b/src/main/java/com/android/tools/r8/shaking/ProguardAssumeValuesRule.java index 94cf7588f..97cb5c383 100644 --- a/src/main/java/com/android/tools/r8/shaking/ProguardAssumeValuesRule.java +++ b/src/main/java/com/android/tools/r8/shaking/ProguardAssumeValuesRule.java @@ -3,7 +3,6 @@ // BSD-style license that can be found in the LICENSE file. package com.android.tools.r8.shaking; -import com.android.tools.r8.graph.DexAccessFlags; import java.util.Set; public class ProguardAssumeValuesRule extends ProguardConfigurationRule { @@ -20,8 +19,8 @@ public class ProguardAssumeValuesRule extends ProguardConfigurationRule { private ProguardAssumeValuesRule( ProguardTypeMatcher classAnnotation, - DexAccessFlags classAccessFlags, - DexAccessFlags negatedClassAccessFlags, + ProguardAccessFlags classAccessFlags, + ProguardAccessFlags negatedClassAccessFlags, boolean classTypeNegated, ProguardClassType classType, ProguardClassNameList classNames, diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardCheckDiscardRule.java b/src/main/java/com/android/tools/r8/shaking/ProguardCheckDiscardRule.java index 7f69e18bc..da5bb2653 100644 --- a/src/main/java/com/android/tools/r8/shaking/ProguardCheckDiscardRule.java +++ b/src/main/java/com/android/tools/r8/shaking/ProguardCheckDiscardRule.java @@ -3,7 +3,6 @@ // BSD-style license that can be found in the LICENSE file. package com.android.tools.r8.shaking; -import com.android.tools.r8.graph.DexAccessFlags; import java.util.Set; public class ProguardCheckDiscardRule extends ProguardConfigurationRule { @@ -22,8 +21,8 @@ public class ProguardCheckDiscardRule extends ProguardConfigurationRule { private ProguardCheckDiscardRule( ProguardTypeMatcher classAnnotation, - DexAccessFlags classAccessFlags, - DexAccessFlags negatedClassAccessFlags, + ProguardAccessFlags classAccessFlags, + ProguardAccessFlags negatedClassAccessFlags, boolean classTypeNegated, ProguardClassType classType, ProguardClassNameList classNames, diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardClassSpecification.java b/src/main/java/com/android/tools/r8/shaking/ProguardClassSpecification.java index b8006d321..8e981a73e 100644 --- a/src/main/java/com/android/tools/r8/shaking/ProguardClassSpecification.java +++ b/src/main/java/com/android/tools/r8/shaking/ProguardClassSpecification.java @@ -3,7 +3,6 @@ // BSD-style license that can be found in the LICENSE file. package com.android.tools.r8.shaking; -import com.android.tools.r8.graph.DexAccessFlags; import com.android.tools.r8.utils.StringUtils; import java.util.Collections; import java.util.LinkedHashSet; @@ -15,8 +14,8 @@ public abstract class ProguardClassSpecification { public static class Builder { protected ProguardTypeMatcher classAnnotation; - protected DexAccessFlags classAccessFlags = new DexAccessFlags(0); - protected DexAccessFlags negatedClassAccessFlags = new DexAccessFlags(0); + protected ProguardAccessFlags classAccessFlags = new ProguardAccessFlags(); + protected ProguardAccessFlags negatedClassAccessFlags = new ProguardAccessFlags(); protected boolean classTypeNegated = false; protected ProguardClassType classType; protected ProguardClassNameList classNames; @@ -88,19 +87,19 @@ public abstract class ProguardClassSpecification { this.classTypeNegated = classTypeNegated; } - public DexAccessFlags getClassAccessFlags() { + public ProguardAccessFlags getClassAccessFlags() { return classAccessFlags; } - public void setClassAccessFlags(DexAccessFlags flags) { + public void setClassAccessFlags(ProguardAccessFlags flags) { classAccessFlags = flags; } - public DexAccessFlags getNegatedClassAccessFlags() { + public ProguardAccessFlags getNegatedClassAccessFlags() { return negatedClassAccessFlags; } - public void setNegatedClassAccessFlags(DexAccessFlags flags) { + public void setNegatedClassAccessFlags(ProguardAccessFlags flags) { negatedClassAccessFlags = flags; } @@ -119,8 +118,8 @@ public abstract class ProguardClassSpecification { } private final ProguardTypeMatcher classAnnotation; - private final DexAccessFlags classAccessFlags; - private final DexAccessFlags negatedClassAccessFlags; + private final ProguardAccessFlags classAccessFlags; + private final ProguardAccessFlags negatedClassAccessFlags; private final boolean classTypeNegated; private final ProguardClassType classType; private final ProguardClassNameList classNames; @@ -131,8 +130,8 @@ public abstract class ProguardClassSpecification { protected ProguardClassSpecification( ProguardTypeMatcher classAnnotation, - DexAccessFlags classAccessFlags, - DexAccessFlags negatedClassAccessFlags, + ProguardAccessFlags classAccessFlags, + ProguardAccessFlags negatedClassAccessFlags, boolean classTypeNegated, ProguardClassType classType, ProguardClassNameList classNames, @@ -184,11 +183,11 @@ public abstract class ProguardClassSpecification { return classTypeNegated; } - public DexAccessFlags getClassAccessFlags() { + public ProguardAccessFlags getClassAccessFlags() { return classAccessFlags; } - public DexAccessFlags getNegatedClassAccessFlags() { + public ProguardAccessFlags getNegatedClassAccessFlags() { return negatedClassAccessFlags; } diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java index d24a3578f..7997b4425 100644 --- a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java +++ b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java @@ -6,7 +6,6 @@ package com.android.tools.r8.shaking; import com.android.tools.r8.CompilationException; import com.android.tools.r8.DiagnosticsHandler; import com.android.tools.r8.dex.Constants; -import com.android.tools.r8.graph.DexAccessFlags; import com.android.tools.r8.graph.DexField; import com.android.tools.r8.graph.DexItemFactory; import com.android.tools.r8.graph.DexString; @@ -561,9 +560,10 @@ public class ProguardConfigurationParser { assert builder.getClassAnnotation() == null; builder.setClassAnnotation(annotation); } else { - DexAccessFlags flags = - parseNegation() ? builder.getNegatedClassAccessFlags() : - builder.getClassAccessFlags(); + ProguardAccessFlags flags = + parseNegation() + ? builder.getNegatedClassAccessFlags() + : builder.getClassAccessFlags(); skipWhitespace(); if (acceptString("public")) { flags.setPublic(); @@ -636,7 +636,7 @@ public class ProguardConfigurationParser { boolean found = true; while (found && !eof()) { found = false; - DexAccessFlags flags = + ProguardAccessFlags flags = parseNegation() ? ruleBuilder.getNegatedAccessFlags() : ruleBuilder.getAccessFlags(); skipWhitespace(); switch (peekChar()) { diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationRule.java b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationRule.java index 1021f6744..223307cfa 100644 --- a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationRule.java +++ b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationRule.java @@ -3,15 +3,14 @@ // BSD-style license that can be found in the LICENSE file. package com.android.tools.r8.shaking; -import com.android.tools.r8.graph.DexAccessFlags; import com.android.tools.r8.utils.StringUtils; import java.util.Set; public abstract class ProguardConfigurationRule extends ProguardClassSpecification { ProguardConfigurationRule( ProguardTypeMatcher classAnnotation, - DexAccessFlags classAccessFlags, - DexAccessFlags negatedClassAccessFlags, + ProguardAccessFlags classAccessFlags, + ProguardAccessFlags negatedClassAccessFlags, boolean classTypeNegated, ProguardClassType classType, ProguardClassNameList classNames, diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardIdentifierNameStringRule.java b/src/main/java/com/android/tools/r8/shaking/ProguardIdentifierNameStringRule.java index 6cfd15449..e006bd444 100644 --- a/src/main/java/com/android/tools/r8/shaking/ProguardIdentifierNameStringRule.java +++ b/src/main/java/com/android/tools/r8/shaking/ProguardIdentifierNameStringRule.java @@ -3,7 +3,6 @@ // BSD-style license that can be found in the LICENSE file. package com.android.tools.r8.shaking; -import com.android.tools.r8.graph.DexAccessFlags; import java.util.Set; public class ProguardIdentifierNameStringRule extends ProguardConfigurationRule { @@ -21,8 +20,8 @@ public class ProguardIdentifierNameStringRule extends ProguardConfigurationRule private ProguardIdentifierNameStringRule( ProguardTypeMatcher classAnnotation, - DexAccessFlags classAccessFlags, - DexAccessFlags negatedClassAccessFlags, + ProguardAccessFlags classAccessFlags, + ProguardAccessFlags negatedClassAccessFlags, boolean classTypeNegated, ProguardClassType classType, ProguardClassNameList classNames, diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardKeepPackageNamesRule.java b/src/main/java/com/android/tools/r8/shaking/ProguardKeepPackageNamesRule.java index f6db32686..c4731c625 100644 --- a/src/main/java/com/android/tools/r8/shaking/ProguardKeepPackageNamesRule.java +++ b/src/main/java/com/android/tools/r8/shaking/ProguardKeepPackageNamesRule.java @@ -3,7 +3,6 @@ // BSD-style license that can be found in the LICENSE file. package com.android.tools.r8.shaking; -import com.android.tools.r8.graph.DexAccessFlags; import java.util.Set; public class ProguardKeepPackageNamesRule extends ProguardConfigurationRule { @@ -22,8 +21,8 @@ public class ProguardKeepPackageNamesRule extends ProguardConfigurationRule { private ProguardKeepPackageNamesRule( ProguardTypeMatcher classAnnotation, - DexAccessFlags classAccessFlags, - DexAccessFlags negatedClassAccessFlags, + ProguardAccessFlags classAccessFlags, + ProguardAccessFlags negatedClassAccessFlags, boolean classTypeNegated, ProguardClassType classType, ProguardClassNameList classNames, diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardKeepRule.java b/src/main/java/com/android/tools/r8/shaking/ProguardKeepRule.java index 59acd461d..7edceed23 100644 --- a/src/main/java/com/android/tools/r8/shaking/ProguardKeepRule.java +++ b/src/main/java/com/android/tools/r8/shaking/ProguardKeepRule.java @@ -3,7 +3,6 @@ // BSD-style license that can be found in the LICENSE file. package com.android.tools.r8.shaking; -import com.android.tools.r8.graph.DexAccessFlags; import java.util.Set; public class ProguardKeepRule extends ProguardConfigurationRule { @@ -36,8 +35,8 @@ public class ProguardKeepRule extends ProguardConfigurationRule { private ProguardKeepRule( ProguardTypeMatcher classAnnotation, - DexAccessFlags classAccessFlags, - DexAccessFlags negatedClassAccessFlags, + ProguardAccessFlags classAccessFlags, + ProguardAccessFlags negatedClassAccessFlags, boolean classTypeNegated, ProguardClassType classType, ProguardClassNameList classNames, diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardMemberRule.java b/src/main/java/com/android/tools/r8/shaking/ProguardMemberRule.java index 121641b69..5fb5cb2aa 100644 --- a/src/main/java/com/android/tools/r8/shaking/ProguardMemberRule.java +++ b/src/main/java/com/android/tools/r8/shaking/ProguardMemberRule.java @@ -4,7 +4,6 @@ package com.android.tools.r8.shaking; import com.android.tools.r8.errors.Unreachable; -import com.android.tools.r8.graph.DexAccessFlags; import com.android.tools.r8.graph.DexEncodedField; import com.android.tools.r8.graph.DexEncodedMethod; import com.android.tools.r8.graph.DexType; @@ -17,8 +16,8 @@ public class ProguardMemberRule { public static class Builder { private ProguardTypeMatcher annotation; - private DexAccessFlags accessFlags = new DexAccessFlags(0); - private DexAccessFlags negatedAccessFlags = new DexAccessFlags(0); + private ProguardAccessFlags accessFlags = new ProguardAccessFlags(); + private ProguardAccessFlags negatedAccessFlags = new ProguardAccessFlags(); private ProguardMemberType ruleType; private ProguardNameMatcher name; private ProguardTypeMatcher type; @@ -31,19 +30,19 @@ public class ProguardMemberRule { this.annotation = annotation; } - public DexAccessFlags getAccessFlags() { + public ProguardAccessFlags getAccessFlags() { return accessFlags; } - public void setAccessFlags(DexAccessFlags flags) { + public void setAccessFlags(ProguardAccessFlags flags) { accessFlags = flags; } - public DexAccessFlags getNegatedAccessFlags() { + public ProguardAccessFlags getNegatedAccessFlags() { return negatedAccessFlags; } - public void setNegatedAccessFlags(DexAccessFlags flags) { + public void setNegatedAccessFlags(ProguardAccessFlags flags) { negatedAccessFlags = flags; } @@ -83,8 +82,8 @@ public class ProguardMemberRule { } private final ProguardTypeMatcher annotation; - private final DexAccessFlags accessFlags; - private final DexAccessFlags negatedAccessFlags; + private final ProguardAccessFlags accessFlags; + private final ProguardAccessFlags negatedAccessFlags; private final ProguardMemberType ruleType; private final ProguardNameMatcher name; private final ProguardTypeMatcher type; @@ -93,8 +92,8 @@ public class ProguardMemberRule { private ProguardMemberRule( ProguardTypeMatcher annotation, - DexAccessFlags accessFlags, - DexAccessFlags negatedAccessFlags, + ProguardAccessFlags accessFlags, + ProguardAccessFlags negatedAccessFlags, ProguardMemberType ruleType, ProguardNameMatcher name, ProguardTypeMatcher type, @@ -121,11 +120,11 @@ public class ProguardMemberRule { return annotation; } - public DexAccessFlags getAccessFlags() { + public ProguardAccessFlags getAccessFlags() { return accessFlags; } - public DexAccessFlags getNegatedAccessFlags() { + public ProguardAccessFlags getNegatedAccessFlags() { return negatedAccessFlags; } @@ -162,8 +161,8 @@ public class ProguardMemberRule { case ALL: case ALL_FIELDS: // Access flags check. - if (!field.accessFlags.containsAllOf(getAccessFlags()) || - !field.accessFlags.containsNoneOf(getNegatedAccessFlags())) { + if (!getAccessFlags().containsAll(field.accessFlags) + || !getNegatedAccessFlags().containsNone(field.accessFlags)) { break; } // Annotations check. @@ -175,8 +174,8 @@ public class ProguardMemberRule { break; } // Access flags check. - if (!(field.accessFlags.containsAllOf(getAccessFlags()) && - field.accessFlags.containsNoneOf(getNegatedAccessFlags()))) { + if (!getAccessFlags().containsAll(field.accessFlags) + || !getNegatedAccessFlags().containsNone(field.accessFlags)) { break; } // Type check. @@ -206,8 +205,8 @@ public class ProguardMemberRule { // Fall through for all other methods. case ALL: // Access flags check. - if (!method.accessFlags.containsAllOf(getAccessFlags()) || - !method.accessFlags.containsNoneOf(getNegatedAccessFlags())) { + if (!getAccessFlags().containsAll(method.accessFlags) + || !getNegatedAccessFlags().containsNone(method.accessFlags)) { break; } // Annotations check. @@ -226,8 +225,8 @@ public class ProguardMemberRule { break; } // Access flags check. - if (!(method.accessFlags.containsAllOf(getAccessFlags()) && - method.accessFlags.containsNoneOf(getNegatedAccessFlags()))) { + if (!getAccessFlags().containsAll(method.accessFlags) + || !getNegatedAccessFlags().containsNone(method.accessFlags)) { break; } // Annotations check. diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardWhyAreYouKeepingRule.java b/src/main/java/com/android/tools/r8/shaking/ProguardWhyAreYouKeepingRule.java index e029b77fe..ef839265d 100644 --- a/src/main/java/com/android/tools/r8/shaking/ProguardWhyAreYouKeepingRule.java +++ b/src/main/java/com/android/tools/r8/shaking/ProguardWhyAreYouKeepingRule.java @@ -3,7 +3,6 @@ // BSD-style license that can be found in the LICENSE file. package com.android.tools.r8.shaking; -import com.android.tools.r8.graph.DexAccessFlags; import java.util.Set; public class ProguardWhyAreYouKeepingRule extends ProguardConfigurationRule { @@ -22,8 +21,8 @@ public class ProguardWhyAreYouKeepingRule extends ProguardConfigurationRule { private ProguardWhyAreYouKeepingRule( ProguardTypeMatcher classAnnotation, - DexAccessFlags classAccessFlags, - DexAccessFlags negatedClassAccessFlags, + ProguardAccessFlags classAccessFlags, + ProguardAccessFlags negatedClassAccessFlags, boolean classTypeNegated, ProguardClassType classType, ProguardClassNameList classNames, diff --git a/src/main/java/com/android/tools/r8/shaking/ReasonPrinter.java b/src/main/java/com/android/tools/r8/shaking/ReasonPrinter.java index 47893e563..604cf5109 100644 --- a/src/main/java/com/android/tools/r8/shaking/ReasonPrinter.java +++ b/src/main/java/com/android/tools/r8/shaking/ReasonPrinter.java @@ -112,11 +112,7 @@ public class ReasonPrinter { private void printReasonFor(DexEncodedField item) { KeepReason reason = liveFields.get(item); if (reason == null) { - if (item.accessFlags.isAbstract()) { - printOnlyAbstractShell(item, formatter); - } else { - printNoIdeaWhy(item.field, formatter); - } + printNoIdeaWhy(item.field, formatter); } else { formatter.startItem(item.field); formatter.pushIsLivePrefix(); diff --git a/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java b/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java index 177493adc..bb8c08a08 100644 --- a/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java +++ b/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java @@ -117,10 +117,10 @@ public class RootSetBuilder { // Process a class with the keep rule. private void process(DexClass clazz, ProguardConfigurationRule rule) { - if (!clazz.accessFlags.containsAllOf(rule.getClassAccessFlags())) { + if (!rule.getClassAccessFlags().containsAll(clazz.accessFlags)) { return; } - if (!clazz.accessFlags.containsNoneOf(rule.getNegatedClassAccessFlags())) { + if (!rule.getNegatedClassAccessFlags().containsNone(clazz.accessFlags)) { return; } if (!containsAnnotation(rule.getClassAnnotation(), clazz.annotations)) { diff --git a/src/test/java/com/android/tools/r8/dex/JumboStringProcessing.java b/src/test/java/com/android/tools/r8/dex/JumboStringProcessing.java index 98f107102..e3e9ea0e3 100644 --- a/src/test/java/com/android/tools/r8/dex/JumboStringProcessing.java +++ b/src/test/java/com/android/tools/r8/dex/JumboStringProcessing.java @@ -12,12 +12,12 @@ import com.android.tools.r8.code.IfNe; import com.android.tools.r8.code.IfNez; import com.android.tools.r8.code.Instruction; import com.android.tools.r8.code.ReturnVoid; -import com.android.tools.r8.graph.DexAccessFlags; import com.android.tools.r8.graph.DexCode; import com.android.tools.r8.graph.DexCode.Try; import com.android.tools.r8.graph.DexEncodedMethod; import com.android.tools.r8.graph.DexItemFactory; import com.android.tools.r8.graph.DexString; +import com.android.tools.r8.graph.MethodAccessFlags; import com.android.tools.r8.naming.NamingLens; import java.util.ArrayList; import java.util.List; @@ -99,8 +99,7 @@ public class JumboStringProcessing { null, null, null); - DexAccessFlags flags = new DexAccessFlags(0); - flags.setPublic(); + MethodAccessFlags flags = MethodAccessFlags.fromSharedAccessFlags(Constants.ACC_PUBLIC, false); DexEncodedMethod method = new DexEncodedMethod(null, flags, null, null, code); new JumboStringRewriter(method, string, factory).rewrite(); return method.getCode().asDexCode(); diff --git a/src/test/java/com/android/tools/r8/dex/SharedClassWritingTest.java b/src/test/java/com/android/tools/r8/dex/SharedClassWritingTest.java index add8637e1..e0d97b189 100644 --- a/src/test/java/com/android/tools/r8/dex/SharedClassWritingTest.java +++ b/src/test/java/com/android/tools/r8/dex/SharedClassWritingTest.java @@ -8,7 +8,7 @@ import com.android.tools.r8.code.Instruction; import com.android.tools.r8.code.ReturnVoid; import com.android.tools.r8.errors.DexOverflowException; import com.android.tools.r8.errors.Unreachable; -import com.android.tools.r8.graph.DexAccessFlags; +import com.android.tools.r8.graph.ClassAccessFlags; import com.android.tools.r8.graph.DexAnnotationSet; import com.android.tools.r8.graph.DexAnnotationSetRefList; import com.android.tools.r8.graph.DexApplication; @@ -23,6 +23,7 @@ import com.android.tools.r8.graph.DexString; import com.android.tools.r8.graph.DexType; import com.android.tools.r8.graph.DexTypeList; import com.android.tools.r8.graph.DirectMappedDexApplication; +import com.android.tools.r8.graph.MethodAccessFlags; import com.android.tools.r8.naming.NamingLens; import com.android.tools.r8.utils.DescriptorUtils; import com.android.tools.r8.utils.IgnoreContentsOutputSink; @@ -72,10 +73,13 @@ public class SharedClassWritingTest { instructions[stringCount] = new ReturnVoid(); DexCode code = new DexCode(1, 0, 0, instructions, new Try[0], new TryHandler[0], null, strings[startOffset + stringCount - 1]); - return new DexEncodedMethod(dexItemFactory - .createMethod(holder, dexItemFactory.createProto(dexItemFactory.voidType), "theMethod"), - new DexAccessFlags(Constants.ACC_PUBLIC), DexAnnotationSet.empty(), - DexAnnotationSetRefList.empty(), code); + return new DexEncodedMethod( + dexItemFactory.createMethod( + holder, dexItemFactory.createProto(dexItemFactory.voidType), "theMethod"), + MethodAccessFlags.fromSharedAccessFlags(Constants.ACC_PUBLIC, false), + DexAnnotationSet.empty(), + DexAnnotationSetRefList.empty(), + code); } private DexProgramClass makeClass(String name, int stringCount, int startOffset, @@ -86,7 +90,7 @@ public class SharedClassWritingTest { type, null, null, - new DexAccessFlags(Constants.ACC_PUBLIC), + ClassAccessFlags.fromSharedAccessFlags(Constants.ACC_PUBLIC), dexItemFactory.objectType, DexTypeList.empty(), null, @@ -94,7 +98,7 @@ public class SharedClassWritingTest { DexEncodedField.EMPTY_ARRAY, DexEncodedField.EMPTY_ARRAY, DexEncodedMethod.EMPTY_ARRAY, - new DexEncodedMethod[]{makeMethod(type, stringCount, startOffset)}, + new DexEncodedMethod[] {makeMethod(type, stringCount, startOffset)}, synthesizedFrom); } diff --git a/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java b/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java index a358e26fc..29299960d 100644 --- a/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java +++ b/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java @@ -21,10 +21,9 @@ import com.android.tools.r8.dex.Constants; import com.android.tools.r8.errors.CompilationError; import com.android.tools.r8.errors.DexOverflowException; import com.android.tools.r8.errors.Unreachable; -import com.android.tools.r8.graph.AppInfoWithSubtyping; +import com.android.tools.r8.graph.ClassAccessFlags; import com.android.tools.r8.graph.Code; import com.android.tools.r8.graph.DebugLocalInfo; -import com.android.tools.r8.graph.DexAccessFlags; import com.android.tools.r8.graph.DexAnnotationSet; import com.android.tools.r8.graph.DexAnnotationSetRefList; import com.android.tools.r8.graph.DexApplication; @@ -36,6 +35,7 @@ import com.android.tools.r8.graph.DexString; import com.android.tools.r8.graph.DexType; import com.android.tools.r8.graph.DexTypeList; import com.android.tools.r8.graph.DirectMappedDexApplication; +import com.android.tools.r8.graph.MethodAccessFlags; import com.android.tools.r8.ir.code.CatchHandlers; import com.android.tools.r8.ir.code.IRCode; import com.android.tools.r8.ir.code.Position; @@ -577,7 +577,7 @@ public class MainDexListTests extends TestBase { DexType type = factory.createType(desc); DexEncodedMethod[] directMethods = new DexEncodedMethod[methodCount]; for (int i = 0; i < methodCount; i++) { - DexAccessFlags access = new DexAccessFlags(); + MethodAccessFlags access = MethodAccessFlags.fromSharedAccessFlags(0, false); access.setPublic(); access.setStatic(); Code code = new SynthesizedCode(new ReturnVoidCode()); @@ -602,7 +602,7 @@ public class MainDexListTests extends TestBase { type, null, null, - new DexAccessFlags(), + ClassAccessFlags.fromSharedAccessFlags(0), factory.objectType, DexTypeList.empty(), null, diff --git a/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java b/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java index 6dc19aa5a..d119423d8 100644 --- a/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java +++ b/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java @@ -14,8 +14,10 @@ import static org.junit.Assert.fail; import com.android.tools.r8.DiagnosticsHandler; import com.android.tools.r8.TestBase; import com.android.tools.r8.ToolHelper; -import com.android.tools.r8.graph.DexAccessFlags; +import com.android.tools.r8.graph.ClassAccessFlags; import com.android.tools.r8.graph.DexItemFactory; +import com.android.tools.r8.graph.FieldAccessFlags; +import com.android.tools.r8.graph.MethodAccessFlags; import com.android.tools.r8.utils.DefaultDiagnosticsHandler; import com.android.tools.r8.utils.FileUtils; import com.android.tools.r8.utils.InternalOptions.PackageObfuscationMode; @@ -224,33 +226,39 @@ public class ProguardConfigurationParserTest extends TestBase { List<ProguardConfigurationRule> rules = parser.getConfig().getRules(); assertEquals(1, rules.size()); ProguardConfigurationRule rule = rules.get(0); - DexAccessFlags publicAndFinalFlags = new DexAccessFlags(0); + ClassAccessFlags publicAndFinalFlags = ClassAccessFlags.fromSharedAccessFlags(0); publicAndFinalFlags.setPublic(); publicAndFinalFlags.setFinal(); - assertTrue(rule.getClassAccessFlags().containsNoneOf(publicAndFinalFlags)); - assertTrue(rule.getNegatedClassAccessFlags().containsAllOf(publicAndFinalFlags)); - DexAccessFlags abstractFlags = new DexAccessFlags(0); + assertTrue(rule.getClassAccessFlags().containsNone(publicAndFinalFlags)); + assertTrue(rule.getNegatedClassAccessFlags().containsAll(publicAndFinalFlags)); + ClassAccessFlags abstractFlags = ClassAccessFlags.fromSharedAccessFlags(0); abstractFlags.setAbstract(); - assertTrue(rule.getClassAccessFlags().containsAllOf(abstractFlags)); - assertTrue(rule.getNegatedClassAccessFlags().containsNoneOf(abstractFlags)); + assertTrue(rule.getClassAccessFlags().containsAll(abstractFlags)); + assertTrue(rule.getNegatedClassAccessFlags().containsNone(abstractFlags)); for (ProguardMemberRule member : rule.getMemberRules()) { if (member.getRuleType() == ProguardMemberType.ALL_FIELDS) { - DexAccessFlags publicFlags = new DexAccessFlags(0); - publicAndFinalFlags.setPublic(); - assertTrue(member.getAccessFlags().containsAllOf(publicFlags)); - assertTrue(member.getNegatedAccessFlags().containsNoneOf(publicFlags)); - DexAccessFlags staticFlags = new DexAccessFlags(0); + FieldAccessFlags publicFlags = FieldAccessFlags.fromSharedAccessFlags(0); + publicFlags.setPublic(); + assertTrue(member.getAccessFlags().containsAll(publicFlags)); + assertTrue(member.getNegatedAccessFlags().containsNone(publicFlags)); + FieldAccessFlags staticFlags = FieldAccessFlags.fromSharedAccessFlags(0); staticFlags.setStatic(); - assertTrue(member.getAccessFlags().containsNoneOf(staticFlags)); - assertTrue(member.getNegatedAccessFlags().containsAllOf(staticFlags)); + assertTrue(member.getAccessFlags().containsNone(staticFlags)); + assertTrue(member.getNegatedAccessFlags().containsAll(staticFlags)); } else { assertTrue(member.getRuleType() == ProguardMemberType.ALL_METHODS); - DexAccessFlags publicProtectedVolatileFlags = new DexAccessFlags(0); - publicProtectedVolatileFlags.setPublic(); - publicProtectedVolatileFlags.setProtected(); - publicProtectedVolatileFlags.setVolatile(); - assertTrue(member.getAccessFlags().containsNoneOf(publicProtectedVolatileFlags)); - assertTrue(member.getNegatedAccessFlags().containsAllOf(publicProtectedVolatileFlags)); + + MethodAccessFlags publicNativeFlags = MethodAccessFlags.fromSharedAccessFlags(0, false); + publicNativeFlags.setPublic(); + publicNativeFlags.setNative(); + assertTrue(member.getAccessFlags().containsAll(publicNativeFlags)); + assertFalse(member.getNegatedAccessFlags().containsNone(publicNativeFlags)); + + MethodAccessFlags protectedNativeFlags = MethodAccessFlags.fromSharedAccessFlags(0, false); + protectedNativeFlags.setProtected(); + protectedNativeFlags.setNative(); + assertTrue(member.getAccessFlags().containsAll(protectedNativeFlags)); + assertFalse(member.getNegatedAccessFlags().containsNone(protectedNativeFlags)); } } } diff --git a/src/test/java/com/android/tools/r8/shaking/TreeShakingTest.java b/src/test/java/com/android/tools/r8/shaking/TreeShakingTest.java index b285ac060..32cfb1493 100644 --- a/src/test/java/com/android/tools/r8/shaking/TreeShakingTest.java +++ b/src/test/java/com/android/tools/r8/shaking/TreeShakingTest.java @@ -9,8 +9,6 @@ import com.android.tools.r8.CompilationException; import com.android.tools.r8.R8Command; import com.android.tools.r8.ToolHelper; import com.android.tools.r8.ToolHelper.ArtCommandBuilder; -import com.android.tools.r8.dex.Constants; -import com.android.tools.r8.graph.DexAccessFlags; import com.android.tools.r8.naming.MemberNaming.FieldSignature; import com.android.tools.r8.naming.MemberNaming.MethodSignature; import com.android.tools.r8.utils.AndroidApp; @@ -196,14 +194,13 @@ public class TreeShakingTest { private static void hasNoPrivateMethods(DexInspector inspector) { inspector.forAllClasses(clazz -> clazz.forAllMethods( - method -> Assert.assertTrue(method.hasNone(new DexAccessFlags(Constants.ACC_PRIVATE))) - )); + method -> Assert.assertTrue(!method.getMethod().accessFlags.isPrivate()))); } private static void hasNoPublicMethodsButPrivate(DexInspector inspector) { inspector.forAllClasses(clazz -> clazz.forAllMethods(method -> { if (!method.isStatic() && !method.isFinal()) { - Assert.assertTrue(method.hasNone(new DexAccessFlags(Constants.ACC_PUBLIC))); + Assert.assertTrue(!method.getMethod().accessFlags.isPublic()); } })); Assert.assertTrue(inspector.clazz("shaking6.Superclass") @@ -255,7 +252,7 @@ public class TreeShakingTest { private static void shaking7HasOnlyPublicFields(DexInspector inspector) { inspector.forAllClasses(clazz -> { clazz.forAllFields(field -> { - Assert.assertTrue(field.hasAll(new DexAccessFlags(Constants.ACC_PUBLIC))); + Assert.assertTrue(field.getField().accessFlags.isPublic()); }); }); ClassSubject subclass = inspector.clazz("shaking7.Subclass"); @@ -283,7 +280,7 @@ public class TreeShakingTest { private static void shaking7HasOnlyPublicFieldsNamedTheDoubleField(DexInspector inspector) { inspector.forAllClasses(clazz -> { clazz.forAllFields(field -> { - Assert.assertTrue(field.hasAll(new DexAccessFlags(Constants.ACC_PUBLIC))); + Assert.assertTrue(field.getField().accessFlags.isPublic()); }); }); ClassSubject subclass = inspector.clazz("shaking7.Subclass"); @@ -297,7 +294,7 @@ public class TreeShakingTest { private static void shaking7HasOnlyPublicFieldsNamedTheIntField(DexInspector inspector) { inspector.forAllClasses(clazz -> { clazz.forAllFields(field -> { - Assert.assertTrue(field.hasAll(new DexAccessFlags(Constants.ACC_PUBLIC))); + Assert.assertTrue(field.getField().accessFlags.isPublic()); }); }); ClassSubject subclass = inspector.clazz("shaking7.Subclass"); diff --git a/src/test/java/com/android/tools/r8/utils/DexInspector.java b/src/test/java/com/android/tools/r8/utils/DexInspector.java index 612043efe..e70f6f7f6 100644 --- a/src/test/java/com/android/tools/r8/utils/DexInspector.java +++ b/src/test/java/com/android/tools/r8/utils/DexInspector.java @@ -43,7 +43,6 @@ import com.android.tools.r8.code.SputObject; import com.android.tools.r8.code.SputShort; import com.android.tools.r8.code.SputWide; import com.android.tools.r8.dex.ApplicationReader; -import com.android.tools.r8.graph.DexAccessFlags; import com.android.tools.r8.graph.DexAnnotation; import com.android.tools.r8.graph.DexApplication; import com.android.tools.r8.graph.DexClass; @@ -503,10 +502,6 @@ public class DexInspector { public abstract class MemberSubject extends Subject { - public abstract boolean hasAll(DexAccessFlags flags); - - public abstract boolean hasNone(DexAccessFlags flags); - public abstract boolean isStatic(); public abstract boolean isFinal(); @@ -551,16 +546,6 @@ public class DexInspector { } @Override - public boolean hasAll(DexAccessFlags flags) { - return false; - } - - @Override - public boolean hasNone(DexAccessFlags flags) { - return true; - } - - @Override public boolean isStatic() { return false; } @@ -622,16 +607,6 @@ public class DexInspector { } @Override - public boolean hasAll(DexAccessFlags flags) { - return dexMethod.accessFlags.containsAllOf(flags); - } - - @Override - public boolean hasNone(DexAccessFlags flags) { - return dexMethod.accessFlags.containsNoneOf(flags); - } - - @Override public boolean isStatic() { return dexMethod.accessFlags.isStatic(); } @@ -704,16 +679,6 @@ public class DexInspector { public class AbsentFieldSubject extends FieldSubject { @Override - public boolean hasAll(DexAccessFlags flags) { - return false; - } - - @Override - public boolean hasNone(DexAccessFlags flags) { - return true; - } - - @Override public boolean isStatic() { return false; } @@ -770,16 +735,6 @@ public class DexInspector { } @Override - public boolean hasAll(DexAccessFlags flags) { - return dexField.accessFlags.containsAllOf(flags); - } - - @Override - public boolean hasNone(DexAccessFlags flags) { - return dexField.accessFlags.containsNoneOf(flags); - } - - @Override public boolean isStatic() { return dexField.accessFlags.isStatic(); } diff --git a/src/test/proguard/valid/access-flags.flags b/src/test/proguard/valid/access-flags.flags index 8096b5903..8d47c33c4 100644 --- a/src/test/proguard/valid/access-flags.flags +++ b/src/test/proguard/valid/access-flags.flags @@ -1,4 +1,4 @@ -keep !public abstract !final @com.company.Something class * { public !static <fields>; - !public !protected ! volatile <methods>; + !public !protected ! native <methods>; }
\ No newline at end of file |