From 6ddec9b70e3592b19a7a9d9e1800d680a8ab14b9 Mon Sep 17 00:00:00 2001 From: Ivan Gavrilovic Date: Mon, 20 Mar 2017 17:47:32 +0000 Subject: Manually initialze the intern table. So it can be reset when clearInterns is called Test: Unit: CstTypeTest, TypeTest, existing shell script tests pass. Change-Id: I2c8144caa7890db1476174e607b93f0bc5de565f --- .../com/android/dx/rop/cst/CstTypeTest.java | 43 +++++++ .../com/android/dx/rop/type/TypeTest.java | 41 +++++++ dx/src/com/android/dx/rop/cst/CstType.java | 73 ++++++++---- dx/src/com/android/dx/rop/type/Type.java | 125 +++++++++++++-------- 4 files changed, 219 insertions(+), 63 deletions(-) create mode 100644 dx/junit-tests/com/android/dx/rop/cst/CstTypeTest.java create mode 100644 dx/junit-tests/com/android/dx/rop/type/TypeTest.java diff --git a/dx/junit-tests/com/android/dx/rop/cst/CstTypeTest.java b/dx/junit-tests/com/android/dx/rop/cst/CstTypeTest.java new file mode 100644 index 000000000..e0a0295e3 --- /dev/null +++ b/dx/junit-tests/com/android/dx/rop/cst/CstTypeTest.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.dx.rop.cst; + +import com.android.dx.rop.type.Type; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class CstTypeTest { + + + @Test + public void checkClearInternTable() { + CstType boolArray = CstType.BOOLEAN_ARRAY; + assertTrue(boolArray == CstType.intern(Type.BOOLEAN_ARRAY)); + CstType myClass = CstType.intern(Type.intern("Lcom/example/Foo;")); + + CstType.clearInternTable(); + Type.clearInternTable(); + + assertTrue(boolArray == CstType.intern(Type.BOOLEAN_ARRAY)); + CstType myClass2 = CstType.intern(Type.intern("Lcom/example/Foo;")); + assertEquals(myClass.getClassType(), myClass2.getClassType()); + assertFalse(myClass == myClass2); + } +} \ No newline at end of file diff --git a/dx/junit-tests/com/android/dx/rop/type/TypeTest.java b/dx/junit-tests/com/android/dx/rop/type/TypeTest.java new file mode 100644 index 000000000..d7f465fe0 --- /dev/null +++ b/dx/junit-tests/com/android/dx/rop/type/TypeTest.java @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +package com.android.dx.rop.type; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class TypeTest { + + @Test + public void testClearInternTable() { + Type boolArray = Type.BOOLEAN.getArrayType(); + assertTrue(boolArray == Type.BOOLEAN_ARRAY); + assertTrue(boolArray == Type.intern("[Z")); + Type myClass = Type.intern("Lcom/example/Foo;"); + + Type.clearInternTable(); + + assertTrue(boolArray == Type.intern("[Z")); + Type myClass2 = Type.intern("Lcom/example/Foo;"); + assertEquals(myClass, myClass2); + assertFalse(myClass == myClass2); + } +} \ No newline at end of file diff --git a/dx/src/com/android/dx/rop/cst/CstType.java b/dx/src/com/android/dx/rop/cst/CstType.java index 35168820d..4b524e513 100644 --- a/dx/src/com/android/dx/rop/cst/CstType.java +++ b/dx/src/com/android/dx/rop/cst/CstType.java @@ -36,63 +36,96 @@ public final class CstType extends TypedConstant { new ConcurrentHashMap<>(1_000, 0.75f, Main.CONCURRENCY_LEVEL); /** {@code non-null;} instance corresponding to the class {@code Object} */ - public static final CstType OBJECT = intern(Type.OBJECT); + public static final CstType OBJECT = new CstType(Type.OBJECT); /** {@code non-null;} instance corresponding to the class {@code Boolean} */ - public static final CstType BOOLEAN = intern(Type.BOOLEAN_CLASS); + public static final CstType BOOLEAN = new CstType(Type.BOOLEAN_CLASS); /** {@code non-null;} instance corresponding to the class {@code Byte} */ - public static final CstType BYTE = intern(Type.BYTE_CLASS); + public static final CstType BYTE = new CstType(Type.BYTE_CLASS); /** {@code non-null;} instance corresponding to the class {@code Character} */ - public static final CstType CHARACTER = intern(Type.CHARACTER_CLASS); + public static final CstType CHARACTER = new CstType(Type.CHARACTER_CLASS); /** {@code non-null;} instance corresponding to the class {@code Double} */ - public static final CstType DOUBLE = intern(Type.DOUBLE_CLASS); + public static final CstType DOUBLE = new CstType(Type.DOUBLE_CLASS); /** {@code non-null;} instance corresponding to the class {@code Float} */ - public static final CstType FLOAT = intern(Type.FLOAT_CLASS); + public static final CstType FLOAT = new CstType(Type.FLOAT_CLASS); /** {@code non-null;} instance corresponding to the class {@code Long} */ - public static final CstType LONG = intern(Type.LONG_CLASS); + public static final CstType LONG = new CstType(Type.LONG_CLASS); /** {@code non-null;} instance corresponding to the class {@code Integer} */ - public static final CstType INTEGER = intern(Type.INTEGER_CLASS); + public static final CstType INTEGER = new CstType(Type.INTEGER_CLASS); /** {@code non-null;} instance corresponding to the class {@code Short} */ - public static final CstType SHORT = intern(Type.SHORT_CLASS); + public static final CstType SHORT = new CstType(Type.SHORT_CLASS); /** {@code non-null;} instance corresponding to the class {@code Void} */ - public static final CstType VOID = intern(Type.VOID_CLASS); + public static final CstType VOID = new CstType(Type.VOID_CLASS); /** {@code non-null;} instance corresponding to the type {@code boolean[]} */ - public static final CstType BOOLEAN_ARRAY = intern(Type.BOOLEAN_ARRAY); + public static final CstType BOOLEAN_ARRAY = new CstType(Type.BOOLEAN_ARRAY); /** {@code non-null;} instance corresponding to the type {@code byte[]} */ - public static final CstType BYTE_ARRAY = intern(Type.BYTE_ARRAY); + public static final CstType BYTE_ARRAY = new CstType(Type.BYTE_ARRAY); /** {@code non-null;} instance corresponding to the type {@code char[]} */ - public static final CstType CHAR_ARRAY = intern(Type.CHAR_ARRAY); + public static final CstType CHAR_ARRAY = new CstType(Type.CHAR_ARRAY); /** {@code non-null;} instance corresponding to the type {@code double[]} */ - public static final CstType DOUBLE_ARRAY = intern(Type.DOUBLE_ARRAY); + public static final CstType DOUBLE_ARRAY = new CstType(Type.DOUBLE_ARRAY); /** {@code non-null;} instance corresponding to the type {@code float[]} */ - public static final CstType FLOAT_ARRAY = intern(Type.FLOAT_ARRAY); + public static final CstType FLOAT_ARRAY = new CstType(Type.FLOAT_ARRAY); /** {@code non-null;} instance corresponding to the type {@code long[]} */ - public static final CstType LONG_ARRAY = intern(Type.LONG_ARRAY); + public static final CstType LONG_ARRAY = new CstType(Type.LONG_ARRAY); /** {@code non-null;} instance corresponding to the type {@code int[]} */ - public static final CstType INT_ARRAY = intern(Type.INT_ARRAY); + public static final CstType INT_ARRAY = new CstType(Type.INT_ARRAY); /** {@code non-null;} instance corresponding to the type {@code short[]} */ - public static final CstType SHORT_ARRAY = intern(Type.SHORT_ARRAY); + public static final CstType SHORT_ARRAY = new CstType(Type.SHORT_ARRAY); /** * {@code non-null;} instance corresponding to the type {@code java.lang.invoke.MethodHandle} */ - public static final CstType METHOD_HANDLE = intern(Type.METHOD_HANDLE); + public static final CstType METHOD_HANDLE = new CstType(Type.METHOD_HANDLE); + + static { + initInterns(); + } + + private static void initInterns() { + internInitial(OBJECT); + internInitial(BOOLEAN); + internInitial(BYTE); + internInitial(CHARACTER); + internInitial(DOUBLE); + internInitial(FLOAT); + internInitial(LONG); + internInitial(INTEGER); + internInitial(SHORT); + internInitial(VOID); + internInitial(BOOLEAN_ARRAY); + internInitial(BYTE_ARRAY); + internInitial(CHAR_ARRAY); + internInitial(DOUBLE_ARRAY); + internInitial(FLOAT_ARRAY); + internInitial(LONG_ARRAY); + internInitial(INT_ARRAY); + internInitial(SHORT_ARRAY); + internInitial(METHOD_HANDLE); + } + + private static void internInitial(CstType cst) { + if (interns.putIfAbsent(cst.getClassType(), cst) != null) { + throw new IllegalStateException("Attempted re-init of " + cst); + } + } + /** {@code non-null;} the underlying type */ private final Type type; @@ -257,5 +290,7 @@ public final class CstType extends TypedConstant { public static void clearInternTable() { interns.clear(); + initInterns(); } + } diff --git a/dx/src/com/android/dx/rop/type/Type.java b/dx/src/com/android/dx/rop/type/Type.java index f806adc59..d7879eb96 100644 --- a/dx/src/com/android/dx/rop/type/Type.java +++ b/dx/src/com/android/dx/rop/type/Type.java @@ -106,142 +106,178 @@ public final class Type implements TypeBearer, Comparable { /** {@code non-null;} instance representing a subroutine return address */ public static final Type RETURN_ADDRESS = new Type("", BT_ADDR); - static { - /* - * Put all the primitive types into the intern table. This needs - * to happen before the array types below get interned. - */ - putIntern(BOOLEAN); - putIntern(BYTE); - putIntern(CHAR); - putIntern(DOUBLE); - putIntern(FLOAT); - putIntern(INT); - putIntern(LONG); - putIntern(SHORT); - /* - * Note: VOID isn't put in the intern table, since it's special and - * shouldn't be found by a normal call to intern(). - */ - } /** * {@code non-null;} instance representing * {@code java.lang.annotation.Annotation} */ public static final Type ANNOTATION = - intern("Ljava/lang/annotation/Annotation;"); + new Type("Ljava/lang/annotation/Annotation;", BT_OBJECT); /** {@code non-null;} instance representing {@code java.lang.Class} */ - public static final Type CLASS = intern("Ljava/lang/Class;"); + public static final Type CLASS = new Type("Ljava/lang/Class;", BT_OBJECT); /** {@code non-null;} instance representing {@code java.lang.Cloneable} */ - public static final Type CLONEABLE = intern("Ljava/lang/Cloneable;"); + public static final Type CLONEABLE = new Type("Ljava/lang/Cloneable;", BT_OBJECT); /** {@code non-null;} instance representing {@code java.lang.invoke.MethodHandle} */ - public static final Type METHOD_HANDLE = intern("Ljava/lang/invoke/MethodHandle;"); + public static final Type METHOD_HANDLE = new Type("Ljava/lang/invoke/MethodHandle;", BT_OBJECT); /** {@code non-null;} instance representing {@code java.lang.Object} */ - public static final Type OBJECT = intern("Ljava/lang/Object;"); + public static final Type OBJECT = new Type("Ljava/lang/Object;", BT_OBJECT); /** {@code non-null;} instance representing {@code java.io.Serializable} */ - public static final Type SERIALIZABLE = intern("Ljava/io/Serializable;"); + public static final Type SERIALIZABLE = new Type("Ljava/io/Serializable;", BT_OBJECT); /** {@code non-null;} instance representing {@code java.lang.String} */ - public static final Type STRING = intern("Ljava/lang/String;"); + public static final Type STRING = new Type("Ljava/lang/String;", BT_OBJECT); /** {@code non-null;} instance representing {@code java.lang.Throwable} */ - public static final Type THROWABLE = intern("Ljava/lang/Throwable;"); + public static final Type THROWABLE = new Type("Ljava/lang/Throwable;", BT_OBJECT); /** * {@code non-null;} instance representing {@code java.lang.Boolean}; the * suffix on the name helps disambiguate this from the instance * representing a primitive type */ - public static final Type BOOLEAN_CLASS = intern("Ljava/lang/Boolean;"); + public static final Type BOOLEAN_CLASS = new Type("Ljava/lang/Boolean;", BT_OBJECT); /** * {@code non-null;} instance representing {@code java.lang.Byte}; the * suffix on the name helps disambiguate this from the instance * representing a primitive type */ - public static final Type BYTE_CLASS = intern("Ljava/lang/Byte;"); + public static final Type BYTE_CLASS = new Type("Ljava/lang/Byte;", BT_OBJECT); /** * {@code non-null;} instance representing {@code java.lang.Character}; the * suffix on the name helps disambiguate this from the instance * representing a primitive type */ - public static final Type CHARACTER_CLASS = intern("Ljava/lang/Character;"); + public static final Type CHARACTER_CLASS = new Type("Ljava/lang/Character;", BT_OBJECT); /** * {@code non-null;} instance representing {@code java.lang.Double}; the * suffix on the name helps disambiguate this from the instance * representing a primitive type */ - public static final Type DOUBLE_CLASS = intern("Ljava/lang/Double;"); + public static final Type DOUBLE_CLASS = new Type("Ljava/lang/Double;", BT_OBJECT); /** * {@code non-null;} instance representing {@code java.lang.Float}; the * suffix on the name helps disambiguate this from the instance * representing a primitive type */ - public static final Type FLOAT_CLASS = intern("Ljava/lang/Float;"); + public static final Type FLOAT_CLASS = new Type("Ljava/lang/Float;", BT_OBJECT); /** * {@code non-null;} instance representing {@code java.lang.Integer}; the * suffix on the name helps disambiguate this from the instance * representing a primitive type */ - public static final Type INTEGER_CLASS = intern("Ljava/lang/Integer;"); + public static final Type INTEGER_CLASS = new Type("Ljava/lang/Integer;", BT_OBJECT); /** * {@code non-null;} instance representing {@code java.lang.Long}; the * suffix on the name helps disambiguate this from the instance * representing a primitive type */ - public static final Type LONG_CLASS = intern("Ljava/lang/Long;"); + public static final Type LONG_CLASS = new Type("Ljava/lang/Long;", BT_OBJECT); /** * {@code non-null;} instance representing {@code java.lang.Short}; the * suffix on the name helps disambiguate this from the instance * representing a primitive type */ - public static final Type SHORT_CLASS = intern("Ljava/lang/Short;"); + public static final Type SHORT_CLASS = new Type("Ljava/lang/Short;", BT_OBJECT); /** * {@code non-null;} instance representing {@code java.lang.Void}; the * suffix on the name helps disambiguate this from the instance * representing a primitive type */ - public static final Type VOID_CLASS = intern("Ljava/lang/Void;"); + public static final Type VOID_CLASS = new Type("Ljava/lang/Void;", BT_OBJECT); /** {@code non-null;} instance representing {@code boolean[]} */ - public static final Type BOOLEAN_ARRAY = BOOLEAN.getArrayType(); + public static final Type BOOLEAN_ARRAY = new Type("[" + BOOLEAN.descriptor, BT_OBJECT); /** {@code non-null;} instance representing {@code byte[]} */ - public static final Type BYTE_ARRAY = BYTE.getArrayType(); + public static final Type BYTE_ARRAY = new Type("[" + BYTE.descriptor, BT_OBJECT); /** {@code non-null;} instance representing {@code char[]} */ - public static final Type CHAR_ARRAY = CHAR.getArrayType(); + public static final Type CHAR_ARRAY = new Type("[" + CHAR.descriptor, BT_OBJECT); /** {@code non-null;} instance representing {@code double[]} */ - public static final Type DOUBLE_ARRAY = DOUBLE.getArrayType(); + public static final Type DOUBLE_ARRAY = new Type("[" + DOUBLE.descriptor, BT_OBJECT); /** {@code non-null;} instance representing {@code float[]} */ - public static final Type FLOAT_ARRAY = FLOAT.getArrayType(); + public static final Type FLOAT_ARRAY = new Type("[" + FLOAT.descriptor, BT_OBJECT);; /** {@code non-null;} instance representing {@code int[]} */ - public static final Type INT_ARRAY = INT.getArrayType(); + public static final Type INT_ARRAY = new Type("[" + INT.descriptor, BT_OBJECT); /** {@code non-null;} instance representing {@code long[]} */ - public static final Type LONG_ARRAY = LONG.getArrayType(); + public static final Type LONG_ARRAY = new Type("[" + LONG.descriptor, BT_OBJECT); /** {@code non-null;} instance representing {@code Object[]} */ - public static final Type OBJECT_ARRAY = OBJECT.getArrayType(); + public static final Type OBJECT_ARRAY = new Type("[" + OBJECT.descriptor, BT_OBJECT); /** {@code non-null;} instance representing {@code short[]} */ - public static final Type SHORT_ARRAY = SHORT.getArrayType(); + public static final Type SHORT_ARRAY = new Type("[" + SHORT.descriptor, BT_OBJECT); + + static { + initInterns(); + } + + /** + * Put the constant fields, including primitive types in to the intern table. + * + *

Must be called after the types are initialized above. + */ + private static void initInterns() { + putIntern(BOOLEAN); + putIntern(BYTE); + putIntern(CHAR); + putIntern(DOUBLE); + putIntern(FLOAT); + putIntern(INT); + putIntern(LONG); + putIntern(SHORT); + /* + * Note: VOID isn't put in the intern table, since it's special and + * shouldn't be found by a normal call to intern(). + */ + + putIntern(ANNOTATION); + putIntern(CLASS); + putIntern(CLONEABLE); + putIntern(METHOD_HANDLE); + putIntern(OBJECT); + putIntern(SERIALIZABLE); + putIntern(STRING); + putIntern(THROWABLE); + putIntern(BOOLEAN_CLASS); + putIntern(BYTE_CLASS); + putIntern(CHARACTER_CLASS); + putIntern(DOUBLE_CLASS); + putIntern(FLOAT_CLASS); + putIntern(INTEGER_CLASS); + putIntern(LONG_CLASS); + putIntern(SHORT_CLASS); + putIntern(VOID_CLASS); + + // Array types + putIntern(BOOLEAN_ARRAY); + putIntern(BYTE_ARRAY); + putIntern(CHAR_ARRAY); + putIntern(DOUBLE_ARRAY); + putIntern(FLOAT_ARRAY); + putIntern(INT_ARRAY); + putIntern(LONG_ARRAY); + putIntern(OBJECT_ARRAY); + putIntern(SHORT_ARRAY); + } + /** {@code non-null;} field descriptor for the type */ private final String descriptor; @@ -866,5 +902,6 @@ public final class Type implements TypeBearer, Comparable { public static void clearInternTable() { internTable.clear(); + initInterns(); } } -- cgit v1.2.3