Add a debugger hook point during script group compilation at -O0.
This hook supplies the debugger with the name of the script group and the
addresses of its kernels. This allows breakpoints to be placed on a script
group, which has the effect of placing a breakpoint on its constituent kernels.
This is only executed when compiling at -O0.
Test: Run the renderscript lldb test suite.
Change-Id: I7c688d59aa702696406214423303853ec8dfa6b7
Signed-off-by: Aidan Dodds <[email protected]>
diff --git a/cpu_ref/rsCpuScriptGroup2.cpp b/cpu_ref/rsCpuScriptGroup2.cpp
index 2382cd6..2dd43ff 100644
--- a/cpu_ref/rsCpuScriptGroup2.cpp
+++ b/cpu_ref/rsCpuScriptGroup2.cpp
@@ -331,12 +331,46 @@
} // anonymous namespace
+extern __attribute__((noinline))
+void debugHintScriptGroup2(const char* groupName,
+ const uint32_t groupNameSize,
+ const ExpandFuncTy* kernel,
+ const uint32_t kernelCount) {
+ ALOGV("group name: %d:%s\n", groupNameSize, groupName);
+ for (uint32_t i=0; i < kernelCount; ++i) {
+ const char* f1 = (const char*)(kernel[i]);
+ ALOGV(" closure: %p\n", (const void*)f1);
+ }
+ // do nothing, this is just a hook point for the debugger.
+ return;
+}
+
void CpuScriptGroup2Impl::compile(const char* cacheDir) {
#ifndef RS_COMPATIBILITY_LIB
if (mGroup->mClosures.size() < 2) {
return;
}
+ const int optLevel = getCpuRefImpl()->getContext()->getOptLevel();
+ if (optLevel == 0) {
+ std::vector<ExpandFuncTy> kernels;
+ for (const Batch* b : mBatches)
+ for (const CPUClosure* c : b->mClosures)
+ kernels.push_back(c->mFunc);
+
+ if (kernels.size()) {
+ // pass this information on to the debugger via a hint function.
+ debugHintScriptGroup2(mGroup->mName,
+ strlen(mGroup->mName),
+ kernels.data(),
+ kernels.size());
+ }
+
+ // skip script group compilation forcing the driver to use the fallback
+ // execution path which currently has better support for debugging.
+ return;
+ }
+
auto comparator = [](const char* str1, const char* str2) -> bool {
return strcmp(str1, str2) < 0;
};
@@ -392,8 +426,6 @@
const string& coreLibPath = getCoreLibPath(getCpuRefImpl()->getContext(),
&coreLibRelaxedPath);
- int optLevel = getCpuRefImpl()->getContext()->getOptLevel();
-
vector<const char*> arguments;
bool emitGlobalInfo = getCpuRefImpl()->getEmbedGlobalInfo();
bool emitGlobalInfoSkipConstant = getCpuRefImpl()->getEmbedGlobalInfoSkipConstant();
diff --git a/tests/lldb/java/ScriptGroup/Android.mk b/tests/lldb/java/ScriptGroup/Android.mk
new file mode 100644
index 0000000..3540ed4
--- /dev/null
+++ b/tests/lldb/java/ScriptGroup/Android.mk
@@ -0,0 +1,12 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
+
+LOCAL_PACKAGE_NAME := ScriptGroup
+
+LOCAL_RENDERSCRIPT_FLAGS := -g -O0 -target-api 0
+
+include $(BUILD_PACKAGE)
diff --git a/tests/lldb/java/ScriptGroup/AndroidManifest.xml b/tests/lldb/java/ScriptGroup/AndroidManifest.xml
new file mode 100644
index 0000000..5288c74
--- /dev/null
+++ b/tests/lldb/java/ScriptGroup/AndroidManifest.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.rs.scriptgroup">
+ <uses-sdk android:minSdkVersion="21" />
+ <application android:label="scriptgroup"
+ android:hardwareAccelerated="true">
+ <activity android:name="MainActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
diff --git a/tests/lldb/java/ScriptGroup/res/layout/main_layout.xml b/tests/lldb/java/ScriptGroup/res/layout/main_layout.xml
new file mode 100644
index 0000000..4ef172f
--- /dev/null
+++ b/tests/lldb/java/ScriptGroup/res/layout/main_layout.xml
@@ -0,0 +1,14 @@
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="#0099cc"
+ tools:context=".MainActivity">
+
+ <ImageView
+ android:id="@+id/imageView"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:scaleType="fitCenter" />
+
+</FrameLayout>
diff --git a/tests/lldb/java/ScriptGroup/src/com/android/rs/scriptgroup/MainActivity.java b/tests/lldb/java/ScriptGroup/src/com/android/rs/scriptgroup/MainActivity.java
new file mode 100644
index 0000000..f4c81fd
--- /dev/null
+++ b/tests/lldb/java/ScriptGroup/src/com/android/rs/scriptgroup/MainActivity.java
@@ -0,0 +1,49 @@
+package com.android.rs.scriptgroup;
+
+import android.app.Activity;
+import android.graphics.Bitmap;
+import android.os.Bundle;
+import android.widget.ImageView;
+import android.renderscript.*;
+
+public class MainActivity extends Activity {
+ private static final int ARRAY_SIZE = 8;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.main_layout);
+
+ // create renderscript context
+ RenderScript pRS = RenderScript.create(this, RenderScript.ContextType.NORMAL,
+ RenderScript.CREATE_FLAG_WAIT_FOR_ATTACH | RenderScript.CREATE_FLAG_LOW_LATENCY);
+
+ ScriptC_scriptgroup script = new ScriptC_scriptgroup(pRS);
+
+ // create and initalize a simple input allocation
+ int[] array = new int[ARRAY_SIZE];
+ for (int i = 0; i < ARRAY_SIZE; i++) {
+ array[i] = i;
+ }
+ Allocation input = Allocation.createSized(pRS, Element.I32(pRS), ARRAY_SIZE);
+ input.copyFrom(array);
+
+ ScriptGroup.Builder2 builder = new ScriptGroup.Builder2(pRS);
+
+ ScriptGroup.Input unbound = builder.addInput();
+
+ ScriptGroup.Closure c0 = builder.addKernel(
+ script.getKernelID_foo(), Type.createX(pRS, Element.I32(pRS), ARRAY_SIZE), unbound);
+
+ ScriptGroup.Closure c1 = builder.addKernel(script.getKernelID_goo(),
+ Type.createX(pRS, Element.I32(pRS), ARRAY_SIZE), c0.getReturn());
+
+ ScriptGroup group = builder.create("scriptgroup_test", c1.getReturn());
+
+ int[] a = new int[ARRAY_SIZE];
+ ((Allocation) group.execute(input)[0]).copyTo(a);
+
+ pRS.finish();
+ pRS.destroy();
+ }
+}
diff --git a/tests/lldb/java/ScriptGroup/src/rs/scriptgroup.rs b/tests/lldb/java/ScriptGroup/src/rs/scriptgroup.rs
new file mode 100644
index 0000000..f364114
--- /dev/null
+++ b/tests/lldb/java/ScriptGroup/src/rs/scriptgroup.rs
@@ -0,0 +1,11 @@
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.scriptgroup)
+#pragma rs_fp_full
+
+int __attribute__((kernel)) foo(int a) {
+ return a * a;
+}
+
+int __attribute__((kernel)) goo(int a) {
+ return a + a;
+}
diff --git a/tests/lldb/tests/harness/util_bundle.py b/tests/lldb/tests/harness/util_bundle.py
index 34c0228..cadf10c 100644
--- a/tests/lldb/tests/harness/util_bundle.py
+++ b/tests/lldb/tests/harness/util_bundle.py
@@ -22,7 +22,8 @@
'KernelVariables': 'com.android.rs.kernelvariables',
'Allocations': 'com.android.rs.allocations',
'MultipleRSFiles': 'com.android.rs.multiplersfiles',
- 'SingleSource': 'com.android.rs.singlesource'
+ 'SingleSource': 'com.android.rs.singlesource',
+ 'ScriptGroup': 'com.android.rs.scriptgroup'
}
_tests_jni = {
diff --git a/tests/lldb/tests/testcases/test_script_group.py b/tests/lldb/tests/testcases/test_script_group.py
new file mode 100644
index 0000000..9655cd8
--- /dev/null
+++ b/tests/lldb/tests/testcases/test_script_group.py
@@ -0,0 +1,95 @@
+'''Module that contains the test TestScriptGroup.'''
+
+from __future__ import absolute_import
+
+from harness.test_base_remote import TestBaseRemote
+from harness.decorators import wimpy
+
+
+class TestScriptGroup(TestBaseRemote):
+ bundle_target = {
+ 'java': 'ScriptGroup'
+ }
+
+ def setup(self, android):
+ '''This test requires to be run on one thread.'''
+ android.push_prop('debug.rs.max-threads', 1)
+
+ def teardown(self, android):
+ '''Reset the number of RS threads to the previous value.'''
+ android.pop_prop('debug.rs.max-threads')
+
+ @wimpy
+ def test_kernel_backtrace(self):
+ # number of allocation elements
+ array_size = 8
+
+ self.try_command('language renderscript status',
+ ['Runtime Library discovered',
+ 'Runtime Driver discovered',
+ 'rsdDebugHintScriptGroup2'])
+
+ self.try_command('language renderscript scriptgroup breakpoint set scriptgroup_test',
+ ['Breakpoint 1: no locations (pending)'])
+
+ self.try_command('language renderscript scriptgroup list',
+ ['0 script groups'])
+
+ self.try_command('process continue',
+ ['resuming',
+ 'stopped',
+ 'stop reason = breakpoint',
+ 'librs.scriptgroup.so`foo',
+ 'scriptgroup.rs'])
+
+ self.try_command('breakpoint list',
+ ['scriptgroup_test',
+ 'locations = 1'])
+
+ self.try_command('language renderscript scriptgroup list',
+ ['1 script group',
+ 'scriptgroup_test',
+ 'foo',
+ 'goo'])
+
+ self.try_command('language renderscript scriptgroup breakpoint set --stop-on-all scriptgroup_test',
+ ['Breakpoint 2: 2 locations'])
+
+ self.try_command('breakpoint list',
+ ['scriptgroup_test',
+ 'librs.scriptgroup.so`foo',
+ 'librs.scriptgroup.so`goo'])
+
+ # iterate over foo kernels
+ self.try_command('bt',
+ ['scriptgroup.rs:',
+ 'frame #0', 'librs.scriptgroup.so`foo',
+ 'frame #1', 'librs.scriptgroup.so`foo.expand'])
+
+ for x in range(array_size):
+ self.try_command('frame var',
+ ['(int) a = {0}'.format(x)])
+ self.try_command('process continue',
+ ['resuming',
+ 'stopped',
+ 'stop reason = breakpoint',
+ 'librs.scriptgroup.so`{0}'.format(
+ 'foo' if x < 7 else 'goo')])
+
+ # iterate over goo kernels
+ self.try_command('bt',
+ ['stop reason = breakpoint',
+ 'scriptgroup.rs:',
+ 'frame #0', 'librs.scriptgroup.so`goo',
+ 'frame #1', 'librs.scriptgroup.so`goo.expand'])
+
+ for x in range(array_size):
+ self.try_command('frame var',
+ ['(int) a = {0}'.format(x * x)])
+
+ if x < 7:
+ self.try_command('process continue',
+ ['resuming',
+ 'stopped',
+ 'stop reason = breakpoint',
+ 'librs.scriptgroup.so`goo'])