Moved class ScriptExecutable to its own module
b/19283946
This move also included the related class SharedObjectUtils.
Change-Id: Iefd587b659c4ad99340c330955b41cd92df45563
diff --git a/cpu_ref/Android.mk b/cpu_ref/Android.mk
index 7c63c95..a44db9c 100644
--- a/cpu_ref/Android.mk
+++ b/cpu_ref/Android.mk
@@ -20,6 +20,7 @@
LOCAL_SRC_FILES:= \
rsCpuCore.cpp \
+ rsCpuExecutable.cpp \
rsCpuScript.cpp \
rsCpuRuntimeMath.cpp \
rsCpuRuntimeMathFuncs.cpp \
diff --git a/cpu_ref/rsCpuExecutable.cpp b/cpu_ref/rsCpuExecutable.cpp
new file mode 100644
index 0000000..ae75b07
--- /dev/null
+++ b/cpu_ref/rsCpuExecutable.cpp
@@ -0,0 +1,578 @@
+#include "rsCpuExecutable.h"
+#include "rsCppUtils.h"
+
+#include <fstream>
+#include <set>
+#include <memory>
+
+#ifdef RS_COMPATIBILITY_LIB
+#include <stdio.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#else
+#include "bcc/Config/Config.h"
+#include <bcc/Renderscript/RSInfo.h>
+#include <sys/wait.h>
+#endif
+
+#include <dlfcn.h>
+
+namespace android {
+namespace renderscript {
+
+namespace {
+
+// Create a len length string containing random characters from [A-Za-z0-9].
+static std::string getRandomString(size_t len) {
+ char buf[len + 1];
+ for (size_t i = 0; i < len; i++) {
+ uint32_t r = arc4random() & 0xffff;
+ r %= 62;
+ if (r < 26) {
+ // lowercase
+ buf[i] = 'a' + r;
+ } else if (r < 52) {
+ // uppercase
+ buf[i] = 'A' + (r - 26);
+ } else {
+ // Use a number
+ buf[i] = '0' + (r - 52);
+ }
+ }
+ buf[len] = '\0';
+ return std::string(buf);
+}
+
+// Check if a path exists and attempt to create it if it doesn't.
+static bool ensureCacheDirExists(const char *path) {
+ if (access(path, R_OK | W_OK | X_OK) == 0) {
+ // Done if we can rwx the directory
+ return true;
+ }
+ if (mkdir(path, 0700) == 0) {
+ return true;
+ }
+ return false;
+}
+
+// Copy the file named \p srcFile to \p dstFile.
+// Return 0 on success and -1 if anything wasn't copied.
+static int copyFile(const char *dstFile, const char *srcFile) {
+ std::ifstream srcStream(srcFile);
+ if (!srcStream) {
+ ALOGE("Could not verify or read source file: %s", srcFile);
+ return -1;
+ }
+ std::ofstream dstStream(dstFile);
+ if (!dstStream) {
+ ALOGE("Could not verify or write destination file: %s", dstFile);
+ return -1;
+ }
+ dstStream << srcStream.rdbuf();
+ if (!dstStream) {
+ ALOGE("Could not write destination file: %s", dstFile);
+ return -1;
+ }
+
+ srcStream.close();
+ dstStream.close();
+
+ return 0;
+}
+
+static std::string findSharedObjectName(const char *cacheDir,
+ const char *resName) {
+#ifndef RS_SERVER
+ std::string scriptSOName(cacheDir);
+#if defined(RS_COMPATIBILITY_LIB) && !defined(__LP64__)
+ size_t cutPos = scriptSOName.rfind("cache");
+ if (cutPos != std::string::npos) {
+ scriptSOName.erase(cutPos);
+ } else {
+ ALOGE("Found peculiar cacheDir (missing \"cache\"): %s", cacheDir);
+ }
+ scriptSOName.append("/lib/librs.");
+#else
+ scriptSOName.append("/librs.");
+#endif // RS_COMPATIBILITY_LIB
+
+#else
+ std::string scriptSOName("lib");
+#endif // RS_SERVER
+ scriptSOName.append(resName);
+ scriptSOName.append(".so");
+
+ return scriptSOName;
+}
+
+} // anonymous namespace
+
+const char* SharedLibraryUtils::LD_EXE_PATH = "/system/bin/ld.mc";
+const char* SharedLibraryUtils::RS_CACHE_DIR = "com.android.renderscript.cache";
+
+#ifndef RS_COMPATIBILITY_LIB
+
+bool SharedLibraryUtils::createSharedLibrary(const char *cacheDir, const char *resName) {
+ std::string sharedLibName = findSharedObjectName(cacheDir, resName);
+ std::string objFileName = cacheDir;
+ objFileName.append("/");
+ objFileName.append(resName);
+ objFileName.append(".o");
+
+ const char *compiler_rt = SYSLIBPATH"/libcompiler_rt.so";
+ std::vector<const char *> args = {
+ LD_EXE_PATH,
+ "-shared",
+ "-nostdlib",
+ compiler_rt,
+ "-mtriple", DEFAULT_TARGET_TRIPLE_STRING,
+ "-L", SYSLIBPATH,
+ "-lRSDriver", "-lm", "-lc",
+ objFileName.c_str(),
+ "-o", sharedLibName.c_str(),
+ nullptr
+ };
+
+ std::unique_ptr<const char> joined(
+ rsuJoinStrings(args.size()-1, args.data()));
+ std::string cmdLineStr (joined.get());
+
+ pid_t pid = fork();
+
+ switch (pid) {
+ case -1: { // Error occurred (we attempt no recovery)
+ ALOGE("Couldn't fork for linker (%s) execution", LD_EXE_PATH);
+ return false;
+ }
+ case 0: { // Child process
+ ALOGV("Invoking ld.mc with args '%s'", cmdLineStr.c_str());
+ execv(LD_EXE_PATH, (char* const*) args.data());
+
+ ALOGE("execv() failed: %s", strerror(errno));
+ abort();
+ return false;
+ }
+ default: { // Parent process (actual driver)
+ // Wait on child process to finish compiling the source.
+ int status = 0;
+ pid_t w = waitpid(pid, &status, 0);
+ if (w == -1) {
+ ALOGE("Could not wait for linker (%s)", LD_EXE_PATH);
+ return false;
+ }
+
+ if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
+ return true;
+ }
+
+ ALOGE("Linker (%s) terminated unexpectedly", LD_EXE_PATH);
+ return false;
+ }
+ }
+}
+
+#endif // RS_COMPATIBILITY_LIB
+
+const char* RsdCpuScriptImpl::BCC_EXE_PATH = "/system/bin/bcc";
+
+void* SharedLibraryUtils::loadSharedLibrary(const char *cacheDir,
+ const char *resName,
+ const char *nativeLibDir) {
+ void *loaded = nullptr;
+
+#if defined(RS_COMPATIBILITY_LIB) && defined(__LP64__)
+ std::string scriptSOName = findSharedObjectName(nativeLibDir, resName);
+#else
+ std::string scriptSOName = findSharedObjectName(cacheDir, resName);
+#endif
+
+ // We should check if we can load the library from the standard app
+ // location for shared libraries first.
+ loaded = loadSOHelper(scriptSOName.c_str(), cacheDir, resName);
+
+ if (loaded == nullptr) {
+ ALOGE("Unable to open shared library (%s): %s",
+ scriptSOName.c_str(), dlerror());
+
+#ifdef RS_COMPATIBILITY_LIB
+ // One final attempt to find the library in "/system/lib".
+ // We do this to allow bundled applications to use the compatibility
+ // library fallback path. Those applications don't have a private
+ // library path, so they need to install to the system directly.
+ // Note that this is really just a testing path.
+ std::string scriptSONameSystem("/system/lib/librs.");
+ scriptSONameSystem.append(resName);
+ scriptSONameSystem.append(".so");
+ loaded = loadSOHelper(scriptSONameSystem.c_str(), cacheDir,
+ resName);
+ if (loaded == nullptr) {
+ ALOGE("Unable to open system shared library (%s): %s",
+ scriptSONameSystem.c_str(), dlerror());
+ }
+#endif
+ }
+
+ return loaded;
+}
+
+void* SharedLibraryUtils::loadSOHelper(const char *origName, const char *cacheDir,
+ const char *resName) {
+ // Keep track of which .so libraries have been loaded. Once a library is
+ // in the set (per-process granularity), we must instead make a copy of
+ // the original shared object (randomly named .so file) and load that one
+ // instead. If we don't do this, we end up aliasing global data between
+ // the various Script instances (which are supposed to be completely
+ // independent).
+ static std::set<std::string> LoadedLibraries;
+
+ void *loaded = nullptr;
+
+ // Skip everything if we don't even have the original library available.
+ if (access(origName, F_OK) != 0) {
+ return nullptr;
+ }
+
+ // Common path is that we have not loaded this Script/library before.
+ if (LoadedLibraries.find(origName) == LoadedLibraries.end()) {
+ loaded = dlopen(origName, RTLD_NOW | RTLD_LOCAL);
+ if (loaded) {
+ LoadedLibraries.insert(origName);
+ }
+ return loaded;
+ }
+
+ std::string newName(cacheDir);
+
+ // Append RS_CACHE_DIR only if it is not found in cacheDir
+ // In driver mode, RS_CACHE_DIR is already appended to cacheDir.
+ if (newName.find(RS_CACHE_DIR) == std::string::npos) {
+ newName.append("/");
+ newName.append(RS_CACHE_DIR);
+ newName.append("/");
+ }
+
+ if (!ensureCacheDirExists(newName.c_str())) {
+ ALOGE("Could not verify or create cache dir: %s", cacheDir);
+ return nullptr;
+ }
+
+ // Construct an appropriately randomized filename for the copy.
+ newName.append("librs.");
+ newName.append(resName);
+ newName.append("#");
+ newName.append(getRandomString(6)); // 62^6 potential filename variants.
+ newName.append(".so");
+
+ int r = copyFile(newName.c_str(), origName);
+ if (r != 0) {
+ ALOGE("Could not create copy %s -> %s", origName, newName.c_str());
+ return nullptr;
+ }
+ loaded = dlopen(newName.c_str(), RTLD_NOW | RTLD_LOCAL);
+ r = unlink(newName.c_str());
+ if (r != 0) {
+ ALOGE("Could not unlink copy %s", newName.c_str());
+ }
+ if (loaded) {
+ LoadedLibraries.insert(newName.c_str());
+ }
+
+ return loaded;
+}
+
+#define MAXLINE 500
+#define MAKE_STR_HELPER(S) #S
+#define MAKE_STR(S) MAKE_STR_HELPER(S)
+#define EXPORT_VAR_STR "exportVarCount: "
+#define EXPORT_FUNC_STR "exportFuncCount: "
+#define EXPORT_FOREACH_STR "exportForEachCount: "
+#define OBJECT_SLOT_STR "objectSlotCount: "
+#define PRAGMA_STR "pragmaCount: "
+#define THREADABLE_STR "isThreadable: "
+
+// Copy up to a newline or size chars from str -> s, updating str
+// Returns s when successful and nullptr when '\0' is finally reached.
+static char* strgets(char *s, int size, const char **ppstr) {
+ if (!ppstr || !*ppstr || **ppstr == '\0' || size < 1) {
+ return nullptr;
+ }
+
+ int i;
+ for (i = 0; i < (size - 1); i++) {
+ s[i] = **ppstr;
+ (*ppstr)++;
+ if (s[i] == '\0') {
+ return s;
+ } else if (s[i] == '\n') {
+ s[i+1] = '\0';
+ return s;
+ }
+ }
+
+ // size has been exceeded.
+ s[i] = '\0';
+
+ return s;
+}
+
+ScriptExecutable* ScriptExecutable::createFromSharedObject(
+ Context* RSContext, void* sharedObj) {
+ char line[MAXLINE];
+
+ size_t varCount = 0;
+ size_t funcCount = 0;
+ size_t forEachCount = 0;
+ size_t objectSlotCount = 0;
+ size_t pragmaCount = 0;
+ bool isThreadable = true;
+
+ void** fieldAddress = nullptr;
+ bool* fieldIsObject = nullptr;
+ InvokeFunc_t* invokeFunctions = nullptr;
+ ForEachFunc_t* forEachFunctions = nullptr;
+ uint32_t* forEachSignatures = nullptr;
+ const char ** pragmaKeys = nullptr;
+ const char ** pragmaValues = nullptr;
+
+ const char *rsInfo = (const char *) dlsym(sharedObj, ".rs.info");
+
+ if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
+ return nullptr;
+ }
+ if (sscanf(line, EXPORT_VAR_STR "%zu", &varCount) != 1) {
+ ALOGE("Invalid export var count!: %s", line);
+ return nullptr;
+ }
+
+ fieldAddress = new void*[varCount];
+ if (fieldAddress == nullptr) {
+ return nullptr;
+ }
+
+ fieldIsObject = new bool[varCount];
+ if (fieldIsObject == nullptr) {
+ goto error;
+ }
+
+ for (size_t i = 0; i < varCount; ++i) {
+ if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
+ goto error;
+ }
+ char *c = strrchr(line, '\n');
+ if (c) {
+ *c = '\0';
+ }
+ void* addr = dlsym(sharedObj, line);
+ if (addr == nullptr) {
+ ALOGE("Failed to find variable address for %s: %s",
+ line, dlerror());
+ // Not a critical error if we don't find a global variable.
+ }
+ fieldAddress[i] = addr;
+ fieldIsObject[i] = false;
+ }
+
+ if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
+ goto error;
+ }
+ if (sscanf(line, EXPORT_FUNC_STR "%zu", &funcCount) != 1) {
+ ALOGE("Invalid export func count!: %s", line);
+ goto error;
+ }
+
+ invokeFunctions = new InvokeFunc_t[funcCount];
+ if (invokeFunctions == nullptr) {
+ goto error;
+ }
+
+ for (size_t i = 0; i < funcCount; ++i) {
+ if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
+ goto error;
+ }
+ char *c = strrchr(line, '\n');
+ if (c) {
+ *c = '\0';
+ }
+
+ invokeFunctions[i] = (InvokeFunc_t) dlsym(sharedObj, line);
+ if (invokeFunctions[i] == nullptr) {
+ ALOGE("Failed to get function address for %s(): %s",
+ line, dlerror());
+ goto error;
+ }
+ }
+
+ if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
+ goto error;
+ }
+ if (sscanf(line, EXPORT_FOREACH_STR "%zu", &forEachCount) != 1) {
+ ALOGE("Invalid export forEach count!: %s", line);
+ goto error;
+ }
+
+ forEachFunctions = new ForEachFunc_t[forEachCount];
+ if (forEachFunctions == nullptr) {
+ goto error;
+ }
+
+ forEachSignatures = new uint32_t[forEachCount];
+ if (forEachSignatures == nullptr) {
+ goto error;
+ }
+
+ for (size_t i = 0; i < forEachCount; ++i) {
+ unsigned int tmpSig = 0;
+ char tmpName[MAXLINE];
+
+ if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
+ goto error;
+ }
+ if (sscanf(line, "%u - %" MAKE_STR(MAXLINE) "s",
+ &tmpSig, tmpName) != 2) {
+ ALOGE("Invalid export forEach!: %s", line);
+ goto error;
+ }
+
+ // Lookup the expanded ForEach kernel.
+ strncat(tmpName, ".expand", MAXLINE-1-strlen(tmpName));
+ forEachSignatures[i] = tmpSig;
+ forEachFunctions[i] =
+ (ForEachFunc_t) dlsym(sharedObj, tmpName);
+ if (i != 0 && forEachFunctions[i] == nullptr) {
+ // Ignore missing root.expand functions.
+ // root() is always specified at location 0.
+ ALOGE("Failed to find forEach function address for %s: %s",
+ tmpName, dlerror());
+ goto error;
+ }
+ }
+
+ if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
+ goto error;
+ }
+ if (sscanf(line, OBJECT_SLOT_STR "%zu", &objectSlotCount) != 1) {
+ ALOGE("Invalid object slot count!: %s", line);
+ goto error;
+ }
+
+ for (size_t i = 0; i < objectSlotCount; ++i) {
+ uint32_t varNum = 0;
+ if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
+ goto error;
+ }
+ if (sscanf(line, "%u", &varNum) != 1) {
+ ALOGE("Invalid object slot!: %s", line);
+ goto error;
+ }
+
+ if (varNum < varCount) {
+ fieldIsObject[varNum] = true;
+ }
+ }
+
+#ifndef RS_COMPATIBILITY_LIB
+ // Do not attempt to read pragmas or isThreadable flag in compat lib path.
+ // Neither is applicable for compat lib
+
+ if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
+ goto error;
+ }
+
+ if (sscanf(line, PRAGMA_STR "%zu", &pragmaCount) != 1) {
+ ALOGE("Invalid pragma count!: %s", line);
+ goto error;
+ }
+
+ pragmaKeys = new const char*[pragmaCount];
+ if (pragmaKeys == nullptr) {
+ goto error;
+ }
+
+ pragmaValues = new const char*[pragmaCount];
+ if (pragmaValues == nullptr) {
+ goto error;
+ }
+
+ bzero(pragmaKeys, sizeof(char*) * pragmaCount);
+ bzero(pragmaValues, sizeof(char*) * pragmaCount);
+
+ for (size_t i = 0; i < pragmaCount; ++i) {
+ if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
+ ALOGE("Unable to read pragma at index %zu!", i);
+ goto error;
+ }
+
+ char key[MAXLINE];
+ char value[MAXLINE] = ""; // initialize in case value is empty
+
+ // pragmas can just have a key and no value. Only check to make sure
+ // that the key is not empty
+ if (sscanf(line, "%" MAKE_STR(MAXLINE) "s - %" MAKE_STR(MAXLINE) "s",
+ key, value) == 0 ||
+ strlen(key) == 0)
+ {
+ ALOGE("Invalid pragma value!: %s", line);
+
+ goto error;
+ }
+
+ char *pKey = new char[strlen(key)+1];
+ strcpy(pKey, key);
+ pragmaKeys[i] = pKey;
+
+ char *pValue = new char[strlen(value)+1];
+ strcpy(pValue, value);
+ pragmaValues[i] = pValue;
+ //ALOGE("Pragma %zu: Key: '%s' Value: '%s'", i, pKey, pValue);
+ }
+
+ if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
+ goto error;
+ }
+
+ char tmpFlag[4];
+ if (sscanf(line, THREADABLE_STR "%4s", tmpFlag) != 1) {
+ ALOGE("Invalid threadable flag!: %s", line);
+ goto error;
+ }
+ if (strcmp(tmpFlag, "yes") == 0) {
+ isThreadable = true;
+ } else if (strcmp(tmpFlag, "no") == 0) {
+ isThreadable = false;
+ } else {
+ ALOGE("Invalid threadable flag!: %s", tmpFlag);
+ goto error;
+ }
+
+#endif // RS_COMPATIBILITY_LIB
+
+ return new ScriptExecutable(
+ RSContext, fieldAddress, fieldIsObject, varCount,
+ invokeFunctions, funcCount,
+ forEachFunctions, forEachSignatures, forEachCount,
+ pragmaKeys, pragmaValues, pragmaCount,
+ isThreadable);
+
+error:
+
+#ifndef RS_COMPATIBILITY_LIB
+ for (size_t idx = 0; idx < pragmaCount; ++idx) {
+ delete [] pragmaKeys[idx];
+ delete [] pragmaValues[idx];
+ }
+
+ delete[] pragmaValues;
+ delete[] pragmaKeys;
+#endif // RS_COMPATIBILITY_LIB
+
+ delete[] forEachSignatures;
+ delete[] forEachFunctions;
+ delete[] invokeFunctions;
+ delete[] fieldIsObject;
+ delete[] fieldAddress;
+
+ return nullptr;
+}
+
+} // namespace renderscript
+} // namespace android
diff --git a/cpu_ref/rsCpuExecutable.h b/cpu_ref/rsCpuExecutable.h
new file mode 100644
index 0000000..acf092c
--- /dev/null
+++ b/cpu_ref/rsCpuExecutable.h
@@ -0,0 +1,145 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_RENDERSCRIPT_EXECUTABLE_H
+#define ANDROID_RENDERSCRIPT_EXECUTABLE_H
+
+#include <stdlib.h>
+
+#include "rsCpuScript.h"
+
+namespace android {
+namespace renderscript {
+
+class Context;
+
+class SharedLibraryUtils {
+public:
+#ifndef RS_COMPATIBILITY_LIB
+ static bool createSharedLibrary(const char* cacheDir, const char* resName);
+#endif
+
+ // Load the shared library referred to by cacheDir and resName. If we have
+ // already loaded this library, we instead create a new copy (in the
+ // cache dir) and then load that. We then immediately destroy the copy.
+ // This is required behavior to implement script instancing for the support
+ // library, since shared objects are loaded and de-duped by name only.
+
+ // For 64bit RS Support Lib, the shared lib path cannot be constructed from
+ // cacheDir, so nativeLibDir is needed to load shared libs.
+ static void* loadSharedLibrary(const char *cacheDir, const char *resName,
+ const char *nativeLibDir = nullptr);
+
+private:
+ // Attempt to load the shared library from origName, but then fall back to
+ // creating a copy of the shared library if necessary (to ensure instancing).
+ // This function returns the dlopen()-ed handle if successful.
+ static void *loadSOHelper(const char *origName, const char *cacheDir,
+ const char *resName);
+
+ static const char* LD_EXE_PATH;
+ static const char* RS_CACHE_DIR;
+};
+
+class ScriptExecutable {
+public:
+ ScriptExecutable(Context* RSContext,
+ void** fieldAddress, bool* fieldIsObject, size_t varCount,
+ InvokeFunc_t* invokeFunctions, size_t funcCount,
+ ForEachFunc_t* forEachFunctions, uint32_t* forEachSignatures,
+ size_t forEachCount,
+ const char ** pragmaKeys, const char ** pragmaValues,
+ size_t pragmaCount,
+ bool isThreadable) :
+ mFieldAddress(fieldAddress), mFieldIsObject(fieldIsObject),
+ mExportedVarCount(varCount),
+ mInvokeFunctions(invokeFunctions), mFuncCount(funcCount),
+ mForEachFunctions(forEachFunctions), mForEachSignatures(forEachSignatures),
+ mForEachCount(forEachCount),
+ mPragmaKeys(pragmaKeys), mPragmaValues(pragmaValues),
+ mPragmaCount(pragmaCount),
+ mIsThreadable(isThreadable), mRS(RSContext) {
+ }
+
+ ~ScriptExecutable() {
+ for (size_t i = 0; i < mExportedVarCount; ++i) {
+ if (mFieldIsObject[i]) {
+ if (mFieldAddress[i] != nullptr) {
+ rs_object_base *obj_addr =
+ reinterpret_cast<rs_object_base *>(mFieldAddress[i]);
+ rsrClearObject(mRS, obj_addr);
+ }
+ }
+ }
+
+ for (size_t i = 0; i < mPragmaCount; ++i) {
+ delete [] mPragmaKeys[i];
+ delete [] mPragmaValues[i];
+ }
+
+ delete[] mPragmaValues;
+ delete[] mPragmaKeys;
+ delete[] mForEachSignatures;
+ delete[] mForEachFunctions;
+ delete[] mInvokeFunctions;
+ delete[] mFieldIsObject;
+ delete[] mFieldAddress;
+ }
+
+ static ScriptExecutable*
+ createFromSharedObject(Context* RSContext, void* sharedObj);
+
+ size_t getExportedVariableCount() const { return mExportedVarCount; }
+ size_t getExportedFunctionCount() const { return mFuncCount; }
+ size_t getExportedForEachCount() const { return mForEachCount; }
+ size_t getPragmaCount() const { return mPragmaCount; }
+
+ void* getFieldAddress(int slot) const { return mFieldAddress[slot]; }
+ bool getFieldIsObject(int slot) const { return mFieldIsObject[slot]; }
+ InvokeFunc_t getInvokeFunction(int slot) const { return mInvokeFunctions[slot]; }
+ ForEachFunc_t getForEachFunction(int slot) const { return mForEachFunctions[slot]; }
+ uint32_t getForEachSignature(int slot) const { return mForEachSignatures[slot]; }
+
+ const char ** getPragmaKeys() const { return mPragmaKeys; }
+ const char ** getPragmaValues() const { return mPragmaValues; }
+
+ bool getThreadable() const { return mIsThreadable; }
+
+private:
+ void** mFieldAddress;
+ bool* mFieldIsObject;
+ size_t mExportedVarCount;
+
+ InvokeFunc_t* mInvokeFunctions;
+ size_t mFuncCount;
+
+ ForEachFunc_t* mForEachFunctions;
+ uint32_t* mForEachSignatures;
+ size_t mForEachCount;
+
+ const char ** mPragmaKeys;
+ const char ** mPragmaValues;
+ size_t mPragmaCount;
+
+ bool mIsThreadable;
+
+ Context* mRS;
+};
+
+} // namespace renderscript
+} // namespace android
+
+#endif // ANDROID_RENDERSCRIPT_EXECUTABLE_H
diff --git a/cpu_ref/rsCpuScript.cpp b/cpu_ref/rsCpuScript.cpp
index 1c7fdac..af8b640 100644
--- a/cpu_ref/rsCpuScript.cpp
+++ b/cpu_ref/rsCpuScript.cpp
@@ -16,6 +16,7 @@
#include "rsCpuCore.h"
#include "rsCpuScript.h"
+#include "rsCpuExecutable.h"
#ifdef RS_COMPATIBILITY_LIB
#include <stdio.h>
@@ -41,7 +42,6 @@
#include <dlfcn.h>
#include <stdlib.h>
#include <string.h>
-#include <fstream>
#include <iostream>
#ifdef __LP64__
@@ -51,90 +51,6 @@
#endif
namespace {
-
-// Create a len length string containing random characters from [A-Za-z0-9].
-static std::string getRandomString(size_t len) {
- char buf[len + 1];
- for (size_t i = 0; i < len; i++) {
- uint32_t r = arc4random() & 0xffff;
- r %= 62;
- if (r < 26) {
- // lowercase
- buf[i] = 'a' + r;
- } else if (r < 52) {
- // uppercase
- buf[i] = 'A' + (r - 26);
- } else {
- // Use a number
- buf[i] = '0' + (r - 52);
- }
- }
- buf[len] = '\0';
- return std::string(buf);
-}
-
-// Check if a path exists and attempt to create it if it doesn't.
-static bool ensureCacheDirExists(const char *path) {
- if (access(path, R_OK | W_OK | X_OK) == 0) {
- // Done if we can rwx the directory
- return true;
- }
- if (mkdir(path, 0700) == 0) {
- return true;
- }
- return false;
-}
-
-// Copy the file named \p srcFile to \p dstFile.
-// Return 0 on success and -1 if anything wasn't copied.
-static int copyFile(const char *dstFile, const char *srcFile) {
- std::ifstream srcStream(srcFile);
- if (!srcStream) {
- ALOGE("Could not verify or read source file: %s", srcFile);
- return -1;
- }
- std::ofstream dstStream(dstFile);
- if (!dstStream) {
- ALOGE("Could not verify or write destination file: %s", dstFile);
- return -1;
- }
- dstStream << srcStream.rdbuf();
- if (!dstStream) {
- ALOGE("Could not write destination file: %s", dstFile);
- return -1;
- }
-
- srcStream.close();
- dstStream.close();
-
- return 0;
-}
-
-static std::string findSharedObjectName(const char *cacheDir,
- const char *resName) {
-#ifndef RS_SERVER
- std::string scriptSOName(cacheDir);
-#if defined(RS_COMPATIBILITY_LIB) && !defined(__LP64__)
- size_t cutPos = scriptSOName.rfind("cache");
- if (cutPos != std::string::npos) {
- scriptSOName.erase(cutPos);
- } else {
- ALOGE("Found peculiar cacheDir (missing \"cache\"): %s", cacheDir);
- }
- scriptSOName.append("/lib/librs.");
-#else
- scriptSOName.append("/librs.");
-#endif // RS_COMPATIBILITY_LIB
-
-#else
- std::string scriptSOName("lib");
-#endif // RS_SERVER
- scriptSOName.append(resName);
- scriptSOName.append(".so");
-
- return scriptSOName;
-}
-
#ifndef RS_COMPATIBILITY_LIB
static bool is_force_recompile() {
@@ -256,228 +172,12 @@
}
}
-std::string getCommandLine(int argc, const char* const* argv) {
- std::string s;
- for (int i = 0; i < argc; i++) {
- if (i > 0) {
- s += ' ';
- }
- s += argv[i];
- }
- return s;
-}
-
#endif // !defined(RS_COMPATIBILITY_LIB)
} // namespace
namespace android {
namespace renderscript {
-const char* SharedLibraryUtils::LD_EXE_PATH = "/system/bin/ld.mc";
-const char* SharedLibraryUtils::RS_CACHE_DIR = "com.android.renderscript.cache";
-
-#ifndef RS_COMPATIBILITY_LIB
-
-bool SharedLibraryUtils::createSharedLibrary(const char *cacheDir, const char *resName) {
- std::string sharedLibName = findSharedObjectName(cacheDir, resName);
- std::string objFileName = cacheDir;
- objFileName.append("/");
- objFileName.append(resName);
- objFileName.append(".o");
-
- const char *compiler_rt = SYSLIBPATH"/libcompiler_rt.so";
- std::vector<const char *> args = {
- LD_EXE_PATH,
- "-shared",
- "-nostdlib",
- compiler_rt,
- "-mtriple", DEFAULT_TARGET_TRIPLE_STRING,
- "-L", SYSLIBPATH,
- "-lRSDriver", "-lm", "-lc",
- objFileName.c_str(),
- "-o", sharedLibName.c_str(),
- nullptr
- };
-
- std::string cmdLineStr = getCommandLine(args.size()-1, args.data());
-
- pid_t pid = fork();
-
- switch (pid) {
- case -1: { // Error occurred (we attempt no recovery)
- ALOGE("Couldn't fork for linker (%s) execution", LD_EXE_PATH);
- return false;
- }
- case 0: { // Child process
- ALOGV("Invoking ld.mc with args '%s'", cmdLineStr.c_str());
- execv(LD_EXE_PATH, (char* const*) args.data());
-
- ALOGE("execv() failed: %s", strerror(errno));
- abort();
- return false;
- }
- default: { // Parent process (actual driver)
- // Wait on child process to finish compiling the source.
- int status = 0;
- pid_t w = waitpid(pid, &status, 0);
- if (w == -1) {
- ALOGE("Could not wait for linker (%s)", LD_EXE_PATH);
- return false;
- }
-
- if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
- return true;
- }
-
- ALOGE("Linker (%s) terminated unexpectedly", LD_EXE_PATH);
- return false;
- }
- }
-}
-
-#endif // RS_COMPATIBILITY_LIB
-
-
-void* SharedLibraryUtils::loadSharedLibrary(const char *cacheDir, const char *resName, const char *nativeLibDir) {
- void *loaded = nullptr;
-
-#if defined(RS_COMPATIBILITY_LIB) && defined(__LP64__)
- std::string scriptSOName = findSharedObjectName(nativeLibDir, resName);
-#else
- std::string scriptSOName = findSharedObjectName(cacheDir, resName);
-#endif
-
- // We should check if we can load the library from the standard app
- // location for shared libraries first.
- loaded = loadSOHelper(scriptSOName.c_str(), cacheDir, resName);
-
- if (loaded == nullptr) {
- ALOGE("Unable to open shared library (%s): %s",
- scriptSOName.c_str(), dlerror());
-
-#ifdef RS_COMPATIBILITY_LIB
- // One final attempt to find the library in "/system/lib".
- // We do this to allow bundled applications to use the compatibility
- // library fallback path. Those applications don't have a private
- // library path, so they need to install to the system directly.
- // Note that this is really just a testing path.
- std::string scriptSONameSystem("/system/lib/librs.");
- scriptSONameSystem.append(resName);
- scriptSONameSystem.append(".so");
- loaded = loadSOHelper(scriptSONameSystem.c_str(), cacheDir,
- resName);
- if (loaded == nullptr) {
- ALOGE("Unable to open system shared library (%s): %s",
- scriptSONameSystem.c_str(), dlerror());
- }
-#endif
- }
-
- return loaded;
-}
-
-void* SharedLibraryUtils::loadSOHelper(const char *origName, const char *cacheDir,
- const char *resName) {
- // Keep track of which .so libraries have been loaded. Once a library is
- // in the set (per-process granularity), we must instead make a copy of
- // the original shared object (randomly named .so file) and load that one
- // instead. If we don't do this, we end up aliasing global data between
- // the various Script instances (which are supposed to be completely
- // independent).
- static std::set<std::string> LoadedLibraries;
-
- void *loaded = nullptr;
-
- // Skip everything if we don't even have the original library available.
- if (access(origName, F_OK) != 0) {
- return nullptr;
- }
-
- // Common path is that we have not loaded this Script/library before.
- if (LoadedLibraries.find(origName) == LoadedLibraries.end()) {
- loaded = dlopen(origName, RTLD_NOW | RTLD_LOCAL);
- if (loaded) {
- LoadedLibraries.insert(origName);
- }
- return loaded;
- }
-
- std::string newName(cacheDir);
-
- // Append RS_CACHE_DIR only if it is not found in cacheDir
- // In driver mode, RS_CACHE_DIR is already appended to cacheDir.
- if (newName.find(RS_CACHE_DIR) == std::string::npos) {
- newName.append("/");
- newName.append(RS_CACHE_DIR);
- newName.append("/");
- }
-
- if (!ensureCacheDirExists(newName.c_str())) {
- ALOGE("Could not verify or create cache dir: %s", cacheDir);
- return nullptr;
- }
-
- // Construct an appropriately randomized filename for the copy.
- newName.append("librs.");
- newName.append(resName);
- newName.append("#");
- newName.append(getRandomString(6)); // 62^6 potential filename variants.
- newName.append(".so");
-
- int r = copyFile(newName.c_str(), origName);
- if (r != 0) {
- ALOGE("Could not create copy %s -> %s", origName, newName.c_str());
- return nullptr;
- }
- loaded = dlopen(newName.c_str(), RTLD_NOW | RTLD_LOCAL);
- r = unlink(newName.c_str());
- if (r != 0) {
- ALOGE("Could not unlink copy %s", newName.c_str());
- }
- if (loaded) {
- LoadedLibraries.insert(newName.c_str());
- }
-
- return loaded;
-}
-
-const char* RsdCpuScriptImpl::BCC_EXE_PATH = "/system/bin/bcc";
-
-#define MAXLINE 500
-#define MAKE_STR_HELPER(S) #S
-#define MAKE_STR(S) MAKE_STR_HELPER(S)
-#define EXPORT_VAR_STR "exportVarCount: "
-#define EXPORT_FUNC_STR "exportFuncCount: "
-#define EXPORT_FOREACH_STR "exportForEachCount: "
-#define OBJECT_SLOT_STR "objectSlotCount: "
-#define PRAGMA_STR "pragmaCount: "
-#define THREADABLE_STR "isThreadable: "
-
-// Copy up to a newline or size chars from str -> s, updating str
-// Returns s when successful and nullptr when '\0' is finally reached.
-static char* strgets(char *s, int size, const char **ppstr) {
- if (!ppstr || !*ppstr || **ppstr == '\0' || size < 1) {
- return nullptr;
- }
-
- int i;
- for (i = 0; i < (size - 1); i++) {
- s[i] = **ppstr;
- (*ppstr)++;
- if (s[i] == '\0') {
- return s;
- } else if (s[i] == '\n') {
- s[i+1] = '\0';
- return s;
- }
- }
-
- // size has been exceeded.
- s[i] = '\0';
-
- return s;
-}
-
RsdCpuScriptImpl::RsdCpuScriptImpl(RsdCpuReferenceImpl *ctx, const Script *s) {
mCtx = ctx;
mScript = s;
@@ -537,265 +237,6 @@
return true;
}
-ScriptExecutable* ScriptExecutable::createFromSharedObject(
- Context* RSContext, void* sharedObj) {
- char line[MAXLINE];
-
- size_t varCount = 0;
- size_t funcCount = 0;
- size_t forEachCount = 0;
- size_t objectSlotCount = 0;
- size_t pragmaCount = 0;
- bool isThreadable = true;
-
- void** fieldAddress = nullptr;
- bool* fieldIsObject = nullptr;
- InvokeFunc_t* invokeFunctions = nullptr;
- ForEachFunc_t* forEachFunctions = nullptr;
- uint32_t* forEachSignatures = nullptr;
- const char ** pragmaKeys = nullptr;
- const char ** pragmaValues = nullptr;
-
- const char *rsInfo = (const char *) dlsym(sharedObj, ".rs.info");
-
- if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
- return nullptr;
- }
- if (sscanf(line, EXPORT_VAR_STR "%zu", &varCount) != 1) {
- ALOGE("Invalid export var count!: %s", line);
- return nullptr;
- }
-
- fieldAddress = new void*[varCount];
- if (fieldAddress == nullptr) {
- return nullptr;
- }
-
- fieldIsObject = new bool[varCount];
- if (fieldIsObject == nullptr) {
- goto error;
- }
-
- for (size_t i = 0; i < varCount; ++i) {
- if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
- goto error;
- }
- char *c = strrchr(line, '\n');
- if (c) {
- *c = '\0';
- }
- void* addr = dlsym(sharedObj, line);
- if (addr == nullptr) {
- ALOGE("Failed to find variable address for %s: %s",
- line, dlerror());
- // Not a critical error if we don't find a global variable.
- }
- fieldAddress[i] = addr;
- fieldIsObject[i] = false;
- }
-
- if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
- goto error;
- }
- if (sscanf(line, EXPORT_FUNC_STR "%zu", &funcCount) != 1) {
- ALOGE("Invalid export func count!: %s", line);
- goto error;
- }
-
- invokeFunctions = new InvokeFunc_t[funcCount];
- if (invokeFunctions == nullptr) {
- goto error;
- }
-
- for (size_t i = 0; i < funcCount; ++i) {
- if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
- goto error;
- }
- char *c = strrchr(line, '\n');
- if (c) {
- *c = '\0';
- }
-
- invokeFunctions[i] = (InvokeFunc_t) dlsym(sharedObj, line);
- if (invokeFunctions[i] == nullptr) {
- ALOGE("Failed to get function address for %s(): %s",
- line, dlerror());
- goto error;
- }
- }
-
- if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
- goto error;
- }
- if (sscanf(line, EXPORT_FOREACH_STR "%zu", &forEachCount) != 1) {
- ALOGE("Invalid export forEach count!: %s", line);
- goto error;
- }
-
- forEachFunctions = new ForEachFunc_t[forEachCount];
- if (forEachFunctions == nullptr) {
- goto error;
- }
-
- forEachSignatures = new uint32_t[forEachCount];
- if (forEachSignatures == nullptr) {
- goto error;
- }
-
- for (size_t i = 0; i < forEachCount; ++i) {
- unsigned int tmpSig = 0;
- char tmpName[MAXLINE];
-
- if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
- goto error;
- }
- if (sscanf(line, "%u - %" MAKE_STR(MAXLINE) "s",
- &tmpSig, tmpName) != 2) {
- ALOGE("Invalid export forEach!: %s", line);
- goto error;
- }
-
- // Lookup the expanded ForEach kernel.
- strncat(tmpName, ".expand", MAXLINE-1-strlen(tmpName));
- forEachSignatures[i] = tmpSig;
- forEachFunctions[i] =
- (ForEachFunc_t) dlsym(sharedObj, tmpName);
- if (i != 0 && forEachFunctions[i] == nullptr) {
- // Ignore missing root.expand functions.
- // root() is always specified at location 0.
- ALOGE("Failed to find forEach function address for %s: %s",
- tmpName, dlerror());
- goto error;
- }
- }
-
- if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
- goto error;
- }
- if (sscanf(line, OBJECT_SLOT_STR "%zu", &objectSlotCount) != 1) {
- ALOGE("Invalid object slot count!: %s", line);
- goto error;
- }
-
- for (size_t i = 0; i < objectSlotCount; ++i) {
- uint32_t varNum = 0;
- if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
- goto error;
- }
- if (sscanf(line, "%u", &varNum) != 1) {
- ALOGE("Invalid object slot!: %s", line);
- goto error;
- }
-
- if (varNum < varCount) {
- fieldIsObject[varNum] = true;
- }
- }
-
-#ifndef RS_COMPATIBILITY_LIB
- // Do not attempt to read pragmas or isThreadable flag in compat lib path.
- // Neither is applicable for compat lib
-
- if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
- goto error;
- }
-
- if (sscanf(line, PRAGMA_STR "%zu", &pragmaCount) != 1) {
- ALOGE("Invalid pragma count!: %s", line);
- goto error;
- }
-
- pragmaKeys = new const char*[pragmaCount];
- if (pragmaKeys == nullptr) {
- goto error;
- }
-
- pragmaValues = new const char*[pragmaCount];
- if (pragmaValues == nullptr) {
- goto error;
- }
-
- bzero(pragmaKeys, sizeof(char*) * pragmaCount);
- bzero(pragmaValues, sizeof(char*) * pragmaCount);
-
- for (size_t i = 0; i < pragmaCount; ++i) {
- if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
- ALOGE("Unable to read pragma at index %zu!", i);
- goto error;
- }
-
- char key[MAXLINE];
- char value[MAXLINE] = ""; // initialize in case value is empty
-
- // pragmas can just have a key and no value. Only check to make sure
- // that the key is not empty
- if (sscanf(line, "%" MAKE_STR(MAXLINE) "s - %" MAKE_STR(MAXLINE) "s",
- key, value) == 0 ||
- strlen(key) == 0)
- {
- ALOGE("Invalid pragma value!: %s", line);
-
- goto error;
- }
-
- char *pKey = new char[strlen(key)+1];
- strcpy(pKey, key);
- pragmaKeys[i] = pKey;
-
- char *pValue = new char[strlen(value)+1];
- strcpy(pValue, value);
- pragmaValues[i] = pValue;
- //ALOGE("Pragma %zu: Key: '%s' Value: '%s'", i, pKey, pValue);
- }
-
- if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
- goto error;
- }
-
- char tmpFlag[4];
- if (sscanf(line, THREADABLE_STR "%4s", tmpFlag) != 1) {
- ALOGE("Invalid threadable flag!: %s", line);
- goto error;
- }
- if (strcmp(tmpFlag, "yes") == 0) {
- isThreadable = true;
- } else if (strcmp(tmpFlag, "no") == 0) {
- isThreadable = false;
- } else {
- ALOGE("Invalid threadable flag!: %s", tmpFlag);
- goto error;
- }
-
-#endif // RS_COMPATIBILITY_LIB
-
- return new ScriptExecutable(
- RSContext, fieldAddress, fieldIsObject, varCount,
- invokeFunctions, funcCount,
- forEachFunctions, forEachSignatures, forEachCount,
- pragmaKeys, pragmaValues, pragmaCount,
- isThreadable);
-
-error:
-
-#ifndef RS_COMPATIBILITY_LIB
- for (size_t idx = 0; idx < pragmaCount; ++idx) {
- delete [] pragmaKeys[idx];
- delete [] pragmaValues[idx];
- }
-
- delete[] pragmaValues;
- delete[] pragmaKeys;
-#endif // RS_COMPATIBILITY_LIB
-
- delete[] forEachSignatures;
- delete[] forEachFunctions;
- delete[] invokeFunctions;
- delete[] fieldIsObject;
- delete[] fieldAddress;
-
- return nullptr;
-}
-
bool RsdCpuScriptImpl::init(char const *resName, char const *cacheDir,
uint8_t const *bitcode, size_t bitcodeSize,
uint32_t flags, char const *bccPluginName) {
@@ -846,8 +287,9 @@
setCompileArguments(&compileArguments, bcFileName, cacheDir, resName, core_lib,
useRSDebugContext, bccPluginName);
// The last argument of compileArguments ia a nullptr, so remove 1 from the size.
- std::string compileCommandLine =
- getCommandLine(compileArguments.size() - 1, compileArguments.data());
+ std::unique_ptr<const char> joined(
+ rsuJoinStrings(compileArguments.size() - 1, compileArguments.data()));
+ std::string compileCommandLine (joined.get());
if (!is_force_recompile() && !useRSDebugContext) {
mScriptSO = SharedLibraryUtils::loadSharedLibrary(cacheDir, resName);
diff --git a/cpu_ref/rsCpuScript.h b/cpu_ref/rsCpuScript.h
index a775c73..03aabf4 100644
--- a/cpu_ref/rsCpuScript.h
+++ b/cpu_ref/rsCpuScript.h
@@ -38,118 +38,7 @@
namespace android {
namespace renderscript {
-class SharedLibraryUtils {
- public:
-#ifndef RS_COMPATIBILITY_LIB
- static bool createSharedLibrary(const char* cacheDir, const char* resName);
-#endif
-
- // Load the shared library referred to by cacheDir and resName. If we have
- // already loaded this library, we instead create a new copy (in the
- // cache dir) and then load that. We then immediately destroy the copy.
- // This is required behavior to implement script instancing for the support
- // library, since shared objects are loaded and de-duped by name only.
-
- // For 64bit RS Support Lib, the shared lib path cannot be constructed from
- // cacheDir, so nativeLibDir is needed to load shared libs.
- static void* loadSharedLibrary(const char *cacheDir, const char *resName,
- const char *nativeLibDir = nullptr);
-
- private:
- // Attempt to load the shared library from origName, but then fall back to
- // creating a copy of the shared library if necessary (to ensure instancing).
- // This function returns the dlopen()-ed handle if successful.
- static void *loadSOHelper(const char *origName, const char *cacheDir,
- const char *resName);
-
- static const char* LD_EXE_PATH;
- static const char* RS_CACHE_DIR;
-};
-
-class ScriptExecutable {
- public:
- ScriptExecutable(Context* RSContext,
- void** fieldAddress, bool* fieldIsObject, size_t varCount,
- InvokeFunc_t* invokeFunctions, size_t funcCount,
- ForEachFunc_t* forEachFunctions, uint32_t* forEachSignatures,
- size_t forEachCount,
- const char ** pragmaKeys, const char ** pragmaValues,
- size_t pragmaCount,
- bool isThreadable) :
- mFieldAddress(fieldAddress), mFieldIsObject(fieldIsObject),
- mExportedVarCount(varCount),
- mInvokeFunctions(invokeFunctions), mFuncCount(funcCount),
- mForEachFunctions(forEachFunctions), mForEachSignatures(forEachSignatures),
- mForEachCount(forEachCount),
- mPragmaKeys(pragmaKeys), mPragmaValues(pragmaValues),
- mPragmaCount(pragmaCount),
- mIsThreadable(isThreadable), mRS(RSContext) {
- }
-
- ~ScriptExecutable() {
- for (size_t i = 0; i < mExportedVarCount; ++i) {
- if (mFieldIsObject[i]) {
- if (mFieldAddress[i] != nullptr) {
- rs_object_base *obj_addr =
- reinterpret_cast<rs_object_base *>(mFieldAddress[i]);
- rsrClearObject(mRS, obj_addr);
- }
- }
- }
-
- for (size_t i = 0; i < mPragmaCount; ++i) {
- delete [] mPragmaKeys[i];
- delete [] mPragmaValues[i];
- }
-
- delete[] mPragmaValues;
- delete[] mPragmaKeys;
- delete[] mForEachSignatures;
- delete[] mForEachFunctions;
- delete[] mInvokeFunctions;
- delete[] mFieldIsObject;
- delete[] mFieldAddress;
- }
-
- static ScriptExecutable*
- createFromSharedObject(Context* RSContext, void* sharedObj);
-
- size_t getExportedVariableCount() const { return mExportedVarCount; }
- size_t getExportedFunctionCount() const { return mFuncCount; }
- size_t getExportedForEachCount() const { return mForEachCount; }
- size_t getPragmaCount() const { return mPragmaCount; }
-
- void* getFieldAddress(int slot) const { return mFieldAddress[slot]; }
- bool getFieldIsObject(int slot) const { return mFieldIsObject[slot]; }
- InvokeFunc_t getInvokeFunction(int slot) const { return mInvokeFunctions[slot]; }
- ForEachFunc_t getForEachFunction(int slot) const { return mForEachFunctions[slot]; }
- uint32_t getForEachSignature(int slot) const { return mForEachSignatures[slot]; }
-
- const char ** getPragmaKeys() const { return mPragmaKeys; }
- const char ** getPragmaValues() const { return mPragmaValues; }
-
- bool getThreadable() const { return mIsThreadable; }
-
- private:
- void** mFieldAddress;
- bool* mFieldIsObject;
- size_t mExportedVarCount;
-
- InvokeFunc_t* mInvokeFunctions;
- size_t mFuncCount;
-
- ForEachFunc_t* mForEachFunctions;
- uint32_t* mForEachSignatures;
- size_t mForEachCount;
-
- const char ** mPragmaKeys;
- const char ** mPragmaValues;
- size_t mPragmaCount;
-
- bool mIsThreadable;
-
- Context* mRS;
-};
+class ScriptExecutable;
class RsdCpuScriptImpl : public RsdCpuReferenceImpl::CpuScript {
public:
@@ -240,12 +129,12 @@
void * mIntrinsicData;
bool mIsThreadable;
- public:
- static const char* BCC_EXE_PATH;
- const char* getBitcodeFilePath() const { return mBitcodeFilePath.string(); }
+public:
+ static const char* BCC_EXE_PATH;
+ const char* getBitcodeFilePath() const { return mBitcodeFilePath.string(); }
- private:
- String8 mBitcodeFilePath;
+private:
+ String8 mBitcodeFilePath;
};
Allocation * rsdScriptGetAllocationForPointer(
diff --git a/cpu_ref/rsCpuScriptGroup2.cpp b/cpu_ref/rsCpuScriptGroup2.cpp
index 80c46a0..bd47403 100644
--- a/cpu_ref/rsCpuScriptGroup2.cpp
+++ b/cpu_ref/rsCpuScriptGroup2.cpp
@@ -14,6 +14,7 @@
#include "rsClosure.h"
#include "rsContext.h"
#include "rsCpuCore.h"
+#include "rsCpuExecutable.h"
#include "rsCpuScript.h"
#include "rsScript.h"
#include "rsScriptGroup2.h"
@@ -210,16 +211,6 @@
args->push_back(nullptr);
}
-string convertListToString(int n, const char* const* strs) {
- string ret;
- ret.append(strs[0]);
- for (int i = 1; i < n; i++) {
- ret.append(" ");
- ret.append(strs[i]);
- }
- return ret;
-}
-
bool fuseAndCompile(const char** arguments,
const string& commandLine) {
const pid_t pid = fork();
@@ -296,8 +287,9 @@
vector<const char*> arguments;
setupCompileArguments(inputFiles, slots, cacheDir, outputFileName, rsLibPath,
&arguments);
- string commandLine =
- convertListToString(arguments.size() - 1, arguments.data());
+ std::unique_ptr<const char> joined(
+ rsuJoinStrings(arguments.size() - 1, arguments.data()));
+ string commandLine (joined.get());
if (!fuseAndCompile(arguments.data(), commandLine)) {
return;
diff --git a/rsCppUtils.cpp b/rsCppUtils.cpp
index 79cb4d3..c9a19c2 100644
--- a/rsCppUtils.cpp
+++ b/rsCppUtils.cpp
@@ -17,6 +17,8 @@
#include "rsUtils.h"
#include "rsCppUtils.h"
+#include <string>
+
#include <string.h>
namespace android {
@@ -33,6 +35,16 @@
return n;
}
+const char* rsuJoinStrings(int n, const char* const* strs) {
+ std::string tmp;
+ for (int i = 0; i < n; i++) {
+ if (i > 0) {
+ tmp.append(" ");
+ }
+ tmp.append(strs[i]);
+ }
+ return strndup(tmp.c_str(), tmp.size());
+}
}
}
diff --git a/rsCppUtils.h b/rsCppUtils.h
index 1f792bc..cc6d6cf 100644
--- a/rsCppUtils.h
+++ b/rsCppUtils.h
@@ -180,7 +180,6 @@
return secs/1000000;
}
-
#endif // RS_SERVER || RS_COMPATIBILITY_LIB
namespace android {
@@ -282,6 +281,8 @@
return (r >> 2) | ((g >> 2) << 8) | ((b >> 2) << 16) | ((a >> 2) << 24);
}
+const char* rsuJoinStrings(int n, const char* const* strs);
+
}
}