| // 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.ir.conversion; |
| |
| import com.android.tools.r8.graph.DexEncodedMethod; |
| import com.android.tools.r8.graph.DexEncodedMethod.ClassInlinerEligibility; |
| import com.android.tools.r8.graph.DexEncodedMethod.TrivialInitializer; |
| import com.android.tools.r8.graph.ParameterUsagesInfo; |
| import com.android.tools.r8.graph.UpdatableOptimizationInfo; |
| import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget; |
| import com.android.tools.r8.utils.IteratorUtils; |
| import java.util.BitSet; |
| import java.util.IdentityHashMap; |
| import java.util.Map; |
| |
| public class OptimizationFeedbackDelayed implements OptimizationFeedback { |
| |
| // Caching of updated optimization info and processed status. |
| private final Map<DexEncodedMethod, UpdatableOptimizationInfo> optimizationInfos = |
| new IdentityHashMap<>(); |
| private final Map<DexEncodedMethod, ConstraintWithTarget> processed = new IdentityHashMap<>(); |
| |
| private synchronized UpdatableOptimizationInfo getOptimizationInfoForUpdating( |
| DexEncodedMethod method) { |
| UpdatableOptimizationInfo info = optimizationInfos.get(method); |
| if (info != null) { |
| return info; |
| } |
| info = method.getOptimizationInfo().mutableCopy(); |
| optimizationInfos.put(method, info); |
| return info; |
| } |
| |
| @Override |
| public synchronized void methodReturnsArgument(DexEncodedMethod method, int argument) { |
| getOptimizationInfoForUpdating(method).markReturnsArgument(argument); |
| } |
| |
| @Override |
| public synchronized void methodReturnsConstant(DexEncodedMethod method, long value) { |
| getOptimizationInfoForUpdating(method).markReturnsConstant(value); |
| } |
| |
| @Override |
| public synchronized void methodNeverReturnsNull(DexEncodedMethod method) { |
| getOptimizationInfoForUpdating(method).markNeverReturnsNull(); |
| } |
| |
| @Override |
| public synchronized void methodNeverReturnsNormally(DexEncodedMethod method) { |
| getOptimizationInfoForUpdating(method).markNeverReturnsNormally(); |
| } |
| |
| @Override |
| public synchronized void markProcessed(DexEncodedMethod method, ConstraintWithTarget state) { |
| processed.put(method, state); |
| } |
| |
| @Override |
| public synchronized void markUseIdentifierNameString(DexEncodedMethod method) { |
| getOptimizationInfoForUpdating(method).markUseIdentifierNameString(); |
| } |
| |
| @Override |
| public synchronized void markCheckNullReceiverBeforeAnySideEffect( |
| DexEncodedMethod method, boolean mark) { |
| getOptimizationInfoForUpdating(method).markCheckNullReceiverBeforeAnySideEffect(mark); |
| } |
| |
| @Override |
| public synchronized void markTriggerClassInitBeforeAnySideEffect( |
| DexEncodedMethod method, boolean mark) { |
| getOptimizationInfoForUpdating(method).markTriggerClassInitBeforeAnySideEffect(mark); |
| } |
| |
| @Override |
| public synchronized void setClassInlinerEligibility( |
| DexEncodedMethod method, ClassInlinerEligibility eligibility) { |
| getOptimizationInfoForUpdating(method).setClassInlinerEligibility(eligibility); |
| } |
| |
| @Override |
| public synchronized void setTrivialInitializer(DexEncodedMethod method, TrivialInitializer info) { |
| getOptimizationInfoForUpdating(method).setTrivialInitializer(info); |
| } |
| |
| @Override |
| public synchronized void setInitializerEnablingJavaAssertions(DexEncodedMethod method) { |
| getOptimizationInfoForUpdating(method).setInitializerEnablingJavaAssertions(); |
| } |
| |
| @Override |
| public synchronized void setParameterUsages( |
| DexEncodedMethod method, ParameterUsagesInfo parameterUsagesInfo) { |
| getOptimizationInfoForUpdating(method).setParameterUsages(parameterUsagesInfo); |
| } |
| |
| @Override |
| public synchronized void setNonNullParamOrThrow(DexEncodedMethod method, BitSet facts) { |
| getOptimizationInfoForUpdating(method).setNonNullParamOrThrow(facts); |
| } |
| |
| @Override |
| public synchronized void setNonNullParamOnNormalExits(DexEncodedMethod method, BitSet facts) { |
| getOptimizationInfoForUpdating(method).setNonNullParamOnNormalExits(facts); |
| } |
| |
| public void updateVisibleOptimizationInfo() { |
| // Remove methods that have become obsolete. A method may become obsolete, for example, as a |
| // result of the class staticizer, which aims to transform virtual methods on companion classes |
| // into static methods on the enclosing class of the companion class. |
| IteratorUtils.removeIf( |
| optimizationInfos.entrySet().iterator(), entry -> entry.getKey().isObsolete()); |
| IteratorUtils.removeIf(processed.entrySet().iterator(), entry -> entry.getKey().isObsolete()); |
| optimizationInfos.forEach(DexEncodedMethod::setOptimizationInfo); |
| processed.forEach(DexEncodedMethod::markProcessed); |
| optimizationInfos.clear(); |
| processed.clear(); |
| } |
| } |