Add benchmark for ScopedPrimitiveArray

TODO: Make this into a caliper benchmark.

Bug: 19664826
Change-Id: If1484a68cc62603f1d216b1662ca55cceac1d619
diff --git a/test/998-scoped-primitive-array/check b/test/998-scoped-primitive-array/check
new file mode 100755
index 0000000..842bdc6
--- /dev/null
+++ b/test/998-scoped-primitive-array/check
@@ -0,0 +1,22 @@
+#!/bin/bash
+#
+# Copyright (C) 2015 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.
+
+# Check that the string "error" isn't present
+if grep error "$2"; then
+    exit 1
+else
+    exit 0
+fi
diff --git a/test/998-scoped-primitive-array/expected.txt b/test/998-scoped-primitive-array/expected.txt
new file mode 100644
index 0000000..a965a70
--- /dev/null
+++ b/test/998-scoped-primitive-array/expected.txt
@@ -0,0 +1 @@
+Done
diff --git a/test/998-scoped-primitive-array/info.txt b/test/998-scoped-primitive-array/info.txt
new file mode 100644
index 0000000..93abb7c
--- /dev/null
+++ b/test/998-scoped-primitive-array/info.txt
@@ -0,0 +1 @@
+Tests for measuring performance of ScopedPrimitiveArray.
diff --git a/test/998-scoped-primitive-array/scoped_primitive_array.cc b/test/998-scoped-primitive-array/scoped_primitive_array.cc
new file mode 100644
index 0000000..c224a06
--- /dev/null
+++ b/test/998-scoped-primitive-array/scoped_primitive_array.cc
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#include "jni.h"
+#include "ScopedPrimitiveArray.h"
+
+extern "C" JNIEXPORT jlong JNICALL Java_Main_measureByteArray(JNIEnv* env,
+                                                              jclass,
+                                                              jlong reps,
+                                                              jbyteArray arr) {
+  jlong ret = 0;
+  for (jlong i = 0; i < reps; ++i) {
+    ScopedByteArrayRO sc(env, arr);
+    ret += sc[0] + sc[sc.size() - 1];
+  }
+  return ret;
+}
+
+extern "C" JNIEXPORT jlong JNICALL Java_Main_measureShortArray(JNIEnv* env,
+                                                               jclass,
+                                                               jlong reps,
+                                                               jshortArray arr) {
+  jlong ret = 0;
+  for (jlong i = 0; i < reps; ++i) {
+    ScopedShortArrayRO sc(env, arr);
+    ret += sc[0] + sc[sc.size() - 1];
+  }
+  return ret;
+}
+
+extern "C" JNIEXPORT jlong JNICALL Java_Main_measureIntArray(JNIEnv* env,
+                                                             jclass,
+                                                             jlong reps,
+                                                             jintArray arr) {
+  jlong ret = 0;
+  for (jlong i = 0; i < reps; ++i) {
+    ScopedIntArrayRO sc(env, arr);
+    ret += sc[0] + sc[sc.size() - 1];
+  }
+  return ret;
+}
+
+extern "C" JNIEXPORT jlong JNICALL Java_Main_measureLongArray(JNIEnv* env,
+                                                              jclass,
+                                                              jlong reps,
+                                                              jlongArray arr) {
+  jlong ret = 0;
+  for (jlong i = 0; i < reps; ++i) {
+    ScopedLongArrayRO sc(env, arr);
+    ret += sc[0] + sc[sc.size() - 1];
+  }
+  return ret;
+}
diff --git a/test/998-scoped-primitive-array/src/Main.java b/test/998-scoped-primitive-array/src/Main.java
new file mode 100644
index 0000000..630e0dc
--- /dev/null
+++ b/test/998-scoped-primitive-array/src/Main.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+public class Main {
+  public Main() {}
+
+  // Measure adds the first and last element of the array by using ScopedPrimitiveArray.
+  static native long measureByteArray(long reps, byte[] arr);
+  static native long measureShortArray(long reps, short[] arr);
+  static native long measureIntArray(long reps, int[] arr);
+  static native long measureLongArray(long reps, long[] arr);
+
+  static void checkEq(long expected, long value) {
+    if (expected != value) {
+      System.out.println("error: Expected " + expected + " but got " + value);
+    }
+  }
+
+  static void runPerfTest(long reps) {
+    for (int length = 1; length <= 8192; length *= 8) {
+      byte[] bytes = new byte[length];
+      bytes[0] = 1;
+      bytes[length - 1] = 2;
+      short[] shorts = new short[length];
+      shorts[0] = 1;
+      shorts[length - 1] = 2;
+      int[] ints = new int[length];
+      ints[0] = 1;
+      ints[length - 1] = 2;
+      long[] longs = new long[length];
+      longs[0] = 1;
+      longs[length - 1] = 2;
+      long value = 0;
+      long elapsed = 0;
+      long start = 0;
+
+      start = System.nanoTime();
+      value = measureByteArray(reps, bytes);
+      elapsed = System.nanoTime() - start;
+      System.out.println("Byte length=" + length + " ns/op=" + (double) elapsed / reps);
+      checkEq(value, reps * (long) (bytes[0] + bytes[length - 1]));
+
+      start = System.nanoTime();
+      value = measureShortArray(reps, shorts);
+      elapsed = System.nanoTime() - start;
+      System.out.println("Short length=" + length + " ns/op=" + (double) elapsed / reps);
+      checkEq(value, reps * (long) (shorts[0] + shorts[length - 1]));
+
+      start = System.nanoTime();
+      value = measureIntArray(reps, ints);
+      elapsed = System.nanoTime() - start;
+      System.out.println("Int length=" + length + " ns/op=" + (double) elapsed / reps);
+      checkEq(value, reps * (ints[0] + ints[length - 1]));
+
+      start = System.nanoTime();
+      value = measureLongArray(reps, longs);
+      elapsed = System.nanoTime() - start;
+      System.out.println("Long length=" + length + " ns/op=" + (double) elapsed / reps);
+      checkEq(value, reps * (longs[0] + longs[length - 1]));
+    }
+  }
+
+  public static void main(String[] args) {
+    System.loadLibrary(args[0]);
+    long iterations = 2000000;
+    if (args.length > 1) {
+      iterations = Long.parseLong(args[1], 10);
+    }
+    runPerfTest(iterations);
+    System.out.println("Done");
+  }
+}
diff --git a/test/Android.libarttest.mk b/test/Android.libarttest.mk
index c3d1576..6d9d7c3 100644
--- a/test/Android.libarttest.mk
+++ b/test/Android.libarttest.mk
@@ -38,6 +38,7 @@
   461-get-reference-vreg/get_reference_vreg_jni.cc \
   466-get-live-vreg/get_live_vreg_jni.cc \
   497-inlining-and-class-loader/clear_dex_cache.cc \
+  998-scoped-primitive-array/scoped_primitive_array.cc \
   999-jni-perf/perf-jni.cc
 
 ART_TARGET_LIBARTTEST_$(ART_PHONY_TEST_TARGET_SUFFIX) += $(ART_TARGET_TEST_OUT)/$(TARGET_ARCH)/libarttest.so
@@ -72,7 +73,7 @@
     LOCAL_MODULE_TAGS := tests
   endif
   LOCAL_SRC_FILES := $(LIBARTTEST_COMMON_SRC_FILES)
-  LOCAL_SHARED_LIBRARIES += libart$$(suffix) libbacktrace
+  LOCAL_SHARED_LIBRARIES += libart$$(suffix) libbacktrace libnativehelper
   LOCAL_C_INCLUDES += $(ART_C_INCLUDES) art/runtime
   LOCAL_ADDITIONAL_DEPENDENCIES := art/build/Android.common_build.mk
   LOCAL_ADDITIONAL_DEPENDENCIES += $(LOCAL_PATH)/Android.libarttest.mk