1709a0978ae141198018ca9769f8d96292a8928e6Jason Sams/* 2709a0978ae141198018ca9769f8d96292a8928e6Jason Sams * Copyright (C) 2011-2012 The Android Open Source Project 3709a0978ae141198018ca9769f8d96292a8928e6Jason Sams * 4709a0978ae141198018ca9769f8d96292a8928e6Jason Sams * Licensed under the Apache License, Version 2.0 (the "License"); 5709a0978ae141198018ca9769f8d96292a8928e6Jason Sams * you may not use this file except in compliance with the License. 6709a0978ae141198018ca9769f8d96292a8928e6Jason Sams * You may obtain a copy of the License at 7709a0978ae141198018ca9769f8d96292a8928e6Jason Sams * 8709a0978ae141198018ca9769f8d96292a8928e6Jason Sams * http://www.apache.org/licenses/LICENSE-2.0 9709a0978ae141198018ca9769f8d96292a8928e6Jason Sams * 10709a0978ae141198018ca9769f8d96292a8928e6Jason Sams * Unless required by applicable law or agreed to in writing, software 11709a0978ae141198018ca9769f8d96292a8928e6Jason Sams * distributed under the License is distributed on an "AS IS" BASIS, 12709a0978ae141198018ca9769f8d96292a8928e6Jason Sams * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13709a0978ae141198018ca9769f8d96292a8928e6Jason Sams * See the License for the specific language governing permissions and 14709a0978ae141198018ca9769f8d96292a8928e6Jason Sams * limitations under the License. 15709a0978ae141198018ca9769f8d96292a8928e6Jason Sams */ 16709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 17709a0978ae141198018ca9769f8d96292a8928e6Jason Sams#include "rsCpuCore.h" 18709a0978ae141198018ca9769f8d96292a8928e6Jason Sams#include "rsCpuScript.h" 19709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 20110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams#ifdef RS_COMPATIBILITY_LIB 21c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines #include <set> 22c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines #include <string> 23110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams #include <dlfcn.h> 24110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams #include <stdio.h> 25c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines #include <stdlib.h> 26110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams #include <string.h> 27661a62c34b6b6892346274272a5537e5e68c712cStephen Hines #include <sys/stat.h> 28c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines #include <unistd.h> 29110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams#else 30110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams #include <bcc/BCCContext.h> 31110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams #include <bcc/Renderscript/RSCompilerDriver.h> 32110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams #include <bcc/Renderscript/RSExecutable.h> 33110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams #include <bcc/Renderscript/RSInfo.h> 34b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines #include <bcinfo/MetadataExtractor.h> 35ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines #include <cutils/properties.h> 36b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines 37b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines #include <sys/types.h> 38b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines #include <sys/wait.h> 39b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines #include <unistd.h> 40110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams#endif 41709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 42ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hinesnamespace { 43c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines#ifdef RS_COMPATIBILITY_LIB 44c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines 45c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines// Create a len length string containing random characters from [A-Za-z0-9]. 46c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hinesstatic std::string getRandomString(size_t len) { 47c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines char buf[len + 1]; 48c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines for (size_t i = 0; i < len; i++) { 49c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines uint32_t r = arc4random() & 0xffff; 50c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines r %= 62; 51c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines if (r < 26) { 52c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines // lowercase 53c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines buf[i] = 'a' + r; 54c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines } else if (r < 52) { 55c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines // uppercase 56c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines buf[i] = 'A' + (r - 26); 57c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines } else { 58c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines // Use a number 59c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines buf[i] = '0' + (r - 52); 60c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines } 61c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines } 62c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines buf[len] = '\0'; 63c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines return std::string(buf); 64c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines} 65c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines 66661a62c34b6b6892346274272a5537e5e68c712cStephen Hines// Check if a path exists and attempt to create it if it doesn't. 67661a62c34b6b6892346274272a5537e5e68c712cStephen Hinesstatic bool ensureCacheDirExists(const char *path) { 68661a62c34b6b6892346274272a5537e5e68c712cStephen Hines if (access(path, R_OK | W_OK | X_OK) == 0) { 69661a62c34b6b6892346274272a5537e5e68c712cStephen Hines // Done if we can rwx the directory 70661a62c34b6b6892346274272a5537e5e68c712cStephen Hines return true; 71661a62c34b6b6892346274272a5537e5e68c712cStephen Hines } 72661a62c34b6b6892346274272a5537e5e68c712cStephen Hines if (mkdir(path, 0700) == 0) { 73661a62c34b6b6892346274272a5537e5e68c712cStephen Hines return true; 74661a62c34b6b6892346274272a5537e5e68c712cStephen Hines } 75661a62c34b6b6892346274272a5537e5e68c712cStephen Hines return false; 76661a62c34b6b6892346274272a5537e5e68c712cStephen Hines} 77661a62c34b6b6892346274272a5537e5e68c712cStephen Hines 78c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines// Attempt to load the shared library from origName, but then fall back to 79c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines// creating the symlinked shared library if necessary (to ensure instancing). 80c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines// This function returns the dlopen()-ed handle if successful. 81c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hinesstatic void *loadSOHelper(const char *origName, const char *cacheDir, 82c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines const char *resName) { 83c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines // Keep track of which .so libraries have been loaded. Once a library is 84c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines // in the set (per-process granularity), we must instead make a symlink to 85c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines // the original shared object (randomly named .so file) and load that one 86c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines // instead. If we don't do this, we end up aliasing global data between 87c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines // the various Script instances (which are supposed to be completely 88c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines // independent). 89c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines static std::set<std::string> LoadedLibraries; 90c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines 91c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines void *loaded = NULL; 92c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines 93c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines // Skip everything if we don't even have the original library available. 94c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines if (access(origName, F_OK) != 0) { 95c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines return NULL; 96c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines } 97c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines 98c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines // Common path is that we have not loaded this Script/library before. 99c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines if (LoadedLibraries.find(origName) == LoadedLibraries.end()) { 100c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines loaded = dlopen(origName, RTLD_NOW | RTLD_LOCAL); 101c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines if (loaded) { 102c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines LoadedLibraries.insert(origName); 103c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines } 104c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines return loaded; 105c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines } 106c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines 107c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines std::string newName(cacheDir); 108661a62c34b6b6892346274272a5537e5e68c712cStephen Hines newName.append("/com.android.renderscript.cache/"); 109661a62c34b6b6892346274272a5537e5e68c712cStephen Hines 110661a62c34b6b6892346274272a5537e5e68c712cStephen Hines if (!ensureCacheDirExists(newName.c_str())) { 111661a62c34b6b6892346274272a5537e5e68c712cStephen Hines ALOGE("Could not verify or create cache dir: %s", cacheDir); 112661a62c34b6b6892346274272a5537e5e68c712cStephen Hines return NULL; 113661a62c34b6b6892346274272a5537e5e68c712cStephen Hines } 114661a62c34b6b6892346274272a5537e5e68c712cStephen Hines 115661a62c34b6b6892346274272a5537e5e68c712cStephen Hines // Construct an appropriately randomized filename for the symlink. 116661a62c34b6b6892346274272a5537e5e68c712cStephen Hines newName.append("librs."); 117c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines newName.append(resName); 118c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines newName.append("#"); 119c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines newName.append(getRandomString(6)); // 62^6 potential filename variants. 120c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines newName.append(".so"); 121c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines 122c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines int r = symlink(origName, newName.c_str()); 123c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines if (r != 0) { 124c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines ALOGE("Could not create symlink %s -> %s", newName.c_str(), origName); 125c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines return NULL; 126c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines } 127c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines loaded = dlopen(newName.c_str(), RTLD_NOW | RTLD_LOCAL); 128c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines r = unlink(newName.c_str()); 129c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines if (r != 0) { 130c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines ALOGE("Could not unlink symlink %s", newName.c_str()); 131c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines } 132c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines if (loaded) { 133c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines LoadedLibraries.insert(newName.c_str()); 134c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines } 135c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines 136c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines return loaded; 137c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines} 138c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines 139c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines// Load the shared library referred to by cacheDir and resName. If we have 140c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines// already loaded this library, we instead create a new symlink (in the 141c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines// cache dir) and then load that. We then immediately destroy the symlink. 142c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines// This is required behavior to implement script instancing for the support 143c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines// library, since shared objects are loaded and de-duped by name only. 144c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hinesstatic void *loadSharedLibrary(const char *cacheDir, const char *resName) { 145c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines void *loaded = NULL; 146c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines //arc4random_stir(); 147c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines#ifndef RS_SERVER 148c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines std::string scriptSOName(cacheDir); 149c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines size_t cutPos = scriptSOName.rfind("cache"); 150c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines if (cutPos != std::string::npos) { 151c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines scriptSOName.erase(cutPos); 152c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines } else { 153c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines ALOGE("Found peculiar cacheDir (missing \"cache\"): %s", cacheDir); 154c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines } 155c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines scriptSOName.append("/lib/librs."); 156c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines#else 157c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines std::string scriptSOName("lib"); 158c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines#endif 159c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines scriptSOName.append(resName); 160c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines scriptSOName.append(".so"); 161c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines 162c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines // We should check if we can load the library from the standard app 163c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines // location for shared libraries first. 164c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines loaded = loadSOHelper(scriptSOName.c_str(), cacheDir, resName); 165c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines 166c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines if (loaded == NULL) { 167c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines ALOGE("Unable to open shared library (%s): %s", 168c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines scriptSOName.c_str(), dlerror()); 169c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines 170c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines // One final attempt to find the library in "/system/lib". 171c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines // We do this to allow bundled applications to use the compatibility 172c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines // library fallback path. Those applications don't have a private 173c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines // library path, so they need to install to the system directly. 174c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines // Note that this is really just a testing path. 175c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines android::String8 scriptSONameSystem("/system/lib/librs."); 176c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines scriptSONameSystem.append(resName); 177c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines scriptSONameSystem.append(".so"); 178c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines loaded = loadSOHelper(scriptSONameSystem.c_str(), cacheDir, 179c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines resName); 180c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines if (loaded == NULL) { 181c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines ALOGE("Unable to open system shared library (%s): %s", 182c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines scriptSONameSystem.c_str(), dlerror()); 183c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines } 184c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines } 185c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines 186c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines return loaded; 187c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines} 188c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines 189c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines 190c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines#else 191ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hinesstatic bool is_force_recompile() { 192ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines#ifdef RS_SERVER 193ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines return false; 194ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines#else 195ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines char buf[PROPERTY_VALUE_MAX]; 196ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines 197ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines // Re-compile if floating point precision has been overridden. 198ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines property_get("debug.rs.precision", buf, ""); 199ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines if (buf[0] != '\0') { 200ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines return true; 201ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines } 202ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines 203ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines // Re-compile if debug.rs.forcerecompile is set. 204ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines property_get("debug.rs.forcerecompile", buf, "0"); 205ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines if ((::strcmp(buf, "1") == 0) || (::strcmp(buf, "true") == 0)) { 206ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines return true; 207ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines } else { 208ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines return false; 209ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines } 210ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines#endif // RS_SERVER 211ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines} 212b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines 213b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines//#define EXTERNAL_BCC_COMPILER 1 214b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines#ifdef EXTERNAL_BCC_COMPILER 215b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hinesconst static char *BCC_EXE_PATH = "/system/bin/bcc"; 216b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines 217b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hinesstatic bool compileBitcode(const char *cacheDir, 218b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines const char *resName, 219b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines const char *bitcode, 220b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines size_t bitcodeSize, 221b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines const char *core_lib) { 222b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines rsAssert(cacheDir && resName && bitcode && bitcodeSize && core_lib); 223b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines 224b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines android::String8 bcFilename(cacheDir); 225b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines bcFilename.append("/"); 226b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines bcFilename.append(resName); 227b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines bcFilename.append(".bc"); 228b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines FILE *bcfile = fopen(bcFilename.string(), "w"); 229b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines if (!bcfile) { 230b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines ALOGE("Could not write to %s", bcFilename.string()); 231b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines return false; 232b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines } 233b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines size_t nwritten = fwrite(bitcode, 1, bitcodeSize, bcfile); 234b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines fclose(bcfile); 235b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines if (nwritten != bitcodeSize) { 236b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines ALOGE("Could not write %zu bytes to %s", bitcodeSize, 237b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines bcFilename.string()); 238b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines return false; 239b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines } 240b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines 241b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines pid_t pid = fork(); 242b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines switch (pid) { 243b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines case -1: { // Error occurred (we attempt no recovery) 244b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines ALOGE("Couldn't fork for bcc compiler execution"); 245b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines return false; 246b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines } 247b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines case 0: { // Child process 248b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines // Execute the bcc compiler. 249b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines execl(BCC_EXE_PATH, 250b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines BCC_EXE_PATH, 251b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines "-o", resName, 252b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines "-output_path", cacheDir, 253b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines "-bclib", core_lib, 254b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines bcFilename.string(), 255b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines (char *) NULL); 256b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines ALOGE("execl() failed: %s", strerror(errno)); 257b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines abort(); 258b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines return false; 259b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines } 260b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines default: { // Parent process (actual driver) 261b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines // Wait on child process to finish compiling the source. 262b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines int status = 0; 263b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines pid_t w = waitpid(pid, &status, 0); 264b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines if (w == -1) { 265b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines ALOGE("Could not wait for bcc compiler"); 266b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines return false; 267b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines } 268b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines 269b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { 270b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines return true; 271b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines } 272b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines 273b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines ALOGE("bcc compiler terminated unexpectedly"); 274b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines return false; 275b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines } 276b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines } 277b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines} 278b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines#endif // EXTERNAL_BCC_COMPILER 279b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines 280ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines#endif // !defined(RS_COMPATIBILITY_LIB) 281c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines} // namespace 282ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines 283709a0978ae141198018ca9769f8d96292a8928e6Jason Samsnamespace android { 284709a0978ae141198018ca9769f8d96292a8928e6Jason Samsnamespace renderscript { 285709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 286709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 287110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams#ifdef RS_COMPATIBILITY_LIB 288110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams#define MAXLINE 500 289110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams#define MAKE_STR_HELPER(S) #S 290110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams#define MAKE_STR(S) MAKE_STR_HELPER(S) 291110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams#define EXPORT_VAR_STR "exportVarCount: " 292110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams#define EXPORT_VAR_STR_LEN strlen(EXPORT_VAR_STR) 293110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams#define EXPORT_FUNC_STR "exportFuncCount: " 294110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams#define EXPORT_FUNC_STR_LEN strlen(EXPORT_FUNC_STR) 295110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams#define EXPORT_FOREACH_STR "exportForEachCount: " 296110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams#define EXPORT_FOREACH_STR_LEN strlen(EXPORT_FOREACH_STR) 297110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams#define OBJECT_SLOT_STR "objectSlotCount: " 298110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams#define OBJECT_SLOT_STR_LEN strlen(OBJECT_SLOT_STR) 299110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams 300110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams// Copy up to a newline or size chars from str -> s, updating str 301110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams// Returns s when successful and NULL when '\0' is finally reached. 302110f181b7966212a36ef18016f9b81c7322d0a2fJason Samsstatic char* strgets(char *s, int size, const char **ppstr) { 303110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams if (!ppstr || !*ppstr || **ppstr == '\0' || size < 1) { 304110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams return NULL; 305110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams } 306110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams 307110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams int i; 308110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams for (i = 0; i < (size - 1); i++) { 309110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams s[i] = **ppstr; 310110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams (*ppstr)++; 311110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams if (s[i] == '\0') { 312110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams return s; 313110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams } else if (s[i] == '\n') { 314110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams s[i+1] = '\0'; 315110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams return s; 316110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams } 317110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams } 318110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams 319110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams // size has been exceeded. 320110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams s[i] = '\0'; 321110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams 322110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams return s; 323110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams} 324110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams#endif 325709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 326709a0978ae141198018ca9769f8d96292a8928e6Jason SamsRsdCpuScriptImpl::RsdCpuScriptImpl(RsdCpuReferenceImpl *ctx, const Script *s) { 327709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mCtx = ctx; 328709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mScript = s; 329709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 330110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams#ifdef RS_COMPATIBILITY_LIB 331110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams mScriptSO = NULL; 332110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams mInvokeFunctions = NULL; 333110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams mForEachFunctions = NULL; 334110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams mFieldAddress = NULL; 335110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams mFieldIsObject = NULL; 336110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams mForEachSignatures = NULL; 337110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams#else 338110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams mCompilerContext = NULL; 339110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams mCompilerDriver = NULL; 340110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams mExecutable = NULL; 341110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams#endif 342110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams 343709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mRoot = NULL; 344709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mRootExpand = NULL; 345709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mInit = NULL; 346709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mFreeChildren = NULL; 347709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 348709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 349709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mBoundAllocs = NULL; 350709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mIntrinsicData = NULL; 351709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mIsThreadable = true; 352709a0978ae141198018ca9769f8d96292a8928e6Jason Sams} 353709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 354709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 355709a0978ae141198018ca9769f8d96292a8928e6Jason Samsbool RsdCpuScriptImpl::init(char const *resName, char const *cacheDir, 356709a0978ae141198018ca9769f8d96292a8928e6Jason Sams uint8_t const *bitcode, size_t bitcodeSize, 357709a0978ae141198018ca9769f8d96292a8928e6Jason Sams uint32_t flags) { 358709a0978ae141198018ca9769f8d96292a8928e6Jason Sams //ALOGE("rsdScriptCreate %p %p %p %p %i %i %p", rsc, resName, cacheDir, bitcode, bitcodeSize, flags, lookupFunc); 359709a0978ae141198018ca9769f8d96292a8928e6Jason Sams //ALOGE("rsdScriptInit %p %p", rsc, script); 360709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 361709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mCtx->lockMutex(); 362709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 363110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams#ifndef RS_COMPATIBILITY_LIB 364ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines bcc::RSExecutable *exec = NULL; 365709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 366709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mCompilerContext = NULL; 367709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mCompilerDriver = NULL; 368709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mExecutable = NULL; 369709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 370709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mCompilerContext = new bcc::BCCContext(); 371709a0978ae141198018ca9769f8d96292a8928e6Jason Sams if (mCompilerContext == NULL) { 372709a0978ae141198018ca9769f8d96292a8928e6Jason Sams ALOGE("bcc: FAILS to create compiler context (out of memory)"); 373709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mCtx->unlockMutex(); 374709a0978ae141198018ca9769f8d96292a8928e6Jason Sams return false; 375709a0978ae141198018ca9769f8d96292a8928e6Jason Sams } 376709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 377709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mCompilerDriver = new bcc::RSCompilerDriver(); 378709a0978ae141198018ca9769f8d96292a8928e6Jason Sams if (mCompilerDriver == NULL) { 379709a0978ae141198018ca9769f8d96292a8928e6Jason Sams ALOGE("bcc: FAILS to create compiler driver (out of memory)"); 380709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mCtx->unlockMutex(); 381709a0978ae141198018ca9769f8d96292a8928e6Jason Sams return false; 382709a0978ae141198018ca9769f8d96292a8928e6Jason Sams } 383709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 384709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mCompilerDriver->setRSRuntimeLookupFunction(lookupRuntimeStub); 385709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mCompilerDriver->setRSRuntimeLookupContext(this); 386709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 387b7d9c80c98fc96aa7c638e3124be24f13a6436b2Stephen Hines // Run any compiler setup functions we have been provided with. 388b7d9c80c98fc96aa7c638e3124be24f13a6436b2Stephen Hines RSSetupCompilerCallback setupCompilerCallback = 389b7d9c80c98fc96aa7c638e3124be24f13a6436b2Stephen Hines mCtx->getSetupCompilerCallback(); 390b7d9c80c98fc96aa7c638e3124be24f13a6436b2Stephen Hines if (setupCompilerCallback != NULL) { 391b7d9c80c98fc96aa7c638e3124be24f13a6436b2Stephen Hines setupCompilerCallback(mCompilerDriver); 392b7d9c80c98fc96aa7c638e3124be24f13a6436b2Stephen Hines } 393b7d9c80c98fc96aa7c638e3124be24f13a6436b2Stephen Hines 394b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines const char *core_lib = bcc::RSInfo::LibCLCorePath; 395b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines 396b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines bcinfo::MetadataExtractor ME((const char *) bitcode, bitcodeSize); 397b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines if (!ME.extract()) { 398b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines ALOGE("Could not extract metadata from bitcode"); 399b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines return false; 400b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines } 401b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines 402b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines enum bcinfo::RSFloatPrecision prec = ME.getRSFloatPrecision(); 403b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines switch (prec) { 404b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines case bcinfo::RS_FP_Imprecise: 405b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines case bcinfo::RS_FP_Relaxed: 406b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines#if defined(ARCH_ARM_HAVE_NEON) 407b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines // NEON-capable devices can use an accelerated math library for all 408b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines // reduced precision scripts. 409b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines core_lib = bcc::RSInfo::LibCLCoreNEONPath; 410b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines#endif 411b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines break; 412b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines case bcinfo::RS_FP_Full: 413b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines break; 414b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines default: 415b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines ALOGE("Unknown precision for bitcode"); 416b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines return false; 417b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines } 418b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines 419b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines#if defined(ARCH_X86_HAVE_SSE2) 420b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines // SSE2- or above capable devices will use an optimized library. 421b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines core_lib = bcc::RSInfo::LibCLCoreX86Path; 422b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines#endif 423b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines 4241d476620399d54774e4fd386c1d23cc583d49522Stephen Hines RSSelectRTCallback selectRTCallback = mCtx->getSelectRTCallback(); 4251d476620399d54774e4fd386c1d23cc583d49522Stephen Hines if (selectRTCallback != NULL) { 4261d476620399d54774e4fd386c1d23cc583d49522Stephen Hines core_lib = selectRTCallback((const char *)bitcode, bitcodeSize); 4271d476620399d54774e4fd386c1d23cc583d49522Stephen Hines } 428cca3d6ca444bef3b6d75431ec19bd07bfe40a733Stephen Hines 429cca3d6ca444bef3b6d75431ec19bd07bfe40a733Stephen Hines if (mCtx->getContext()->getContextType() == RS_CONTEXT_TYPE_DEBUG) { 430cca3d6ca444bef3b6d75431ec19bd07bfe40a733Stephen Hines // Use the libclcore_debug.bc instead of the default library. 431cca3d6ca444bef3b6d75431ec19bd07bfe40a733Stephen Hines core_lib = bcc::RSInfo::LibCLCoreDebugPath; 432f47e8b4b86bf194e65398032f3f5f47a6da89f3fStephen Hines mCompilerDriver->setDebugContext(true); 433ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines // Skip the cache lookup 434ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines } else if (!is_force_recompile()) { 435ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines // Attempt to just load the script from cache first if we can. 436ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines exec = mCompilerDriver->loadScript(cacheDir, resName, 437ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines (const char *)bitcode, bitcodeSize); 438ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines } 439ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines 440ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines if (exec == NULL) { 441b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines#ifdef EXTERNAL_BCC_COMPILER 442b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines bool built = compileBitcode(cacheDir, resName, (const char *)bitcode, 443b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines bitcodeSize, core_lib); 444b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines#else 445ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines bool built = mCompilerDriver->build(*mCompilerContext, cacheDir, 446ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines resName, (const char *)bitcode, 447ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines bitcodeSize, core_lib, 448ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines mCtx->getLinkRuntimeCallback()); 449b58d9adf52f0216c0281c749023bdd5b52236875Stephen Hines#endif // EXTERNAL_BCC_COMPILER 450ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines if (built) { 451ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines exec = mCompilerDriver->loadScript(cacheDir, resName, 452ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines (const char *)bitcode, 453ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines bitcodeSize); 454ba17ae494add84056bbf3275b68e40e62a643db0Stephen Hines } 455cca3d6ca444bef3b6d75431ec19bd07bfe40a733Stephen Hines } 456709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 457709a0978ae141198018ca9769f8d96292a8928e6Jason Sams if (exec == NULL) { 458709a0978ae141198018ca9769f8d96292a8928e6Jason Sams ALOGE("bcc: FAILS to prepare executable for '%s'", resName); 459709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mCtx->unlockMutex(); 460709a0978ae141198018ca9769f8d96292a8928e6Jason Sams return false; 461709a0978ae141198018ca9769f8d96292a8928e6Jason Sams } 462709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 463709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mExecutable = exec; 464709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 465709a0978ae141198018ca9769f8d96292a8928e6Jason Sams exec->setThreadable(mIsThreadable); 466709a0978ae141198018ca9769f8d96292a8928e6Jason Sams if (!exec->syncInfo()) { 467709a0978ae141198018ca9769f8d96292a8928e6Jason Sams ALOGW("bcc: FAILS to synchronize the RS info file to the disk"); 468709a0978ae141198018ca9769f8d96292a8928e6Jason Sams } 469709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 470709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mRoot = reinterpret_cast<int (*)()>(exec->getSymbolAddress("root")); 471709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mRootExpand = 472709a0978ae141198018ca9769f8d96292a8928e6Jason Sams reinterpret_cast<int (*)()>(exec->getSymbolAddress("root.expand")); 473709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mInit = reinterpret_cast<void (*)()>(exec->getSymbolAddress("init")); 474709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mFreeChildren = 475709a0978ae141198018ca9769f8d96292a8928e6Jason Sams reinterpret_cast<void (*)()>(exec->getSymbolAddress(".rs.dtor")); 476709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 477709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 4781d476620399d54774e4fd386c1d23cc583d49522Stephen Hines const bcc::RSInfo *info = &mExecutable->getInfo(); 479709a0978ae141198018ca9769f8d96292a8928e6Jason Sams if (info->getExportVarNames().size()) { 480709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mBoundAllocs = new Allocation *[info->getExportVarNames().size()]; 481709a0978ae141198018ca9769f8d96292a8928e6Jason Sams memset(mBoundAllocs, 0, sizeof(void *) * info->getExportVarNames().size()); 482709a0978ae141198018ca9769f8d96292a8928e6Jason Sams } 483709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 484110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams#else 485110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams 486c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines mScriptSO = loadSharedLibrary(cacheDir, resName); 487110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams 488110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams if (mScriptSO) { 489110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams char line[MAXLINE]; 490110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams mRoot = (RootFunc_t) dlsym(mScriptSO, "root"); 491110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams if (mRoot) { 492110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams //ALOGE("Found root(): %p", mRoot); 493110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams } 494110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams mRootExpand = (RootFunc_t) dlsym(mScriptSO, "root.expand"); 495110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams if (mRootExpand) { 496110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams //ALOGE("Found root.expand(): %p", mRootExpand); 497110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams } 498110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams mInit = (InvokeFunc_t) dlsym(mScriptSO, "init"); 499110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams if (mInit) { 500110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams //ALOGE("Found init(): %p", mInit); 501110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams } 502110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams mFreeChildren = (InvokeFunc_t) dlsym(mScriptSO, ".rs.dtor"); 503110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams if (mFreeChildren) { 504110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams //ALOGE("Found .rs.dtor(): %p", mFreeChildren); 505110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams } 506110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams 507110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams const char *rsInfo = (const char *) dlsym(mScriptSO, ".rs.info"); 508110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams if (rsInfo) { 509110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams //ALOGE("Found .rs.info(): %p - %s", rsInfo, rsInfo); 510110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams } 511110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams 512110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams size_t varCount = 0; 513110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams if (strgets(line, MAXLINE, &rsInfo) == NULL) { 514110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams goto error; 515110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams } 516110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams if (sscanf(line, EXPORT_VAR_STR "%zu", &varCount) != 1) { 517110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams ALOGE("Invalid export var count!: %s", line); 518110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams goto error; 519110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams } 520110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams 521110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams mExportedVariableCount = varCount; 522110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams //ALOGE("varCount: %zu", varCount); 523110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams if (varCount > 0) { 524110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams // Start by creating/zeroing this member, since we don't want to 525110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams // accidentally clean up invalid pointers later (if we error out). 526110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams mFieldIsObject = new bool[varCount]; 527110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams if (mFieldIsObject == NULL) { 528110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams goto error; 529110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams } 530110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams memset(mFieldIsObject, 0, varCount * sizeof(*mFieldIsObject)); 531110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams mFieldAddress = new void*[varCount]; 532110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams if (mFieldAddress == NULL) { 533110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams goto error; 534110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams } 535110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams for (size_t i = 0; i < varCount; ++i) { 536110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams if (strgets(line, MAXLINE, &rsInfo) == NULL) { 537110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams goto error; 538110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams } 539110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams char *c = strrchr(line, '\n'); 540110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams if (c) { 541110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams *c = '\0'; 542110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams } 543110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams mFieldAddress[i] = dlsym(mScriptSO, line); 544110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams if (mFieldAddress[i] == NULL) { 545110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams ALOGE("Failed to find variable address for %s: %s", 546110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams line, dlerror()); 547110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams // Not a critical error if we don't find a global variable. 548110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams } 549110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams else { 550110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams //ALOGE("Found variable %s at %p", line, 551110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams //mFieldAddress[i]); 552110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams } 553110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams } 554110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams } 555110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams 556110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams size_t funcCount = 0; 557110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams if (strgets(line, MAXLINE, &rsInfo) == NULL) { 558110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams goto error; 559110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams } 560110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams if (sscanf(line, EXPORT_FUNC_STR "%zu", &funcCount) != 1) { 561110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams ALOGE("Invalid export func count!: %s", line); 562110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams goto error; 563110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams } 564110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams 565110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams mExportedFunctionCount = funcCount; 566110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams //ALOGE("funcCount: %zu", funcCount); 567110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams 568110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams if (funcCount > 0) { 569110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams mInvokeFunctions = new InvokeFunc_t[funcCount]; 570110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams if (mInvokeFunctions == NULL) { 571110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams goto error; 572110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams } 573110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams for (size_t i = 0; i < funcCount; ++i) { 574110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams if (strgets(line, MAXLINE, &rsInfo) == NULL) { 575110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams goto error; 576110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams } 577110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams char *c = strrchr(line, '\n'); 578110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams if (c) { 579110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams *c = '\0'; 580110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams } 581110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams 582110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams mInvokeFunctions[i] = (InvokeFunc_t) dlsym(mScriptSO, line); 583110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams if (mInvokeFunctions[i] == NULL) { 584110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams ALOGE("Failed to get function address for %s(): %s", 585110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams line, dlerror()); 586110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams goto error; 587110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams } 588110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams else { 589110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams //ALOGE("Found InvokeFunc_t %s at %p", line, mInvokeFunctions[i]); 590110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams } 591110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams } 592110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams } 593110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams 594110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams size_t forEachCount = 0; 595110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams if (strgets(line, MAXLINE, &rsInfo) == NULL) { 596110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams goto error; 597110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams } 598110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams if (sscanf(line, EXPORT_FOREACH_STR "%zu", &forEachCount) != 1) { 599110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams ALOGE("Invalid export forEach count!: %s", line); 600110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams goto error; 601110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams } 602110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams 603110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams if (forEachCount > 0) { 604110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams 605110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams mForEachSignatures = new uint32_t[forEachCount]; 606110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams if (mForEachSignatures == NULL) { 607110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams goto error; 608110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams } 609110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams mForEachFunctions = new ForEachFunc_t[forEachCount]; 610110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams if (mForEachFunctions == NULL) { 611110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams goto error; 612110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams } 613110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams for (size_t i = 0; i < forEachCount; ++i) { 614110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams unsigned int tmpSig = 0; 615110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams char tmpName[MAXLINE]; 616110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams 617110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams if (strgets(line, MAXLINE, &rsInfo) == NULL) { 618110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams goto error; 619110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams } 620110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams if (sscanf(line, "%u - %" MAKE_STR(MAXLINE) "s", 621110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams &tmpSig, tmpName) != 2) { 622110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams ALOGE("Invalid export forEach!: %s", line); 623110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams goto error; 624110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams } 625110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams 626110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams // Lookup the expanded ForEach kernel. 627110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams strncat(tmpName, ".expand", MAXLINE-1-strlen(tmpName)); 628110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams mForEachSignatures[i] = tmpSig; 629110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams mForEachFunctions[i] = 630110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams (ForEachFunc_t) dlsym(mScriptSO, tmpName); 631ef7481e2f0a4ad7b32bb626245e4207cabe171dcStephen Hines if (i != 0 && mForEachFunctions[i] == NULL) { 632110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams // Ignore missing root.expand functions. 633110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams // root() is always specified at location 0. 634ef7481e2f0a4ad7b32bb626245e4207cabe171dcStephen Hines ALOGE("Failed to find forEach function address for %s: %s", 635ef7481e2f0a4ad7b32bb626245e4207cabe171dcStephen Hines tmpName, dlerror()); 636ef7481e2f0a4ad7b32bb626245e4207cabe171dcStephen Hines goto error; 637110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams } 638110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams else { 639110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams //ALOGE("Found forEach %s at %p", tmpName, mForEachFunctions[i]); 640110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams } 641110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams } 642110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams } 643110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams 644110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams size_t objectSlotCount = 0; 645110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams if (strgets(line, MAXLINE, &rsInfo) == NULL) { 646110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams goto error; 647110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams } 648110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams if (sscanf(line, OBJECT_SLOT_STR "%zu", &objectSlotCount) != 1) { 649110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams ALOGE("Invalid object slot count!: %s", line); 650110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams goto error; 651110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams } 652110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams 653110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams if (objectSlotCount > 0) { 654110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams rsAssert(varCount > 0); 655110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams for (size_t i = 0; i < objectSlotCount; ++i) { 656110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams uint32_t varNum = 0; 657110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams if (strgets(line, MAXLINE, &rsInfo) == NULL) { 658110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams goto error; 659110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams } 660110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams if (sscanf(line, "%u", &varNum) != 1) { 661110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams ALOGE("Invalid object slot!: %s", line); 662110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams goto error; 663110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams } 664110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams 665110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams if (varNum < varCount) { 666110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams mFieldIsObject[varNum] = true; 667110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams } 668110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams } 669110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams } 670110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams 671110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams if (varCount > 0) { 672110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams mBoundAllocs = new Allocation *[varCount]; 673110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams memset(mBoundAllocs, 0, varCount * sizeof(*mBoundAllocs)); 674110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams } 675110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams 676110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams if (mScriptSO == (void*)1) { 677110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams //rsdLookupRuntimeStub(script, "acos"); 678110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams } 679c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines } else { 680c2c11cc9037d5ddd55282c6dab82db542b398d9eStephen Hines goto error; 681110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams } 682110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams#endif 683110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams 684709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mCtx->unlockMutex(); 685709a0978ae141198018ca9769f8d96292a8928e6Jason Sams return true; 686110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams 687110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams#ifdef RS_COMPATIBILITY_LIB 688110f181b7966212a36ef18016f9b81c7322d0a2fJason Samserror: 689110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams 690110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams mCtx->unlockMutex(); 691110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams delete[] mInvokeFunctions; 692110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams delete[] mForEachFunctions; 693110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams delete[] mFieldAddress; 694110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams delete[] mFieldIsObject; 695110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams delete[] mForEachSignatures; 696110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams delete[] mBoundAllocs; 697110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams if (mScriptSO) { 698110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams dlclose(mScriptSO); 699110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams } 700110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams return false; 701110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams#endif 702709a0978ae141198018ca9769f8d96292a8928e6Jason Sams} 703709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 704709a0978ae141198018ca9769f8d96292a8928e6Jason Samsvoid RsdCpuScriptImpl::populateScript(Script *script) { 705110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams#ifndef RS_COMPATIBILITY_LIB 706709a0978ae141198018ca9769f8d96292a8928e6Jason Sams const bcc::RSInfo *info = &mExecutable->getInfo(); 707709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 708709a0978ae141198018ca9769f8d96292a8928e6Jason Sams // Copy info over to runtime 709709a0978ae141198018ca9769f8d96292a8928e6Jason Sams script->mHal.info.exportedFunctionCount = info->getExportFuncNames().size(); 710709a0978ae141198018ca9769f8d96292a8928e6Jason Sams script->mHal.info.exportedVariableCount = info->getExportVarNames().size(); 71147935ac8e3dd619f758abd576605a564e33bb59cTobias Grosser script->mHal.info.exportedForeachFuncList = info->getExportForeachFuncs().array(); 712709a0978ae141198018ca9769f8d96292a8928e6Jason Sams script->mHal.info.exportedPragmaCount = info->getPragmas().size(); 713709a0978ae141198018ca9769f8d96292a8928e6Jason Sams script->mHal.info.exportedPragmaKeyList = 714709a0978ae141198018ca9769f8d96292a8928e6Jason Sams const_cast<const char**>(mExecutable->getPragmaKeys().array()); 715709a0978ae141198018ca9769f8d96292a8928e6Jason Sams script->mHal.info.exportedPragmaValueList = 716709a0978ae141198018ca9769f8d96292a8928e6Jason Sams const_cast<const char**>(mExecutable->getPragmaValues().array()); 717709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 718709a0978ae141198018ca9769f8d96292a8928e6Jason Sams if (mRootExpand) { 719709a0978ae141198018ca9769f8d96292a8928e6Jason Sams script->mHal.info.root = mRootExpand; 720709a0978ae141198018ca9769f8d96292a8928e6Jason Sams } else { 721709a0978ae141198018ca9769f8d96292a8928e6Jason Sams script->mHal.info.root = mRoot; 722709a0978ae141198018ca9769f8d96292a8928e6Jason Sams } 723110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams#else 724110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams // Copy info over to runtime 725110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams script->mHal.info.exportedFunctionCount = mExportedFunctionCount; 726110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams script->mHal.info.exportedVariableCount = mExportedVariableCount; 727110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams script->mHal.info.exportedPragmaCount = 0; 728110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams script->mHal.info.exportedPragmaKeyList = 0; 729110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams script->mHal.info.exportedPragmaValueList = 0; 730110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams 731110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams // Bug, need to stash in metadata 732110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams if (mRootExpand) { 733110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams script->mHal.info.root = mRootExpand; 734110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams } else { 735110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams script->mHal.info.root = mRoot; 736110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams } 737110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams#endif 738709a0978ae141198018ca9769f8d96292a8928e6Jason Sams} 739709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 740709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 741709a0978ae141198018ca9769f8d96292a8928e6Jason Samstypedef void (*rs_t)(const void *, void *, const void *, uint32_t, uint32_t, uint32_t, uint32_t); 742709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 743709a0978ae141198018ca9769f8d96292a8928e6Jason Samsvoid RsdCpuScriptImpl::forEachMtlsSetup(const Allocation * ain, Allocation * aout, 744709a0978ae141198018ca9769f8d96292a8928e6Jason Sams const void * usr, uint32_t usrLen, 745709a0978ae141198018ca9769f8d96292a8928e6Jason Sams const RsScriptCall *sc, 746709a0978ae141198018ca9769f8d96292a8928e6Jason Sams MTLaunchStruct *mtls) { 747709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 748709a0978ae141198018ca9769f8d96292a8928e6Jason Sams memset(mtls, 0, sizeof(MTLaunchStruct)); 749709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 7503a25fdd3786c1a08b783d8a83ef94b756347ff5cTim Murray // possible for this to occur if IO_OUTPUT/IO_INPUT with no bound surface 7513a25fdd3786c1a08b783d8a83ef94b756347ff5cTim Murray if (ain && (const uint8_t *)ain->mHal.drvState.lod[0].mallocPtr == NULL) { 752ddceab9a001f07a3395226c5e06e3b420720af0fJason Sams mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT, "rsForEach called with null in allocations"); 7533a25fdd3786c1a08b783d8a83ef94b756347ff5cTim Murray return; 7543a25fdd3786c1a08b783d8a83ef94b756347ff5cTim Murray } 7553a25fdd3786c1a08b783d8a83ef94b756347ff5cTim Murray if (aout && (const uint8_t *)aout->mHal.drvState.lod[0].mallocPtr == NULL) { 756ddceab9a001f07a3395226c5e06e3b420720af0fJason Sams mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT, "rsForEach called with null out allocations"); 7573a25fdd3786c1a08b783d8a83ef94b756347ff5cTim Murray return; 7583a25fdd3786c1a08b783d8a83ef94b756347ff5cTim Murray } 7593a25fdd3786c1a08b783d8a83ef94b756347ff5cTim Murray 760709a0978ae141198018ca9769f8d96292a8928e6Jason Sams if (ain) { 761709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mtls->fep.dimX = ain->getType()->getDimX(); 762709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mtls->fep.dimY = ain->getType()->getDimY(); 763709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mtls->fep.dimZ = ain->getType()->getDimZ(); 764709a0978ae141198018ca9769f8d96292a8928e6Jason Sams //mtls->dimArray = ain->getType()->getDimArray(); 765709a0978ae141198018ca9769f8d96292a8928e6Jason Sams } else if (aout) { 766709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mtls->fep.dimX = aout->getType()->getDimX(); 767709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mtls->fep.dimY = aout->getType()->getDimY(); 768709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mtls->fep.dimZ = aout->getType()->getDimZ(); 769709a0978ae141198018ca9769f8d96292a8928e6Jason Sams //mtls->dimArray = aout->getType()->getDimArray(); 770709a0978ae141198018ca9769f8d96292a8928e6Jason Sams } else { 771709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT, "rsForEach called with null allocations"); 772709a0978ae141198018ca9769f8d96292a8928e6Jason Sams return; 773709a0978ae141198018ca9769f8d96292a8928e6Jason Sams } 774709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 775709a0978ae141198018ca9769f8d96292a8928e6Jason Sams if (!sc || (sc->xEnd == 0)) { 776709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mtls->xEnd = mtls->fep.dimX; 777709a0978ae141198018ca9769f8d96292a8928e6Jason Sams } else { 778709a0978ae141198018ca9769f8d96292a8928e6Jason Sams rsAssert(sc->xStart < mtls->fep.dimX); 779709a0978ae141198018ca9769f8d96292a8928e6Jason Sams rsAssert(sc->xEnd <= mtls->fep.dimX); 780709a0978ae141198018ca9769f8d96292a8928e6Jason Sams rsAssert(sc->xStart < sc->xEnd); 781709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mtls->xStart = rsMin(mtls->fep.dimX, sc->xStart); 782709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mtls->xEnd = rsMin(mtls->fep.dimX, sc->xEnd); 783709a0978ae141198018ca9769f8d96292a8928e6Jason Sams if (mtls->xStart >= mtls->xEnd) return; 784709a0978ae141198018ca9769f8d96292a8928e6Jason Sams } 785709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 786709a0978ae141198018ca9769f8d96292a8928e6Jason Sams if (!sc || (sc->yEnd == 0)) { 787709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mtls->yEnd = mtls->fep.dimY; 788709a0978ae141198018ca9769f8d96292a8928e6Jason Sams } else { 789709a0978ae141198018ca9769f8d96292a8928e6Jason Sams rsAssert(sc->yStart < mtls->fep.dimY); 790709a0978ae141198018ca9769f8d96292a8928e6Jason Sams rsAssert(sc->yEnd <= mtls->fep.dimY); 791709a0978ae141198018ca9769f8d96292a8928e6Jason Sams rsAssert(sc->yStart < sc->yEnd); 792709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mtls->yStart = rsMin(mtls->fep.dimY, sc->yStart); 793709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mtls->yEnd = rsMin(mtls->fep.dimY, sc->yEnd); 794709a0978ae141198018ca9769f8d96292a8928e6Jason Sams if (mtls->yStart >= mtls->yEnd) return; 795709a0978ae141198018ca9769f8d96292a8928e6Jason Sams } 796709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 797d4ecb17adc9b099351f2ca1779a74f5283f20a3dTim Murray if (!sc || (sc->zEnd == 0)) { 798d4ecb17adc9b099351f2ca1779a74f5283f20a3dTim Murray mtls->zEnd = mtls->fep.dimZ; 799d4ecb17adc9b099351f2ca1779a74f5283f20a3dTim Murray } else { 800d4ecb17adc9b099351f2ca1779a74f5283f20a3dTim Murray rsAssert(sc->zStart < mtls->fep.dimZ); 801d4ecb17adc9b099351f2ca1779a74f5283f20a3dTim Murray rsAssert(sc->zEnd <= mtls->fep.dimZ); 802d4ecb17adc9b099351f2ca1779a74f5283f20a3dTim Murray rsAssert(sc->zStart < sc->zEnd); 803d4ecb17adc9b099351f2ca1779a74f5283f20a3dTim Murray mtls->zStart = rsMin(mtls->fep.dimZ, sc->zStart); 804d4ecb17adc9b099351f2ca1779a74f5283f20a3dTim Murray mtls->zEnd = rsMin(mtls->fep.dimZ, sc->zEnd); 805d4ecb17adc9b099351f2ca1779a74f5283f20a3dTim Murray if (mtls->zStart >= mtls->zEnd) return; 806d4ecb17adc9b099351f2ca1779a74f5283f20a3dTim Murray } 807d4ecb17adc9b099351f2ca1779a74f5283f20a3dTim Murray 808709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mtls->xEnd = rsMax((uint32_t)1, mtls->xEnd); 809709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mtls->yEnd = rsMax((uint32_t)1, mtls->yEnd); 810709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mtls->zEnd = rsMax((uint32_t)1, mtls->zEnd); 811709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mtls->arrayEnd = rsMax((uint32_t)1, mtls->arrayEnd); 812709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 813709a0978ae141198018ca9769f8d96292a8928e6Jason Sams rsAssert(!ain || (ain->getType()->getDimZ() == 0)); 814709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 815709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mtls->rsc = mCtx; 816709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mtls->ain = ain; 817709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mtls->aout = aout; 818709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mtls->fep.usr = usr; 819709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mtls->fep.usrLen = usrLen; 820709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mtls->mSliceSize = 1; 821709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mtls->mSliceNum = 0; 822709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 823709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mtls->fep.ptrIn = NULL; 824709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mtls->fep.eStrideIn = 0; 825709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mtls->isThreadable = mIsThreadable; 826709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 827709a0978ae141198018ca9769f8d96292a8928e6Jason Sams if (ain) { 828709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mtls->fep.ptrIn = (const uint8_t *)ain->mHal.drvState.lod[0].mallocPtr; 829709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mtls->fep.eStrideIn = ain->getType()->getElementSizeBytes(); 830709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mtls->fep.yStrideIn = ain->mHal.drvState.lod[0].stride; 831709a0978ae141198018ca9769f8d96292a8928e6Jason Sams } 832709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 833709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mtls->fep.ptrOut = NULL; 834709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mtls->fep.eStrideOut = 0; 835709a0978ae141198018ca9769f8d96292a8928e6Jason Sams if (aout) { 836709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mtls->fep.ptrOut = (uint8_t *)aout->mHal.drvState.lod[0].mallocPtr; 837709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mtls->fep.eStrideOut = aout->getType()->getElementSizeBytes(); 838709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mtls->fep.yStrideOut = aout->mHal.drvState.lod[0].stride; 839709a0978ae141198018ca9769f8d96292a8928e6Jason Sams } 840709a0978ae141198018ca9769f8d96292a8928e6Jason Sams} 841709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 842709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 843709a0978ae141198018ca9769f8d96292a8928e6Jason Samsvoid RsdCpuScriptImpl::invokeForEach(uint32_t slot, 844709a0978ae141198018ca9769f8d96292a8928e6Jason Sams const Allocation * ain, 845709a0978ae141198018ca9769f8d96292a8928e6Jason Sams Allocation * aout, 846709a0978ae141198018ca9769f8d96292a8928e6Jason Sams const void * usr, 847709a0978ae141198018ca9769f8d96292a8928e6Jason Sams uint32_t usrLen, 848709a0978ae141198018ca9769f8d96292a8928e6Jason Sams const RsScriptCall *sc) { 849709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 850709a0978ae141198018ca9769f8d96292a8928e6Jason Sams MTLaunchStruct mtls; 851709a0978ae141198018ca9769f8d96292a8928e6Jason Sams forEachMtlsSetup(ain, aout, usr, usrLen, sc, &mtls); 852709a0978ae141198018ca9769f8d96292a8928e6Jason Sams forEachKernelSetup(slot, &mtls); 853709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 854709a0978ae141198018ca9769f8d96292a8928e6Jason Sams RsdCpuScriptImpl * oldTLS = mCtx->setTLS(this); 855709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mCtx->launchThreads(ain, aout, sc, &mtls); 856709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mCtx->setTLS(oldTLS); 857709a0978ae141198018ca9769f8d96292a8928e6Jason Sams} 858709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 859709a0978ae141198018ca9769f8d96292a8928e6Jason Samsvoid RsdCpuScriptImpl::forEachKernelSetup(uint32_t slot, MTLaunchStruct *mtls) { 860709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mtls->script = this; 861709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mtls->fep.slot = slot; 862110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams#ifndef RS_COMPATIBILITY_LIB 863709a0978ae141198018ca9769f8d96292a8928e6Jason Sams rsAssert(slot < mExecutable->getExportForeachFuncAddrs().size()); 864709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mtls->kernel = reinterpret_cast<ForEachFunc_t>( 865709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mExecutable->getExportForeachFuncAddrs()[slot]); 866709a0978ae141198018ca9769f8d96292a8928e6Jason Sams rsAssert(mtls->kernel != NULL); 867709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mtls->sig = mExecutable->getInfo().getExportForeachFuncs()[slot].second; 868110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams#else 869110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams mtls->kernel = reinterpret_cast<ForEachFunc_t>(mForEachFunctions[slot]); 870110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams rsAssert(mtls->kernel != NULL); 871110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams mtls->sig = mForEachSignatures[slot]; 872110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams#endif 873709a0978ae141198018ca9769f8d96292a8928e6Jason Sams} 874709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 875709a0978ae141198018ca9769f8d96292a8928e6Jason Samsint RsdCpuScriptImpl::invokeRoot() { 876709a0978ae141198018ca9769f8d96292a8928e6Jason Sams RsdCpuScriptImpl * oldTLS = mCtx->setTLS(this); 877709a0978ae141198018ca9769f8d96292a8928e6Jason Sams int ret = mRoot(); 878709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mCtx->setTLS(oldTLS); 879709a0978ae141198018ca9769f8d96292a8928e6Jason Sams return ret; 880709a0978ae141198018ca9769f8d96292a8928e6Jason Sams} 881709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 882709a0978ae141198018ca9769f8d96292a8928e6Jason Samsvoid RsdCpuScriptImpl::invokeInit() { 883709a0978ae141198018ca9769f8d96292a8928e6Jason Sams if (mInit) { 884709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mInit(); 885709a0978ae141198018ca9769f8d96292a8928e6Jason Sams } 886709a0978ae141198018ca9769f8d96292a8928e6Jason Sams} 887709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 888709a0978ae141198018ca9769f8d96292a8928e6Jason Samsvoid RsdCpuScriptImpl::invokeFreeChildren() { 889709a0978ae141198018ca9769f8d96292a8928e6Jason Sams if (mFreeChildren) { 890709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mFreeChildren(); 891709a0978ae141198018ca9769f8d96292a8928e6Jason Sams } 892709a0978ae141198018ca9769f8d96292a8928e6Jason Sams} 893709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 894709a0978ae141198018ca9769f8d96292a8928e6Jason Samsvoid RsdCpuScriptImpl::invokeFunction(uint32_t slot, const void *params, 895709a0978ae141198018ca9769f8d96292a8928e6Jason Sams size_t paramLength) { 896709a0978ae141198018ca9769f8d96292a8928e6Jason Sams //ALOGE("invoke %p %p %i %p %i", dc, script, slot, params, paramLength); 897709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 898709a0978ae141198018ca9769f8d96292a8928e6Jason Sams RsdCpuScriptImpl * oldTLS = mCtx->setTLS(this); 899709a0978ae141198018ca9769f8d96292a8928e6Jason Sams reinterpret_cast<void (*)(const void *, uint32_t)>( 900110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams#ifndef RS_COMPATIBILITY_LIB 901709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mExecutable->getExportFuncAddrs()[slot])(params, paramLength); 902110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams#else 903110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams mInvokeFunctions[slot])(params, paramLength); 904110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams#endif 905709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mCtx->setTLS(oldTLS); 906709a0978ae141198018ca9769f8d96292a8928e6Jason Sams} 907709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 908709a0978ae141198018ca9769f8d96292a8928e6Jason Samsvoid RsdCpuScriptImpl::setGlobalVar(uint32_t slot, const void *data, size_t dataLength) { 909709a0978ae141198018ca9769f8d96292a8928e6Jason Sams //rsAssert(!script->mFieldIsObject[slot]); 910709a0978ae141198018ca9769f8d96292a8928e6Jason Sams //ALOGE("setGlobalVar %p %p %i %p %i", dc, script, slot, data, dataLength); 911709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 912709a0978ae141198018ca9769f8d96292a8928e6Jason Sams //if (mIntrinsicID) { 913709a0978ae141198018ca9769f8d96292a8928e6Jason Sams //mIntrinsicFuncs.setVar(dc, script, drv->mIntrinsicData, slot, data, dataLength); 914709a0978ae141198018ca9769f8d96292a8928e6Jason Sams //return; 915709a0978ae141198018ca9769f8d96292a8928e6Jason Sams //} 916709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 917110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams#ifndef RS_COMPATIBILITY_LIB 918709a0978ae141198018ca9769f8d96292a8928e6Jason Sams int32_t *destPtr = reinterpret_cast<int32_t *>( 919709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mExecutable->getExportVarAddrs()[slot]); 920110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams#else 921110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams int32_t *destPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]); 922110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams#endif 923709a0978ae141198018ca9769f8d96292a8928e6Jason Sams if (!destPtr) { 924709a0978ae141198018ca9769f8d96292a8928e6Jason Sams //ALOGV("Calling setVar on slot = %i which is null", slot); 925709a0978ae141198018ca9769f8d96292a8928e6Jason Sams return; 926709a0978ae141198018ca9769f8d96292a8928e6Jason Sams } 927709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 928709a0978ae141198018ca9769f8d96292a8928e6Jason Sams memcpy(destPtr, data, dataLength); 929709a0978ae141198018ca9769f8d96292a8928e6Jason Sams} 930709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 9319c64239ebbfa4170190ede812e69150035e008e0Tim Murrayvoid RsdCpuScriptImpl::getGlobalVar(uint32_t slot, void *data, size_t dataLength) { 9329c64239ebbfa4170190ede812e69150035e008e0Tim Murray //rsAssert(!script->mFieldIsObject[slot]); 9339c64239ebbfa4170190ede812e69150035e008e0Tim Murray //ALOGE("getGlobalVar %p %p %i %p %i", dc, script, slot, data, dataLength); 9349c64239ebbfa4170190ede812e69150035e008e0Tim Murray 9359c64239ebbfa4170190ede812e69150035e008e0Tim Murray#ifndef RS_COMPATIBILITY_LIB 9369c64239ebbfa4170190ede812e69150035e008e0Tim Murray int32_t *srcPtr = reinterpret_cast<int32_t *>( 9379c64239ebbfa4170190ede812e69150035e008e0Tim Murray mExecutable->getExportVarAddrs()[slot]); 9389c64239ebbfa4170190ede812e69150035e008e0Tim Murray#else 9399c64239ebbfa4170190ede812e69150035e008e0Tim Murray int32_t *srcPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]); 9409c64239ebbfa4170190ede812e69150035e008e0Tim Murray#endif 9419c64239ebbfa4170190ede812e69150035e008e0Tim Murray if (!srcPtr) { 9429c64239ebbfa4170190ede812e69150035e008e0Tim Murray //ALOGV("Calling setVar on slot = %i which is null", slot); 9439c64239ebbfa4170190ede812e69150035e008e0Tim Murray return; 9449c64239ebbfa4170190ede812e69150035e008e0Tim Murray } 9459c64239ebbfa4170190ede812e69150035e008e0Tim Murray memcpy(data, srcPtr, dataLength); 9469c64239ebbfa4170190ede812e69150035e008e0Tim Murray} 9479c64239ebbfa4170190ede812e69150035e008e0Tim Murray 9489c64239ebbfa4170190ede812e69150035e008e0Tim Murray 949709a0978ae141198018ca9769f8d96292a8928e6Jason Samsvoid RsdCpuScriptImpl::setGlobalVarWithElemDims(uint32_t slot, const void *data, size_t dataLength, 950709a0978ae141198018ca9769f8d96292a8928e6Jason Sams const Element *elem, 951709a0978ae141198018ca9769f8d96292a8928e6Jason Sams const size_t *dims, size_t dimLength) { 952709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 953110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams#ifndef RS_COMPATIBILITY_LIB 954709a0978ae141198018ca9769f8d96292a8928e6Jason Sams int32_t *destPtr = reinterpret_cast<int32_t *>( 955709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mExecutable->getExportVarAddrs()[slot]); 956110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams#else 957110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams int32_t *destPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]); 958110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams#endif 959709a0978ae141198018ca9769f8d96292a8928e6Jason Sams if (!destPtr) { 960709a0978ae141198018ca9769f8d96292a8928e6Jason Sams //ALOGV("Calling setVar on slot = %i which is null", slot); 961709a0978ae141198018ca9769f8d96292a8928e6Jason Sams return; 962709a0978ae141198018ca9769f8d96292a8928e6Jason Sams } 963709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 964709a0978ae141198018ca9769f8d96292a8928e6Jason Sams // We want to look at dimension in terms of integer components, 965709a0978ae141198018ca9769f8d96292a8928e6Jason Sams // but dimLength is given in terms of bytes. 966709a0978ae141198018ca9769f8d96292a8928e6Jason Sams dimLength /= sizeof(int); 967709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 968709a0978ae141198018ca9769f8d96292a8928e6Jason Sams // Only a single dimension is currently supported. 969709a0978ae141198018ca9769f8d96292a8928e6Jason Sams rsAssert(dimLength == 1); 970709a0978ae141198018ca9769f8d96292a8928e6Jason Sams if (dimLength == 1) { 971709a0978ae141198018ca9769f8d96292a8928e6Jason Sams // First do the increment loop. 972709a0978ae141198018ca9769f8d96292a8928e6Jason Sams size_t stride = elem->getSizeBytes(); 973709a0978ae141198018ca9769f8d96292a8928e6Jason Sams const char *cVal = reinterpret_cast<const char *>(data); 974709a0978ae141198018ca9769f8d96292a8928e6Jason Sams for (size_t i = 0; i < dims[0]; i++) { 975709a0978ae141198018ca9769f8d96292a8928e6Jason Sams elem->incRefs(cVal); 976709a0978ae141198018ca9769f8d96292a8928e6Jason Sams cVal += stride; 977709a0978ae141198018ca9769f8d96292a8928e6Jason Sams } 978709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 979709a0978ae141198018ca9769f8d96292a8928e6Jason Sams // Decrement loop comes after (to prevent race conditions). 980709a0978ae141198018ca9769f8d96292a8928e6Jason Sams char *oldVal = reinterpret_cast<char *>(destPtr); 981709a0978ae141198018ca9769f8d96292a8928e6Jason Sams for (size_t i = 0; i < dims[0]; i++) { 982709a0978ae141198018ca9769f8d96292a8928e6Jason Sams elem->decRefs(oldVal); 983709a0978ae141198018ca9769f8d96292a8928e6Jason Sams oldVal += stride; 984709a0978ae141198018ca9769f8d96292a8928e6Jason Sams } 985709a0978ae141198018ca9769f8d96292a8928e6Jason Sams } 986709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 987709a0978ae141198018ca9769f8d96292a8928e6Jason Sams memcpy(destPtr, data, dataLength); 988709a0978ae141198018ca9769f8d96292a8928e6Jason Sams} 989709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 990709a0978ae141198018ca9769f8d96292a8928e6Jason Samsvoid RsdCpuScriptImpl::setGlobalBind(uint32_t slot, Allocation *data) { 991709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 992709a0978ae141198018ca9769f8d96292a8928e6Jason Sams //rsAssert(!script->mFieldIsObject[slot]); 993709a0978ae141198018ca9769f8d96292a8928e6Jason Sams //ALOGE("setGlobalBind %p %p %i %p", dc, script, slot, data); 994709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 995110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams#ifndef RS_COMPATIBILITY_LIB 996709a0978ae141198018ca9769f8d96292a8928e6Jason Sams int32_t *destPtr = reinterpret_cast<int32_t *>( 997709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mExecutable->getExportVarAddrs()[slot]); 998110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams#else 999110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams int32_t *destPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]); 1000110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams#endif 1001709a0978ae141198018ca9769f8d96292a8928e6Jason Sams if (!destPtr) { 1002709a0978ae141198018ca9769f8d96292a8928e6Jason Sams //ALOGV("Calling setVar on slot = %i which is null", slot); 1003709a0978ae141198018ca9769f8d96292a8928e6Jason Sams return; 1004709a0978ae141198018ca9769f8d96292a8928e6Jason Sams } 1005709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 1006709a0978ae141198018ca9769f8d96292a8928e6Jason Sams void *ptr = NULL; 1007709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mBoundAllocs[slot] = data; 1008709a0978ae141198018ca9769f8d96292a8928e6Jason Sams if(data) { 1009709a0978ae141198018ca9769f8d96292a8928e6Jason Sams ptr = data->mHal.drvState.lod[0].mallocPtr; 1010709a0978ae141198018ca9769f8d96292a8928e6Jason Sams } 1011709a0978ae141198018ca9769f8d96292a8928e6Jason Sams memcpy(destPtr, &ptr, sizeof(void *)); 1012709a0978ae141198018ca9769f8d96292a8928e6Jason Sams} 1013709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 1014709a0978ae141198018ca9769f8d96292a8928e6Jason Samsvoid RsdCpuScriptImpl::setGlobalObj(uint32_t slot, ObjectBase *data) { 1015709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 1016709a0978ae141198018ca9769f8d96292a8928e6Jason Sams //rsAssert(script->mFieldIsObject[slot]); 1017709a0978ae141198018ca9769f8d96292a8928e6Jason Sams //ALOGE("setGlobalObj %p %p %i %p", dc, script, slot, data); 1018709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 1019709a0978ae141198018ca9769f8d96292a8928e6Jason Sams //if (mIntrinsicID) { 1020709a0978ae141198018ca9769f8d96292a8928e6Jason Sams //mIntrinsicFuncs.setVarObj(dc, script, drv->mIntrinsicData, slot, alloc); 1021709a0978ae141198018ca9769f8d96292a8928e6Jason Sams //return; 1022709a0978ae141198018ca9769f8d96292a8928e6Jason Sams //} 1023709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 1024110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams#ifndef RS_COMPATIBILITY_LIB 1025709a0978ae141198018ca9769f8d96292a8928e6Jason Sams int32_t *destPtr = reinterpret_cast<int32_t *>( 1026709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mExecutable->getExportVarAddrs()[slot]); 1027110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams#else 1028110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams int32_t *destPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]); 1029110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams#endif 1030709a0978ae141198018ca9769f8d96292a8928e6Jason Sams if (!destPtr) { 1031709a0978ae141198018ca9769f8d96292a8928e6Jason Sams //ALOGV("Calling setVar on slot = %i which is null", slot); 1032709a0978ae141198018ca9769f8d96292a8928e6Jason Sams return; 1033709a0978ae141198018ca9769f8d96292a8928e6Jason Sams } 1034709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 1035709a0978ae141198018ca9769f8d96292a8928e6Jason Sams rsrSetObject(mCtx->getContext(), (ObjectBase **)destPtr, data); 1036709a0978ae141198018ca9769f8d96292a8928e6Jason Sams} 1037709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 1038709a0978ae141198018ca9769f8d96292a8928e6Jason SamsRsdCpuScriptImpl::~RsdCpuScriptImpl() { 1039110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams#ifndef RS_COMPATIBILITY_LIB 1040709a0978ae141198018ca9769f8d96292a8928e6Jason Sams if (mExecutable) { 1041709a0978ae141198018ca9769f8d96292a8928e6Jason Sams Vector<void *>::const_iterator var_addr_iter = 1042709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mExecutable->getExportVarAddrs().begin(); 1043709a0978ae141198018ca9769f8d96292a8928e6Jason Sams Vector<void *>::const_iterator var_addr_end = 1044709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mExecutable->getExportVarAddrs().end(); 1045709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 1046709a0978ae141198018ca9769f8d96292a8928e6Jason Sams bcc::RSInfo::ObjectSlotListTy::const_iterator is_object_iter = 1047709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mExecutable->getInfo().getObjectSlots().begin(); 1048709a0978ae141198018ca9769f8d96292a8928e6Jason Sams bcc::RSInfo::ObjectSlotListTy::const_iterator is_object_end = 1049709a0978ae141198018ca9769f8d96292a8928e6Jason Sams mExecutable->getInfo().getObjectSlots().end(); 1050709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 1051709a0978ae141198018ca9769f8d96292a8928e6Jason Sams while ((var_addr_iter != var_addr_end) && 1052709a0978ae141198018ca9769f8d96292a8928e6Jason Sams (is_object_iter != is_object_end)) { 1053709a0978ae141198018ca9769f8d96292a8928e6Jason Sams // The field address can be NULL if the script-side has optimized 1054709a0978ae141198018ca9769f8d96292a8928e6Jason Sams // the corresponding global variable away. 1055709a0978ae141198018ca9769f8d96292a8928e6Jason Sams ObjectBase **obj_addr = 1056709a0978ae141198018ca9769f8d96292a8928e6Jason Sams reinterpret_cast<ObjectBase **>(*var_addr_iter); 1057709a0978ae141198018ca9769f8d96292a8928e6Jason Sams if (*is_object_iter) { 1058709a0978ae141198018ca9769f8d96292a8928e6Jason Sams if (*var_addr_iter != NULL) { 1059709a0978ae141198018ca9769f8d96292a8928e6Jason Sams rsrClearObject(mCtx->getContext(), obj_addr); 1060709a0978ae141198018ca9769f8d96292a8928e6Jason Sams } 1061709a0978ae141198018ca9769f8d96292a8928e6Jason Sams } 1062709a0978ae141198018ca9769f8d96292a8928e6Jason Sams var_addr_iter++; 1063709a0978ae141198018ca9769f8d96292a8928e6Jason Sams is_object_iter++; 1064709a0978ae141198018ca9769f8d96292a8928e6Jason Sams } 1065709a0978ae141198018ca9769f8d96292a8928e6Jason Sams } 1066709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 1067709a0978ae141198018ca9769f8d96292a8928e6Jason Sams if (mCompilerContext) { 1068709a0978ae141198018ca9769f8d96292a8928e6Jason Sams delete mCompilerContext; 1069709a0978ae141198018ca9769f8d96292a8928e6Jason Sams } 1070709a0978ae141198018ca9769f8d96292a8928e6Jason Sams if (mCompilerDriver) { 1071709a0978ae141198018ca9769f8d96292a8928e6Jason Sams delete mCompilerDriver; 1072709a0978ae141198018ca9769f8d96292a8928e6Jason Sams } 1073709a0978ae141198018ca9769f8d96292a8928e6Jason Sams if (mExecutable) { 1074709a0978ae141198018ca9769f8d96292a8928e6Jason Sams delete mExecutable; 1075709a0978ae141198018ca9769f8d96292a8928e6Jason Sams } 1076709a0978ae141198018ca9769f8d96292a8928e6Jason Sams if (mBoundAllocs) { 1077709a0978ae141198018ca9769f8d96292a8928e6Jason Sams delete[] mBoundAllocs; 1078709a0978ae141198018ca9769f8d96292a8928e6Jason Sams } 1079110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams#else 1080110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams if (mFieldIsObject) { 1081110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams for (size_t i = 0; i < mExportedVariableCount; ++i) { 1082110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams if (mFieldIsObject[i]) { 1083110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams if (mFieldAddress[i] != NULL) { 1084110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams ObjectBase **obj_addr = 1085110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams reinterpret_cast<ObjectBase **>(mFieldAddress[i]); 1086110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams rsrClearObject(mCtx->getContext(), obj_addr); 1087110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams } 1088110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams } 1089110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams } 1090110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams } 1091110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams 1092110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams if (mInvokeFunctions) delete[] mInvokeFunctions; 1093110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams if (mForEachFunctions) delete[] mForEachFunctions; 1094110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams if (mFieldAddress) delete[] mFieldAddress; 1095110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams if (mFieldIsObject) delete[] mFieldIsObject; 1096110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams if (mForEachSignatures) delete[] mForEachSignatures; 1097110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams if (mBoundAllocs) delete[] mBoundAllocs; 1098110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams if (mScriptSO) { 1099110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams dlclose(mScriptSO); 1100110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams } 1101110f181b7966212a36ef18016f9b81c7322d0a2fJason Sams#endif 1102709a0978ae141198018ca9769f8d96292a8928e6Jason Sams} 1103709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 1104709a0978ae141198018ca9769f8d96292a8928e6Jason SamsAllocation * RsdCpuScriptImpl::getAllocationForPointer(const void *ptr) const { 1105709a0978ae141198018ca9769f8d96292a8928e6Jason Sams if (!ptr) { 1106709a0978ae141198018ca9769f8d96292a8928e6Jason Sams return NULL; 1107709a0978ae141198018ca9769f8d96292a8928e6Jason Sams } 1108709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 1109709a0978ae141198018ca9769f8d96292a8928e6Jason Sams for (uint32_t ct=0; ct < mScript->mHal.info.exportedVariableCount; ct++) { 1110709a0978ae141198018ca9769f8d96292a8928e6Jason Sams Allocation *a = mBoundAllocs[ct]; 1111709a0978ae141198018ca9769f8d96292a8928e6Jason Sams if (!a) continue; 1112709a0978ae141198018ca9769f8d96292a8928e6Jason Sams if (a->mHal.drvState.lod[0].mallocPtr == ptr) { 1113709a0978ae141198018ca9769f8d96292a8928e6Jason Sams return a; 1114709a0978ae141198018ca9769f8d96292a8928e6Jason Sams } 1115709a0978ae141198018ca9769f8d96292a8928e6Jason Sams } 1116709a0978ae141198018ca9769f8d96292a8928e6Jason Sams ALOGE("rsGetAllocation, failed to find %p", ptr); 1117709a0978ae141198018ca9769f8d96292a8928e6Jason Sams return NULL; 1118709a0978ae141198018ca9769f8d96292a8928e6Jason Sams} 1119709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 112017e3cdc24776d8fdbf1ce16287b9b4dcd516708fJason Samsvoid RsdCpuScriptImpl::preLaunch(uint32_t slot, const Allocation * ain, 112117e3cdc24776d8fdbf1ce16287b9b4dcd516708fJason Sams Allocation * aout, const void * usr, 112217e3cdc24776d8fdbf1ce16287b9b4dcd516708fJason Sams uint32_t usrLen, const RsScriptCall *sc) 112317e3cdc24776d8fdbf1ce16287b9b4dcd516708fJason Sams{ 112417e3cdc24776d8fdbf1ce16287b9b4dcd516708fJason Sams} 112517e3cdc24776d8fdbf1ce16287b9b4dcd516708fJason Sams 112617e3cdc24776d8fdbf1ce16287b9b4dcd516708fJason Samsvoid RsdCpuScriptImpl::postLaunch(uint32_t slot, const Allocation * ain, 112717e3cdc24776d8fdbf1ce16287b9b4dcd516708fJason Sams Allocation * aout, const void * usr, 112817e3cdc24776d8fdbf1ce16287b9b4dcd516708fJason Sams uint32_t usrLen, const RsScriptCall *sc) 112917e3cdc24776d8fdbf1ce16287b9b4dcd516708fJason Sams{ 113017e3cdc24776d8fdbf1ce16287b9b4dcd516708fJason Sams} 113117e3cdc24776d8fdbf1ce16287b9b4dcd516708fJason Sams 1132709a0978ae141198018ca9769f8d96292a8928e6Jason Sams 1133709a0978ae141198018ca9769f8d96292a8928e6Jason Sams} 1134709a0978ae141198018ca9769f8d96292a8928e6Jason Sams} 1135