blob: e3e9ea0e39a250becab4e201e8e219522d535af5 [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.dex;
import com.android.tools.r8.code.Const4;
import com.android.tools.r8.code.ConstString;
import com.android.tools.r8.code.Goto32;
import com.android.tools.r8.code.IfEq;
import com.android.tools.r8.code.IfEqz;
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.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;
import org.junit.Test;
public class JumboStringProcessing {
@Test
public void branching() {
DexItemFactory factory = new DexItemFactory();
DexString string = factory.createString("turn into jumbo");
factory.sort(NamingLens.getIdentityLens());
Instruction[] instructions = buildInstructions(string, false);
DexCode code = jumboStringProcess(factory, string, instructions);
Instruction[] rewrittenInstructions = code.instructions;
assert rewrittenInstructions[1] instanceof IfEq;
IfEq condition = (IfEq) rewrittenInstructions[1];
assert condition.getOffset() + condition.CCCC == rewrittenInstructions[3].getOffset();
assert rewrittenInstructions[2] instanceof Goto32;
Goto32 jump = (Goto32) rewrittenInstructions[2];
Instruction lastInstruction = rewrittenInstructions[rewrittenInstructions.length - 1];
assert jump.getOffset() + jump.AAAAAAAA == lastInstruction.getOffset();
}
@Test
public void branching2() {
DexItemFactory factory = new DexItemFactory();
DexString string = factory.createString("turn into jumbo");
factory.sort(NamingLens.getIdentityLens());
Instruction[] instructions = buildInstructions(string, true);
DexCode code = jumboStringProcess(factory, string, instructions);
Instruction[] rewrittenInstructions = code.instructions;
assert rewrittenInstructions[1] instanceof IfEqz;
IfEqz condition = (IfEqz) rewrittenInstructions[1];
assert condition.getOffset() + condition.BBBB == rewrittenInstructions[3].getOffset();
assert rewrittenInstructions[2] instanceof Goto32;
Goto32 jump = (Goto32) rewrittenInstructions[2];
Instruction lastInstruction = rewrittenInstructions[rewrittenInstructions.length - 1];
assert jump.getOffset() + jump.AAAAAAAA == lastInstruction.getOffset();
}
private Instruction[] buildInstructions(DexString string, boolean zeroCondition) {
List<Instruction> instructions = new ArrayList<>();
int offset = 0;
Instruction instr = new Const4(0, 0);
instr.setOffset(offset);
instructions.add(instr);
offset += instr.getSize();
int lastInstructionOffset = 15000 * 2 + 2 + offset;
if (zeroCondition) {
instr = new IfNez(0, lastInstructionOffset - offset);
} else {
instr = new IfNe(0, 0, lastInstructionOffset - offset);
}
instr.setOffset(offset);
instructions.add(instr);
offset += instr.getSize();
for (int i = 0; i < 15000; i++) {
instr = new ConstString(0, string);
instr.setOffset(offset);
instructions.add(instr);
offset += instr.getSize();
}
instr = new ReturnVoid();
instr.setOffset(offset);
instructions.add(instr);
assert instr.getOffset() == lastInstructionOffset;
return instructions.toArray(new Instruction[instructions.size()]);
}
private DexCode jumboStringProcess(
DexItemFactory factory, DexString string, Instruction[] instructions) {
DexCode code = new DexCode(
1,
0,
0,
instructions,
new Try[0],
null,
null,
null);
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();
}
}