LayoutLib: Fix System.arraycopy()

Framework has specialized versions of java.lang.System.arraycopy() for
all primitive data types. These versions are not present on the Desktop
VM. This change replaces calls to any of the specialized versions with
the more general alternative - the one using Objects.

Note that this was already being done for char.

Change-Id: If1584125fea8ecc080fb39a5ee6cdb4d922d0c98
(cherry picked from commit e1960cc0b5)
This commit is contained in:
Deepanshu Gupta
2014-07-10 13:20:42 -07:00
parent 8db769dd56
commit 51fb7754fc
3 changed files with 23 additions and 8 deletions

View File

@@ -131,8 +131,8 @@ valid StackMapTable. As a side benefit of this, we can continue to support Java
Mac has horrible font rendering support. Mac has horrible font rendering support.
ReplaceMethodCallsAdapter replaces calls to certain methods. Currently, it only rewrites calls to ReplaceMethodCallsAdapter replaces calls to certain methods. Currently, it only rewrites calls to
java.lang.System.arraycopy([CI[CII)V, which is not part of the Desktop VM to call the more general specialized versions of java.lang.System.arraycopy(), which are not part of the Desktop VM to call
method java.lang.System.arraycopy(Ljava/lang/Object;ILjava/lang/Object;II)V. the more general method java.lang.System.arraycopy(Ljava/lang/Object;ILjava/lang/Object;II)V.
The ClassAdapters are chained together to achieve the desired output. (Look at section 2.2.7 The ClassAdapters are chained together to achieve the desired output. (Look at section 2.2.7
Transformation chains in the asm user guide, link in the References.) The order of execution of Transformation chains in the asm user guide, link in the References.) The order of execution of

View File

@@ -726,9 +726,9 @@ public class AsmAnalyzer {
considerDesc(desc); considerDesc(desc);
// Check if method is java.lang.System.arrayCopy([CI[CII)V // Check if method is a specialized version of java.lang.System.arrayCopy()
if (owner.equals("java/lang/System") && name.equals("arraycopy") if (owner.equals("java/lang/System") && name.equals("arraycopy")
&& desc.equals("([CI[CII)V")) { && !desc.equals("(Ljava/lang/Object;ILjava/lang/Object;II)V")) {
mReplaceMethodCallClasses.add(mOwnerClass); mReplaceMethodCallClasses.add(mOwnerClass);
} }
} }

View File

@@ -20,10 +20,23 @@ import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes; import org.objectweb.asm.Opcodes;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
/** /**
* Replaces calls to certain methods that do not exist in the Desktop VM. * Replaces calls to certain methods that do not exist in the Desktop VM.
*/ */
public class ReplaceMethodCallsAdapter extends ClassVisitor { public class ReplaceMethodCallsAdapter extends ClassVisitor {
/**
* Descriptors for specialized versions {@link System#arraycopy} that are not present on the
* Desktop VM.
*/
private static Set<String> ARRAYCOPY_DESCRIPTORS = new HashSet<String>(Arrays.asList(
"([CI[CII)V", "([BI[BII)V", "([SI[SII)V", "([II[III)V",
"([JI[JII)V", "([FI[FII)V", "([DI[DII)V", "([ZI[ZII)V"));
public ReplaceMethodCallsAdapter(ClassVisitor cv) { public ReplaceMethodCallsAdapter(ClassVisitor cv) {
super(Opcodes.ASM4, cv); super(Opcodes.ASM4, cv);
} }
@@ -42,11 +55,13 @@ public class ReplaceMethodCallsAdapter extends ClassVisitor {
@Override @Override
public void visitMethodInsn(int opcode, String owner, String name, String desc) { public void visitMethodInsn(int opcode, String owner, String name, String desc) {
// Check if method is java.lang.System.arrayCopy([CI[CII)V // Check if method is a specialized version of java.lang.System.arrayCopy
if (owner.equals("java/lang/System") && name.equals("arraycopy") if (owner.equals("java/lang/System") && name.equals("arraycopy")) {
&& desc.equals("([CI[CII)V")) {
if (ARRAYCOPY_DESCRIPTORS.contains(desc)) {
desc = "(Ljava/lang/Object;ILjava/lang/Object;II)V"; desc = "(Ljava/lang/Object;ILjava/lang/Object;II)V";
} }
}
super.visitMethodInsn(opcode, owner, name, desc); super.visitMethodInsn(opcode, owner, name, desc);
} }
} }