blob: 4a5c689c88d3873c5063eec02fa44dcc612d578a [file] [log] [blame]
// 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<MethodAccessFlags> {
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) {
this(flags, flags);
}
private MethodAccessFlags(int originalFlags, int modifiedFlags) {
super(originalFlags, modifiedFlags);
}
public static Builder builder() {
return new Builder();
}
@Override
public MethodAccessFlags copy() {
return new MethodAccessFlags(originalFlags, modifiedFlags);
}
@Override
public MethodAccessFlags self() {
return this;
}
public static MethodAccessFlags createPublicStaticSynthetic() {
return fromSharedAccessFlags(
Constants.ACC_PUBLIC | Constants.ACC_STATIC | Constants.ACC_SYNTHETIC, false);
}
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 getAsCfAccessFlags() {
return materialize() & ~Constants.ACC_CONSTRUCTOR;
}
@Override
public int getAsDexAccessFlags() {
MethodAccessFlags copy = copy();
if (copy.isSynchronized() && !copy.isNative()) {
copy.unsetSynchronized();
copy.setDeclaredSynchronized();
}
return copy.materialize();
}
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 void demoteFromBridge() {
demote(Constants.ACC_BRIDGE);
}
public boolean isVarargs() {
return isSet(Constants.ACC_VARARGS);
}
public void setVarargs() {
set(Constants.ACC_VARARGS);
}
public void unsetVarargs() {
unset(Constants.ACC_VARARGS);
}
public boolean isNative() {
return isSet(Constants.ACC_NATIVE);
}
public void setNative() {
set(Constants.ACC_NATIVE);
}
public void unsetNative() {
unset(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 void unsetStrict() {
unset(Constants.ACC_STRICT);
}
public boolean isConstructor() {
return isSet(Constants.ACC_CONSTRUCTOR);
}
public void setConstructor() {
set(Constants.ACC_CONSTRUCTOR);
}
public void setConstructor(DexMethod method, DexItemFactory dexItemFactory) {
if (dexItemFactory.isConstructor(method) || dexItemFactory.isClassConstructor(method)) {
setConstructor();
}
}
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);
}
public void unsetDeclaredSynchronized() {
unset(Constants.ACC_DECLARED_SYNCHRONIZED);
}
public static class Builder extends BuilderBase<Builder, MethodAccessFlags> {
Builder() {
super(MethodAccessFlags.fromSharedAccessFlags(0, false));
}
public Builder setBridge() {
flags.setBridge();
return this;
}
public Builder setConstructor() {
flags.setConstructor();
return this;
}
public Builder setStrict(boolean value) {
if (value) {
flags.setStrict();
} else {
flags.unsetStrict();
}
return this;
}
public Builder setSynchronized(boolean value) {
if (value) {
flags.setSynchronized();
} else {
flags.unsetSynchronized();
}
return this;
}
@Override
public Builder self() {
return this;
}
}
}