|  | // 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 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 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); | 
|  | } | 
|  |  | 
|  | private void unsetDeclaredSynchronized() { | 
|  | unset(Constants.ACC_DECLARED_SYNCHRONIZED); | 
|  | } | 
|  |  | 
|  | public static class Builder extends BuilderBase<Builder, MethodAccessFlags> { | 
|  |  | 
|  | Builder() { | 
|  | super(MethodAccessFlags.fromSharedAccessFlags(0, false)); | 
|  | } | 
|  |  | 
|  | public Builder setConstructor() { | 
|  | flags.setConstructor(); | 
|  | return this; | 
|  | } | 
|  |  | 
|  | @Override | 
|  | public Builder self() { | 
|  | return this; | 
|  | } | 
|  | } | 
|  | } |