blob: 0abbfde76c143678e5fe0a1323161572daaa6281 [file] [log] [blame]
// Copyright (c) 2018, 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.optimize.string;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.ir.code.ConstNumber;
import com.android.tools.r8.ir.code.ConstString;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Instruction;
import com.android.tools.r8.ir.code.InstructionIterator;
import com.android.tools.r8.ir.code.InvokeVirtual;
import com.android.tools.r8.ir.code.Value;
import com.google.common.annotations.VisibleForTesting;
import java.util.List;
public class StringOptimizer {
@VisibleForTesting
static boolean isStringLength(DexMethod method, DexItemFactory factory) {
boolean isStringClass;
if (factory != null) {
isStringClass = method.getHolder().equals(factory.stringType);
} else {
isStringClass = method.getHolder().toDescriptorString().equals("Ljava/lang/String;");
}
return isStringClass
&& method.getArity() == 0
&& method.proto.returnType.isIntType()
&& method.name.toString().equals("length");
}
// Find String#length() with a constant string and compute the length of it at compile time.
public void computeConstStringLength(IRCode code, DexItemFactory factory) {
// TODO(jsjeon): is it worth having an indicator of String#length()?
if (!code.hasConstString) {
return;
}
InstructionIterator it = code.instructionIterator();
while (it.hasNext()) {
Instruction instr = it.next();
if (!instr.isInvokeVirtual()) {
continue;
}
InvokeVirtual invoke = instr.asInvokeVirtual();
DexMethod invokedMethod = invoke.getInvokedMethod();
if (!isStringLength(invokedMethod, factory)) {
continue;
}
List<Value> ins = invoke.arguments();
assert ins.size() == 1;
Value in = ins.get(0);
if (in.definition == null
|| !in.definition.isConstString()
|| !in.definition.outValue().isConstant()) {
continue;
}
ConstString constString = in.definition.asConstString();
int length = constString.getValue().toString().length();
ConstNumber constNumber = code.createIntConstant(length);
it.replaceCurrentInstruction(constNumber);
}
}
}