--- /dev/null
+#!/bin/bash
+#
+# Copyright (C) 2016 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.
+
+# Use secondary switch to add secondary dex file to class path.
+exec ${RUN} "${@}" --secondary
--- /dev/null
+/*
+ * Copyright (C) 2016 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.
+ */
+
+// We make Main extend an unresolved super class. This will lead to an
+// unresolved access to Foo.field, as we won't know if Main can access
+// a package private field.
+public class Main extends MissingSuperClass {
+
+ public static void main(String[] args) {
+ instanceFieldTest();
+ staticFieldTest();
+ instanceFieldTest2();
+ }
+
+ /// CHECK-START: void Main.instanceFieldTest() inliner (before)
+ /// CHECK-NOT: InstanceFieldSet
+
+ /// CHECK-START: void Main.instanceFieldTest() inliner (after)
+ /// CHECK: InstanceFieldSet
+ /// CHECK: UnresolvedInstanceFieldGet
+
+ // Load store elimination used to remove the InstanceFieldSet, thinking
+ // that the UnresolvedInstanceFieldGet was not related. However inlining
+ // can put you in a situation where the UnresolvedInstanceFieldGet resolves
+ // to the same field as the one in InstanceFieldSet. So the InstanceFieldSet
+ // must be preserved.
+
+ /// CHECK-START: void Main.instanceFieldTest() load_store_elimination (after)
+ /// CHECK: InstanceFieldSet
+ /// CHECK: UnresolvedInstanceFieldGet
+ public static void instanceFieldTest() {
+ Foo f = new Foo();
+ if (f.iField != 42) {
+ throw new Error("Expected 42, got " + f.iField);
+ }
+ }
+
+ /// CHECK-START: void Main.instanceFieldTest2() inliner (before)
+ /// CHECK-NOT: InstanceFieldSet
+ /// CHECK-NOT: InstanceFieldGet
+
+ /// CHECK-START: void Main.instanceFieldTest2() inliner (after)
+ /// CHECK: InstanceFieldSet
+ /// CHECK: InstanceFieldGet
+ /// CHECK: UnresolvedInstanceFieldSet
+ /// CHECK: InstanceFieldGet
+
+ // Load store elimination will eliminate the first InstanceFieldGet because
+ // it simply follows an InstanceFieldSet. It must however not eliminate the second
+ // InstanceFieldGet, as the UnresolvedInstanceFieldSet might resolve to the same
+ // field.
+
+ /// CHECK-START: void Main.instanceFieldTest2() load_store_elimination (after)
+ /// CHECK: InstanceFieldSet
+ /// CHECK-NOT: InstanceFieldGet
+ /// CHECK: UnresolvedInstanceFieldSet
+ /// CHECK: InstanceFieldGet
+ public static void instanceFieldTest2() {
+ Foo f = new Foo();
+ int a = f.$inline$GetInstanceField();
+ f.iField = 43;
+ a = f.$inline$GetInstanceField();
+ if (a != 43) {
+ throw new Error("Expected 43, got " + a);
+ }
+ }
+
+ /// CHECK-START: void Main.staticFieldTest() inliner (before)
+ /// CHECK-NOT: StaticFieldSet
+
+ /// CHECK-START: void Main.staticFieldTest() inliner (after)
+ /// CHECK: StaticFieldSet
+ /// CHECK: StaticFieldSet
+ /// CHECK: UnresolvedStaticFieldGet
+
+ /// CHECK-START: void Main.staticFieldTest() load_store_elimination (after)
+ /// CHECK: StaticFieldSet
+ /// CHECK: StaticFieldSet
+ /// CHECK: UnresolvedStaticFieldGet
+ public static void staticFieldTest() {
+ // Ensure Foo is initialized.
+ Foo f = new Foo();
+ f.$inline$StaticSet42();
+ f.$inline$StaticSet43();
+ if (Foo.sField != 43) {
+ throw new Error("Expected 43, got " + Foo.sField);
+ }
+ }
+}
+
+class Foo {
+ // field needs to be package-private to make the access in Main.main
+ // unresolved.
+ int iField;
+ static int sField;
+
+ public void $inline$StaticSet42() {
+ sField = 42;
+ }
+
+ public void $inline$StaticSet43() {
+ sField = 43;
+ }
+
+ public int $inline$GetInstanceField() {
+ return iField;
+ }
+
+ // Constructor needs to be public to get it resolved in Main.main
+ // and therefore inlined.
+ public Foo() {
+ iField = 42;
+ }
+}