summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMathieu Chartier <mathieuc@google.com>2015-01-28 13:11:44 -0800
committerMathieu Chartier <mathieuc@google.com>2015-01-28 14:26:47 -0800
commite4a91bbeaa118bc01a5c338c6a6d9ee094a6a2c6 (patch)
tree8ee63aced115823626d614e70716d745f72bb3a6
parentab7f56d9b9838811cb01773e45999e2cda4aa03a (diff)
downloadandroid_art-e4a91bbeaa118bc01a5c338c6a6d9ee094a6a2c6.tar.gz
android_art-e4a91bbeaa118bc01a5c338c6a6d9ee094a6a2c6.tar.bz2
android_art-e4a91bbeaa118bc01a5c338c6a6d9ee094a6a2c6.zip
Force set resolved method for static invokes
For static invokes, we may dispatch to the static method in the superclass but resolve using the subclass. To prevent getting slow paths on each invoke, we force set the resolved method for the super class dex method index if we are in the same dex file. Added test. Bug: 19175856 Change-Id: I26f8644a7f725f5c2dc2a94a8e9578f573792507
-rw-r--r--runtime/entrypoints/quick/quick_trampoline_entrypoints.cc10
-rw-r--r--test/133-static-invoke-super/expected.txt3
-rw-r--r--test/133-static-invoke-super/info.txt2
-rwxr-xr-xtest/133-static-invoke-super/run18
-rw-r--r--test/133-static-invoke-super/src/Main.java63
-rw-r--r--test/Android.run-test.mk3
6 files changed, 98 insertions, 1 deletions
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index 8ab90eb7fd..a67ebcaa61 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -930,6 +930,16 @@ extern "C" const void* artQuickResolutionTrampoline(mirror::ArtMethod* called,
(caller->GetDexCacheResolvedMethod(update_dex_cache_method_index) != called)) {
caller->SetDexCacheResolvedMethod(update_dex_cache_method_index, called);
}
+ } else if (invoke_type == kStatic) {
+ const auto called_dex_method_idx = called->GetDexMethodIndex();
+ // For static invokes, we may dispatch to the static method in the superclass but resolve
+ // using the subclass. To prevent getting slow paths on each invoke, we force set the
+ // resolved method for the super class dex method index if we are in the same dex file.
+ // b/19175856
+ if (called->GetDexFile() == called_method.dex_file &&
+ called_method.dex_method_index != called_dex_method_idx) {
+ called->GetDexCache()->SetResolvedMethod(called_dex_method_idx, called);
+ }
}
// Ensure that the called method's class is initialized.
StackHandleScope<1> hs(soa.Self());
diff --git a/test/133-static-invoke-super/expected.txt b/test/133-static-invoke-super/expected.txt
new file mode 100644
index 0000000000..089d8e85aa
--- /dev/null
+++ b/test/133-static-invoke-super/expected.txt
@@ -0,0 +1,3 @@
+basis: performed 50000000 iterations
+test1: performed 50000000 iterations
+Timing is acceptable.
diff --git a/test/133-static-invoke-super/info.txt b/test/133-static-invoke-super/info.txt
new file mode 100644
index 0000000000..606331b5fb
--- /dev/null
+++ b/test/133-static-invoke-super/info.txt
@@ -0,0 +1,2 @@
+This is a performance test of invoking static methods in super class. To see the numbers, invoke
+this test with the "--timing" option.
diff --git a/test/133-static-invoke-super/run b/test/133-static-invoke-super/run
new file mode 100755
index 0000000000..e27a622f40
--- /dev/null
+++ b/test/133-static-invoke-super/run
@@ -0,0 +1,18 @@
+#!/bin/bash
+#
+# Copyright (C) 2012 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.
+
+# As this is a performance test we always use the non-debug build.
+exec ${RUN} "${@/#libartd.so/libart.so}"
diff --git a/test/133-static-invoke-super/src/Main.java b/test/133-static-invoke-super/src/Main.java
new file mode 100644
index 0000000000..7cfd099a53
--- /dev/null
+++ b/test/133-static-invoke-super/src/Main.java
@@ -0,0 +1,63 @@
+
+public class Main {
+ static class SuperClass {
+ protected static int getVar(int w) {
+ return w & 0xF;
+ }
+ }
+ static class SubClass extends SuperClass {
+ final int getVarDirect(int w) {
+ return w & 0xF;
+ }
+ public void testDirect(int max) {
+ for (int i = 0; i < max; ++i) {
+ getVarDirect(max);
+ }
+ }
+ public void testStatic(int max) {
+ for (int i = 0; i < max; ++i) {
+ getVar(max);
+ }
+ }
+ }
+
+ static public void main(String[] args) throws Exception {
+ boolean timing = (args.length >= 1) && args[0].equals("--timing");
+ run(timing);
+ }
+
+ static int testBasis(int interations) {
+ (new SubClass()).testDirect(interations);
+ return interations;
+ }
+
+ static int testStatic(int interations) {
+ (new SubClass()).testStatic(interations);
+ return interations;
+ }
+
+ static public void run(boolean timing) {
+ long time0 = System.nanoTime();
+ int count1 = testBasis(50000000);
+ long time1 = System.nanoTime();
+ int count2 = testStatic(50000000);
+ long time2 = System.nanoTime();
+
+ System.out.println("basis: performed " + count1 + " iterations");
+ System.out.println("test1: performed " + count2 + " iterations");
+
+ double basisMsec = (time1 - time0) / (double) count1 / 1000000;
+ double msec1 = (time2 - time1) / (double) count2 / 1000000;
+
+ if (msec1 < basisMsec * 5) {
+ System.out.println("Timing is acceptable.");
+ } else {
+ System.out.println("Iterations are taking too long!");
+ timing = true;
+ }
+ if (timing) {
+ System.out.printf("basis time: %.3g msec\n", basisMsec);
+ System.out.printf("test1: %.3g msec per iteration\n", msec1);
+ }
+ }
+}
diff --git a/test/Android.run-test.mk b/test/Android.run-test.mk
index b1e969d71c..2057cb9b06 100644
--- a/test/Android.run-test.mk
+++ b/test/Android.run-test.mk
@@ -166,7 +166,8 @@ endef # name-to-var
# Tests that are timing sensitive and flaky on heavily loaded systems.
TEST_ART_TIMING_SENSITIVE_RUN_TESTS := \
053-wait-some \
- 055-enum-performance
+ 055-enum-performance \
+ 133-static-invoke-super
# disable timing sensitive tests on "dist" builds.
ifdef dist_goal