am 97c92c2d: Revert "Introduce new Script class."
* commit '97c92c2d0604ea9cc4cd878f0f1901efc79c8835':
Revert "Introduce new Script class."
diff --git a/lib/ExecutionEngine/Android.mk b/lib/ExecutionEngine/Android.mk
index e26be60..855d055 100644
--- a/lib/ExecutionEngine/Android.mk
+++ b/lib/ExecutionEngine/Android.mk
@@ -31,7 +31,6 @@
GDBJITRegistrar.cpp \
MCCacheWriter.cpp \
MCCacheReader.cpp \
- RSScript.cpp \
Runtime.c \
RuntimeStub.c \
Script.cpp \
diff --git a/lib/ExecutionEngine/MCCacheWriter.cpp b/lib/ExecutionEngine/MCCacheWriter.cpp
index b113ad9..b0bf117 100644
--- a/lib/ExecutionEngine/MCCacheWriter.cpp
+++ b/lib/ExecutionEngine/MCCacheWriter.cpp
@@ -18,7 +18,7 @@
#include "DebugHelper.h"
#include "FileHandle.h"
-#include "RSScript.h"
+#include "Script.h"
#include <map>
#include <string>
@@ -48,7 +48,7 @@
}
bool MCCacheWriter::writeCacheFile(FileHandle *objFile, FileHandle *infoFile,
- RSScript *S, uint32_t libRS_threadable) {
+ Script *S, uint32_t libRS_threadable) {
if (!objFile || objFile->getFD() < 0 || !infoFile || infoFile->getFD() < 0) {
return false;
}
diff --git a/lib/ExecutionEngine/MCCacheWriter.h b/lib/ExecutionEngine/MCCacheWriter.h
index 7fa5cf5..b2bcb12 100644
--- a/lib/ExecutionEngine/MCCacheWriter.h
+++ b/lib/ExecutionEngine/MCCacheWriter.h
@@ -27,11 +27,11 @@
#include <vector>
namespace bcc {
- class RSScript;
+ class Script;
class MCCacheWriter {
private:
- RSScript *mpOwner;
+ Script *mpOwner;
FileHandle *mObjFile, *mInfoFile;
@@ -64,7 +64,7 @@
~MCCacheWriter();
bool writeCacheFile(FileHandle *objFile, FileHandle *infoFile,
- RSScript *S, uint32_t libRS_threadable);
+ Script *S, uint32_t libRS_threadable);
void addDependency(MCO_ResourceType resType,
std::string const &resName,
diff --git a/lib/ExecutionEngine/RSScript.cpp b/lib/ExecutionEngine/RSScript.cpp
deleted file mode 100644
index af37ab6..0000000
--- a/lib/ExecutionEngine/RSScript.cpp
+++ /dev/null
@@ -1,730 +0,0 @@
-/*
- * Copyright 2012, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Script.h"
-
-#include <errno.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <new>
-#include <cstring>
-
-#include <llvm/ADT/STLExtras.h>
-
-#include <cutils/properties.h>
-
-#include "Config.h"
-
-#include "MCCacheReader.h"
-#include "MCCacheWriter.h"
-#include "CompilerOption.h"
-
-#include "DebugHelper.h"
-#include "FileHandle.h"
-#include "GDBJITRegistrar.h"
-#include "ScriptCompiled.h"
-#include "ScriptCached.h"
-#include "Sha1Helper.h"
-#include "Source.h"
-
-namespace {
-
-bool getBooleanProp(const char *str) {
- char buf[PROPERTY_VALUE_MAX];
- property_get(str, buf, "0");
- return strcmp(buf, "0") != 0;
-}
-
-} // namespace anonymous
-
-namespace bcc {
-
-RSScript::SourceDependency::SourceDependency(MCO_ResourceType pSourceType,
- const std::string &pSourceName,
- const uint8_t *pSHA1)
- : mSourceType(pSourceType), mSourceName(pSourceName) {
- ::memcpy(mSHA1, pSHA1, sizeof(mSHA1));
- return;
-}
-
-RSScript::RSScript(Source &pSource)
- : Script(pSource),
- mpExtSymbolLookupFn(NULL),
- mpExtSymbolLookupFnContext(NULL) {
- resetState();
- return;
-}
-
-RSScript::~RSScript() {
- switch (mStatus) {
- case ScriptStatus::Compiled:
- delete mCompiled;
- break;
-
- case ScriptStatus::Cached:
- delete mCached;
- break;
-
- default:
- break;
- }
- llvm::DeleteContainerPointers(mSourceDependencies);
-}
-
-void RSScript::resetState() {
- mErrorCode = BCC_NO_ERROR;
- mStatus = ScriptStatus::Unknown;
- mObjectType = ScriptObject::Unknown;
- mIsContextSlotNotAvail = false;
- // FIXME: mpExtSymbolLookupFn and mpExtSymbolLookupFnContext should be assign
- // to NULL during state resetting.
- //mpExtSymbolLookupFn = NULL;
- //mpExtSymbolLookupFnContext = NULL;
- llvm::DeleteContainerPointers(mSourceDependencies);
- return;
-}
-
-
-bool RSScript::doReset() {
- resetState();
- return true;
-}
-
-bool RSScript::addSourceDependency(MCO_ResourceType pSourceType,
- const std::string &pSourceName,
- const uint8_t *pSHA1) {
- SourceDependency *source_dep =
- new (std::nothrow) SourceDependency(pSourceType, pSourceName, pSHA1);
- if (source_dep == NULL) {
- ALOGE("Out of memory when record dependency information of `%s'!",
- pSourceName.c_str());
- return false;
- }
-
- mSourceDependencies.push_back(source_dep);
- return true;
-}
-
-int RSScript::prepareRelocatable(char const *objPath,
- llvm::Reloc::Model RelocModel,
- unsigned long flags) {
- CompilerOption option;
- option.RelocModelOpt = RelocModel;
- option.LoadAfterCompile = false;
-
- int status = internalCompile(option);
- if (status != 0) {
- ALOGE("LLVM error message: %s\n", getCompilerErrorMessage());
- return status;
- }
-
- FileHandle objFile;
- if (objFile.open(objPath, OpenMode::Write) < 1) {
- ALOGE("Failed to open %s for write.\n", objPath);
- return 1;
- }
-
- if (static_cast<size_t>(objFile.write(getELF(),
- getELFSize())) != getELFSize()) {
- objFile.close();
- ::unlink(objPath);
- ALOGE("Unable to write ELF to file %s.\n", objPath);
- return false;
- }
-
- mObjectType = ScriptObject::Relocatable;
-
- return 0;
-}
-
-
-int RSScript::prepareSharedObject(char const *objPath,
- char const *dsoPath,
- unsigned long flags) {
- // TODO: Support cached shared object.
- return 1;
-}
-
-
-int RSScript::prepareExecutable(char const *cacheDir,
- char const *cacheName,
- unsigned long flags) {
- if (mStatus != ScriptStatus::Unknown) {
- mErrorCode = BCC_INVALID_OPERATION;
- ALOGE("Invalid operation: %s\n", __func__);
- return 1;
- }
-
- int status = internalLoadCache(cacheDir, cacheName, /* checkOnly */ false);
-
- if (status != 0) {
- CompilerOption option;
- status = internalCompile(option);
-
- if (status != 0) {
- ALOGE("LLVM error message: %s\n", getCompilerErrorMessage());
- return status;
- }
-
- status = writeCache();
- if (status != 0) {
- ALOGE("Failed to write the cache for %s\n", cacheName);
- return status;
- }
- }
-
- // FIXME: Registration can be conditional on the presence of debug metadata
- registerObjectWithGDB(getELF(), getELFSize()); // thread-safe registration
-
- mObjectType = ScriptObject::Executable;
-
- return status;
-}
-
-int RSScript::internalLoadCache(char const *cacheDir, char const *cacheName,
- bool checkOnly) {
- if ((cacheDir == NULL) || (cacheName == NULL)) {
- return 1;
- }
-
- // Set cache file Name
- mCacheName = cacheName;
-
- // Santize mCacheDir. Ensure that mCacheDir ends with '/'.
- mCacheDir = cacheDir;
- if (!mCacheDir.empty() && *mCacheDir.rbegin() != '/') {
- mCacheDir.push_back('/');
- }
-
- if (!isCacheable()) {
- return 1;
- }
-
- std::string objPath = getCachedObjectPath();
- std::string infoPath = getCacheInfoPath();
-
- FileHandle objFile;
- if (objFile.open(objPath.c_str(), OpenMode::Read) < 0) {
- // Unable to open the executable file in read mode.
- return 1;
- }
-
- FileHandle infoFile;
- if (infoFile.open(infoPath.c_str(), OpenMode::Read) < 0) {
- // Unable to open the metadata information file in read mode.
- return 1;
- }
-
- MCCacheReader reader;
-
- // Register symbol lookup function
- if (mpExtSymbolLookupFn) {
- reader.registerSymbolCallback(mpExtSymbolLookupFn,
- mpExtSymbolLookupFnContext);
- }
-
- // Dependencies
- reader.addDependency(BCC_FILE_RESOURCE, pathLibBCC_SHA1, sha1LibBCC_SHA1);
- reader.addDependency(BCC_FILE_RESOURCE, pathLibRS, sha1LibRS);
-
- for (unsigned i = 0; i < mSourceDependencies.size(); i++) {
- const SourceDependency *source_dep = mSourceDependencies[i];
- reader.addDependency(source_dep->getSourceType(),
- source_dep->getSourceName(),
- source_dep->getSHA1Checksum());
- }
-
- if (checkOnly)
- return !reader.checkCacheFile(&objFile, &infoFile, this);
-
- // Read cache file
- ScriptCached *cached = reader.readCacheFile(&objFile, &infoFile, this);
-
- if (!cached) {
- mIsContextSlotNotAvail = reader.isContextSlotNotAvail();
- return 1;
- }
-
- mCached = cached;
- mStatus = ScriptStatus::Cached;
-
- // Dirty hack for libRS.
- // TODO(all): This dirty hack should be removed in the future.
- if (!cached->isLibRSThreadable() && mpExtSymbolLookupFn) {
- mpExtSymbolLookupFn(mpExtSymbolLookupFnContext, "__clearThreadable");
- }
-
- return 0;
-}
-
-int RSScript::internalCompile(const CompilerOption &option) {
- // Create the ScriptCompiled object
- mCompiled = new (std::nothrow) ScriptCompiled(this);
-
- if (!mCompiled) {
- mErrorCode = BCC_OUT_OF_MEMORY;
- ALOGE("Out of memory: %s %d\n", __FILE__, __LINE__);
- return 1;
- }
-
- mStatus = ScriptStatus::Compiled;
-
- // Register symbol lookup function
- if (mpExtSymbolLookupFn) {
- mCompiled->registerSymbolCallback(mpExtSymbolLookupFn,
- mpExtSymbolLookupFnContext);
- }
-
- // Set the main source module
- if (mCompiled->readModule(getSource().getModule()) != 0) {
- ALOGE("Unable to read source module\n");
- return 1;
- }
-
- // Compile and JIT the code
- if (mCompiled->compile(option) != 0) {
- ALOGE("Unable to compile.\n");
- return 1;
- }
-
- return 0;
-}
-
-int RSScript::writeCache() {
- // Not compiled script or encountered error during the compilation.
- if ((mStatus != ScriptStatus::Compiled) ||
- (getCompilerErrorMessage() == NULL))
- return 1;
-
- // Note: If we re-compile the script because the cached context slot not
- // available, then we don't have to write the cache.
-
- // Note: If the address of the context is not in the context slot, then
- // we don't have to cache it.
-
- if (isCacheable()) {
-
- std::string objPath = getCachedObjectPath();
- std::string infoPath = getCacheInfoPath();
-
- // Remove the file if it already exists before writing the new file.
- // The old file may still be mapped elsewhere in memory and we do not want
- // to modify its contents. (The same script may be running concurrently in
- // the same process or a different process!)
- ::unlink(objPath.c_str());
- ::unlink(infoPath.c_str());
-
- FileHandle objFile;
- FileHandle infoFile;
-
- if (objFile.open(objPath.c_str(), OpenMode::Write) >= 0 &&
- infoFile.open(infoPath.c_str(), OpenMode::Write) >= 0) {
-
- MCCacheWriter writer;
-
-#ifdef TARGET_BUILD
- // Dependencies
- writer.addDependency(BCC_FILE_RESOURCE, pathLibBCC_SHA1, sha1LibBCC_SHA1);
- writer.addDependency(BCC_FILE_RESOURCE, pathLibRS, sha1LibRS);
-#endif
-
- for (unsigned i = 0; i < mSourceDependencies.size(); i++) {
- const SourceDependency *source_dep = mSourceDependencies[i];
- writer.addDependency(source_dep->getSourceType(),
- source_dep->getSourceName(),
- source_dep->getSHA1Checksum());
- }
-
-
- // libRS is threadable dirty hack
- // TODO: This should be removed in the future
- uint32_t libRS_threadable = 0;
- if (mpExtSymbolLookupFn) {
- libRS_threadable =
- (uint32_t)mpExtSymbolLookupFn(mpExtSymbolLookupFnContext,
- "__isThreadable");
- }
-
- if (!writer.writeCacheFile(&objFile, &infoFile, this, libRS_threadable)) {
- objFile.truncate();
- objFile.close();
-
- if (unlink(objPath.c_str()) != 0) {
- ALOGE("Unable to remove the invalid cache file: %s. (reason: %s)\n",
- objPath.c_str(), strerror(errno));
- }
-
- infoFile.truncate();
- infoFile.close();
-
- if (unlink(infoPath.c_str()) != 0) {
- ALOGE("Unable to remove the invalid cache file: %s. (reason: %s)\n",
- infoPath.c_str(), strerror(errno));
- }
- }
- }
- }
-
- return 0;
-}
-
-
-char const *RSScript::getCompilerErrorMessage() {
- if (mStatus != ScriptStatus::Compiled) {
- mErrorCode = BCC_INVALID_OPERATION;
- return NULL;
- }
-
- return mCompiled->getCompilerErrorMessage();
-}
-
-
-void *RSScript::lookup(const char *name) {
- switch (mStatus) {
- case ScriptStatus::Compiled: {
- return mCompiled->lookup(name);
- }
-
- case ScriptStatus::Cached: {
- return mCached->lookup(name);
- }
-
- default: {
- mErrorCode = BCC_INVALID_OPERATION;
- return NULL;
- }
- }
-}
-
-
-size_t RSScript::getExportVarCount() const {
- switch (mStatus) {
- case ScriptStatus::Compiled: {
- return mCompiled->getExportVarCount();
- }
-
- case ScriptStatus::Cached: {
- return mCached->getExportVarCount();
- }
-
- default: {
- return 0;
- }
- }
-}
-
-
-size_t RSScript::getExportFuncCount() const {
- switch (mStatus) {
- case ScriptStatus::Compiled: {
- return mCompiled->getExportFuncCount();
- }
-
- case ScriptStatus::Cached: {
- return mCached->getExportFuncCount();
- }
-
- default: {
- return 0;
- }
- }
-}
-
-
-size_t RSScript::getExportForEachCount() const {
- switch (mStatus) {
- case ScriptStatus::Compiled: {
- return mCompiled->getExportForEachCount();
- }
-
- case ScriptStatus::Cached: {
- return mCached->getExportForEachCount();
- }
-
- default: {
- return 0;
- }
- }
-}
-
-
-size_t RSScript::getPragmaCount() const {
- switch (mStatus) {
- case ScriptStatus::Compiled: {
- return mCompiled->getPragmaCount();
- }
-
- case ScriptStatus::Cached: {
- return mCached->getPragmaCount();
- }
-
- default: {
- return 0;
- }
- }
-}
-
-
-size_t RSScript::getFuncCount() const {
- switch (mStatus) {
- case ScriptStatus::Compiled: {
- return mCompiled->getFuncCount();
- }
-
- case ScriptStatus::Cached: {
- return mCached->getFuncCount();
- }
-
- default: {
- return 0;
- }
- }
-}
-
-
-size_t RSScript::getObjectSlotCount() const {
- switch (mStatus) {
- case ScriptStatus::Compiled: {
- return mCompiled->getObjectSlotCount();
- }
-
- case ScriptStatus::Cached: {
- return mCached->getObjectSlotCount();
- }
-
- default: {
- return 0;
- }
- }
-}
-
-
-void RSScript::getExportVarList(size_t varListSize, void **varList) {
- switch (mStatus) {
-#define DELEGATE(STATUS) \
- case ScriptStatus::STATUS: \
- m##STATUS->getExportVarList(varListSize, varList); \
- break;
-
- DELEGATE(Cached);
-
- DELEGATE(Compiled);
-#undef DELEGATE
-
- default: {
- mErrorCode = BCC_INVALID_OPERATION;
- }
- }
-}
-
-void RSScript::getExportVarNameList(std::vector<std::string> &varList) {
- switch (mStatus) {
- case ScriptStatus::Compiled: {
- return mCompiled->getExportVarNameList(varList);
- }
-
- default: {
- mErrorCode = BCC_INVALID_OPERATION;
- }
- }
-}
-
-
-void RSScript::getExportFuncList(size_t funcListSize, void **funcList) {
- switch (mStatus) {
-#define DELEGATE(STATUS) \
- case ScriptStatus::STATUS: \
- m##STATUS->getExportFuncList(funcListSize, funcList); \
- break;
-
- DELEGATE(Cached);
-
- DELEGATE(Compiled);
-#undef DELEGATE
-
- default: {
- mErrorCode = BCC_INVALID_OPERATION;
- }
- }
-}
-
-void RSScript::getExportFuncNameList(std::vector<std::string> &funcList) {
- switch (mStatus) {
- case ScriptStatus::Compiled: {
- return mCompiled->getExportFuncNameList(funcList);
- }
-
- default: {
- mErrorCode = BCC_INVALID_OPERATION;
- }
- }
-}
-
-void RSScript::getExportForEachList(size_t funcListSize, void **funcList) {
- switch (mStatus) {
-#define DELEGATE(STATUS) \
- case ScriptStatus::STATUS: \
- m##STATUS->getExportForEachList(funcListSize, funcList); \
- break;
-
- DELEGATE(Cached);
-
- DELEGATE(Compiled);
-#undef DELEGATE
-
- default: {
- mErrorCode = BCC_INVALID_OPERATION;
- }
- }
-}
-
-void RSScript::getExportForEachNameList(std::vector<std::string> &forEachList) {
- switch (mStatus) {
- case ScriptStatus::Compiled: {
- return mCompiled->getExportForEachNameList(forEachList);
- }
-
- default: {
- mErrorCode = BCC_INVALID_OPERATION;
- }
- }
-}
-
-void RSScript::getPragmaList(size_t pragmaListSize,
- char const **keyList,
- char const **valueList) {
- switch (mStatus) {
-#define DELEGATE(STATUS) \
- case ScriptStatus::STATUS: \
- m##STATUS->getPragmaList(pragmaListSize, keyList, valueList); \
- break;
-
- DELEGATE(Cached);
-
- DELEGATE(Compiled);
-#undef DELEGATE
-
- default: {
- mErrorCode = BCC_INVALID_OPERATION;
- }
- }
-}
-
-
-void RSScript::getFuncInfoList(size_t funcInfoListSize,
- FuncInfo *funcInfoList) {
- switch (mStatus) {
-#define DELEGATE(STATUS) \
- case ScriptStatus::STATUS: \
- m##STATUS->getFuncInfoList(funcInfoListSize, funcInfoList); \
- break;
-
- DELEGATE(Cached);
-
- DELEGATE(Compiled);
-#undef DELEGATE
-
- default: {
- mErrorCode = BCC_INVALID_OPERATION;
- }
- }
-}
-
-
-void RSScript::getObjectSlotList(size_t objectSlotListSize,
- uint32_t *objectSlotList) {
- switch (mStatus) {
-#define DELEGATE(STATUS) \
- case ScriptStatus::STATUS: \
- m##STATUS->getObjectSlotList(objectSlotListSize, objectSlotList); \
- break;
-
- DELEGATE(Cached);
-
- DELEGATE(Compiled);
-#undef DELEGATE
-
- default: {
- mErrorCode = BCC_INVALID_OPERATION;
- }
- }
-}
-
-
-int RSScript::registerSymbolCallback(BCCSymbolLookupFn pFn, void *pContext) {
- mpExtSymbolLookupFn = pFn;
- mpExtSymbolLookupFnContext = pContext;
-
- if (mStatus != ScriptStatus::Unknown) {
- mErrorCode = BCC_INVALID_OPERATION;
- ALOGE("Invalid operation: %s\n", __func__);
- return 1;
- }
- return 0;
-}
-
-bool RSScript::isCacheable() const {
- if (getBooleanProp("debug.bcc.nocache")) {
- // Android system environment property: Disables the cache mechanism by
- // setting "debug.bcc.nocache". So we will not load the cache file any
- // way.
- return false;
- }
-
- if (mCacheDir.empty() || mCacheName.empty()) {
- // The application developer has not specified the cachePath, so
- // we don't know where to open the cache file.
- return false;
- }
-
- return true;
-}
-
-size_t RSScript::getELFSize() const {
- switch (mStatus) {
- case ScriptStatus::Compiled: {
- return mCompiled->getELFSize();
- }
-
- case ScriptStatus::Cached: {
- return mCached->getELFSize();
- }
-
- default: {
- return 0;
- }
- }
-}
-
-const char *RSScript::getELF() const {
- switch (mStatus) {
- case ScriptStatus::Compiled: {
- return mCompiled->getELF();
- }
-
- case ScriptStatus::Cached: {
- return mCached->getELF();
- }
-
- default: {
- return NULL;
- }
- }
-}
-
-} // namespace bcc
diff --git a/lib/ExecutionEngine/RSScript.h b/lib/ExecutionEngine/RSScript.h
deleted file mode 100644
index 6e4cd9f..0000000
--- a/lib/ExecutionEngine/RSScript.h
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- * Copyright 2012, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef BCC_EXECUTION_ENGINE_RS_SCRIPT_H
-#define BCC_EXECUTION_ENGINE_RS_SCRIPT_H
-
-#include <vector>
-#include <string>
-
-#include <stdint.h>
-#include <stddef.h>
-
-#include <llvm/ADT/SmallVector.h>
-
-#include <bcc/bcc.h>
-#include <bcc/bcc_mccache.h>
-#include "bcc_internal.h"
-
-#include "Compiler.h"
-#include "Script.h"
-
-namespace llvm {
- class Module;
- class GDBJITRegistrar;
-}
-
-namespace bcc {
- class ScriptCompiled;
- class ScriptCached;
- class Source;
- struct CompilerOption;
-
- namespace ScriptStatus {
- enum StatusType {
- Unknown,
- Compiled,
- Cached
- };
- }
-
- namespace ScriptObject {
- enum ObjectType {
- Unknown,
- Relocatable,
- SharedObject,
- Executable,
- };
- }
-
- class RSScript : public Script {
- public:
- class SourceDependency {
- private:
- MCO_ResourceType mSourceType;
- std::string mSourceName;
- uint8_t mSHA1[20];
-
- public:
- SourceDependency(MCO_ResourceType pSourceType,
- const std::string &pSourceName,
- const uint8_t *pSHA1);
-
- inline MCO_ResourceType getSourceType() const
- { return mSourceType; }
-
- inline const std::string &getSourceName() const
- { return mSourceName; }
-
- inline const uint8_t *getSHA1Checksum() const
- { return mSHA1; }
- };
- typedef llvm::SmallVectorImpl<SourceDependency *> SourceDependencyListTy;
-
- private:
- int mErrorCode;
-
- ScriptStatus::StatusType mStatus;
- // The type of the object behind this script after compilation. For
- // example, after returning from a successful call to prepareRelocatable(),
- // the value of mObjectType will be ScriptObject::Relocatable.
- ScriptObject::ObjectType mObjectType;
-
- union {
- ScriptCompiled *mCompiled;
- ScriptCached *mCached;
- };
-
- std::string mCacheDir;
- std::string mCacheName;
-
- inline std::string getCachedObjectPath() const {
- return std::string(mCacheDir + mCacheName + ".o");
- }
-
- inline std::string getCacheInfoPath() const {
- return getCachedObjectPath().append(".info");
- }
-
- bool mIsContextSlotNotAvail;
-
- llvm::SmallVector<SourceDependency *, 4> mSourceDependencies;
-
- // External Function List
- std::vector<char const *> mUserDefinedExternalSymbols;
-
- // Register Symbol Lookup Function
- BCCSymbolLookupFn mpExtSymbolLookupFn;
- void *mpExtSymbolLookupFnContext;
-
- // This will be invoked when the containing source has been reset.
- virtual bool doReset();
-
- // Reset the state of this script object
- void resetState();
-
- public:
- RSScript(Source &pSource);
-
- ~RSScript();
-
- // Add dependency information for this script given the source named
- // pSourceName. pSHA1 is the SHA-1 checksum of the given source. Return
- // false on error.
- bool addSourceDependency(MCO_ResourceType pSourceType,
- const std::string &pSourceName,
- const uint8_t *pSHA1);
-
- const SourceDependencyListTy &getSourceDependencies() const
- { return mSourceDependencies; }
-
- void markExternalSymbol(char const *name) {
- mUserDefinedExternalSymbols.push_back(name);
- }
-
- std::vector<char const *> const &getUserDefinedExternalSymbols() const {
- return mUserDefinedExternalSymbols;
- }
-
- int prepareExecutable(char const *cacheDir,
- char const *cacheName,
- unsigned long flags);
- int writeCache();
-
- /*
- * Link the given bitcodes in mSource to shared object (.so).
- *
- * Currently, it requires one to provide the relocatable object files with
- * given bitcodes to output a shared object.
- *
- * The usage of this function is flexible. You can have a relocatable object
- * compiled before and pass it in objPath to generate shared object. If the
- * objPath is NULL, we'll invoke prepareRelocatable() to get .o first (if
- * you haven't done that yet) and then link the output relocatable object
- * file to .so in dsoPath.
- *
- * TODO: Currently, we only support to link a bitcode (i.e., mSource.)
- *
- */
- int prepareSharedObject(char const *objPath,
- char const *dsoPath,
- unsigned long flags);
-
- int prepareRelocatable(char const *objPath,
- llvm::Reloc::Model RelocModel,
- unsigned long flags);
-
- char const *getCompilerErrorMessage();
-
- void *lookup(const char *name);
-
- size_t getExportVarCount() const;
-
- size_t getExportFuncCount() const;
-
- size_t getExportForEachCount() const;
-
- size_t getPragmaCount() const;
-
- size_t getFuncCount() const;
-
- size_t getObjectSlotCount() const;
-
- void getExportVarList(size_t size, void **list);
-
- void getExportFuncList(size_t size, void **list);
-
- void getExportForEachList(size_t size, void **list);
-
- void getExportVarNameList(std::vector<std::string> &list);
-
- void getExportFuncNameList(std::vector<std::string> &list);
-
- void getExportForEachNameList(std::vector<std::string> &list);
-
- void getPragmaList(size_t size,
- char const **keyList,
- char const **valueList);
-
- void getFuncInfoList(size_t size, FuncInfo *list);
-
- void getObjectSlotList(size_t size, uint32_t *list);
-
- size_t getELFSize() const;
-
- const char *getELF() const;
-
- int registerSymbolCallback(BCCSymbolLookupFn pFn, void *pContext);
-
- bool isCacheable() const;
-
- void setError(int error) {
- if (mErrorCode == BCC_NO_ERROR && error != BCC_NO_ERROR) {
- mErrorCode = error;
- }
- }
-
- int getError() {
- int result = mErrorCode;
- mErrorCode = BCC_NO_ERROR;
- return result;
- }
-
- private:
- //
- // It returns 0 if there's a cache hit.
- //
- // Side effect: it will set mCacheDir, mCacheName.
- int internalLoadCache(char const *cacheDir, char const *cacheName,
- bool checkOnly);
-
- int internalCompile(const CompilerOption&);
- };
-
-} // namespace bcc
-
-#endif // BCC_EXECUTION_ENGINE_RS_SCRIPT_H
diff --git a/lib/ExecutionEngine/Script.cpp b/lib/ExecutionEngine/Script.cpp
index 785915c..7c79254 100644
--- a/lib/ExecutionEngine/Script.cpp
+++ b/lib/ExecutionEngine/Script.cpp
@@ -1,24 +1,105 @@
/*
- * Copyright 2010-2012, The Android Open Source Project
+ * copyright 2010-2012, the android open source project
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * 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
+ * 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.
+ * unless required by applicable law or agreed to in writing, software
+ * distributed under the license is distributed on an "as is" basis,
+ * without warranties or conditions of any kind, either express or implied.
+ * see the license for the specific language governing permissions and
+ * limitations under the license.
*/
#include "Script.h"
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <new>
+#include <cstring>
+
+#include <llvm/ADT/STLExtras.h>
+
+#include <cutils/properties.h>
+
+#include "Config.h"
+
+#include "MCCacheReader.h"
+#include "MCCacheWriter.h"
+#include "CompilerOption.h"
+
+#include "BCCContextImpl.h"
+#include "DebugHelper.h"
+#include "FileHandle.h"
+#include "GDBJITRegistrar.h"
+#include "ScriptCompiled.h"
+#include "ScriptCached.h"
+#include "Sha1Helper.h"
#include "Source.h"
-using namespace bcc;
+namespace {
+
+bool getBooleanProp(const char *str) {
+ char buf[PROPERTY_VALUE_MAX];
+ property_get(str, buf, "0");
+ return strcmp(buf, "0") != 0;
+}
+
+} // namespace anonymous
+
+namespace bcc {
+
+Script::Script(Source &pSource)
+ : mSource(&pSource),
+ mpExtSymbolLookupFn(NULL),
+ mpExtSymbolLookupFnContext(NULL) {
+ resetState();
+ return;
+}
+
+Script::~Script() {
+ switch (mStatus) {
+ case ScriptStatus::Compiled:
+ delete mCompiled;
+ break;
+
+ case ScriptStatus::Cached:
+ delete mCached;
+ break;
+
+ default:
+ break;
+ }
+ llvm::DeleteContainerPointers(mDependencyInfos);
+}
+
+void Script::resetState() {
+ mErrorCode = BCC_NO_ERROR;
+ mStatus = ScriptStatus::Unknown;
+ mObjectType = ScriptObject::Unknown;
+ mIsContextSlotNotAvail = false;
+ // FIXME: mpExtSymbolLookupFn and mpExtSymbolLookupFnContext should be assign
+ // to NULL during state resetting.
+ //mpExtSymbolLookupFn = NULL;
+ //mpExtSymbolLookupFnContext = NULL;
+ llvm::DeleteContainerPointers(mDependencyInfos);
+ return;
+}
+
+
+Script::DependencyInfo::DependencyInfo(MCO_ResourceType pSourceType,
+ const std::string &pSourceName,
+ const uint8_t *pSHA1)
+ : mSourceType(pSourceType), mSourceName(pSourceName) {
+ ::memcpy(mSHA1, pSHA1, sizeof(mSHA1));
+ return;
+}
bool Script::reset(Source &pSource, bool pPreserveCurrent) {
if (mSource == &pSource) {
@@ -29,9 +110,636 @@
delete mSource;
}
mSource = &pSource;
- return doReset();
+ resetState();
+ return true;
}
bool Script::mergeSource(Source &pSource, bool pPreserveSource) {
return mSource->merge(pSource, pPreserveSource);
}
+
+bool Script::addSourceDependencyInfo(MCO_ResourceType pSourceType,
+ const std::string &pSourceName,
+ const uint8_t *pSHA1) {
+ DependencyInfo *dep_info = new (std::nothrow) DependencyInfo(pSourceType,
+ pSourceName,
+ pSHA1);
+ if (dep_info == NULL) {
+ ALOGE("Out of memory when record dependency information of `%s'!",
+ pSourceName.c_str());
+ return false;
+ }
+
+ mDependencyInfos.push_back(dep_info);
+ return true;
+}
+
+int Script::prepareRelocatable(char const *objPath,
+ llvm::Reloc::Model RelocModel,
+ unsigned long flags) {
+ CompilerOption option;
+ option.RelocModelOpt = RelocModel;
+ option.RunLTO = false;
+ option.LoadAfterCompile = false;
+
+ int status = internalCompile(option);
+ if (status != 0) {
+ ALOGE("LLVM error message: %s\n", getCompilerErrorMessage());
+ return status;
+ }
+
+ FileHandle objFile;
+ if (objFile.open(objPath, OpenMode::Write) < 0) {
+ ALOGE("Failed to open %s for write.\n", objPath);
+ return 1;
+ }
+
+ if (static_cast<size_t>(objFile.write(getELF(),
+ getELFSize())) != getELFSize()) {
+ objFile.close();
+ ::unlink(objPath);
+ ALOGE("Unable to write ELF to file %s.\n", objPath);
+ return false;
+ }
+
+ mObjectType = ScriptObject::Relocatable;
+
+ return 0;
+}
+
+
+int Script::prepareSharedObject(char const *objPath,
+ char const *dsoPath,
+ unsigned long flags) {
+ // TODO: Support cached shared object.
+ return 1;
+}
+
+
+int Script::prepareExecutable(char const *cacheDir,
+ char const *cacheName,
+ unsigned long flags) {
+ if (mStatus != ScriptStatus::Unknown) {
+ mErrorCode = BCC_INVALID_OPERATION;
+ ALOGE("Invalid operation: %s\n", __func__);
+ return 1;
+ }
+
+ int status = internalLoadCache(cacheDir, cacheName, /* checkOnly */ false);
+
+ if (status != 0) {
+ CompilerOption option;
+ status = internalCompile(option);
+
+ if (status != 0) {
+ ALOGE("LLVM error message: %s\n", getCompilerErrorMessage());
+ return status;
+ }
+
+ status = writeCache();
+ if (status != 0) {
+ ALOGE("Failed to write the cache for %s\n", cacheName);
+ return status;
+ }
+ }
+
+ // FIXME: Registration can be conditional on the presence of debug metadata
+ registerObjectWithGDB(getELF(), getELFSize()); // thread-safe registration
+
+ mObjectType = ScriptObject::Executable;
+
+ return status;
+}
+
+int Script::internalLoadCache(char const *cacheDir, char const *cacheName,
+ bool checkOnly) {
+ if ((cacheDir == NULL) || (cacheName == NULL)) {
+ return 1;
+ }
+
+ // Set cache file Name
+ mCacheName = cacheName;
+
+ // Santize mCacheDir. Ensure that mCacheDir ends with '/'.
+ mCacheDir = cacheDir;
+ if (!mCacheDir.empty() && *mCacheDir.rbegin() != '/') {
+ mCacheDir.push_back('/');
+ }
+
+ if (!isCacheable()) {
+ return 1;
+ }
+
+ std::string objPath = getCachedObjectPath();
+ std::string infoPath = getCacheInfoPath();
+
+ FileHandle objFile;
+ if (objFile.open(objPath.c_str(), OpenMode::Read) < 0) {
+ // Unable to open the executable file in read mode.
+ return 1;
+ }
+
+ FileHandle infoFile;
+ if (infoFile.open(infoPath.c_str(), OpenMode::Read) < 0) {
+ // Unable to open the metadata information file in read mode.
+ return 1;
+ }
+
+ MCCacheReader reader;
+
+ // Register symbol lookup function
+ if (mpExtSymbolLookupFn) {
+ reader.registerSymbolCallback(mpExtSymbolLookupFn,
+ mpExtSymbolLookupFnContext);
+ }
+
+ // Dependencies
+ reader.addDependency(BCC_FILE_RESOURCE, pathLibBCC_SHA1, sha1LibBCC_SHA1);
+ reader.addDependency(BCC_FILE_RESOURCE, pathLibRS, sha1LibRS);
+
+ for (unsigned i = 0; i < mDependencyInfos.size(); i++) {
+ const DependencyInfo *dep_info = mDependencyInfos[i];
+ reader.addDependency(dep_info->getSourceType(),
+ dep_info->getSourceName(),
+ dep_info->getSHA1Checksum());
+ }
+
+ if (checkOnly)
+ return !reader.checkCacheFile(&objFile, &infoFile, this);
+
+ // Read cache file
+ ScriptCached *cached = reader.readCacheFile(&objFile, &infoFile, this);
+
+ if (!cached) {
+ mIsContextSlotNotAvail = reader.isContextSlotNotAvail();
+ return 1;
+ }
+
+ mCached = cached;
+ mStatus = ScriptStatus::Cached;
+
+ // Dirty hack for libRS.
+ // TODO(all): This dirty hack should be removed in the future.
+ if (!cached->isLibRSThreadable() && mpExtSymbolLookupFn) {
+ mpExtSymbolLookupFn(mpExtSymbolLookupFnContext, "__clearThreadable");
+ }
+
+ return 0;
+}
+
+int Script::internalCompile(const CompilerOption &option) {
+ // Create the ScriptCompiled object
+ mCompiled = new (std::nothrow) ScriptCompiled(this);
+
+ if (!mCompiled) {
+ mErrorCode = BCC_OUT_OF_MEMORY;
+ ALOGE("Out of memory: %s %d\n", __FILE__, __LINE__);
+ return 1;
+ }
+
+ mStatus = ScriptStatus::Compiled;
+
+ // Register symbol lookup function
+ if (mpExtSymbolLookupFn) {
+ mCompiled->registerSymbolCallback(mpExtSymbolLookupFn,
+ mpExtSymbolLookupFnContext);
+ }
+
+ // Set the main source module
+ if (mCompiled->readModule(mSource->getModule()) != 0) {
+ ALOGE("Unable to read source module\n");
+ return 1;
+ }
+
+ // Compile and JIT the code
+ if (mCompiled->compile(option) != 0) {
+ ALOGE("Unable to compile.\n");
+ return 1;
+ }
+
+ return 0;
+}
+
+int Script::writeCache() {
+ // Not compiled script or encountered error during the compilation.
+ if ((mStatus != ScriptStatus::Compiled) ||
+ (getCompilerErrorMessage() == NULL))
+ return 1;
+
+ // Note: If we re-compile the script because the cached context slot not
+ // available, then we don't have to write the cache.
+
+ // Note: If the address of the context is not in the context slot, then
+ // we don't have to cache it.
+
+ if (isCacheable()) {
+
+ std::string objPath = getCachedObjectPath();
+ std::string infoPath = getCacheInfoPath();
+
+ // Remove the file if it already exists before writing the new file.
+ // The old file may still be mapped elsewhere in memory and we do not want
+ // to modify its contents. (The same script may be running concurrently in
+ // the same process or a different process!)
+ ::unlink(objPath.c_str());
+ ::unlink(infoPath.c_str());
+
+ FileHandle objFile;
+ FileHandle infoFile;
+
+ if (objFile.open(objPath.c_str(), OpenMode::Write) >= 0 &&
+ infoFile.open(infoPath.c_str(), OpenMode::Write) >= 0) {
+
+ MCCacheWriter writer;
+
+#ifdef TARGET_BUILD
+ // Dependencies
+ writer.addDependency(BCC_FILE_RESOURCE, pathLibBCC_SHA1, sha1LibBCC_SHA1);
+ writer.addDependency(BCC_FILE_RESOURCE, pathLibRS, sha1LibRS);
+#endif
+
+ for (unsigned i = 0; i < mDependencyInfos.size(); i++) {
+ const DependencyInfo *dep_info = mDependencyInfos[i];
+ writer.addDependency(dep_info->getSourceType(),
+ dep_info->getSourceName(),
+ dep_info->getSHA1Checksum());
+ }
+
+
+ // libRS is threadable dirty hack
+ // TODO: This should be removed in the future
+ uint32_t libRS_threadable = 0;
+ if (mpExtSymbolLookupFn) {
+ libRS_threadable =
+ (uint32_t)mpExtSymbolLookupFn(mpExtSymbolLookupFnContext,
+ "__isThreadable");
+ }
+
+ if (!writer.writeCacheFile(&objFile, &infoFile, this, libRS_threadable)) {
+ objFile.truncate();
+ objFile.close();
+
+ if (unlink(objPath.c_str()) != 0) {
+ ALOGE("Unable to remove the invalid cache file: %s. (reason: %s)\n",
+ objPath.c_str(), strerror(errno));
+ }
+
+ infoFile.truncate();
+ infoFile.close();
+
+ if (unlink(infoPath.c_str()) != 0) {
+ ALOGE("Unable to remove the invalid cache file: %s. (reason: %s)\n",
+ infoPath.c_str(), strerror(errno));
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+
+char const *Script::getCompilerErrorMessage() {
+ if (mStatus != ScriptStatus::Compiled) {
+ mErrorCode = BCC_INVALID_OPERATION;
+ return NULL;
+ }
+
+ return mCompiled->getCompilerErrorMessage();
+}
+
+
+void *Script::lookup(const char *name) {
+ switch (mStatus) {
+ case ScriptStatus::Compiled: {
+ return mCompiled->lookup(name);
+ }
+
+ case ScriptStatus::Cached: {
+ return mCached->lookup(name);
+ }
+
+ default: {
+ mErrorCode = BCC_INVALID_OPERATION;
+ return NULL;
+ }
+ }
+}
+
+
+size_t Script::getExportVarCount() const {
+ switch (mStatus) {
+ case ScriptStatus::Compiled: {
+ return mCompiled->getExportVarCount();
+ }
+
+ case ScriptStatus::Cached: {
+ return mCached->getExportVarCount();
+ }
+
+ default: {
+ return 0;
+ }
+ }
+}
+
+
+size_t Script::getExportFuncCount() const {
+ switch (mStatus) {
+ case ScriptStatus::Compiled: {
+ return mCompiled->getExportFuncCount();
+ }
+
+ case ScriptStatus::Cached: {
+ return mCached->getExportFuncCount();
+ }
+
+ default: {
+ return 0;
+ }
+ }
+}
+
+
+size_t Script::getExportForEachCount() const {
+ switch (mStatus) {
+ case ScriptStatus::Compiled: {
+ return mCompiled->getExportForEachCount();
+ }
+
+ case ScriptStatus::Cached: {
+ return mCached->getExportForEachCount();
+ }
+
+ default: {
+ return 0;
+ }
+ }
+}
+
+
+size_t Script::getPragmaCount() const {
+ switch (mStatus) {
+ case ScriptStatus::Compiled: {
+ return mCompiled->getPragmaCount();
+ }
+
+ case ScriptStatus::Cached: {
+ return mCached->getPragmaCount();
+ }
+
+ default: {
+ return 0;
+ }
+ }
+}
+
+
+size_t Script::getFuncCount() const {
+ switch (mStatus) {
+ case ScriptStatus::Compiled: {
+ return mCompiled->getFuncCount();
+ }
+
+ case ScriptStatus::Cached: {
+ return mCached->getFuncCount();
+ }
+
+ default: {
+ return 0;
+ }
+ }
+}
+
+
+size_t Script::getObjectSlotCount() const {
+ switch (mStatus) {
+ case ScriptStatus::Compiled: {
+ return mCompiled->getObjectSlotCount();
+ }
+
+ case ScriptStatus::Cached: {
+ return mCached->getObjectSlotCount();
+ }
+
+ default: {
+ return 0;
+ }
+ }
+}
+
+
+void Script::getExportVarList(size_t varListSize, void **varList) {
+ switch (mStatus) {
+#define DELEGATE(STATUS) \
+ case ScriptStatus::STATUS: \
+ m##STATUS->getExportVarList(varListSize, varList); \
+ break;
+
+ DELEGATE(Cached);
+
+ DELEGATE(Compiled);
+#undef DELEGATE
+
+ default: {
+ mErrorCode = BCC_INVALID_OPERATION;
+ }
+ }
+}
+
+void Script::getExportVarNameList(std::vector<std::string> &varList) {
+ switch (mStatus) {
+ case ScriptStatus::Compiled: {
+ return mCompiled->getExportVarNameList(varList);
+ }
+
+ default: {
+ mErrorCode = BCC_INVALID_OPERATION;
+ }
+ }
+}
+
+
+void Script::getExportFuncList(size_t funcListSize, void **funcList) {
+ switch (mStatus) {
+#define DELEGATE(STATUS) \
+ case ScriptStatus::STATUS: \
+ m##STATUS->getExportFuncList(funcListSize, funcList); \
+ break;
+
+ DELEGATE(Cached);
+
+ DELEGATE(Compiled);
+#undef DELEGATE
+
+ default: {
+ mErrorCode = BCC_INVALID_OPERATION;
+ }
+ }
+}
+
+void Script::getExportFuncNameList(std::vector<std::string> &funcList) {
+ switch (mStatus) {
+ case ScriptStatus::Compiled: {
+ return mCompiled->getExportFuncNameList(funcList);
+ }
+
+ default: {
+ mErrorCode = BCC_INVALID_OPERATION;
+ }
+ }
+}
+
+void Script::getExportForEachList(size_t funcListSize, void **funcList) {
+ switch (mStatus) {
+#define DELEGATE(STATUS) \
+ case ScriptStatus::STATUS: \
+ m##STATUS->getExportForEachList(funcListSize, funcList); \
+ break;
+
+ DELEGATE(Cached);
+
+ DELEGATE(Compiled);
+#undef DELEGATE
+
+ default: {
+ mErrorCode = BCC_INVALID_OPERATION;
+ }
+ }
+}
+
+void Script::getExportForEachNameList(std::vector<std::string> &forEachList) {
+ switch (mStatus) {
+ case ScriptStatus::Compiled: {
+ return mCompiled->getExportForEachNameList(forEachList);
+ }
+
+ default: {
+ mErrorCode = BCC_INVALID_OPERATION;
+ }
+ }
+}
+
+void Script::getPragmaList(size_t pragmaListSize,
+ char const **keyList,
+ char const **valueList) {
+ switch (mStatus) {
+#define DELEGATE(STATUS) \
+ case ScriptStatus::STATUS: \
+ m##STATUS->getPragmaList(pragmaListSize, keyList, valueList); \
+ break;
+
+ DELEGATE(Cached);
+
+ DELEGATE(Compiled);
+#undef DELEGATE
+
+ default: {
+ mErrorCode = BCC_INVALID_OPERATION;
+ }
+ }
+}
+
+
+void Script::getFuncInfoList(size_t funcInfoListSize,
+ FuncInfo *funcInfoList) {
+ switch (mStatus) {
+#define DELEGATE(STATUS) \
+ case ScriptStatus::STATUS: \
+ m##STATUS->getFuncInfoList(funcInfoListSize, funcInfoList); \
+ break;
+
+ DELEGATE(Cached);
+
+ DELEGATE(Compiled);
+#undef DELEGATE
+
+ default: {
+ mErrorCode = BCC_INVALID_OPERATION;
+ }
+ }
+}
+
+
+void Script::getObjectSlotList(size_t objectSlotListSize,
+ uint32_t *objectSlotList) {
+ switch (mStatus) {
+#define DELEGATE(STATUS) \
+ case ScriptStatus::STATUS: \
+ m##STATUS->getObjectSlotList(objectSlotListSize, objectSlotList); \
+ break;
+
+ DELEGATE(Cached);
+
+ DELEGATE(Compiled);
+#undef DELEGATE
+
+ default: {
+ mErrorCode = BCC_INVALID_OPERATION;
+ }
+ }
+}
+
+
+int Script::registerSymbolCallback(BCCSymbolLookupFn pFn, void *pContext) {
+ mpExtSymbolLookupFn = pFn;
+ mpExtSymbolLookupFnContext = pContext;
+
+ if (mStatus != ScriptStatus::Unknown) {
+ mErrorCode = BCC_INVALID_OPERATION;
+ ALOGE("Invalid operation: %s\n", __func__);
+ return 1;
+ }
+ return 0;
+}
+
+bool Script::isCacheable() const {
+ if (getBooleanProp("debug.bcc.nocache")) {
+ // Android system environment property: Disables the cache mechanism by
+ // setting "debug.bcc.nocache". So we will not load the cache file any
+ // way.
+ return false;
+ }
+
+ if (mCacheDir.empty() || mCacheName.empty()) {
+ // The application developer has not specified the cachePath, so
+ // we don't know where to open the cache file.
+ return false;
+ }
+
+ return true;
+}
+
+size_t Script::getELFSize() const {
+ switch (mStatus) {
+ case ScriptStatus::Compiled: {
+ return mCompiled->getELFSize();
+ }
+
+ case ScriptStatus::Cached: {
+ return mCached->getELFSize();
+ }
+
+ default: {
+ return 0;
+ }
+ }
+}
+
+const char *Script::getELF() const {
+ switch (mStatus) {
+ case ScriptStatus::Compiled: {
+ return mCompiled->getELF();
+ }
+
+ case ScriptStatus::Cached: {
+ return mCached->getELF();
+ }
+
+ default: {
+ return NULL;
+ }
+ }
+}
+
+} // namespace bcc
diff --git a/lib/ExecutionEngine/Script.h b/lib/ExecutionEngine/Script.h
index aaa5eba..b654797 100644
--- a/lib/ExecutionEngine/Script.h
+++ b/lib/ExecutionEngine/Script.h
@@ -14,49 +14,241 @@
* limitations under the License.
*/
-#ifndef BCC_EXECUTION_ENGINE_SCRIPT_H
-#define BCC_EXECUTION_ENGINE_SCRIPT_H
+#ifndef BCC_SCRIPT_H
+#define BCC_SCRIPT_H
+
+#include <vector>
+#include <string>
+
+#include <stdint.h>
+#include <stddef.h>
+
+#include <llvm/ADT/SmallVector.h>
+
+#include <bcc/bcc.h>
+#include <bcc/bcc_mccache.h>
+#include "bcc_internal.h"
+
+#include "Compiler.h"
+
+namespace llvm {
+ class Module;
+ class GDBJITRegistrar;
+}
namespace bcc {
+ class ScriptCompiled;
+ class ScriptCached;
+ class Source;
+ struct CompilerOption;
-class Source;
+ namespace ScriptStatus {
+ enum StatusType {
+ Unknown,
+ Compiled,
+ Cached
+ };
+ }
-class Script {
-private:
- // This is the source associated with this object and is going to be
- // compiled.
- Source *mSource;
+ namespace ScriptObject {
+ enum ObjectType {
+ Unknown,
+ Relocatable,
+ SharedObject,
+ Executable,
+ };
+ }
-protected:
- // This hook will be invoked after the script object is succssfully reset
- // itself.
- virtual bool doReset()
- { return true; }
+ class Script {
+ private:
+ int mErrorCode;
-public:
- Script(Source &pSource) : mSource(&pSource) { }
+ ScriptStatus::StatusType mStatus;
+ // The type of the object behind this script after compilation. For
+ // example, after returning from a successful call to prepareRelocatable(),
+ // the value of mObjectType will be ScriptObject::Relocatable.
+ ScriptObject::ObjectType mObjectType;
- virtual ~Script() { }
+ union {
+ ScriptCompiled *mCompiled;
+ ScriptCached *mCached;
+ };
- // Reset this object with the new source supplied. Return false if this
- // object remains unchanged after the call (e.g., the supplied source is
- // the same with the one contain in this object.) If pPreserveCurrent is
- // false, the current containing source will be destroyed after successfully
- // reset.
- bool reset(Source &pSource, bool pPreserveCurrent = false);
+ std::string mCacheDir;
+ std::string mCacheName;
- // Merge (or link) another source into the current source associated with
- // this Script object. Return false on error.
- //
- // This is equivalent to the call to Script::merge(...) on mSource.
- bool mergeSource(Source &pSource, bool pPreserveSource = false);
+ inline std::string getCachedObjectPath() const {
+ return std::string(mCacheDir + mCacheName + ".o");
+ }
- inline Source &getSource()
- { return *mSource; }
- inline const Source &getSource() const
- { return *mSource; }
-};
+ inline std::string getCacheInfoPath() const {
+ return getCachedObjectPath().append(".info");
+ }
-} // end namespace bcc
+ bool mIsContextSlotNotAvail;
-#endif // BCC_EXECUTION_ENGINE_SCRIPT_H
+ // This is the source associated with this object and is going to be
+ // compiled.
+ Source *mSource;
+
+ class DependencyInfo {
+ private:
+ MCO_ResourceType mSourceType;
+ std::string mSourceName;
+ uint8_t mSHA1[20];
+
+ public:
+ DependencyInfo(MCO_ResourceType pSourceType,
+ const std::string &pSourceName,
+ const uint8_t *pSHA1);
+
+ inline MCO_ResourceType getSourceType() const
+ { return mSourceType; }
+
+ inline const std::string getSourceName() const
+ { return mSourceName; }
+
+ inline const uint8_t *getSHA1Checksum() const
+ { return mSHA1; }
+ };
+ llvm::SmallVector<DependencyInfo *, 2> mDependencyInfos;
+
+ // External Function List
+ std::vector<char const *> mUserDefinedExternalSymbols;
+
+ // Register Symbol Lookup Function
+ BCCSymbolLookupFn mpExtSymbolLookupFn;
+ void *mpExtSymbolLookupFnContext;
+
+ // Reset the state of this script object
+ void resetState();
+
+ public:
+ Script(Source &pSource);
+
+ ~Script();
+
+ // Reset this object with the new source supplied. Return false if this
+ // object remains unchanged after the call (e.g., the supplied source is
+ // the same with the one contain in this object.) If pPreserveCurrent is
+ // false, the current containing source will be destroyed after successfully
+ // reset.
+ bool reset(Source &pSource, bool pPreserveCurrent = false);
+
+ // Merge (or link) another source into the current source associated with
+ // this Script object. Return false on error.
+ bool mergeSource(Source &pSource, bool pPreserveSource = false);
+
+ // Add dependency information for this script given the source named
+ // pSourceName. pSHA1 is the SHA-1 checksum of the given source. Return
+ // false on error.
+ bool addSourceDependencyInfo(MCO_ResourceType pSourceType,
+ const std::string &pSourceName,
+ const uint8_t *pSHA1);
+
+ void markExternalSymbol(char const *name) {
+ mUserDefinedExternalSymbols.push_back(name);
+ }
+
+ std::vector<char const *> const &getUserDefinedExternalSymbols() const {
+ return mUserDefinedExternalSymbols;
+ }
+
+ int prepareExecutable(char const *cacheDir,
+ char const *cacheName,
+ unsigned long flags);
+ int writeCache();
+
+ /*
+ * Link the given bitcodes in mSource to shared object (.so).
+ *
+ * Currently, it requires one to provide the relocatable object files with
+ * given bitcodes to output a shared object.
+ *
+ * The usage of this function is flexible. You can have a relocatable object
+ * compiled before and pass it in objPath to generate shared object. If the
+ * objPath is NULL, we'll invoke prepareRelocatable() to get .o first (if
+ * you haven't done that yet) and then link the output relocatable object
+ * file to .so in dsoPath.
+ *
+ * TODO: Currently, we only support to link a bitcode (i.e., mSource.)
+ *
+ */
+ int prepareSharedObject(char const *objPath,
+ char const *dsoPath,
+ unsigned long flags);
+
+ int prepareRelocatable(char const *objPath,
+ llvm::Reloc::Model RelocModel,
+ unsigned long flags);
+
+ char const *getCompilerErrorMessage();
+
+ void *lookup(const char *name);
+
+ size_t getExportVarCount() const;
+
+ size_t getExportFuncCount() const;
+
+ size_t getExportForEachCount() const;
+
+ size_t getPragmaCount() const;
+
+ size_t getFuncCount() const;
+
+ size_t getObjectSlotCount() const;
+
+ void getExportVarList(size_t size, void **list);
+
+ void getExportFuncList(size_t size, void **list);
+
+ void getExportForEachList(size_t size, void **list);
+
+ void getExportVarNameList(std::vector<std::string> &list);
+
+ void getExportFuncNameList(std::vector<std::string> &list);
+
+ void getExportForEachNameList(std::vector<std::string> &list);
+
+ void getPragmaList(size_t size,
+ char const **keyList,
+ char const **valueList);
+
+ void getFuncInfoList(size_t size, FuncInfo *list);
+
+ void getObjectSlotList(size_t size, uint32_t *list);
+
+ size_t getELFSize() const;
+
+ const char *getELF() const;
+
+ int registerSymbolCallback(BCCSymbolLookupFn pFn, void *pContext);
+
+ bool isCacheable() const;
+
+ void setError(int error) {
+ if (mErrorCode == BCC_NO_ERROR && error != BCC_NO_ERROR) {
+ mErrorCode = error;
+ }
+ }
+
+ int getError() {
+ int result = mErrorCode;
+ mErrorCode = BCC_NO_ERROR;
+ return result;
+ }
+
+ private:
+ //
+ // It returns 0 if there's a cache hit.
+ //
+ // Side effect: it will set mCacheDir, mCacheName.
+ int internalLoadCache(char const *cacheDir, char const *cacheName,
+ bool checkOnly);
+
+ int internalCompile(const CompilerOption&);
+ };
+
+} // namespace bcc
+
+#endif // BCC_SCRIPT_H
diff --git a/lib/ExecutionEngine/ScriptCompiled.h b/lib/ExecutionEngine/ScriptCompiled.h
index e96dbe2..8752aa3 100644
--- a/lib/ExecutionEngine/ScriptCompiled.h
+++ b/lib/ExecutionEngine/ScriptCompiled.h
@@ -26,7 +26,7 @@
#include <bcc/bcc.h>
#include "Compiler.h"
-#include "RSScript.h"
+#include "Script.h"
namespace llvm {
class Module;
@@ -48,7 +48,7 @@
typedef std::list<uint32_t> ObjectSlotList;
private:
- RSScript *mpOwner;
+ Script *mpOwner;
Compiler mCompiler;
@@ -66,7 +66,7 @@
FuncInfoMap mEmittedFunctions;
public:
- ScriptCompiled(RSScript *owner)
+ ScriptCompiled(Script *owner)
: mpOwner(owner), mCompiler(this)
{
}
diff --git a/lib/ExecutionEngine/bcc.cpp b/lib/ExecutionEngine/bcc.cpp
index 7425d0a..ee6efaa 100644
--- a/lib/ExecutionEngine/bcc.cpp
+++ b/lib/ExecutionEngine/bcc.cpp
@@ -31,7 +31,7 @@
#include "BCCContext.h"
#include "Compiler.h"
#include "DebugHelper.h"
-#include "RSScript.h"
+#include "Script.h"
#include "Sha1Helper.h"
#include "Source.h"
@@ -62,7 +62,7 @@
}
Source *source = Source::CreateEmpty(*context, "empty");
- return wrap(new RSScript(*source));
+ return wrap(new Script(*source));
}
@@ -85,7 +85,7 @@
return unwrap(script)->getError();
}
-static bool helper_add_source(RSScript *pScript,
+static bool helper_add_source(Script *pScript,
char const *pName,
char const *pBitcode,
size_t pBitcodeSize,
@@ -114,7 +114,7 @@
if (need_dependency_check) {
uint8_t sha1[20];
calcSHA1(sha1, pBitcode, pBitcodeSize);
- if (!pScript->addSourceDependency(BCC_APK_RESOURCE, pName, sha1)) {
+ if (!pScript->addSourceDependencyInfo(BCC_APK_RESOURCE, pName, sha1)) {
return false;
}
}
@@ -122,7 +122,7 @@
return ((pIsLink) ? pScript->mergeSource(*source) : pScript->reset(*source));
}
-static bool helper_add_source(RSScript *pScript,
+static bool helper_add_source(Script *pScript,
llvm::Module *pModule,
bool pIsLink) {
if (pModule == NULL)
@@ -146,7 +146,7 @@
return ((pIsLink) ? pScript->mergeSource(*source) : pScript->reset(*source));
}
-static bool helper_add_source(RSScript *pScript,
+static bool helper_add_source(Script *pScript,
char const *pPath,
unsigned long pFlags,
bool pIsLink) {
@@ -164,7 +164,7 @@
if (need_dependency_check) {
uint8_t sha1[20];
calcFileSHA1(sha1, pPath);
- if (!pScript->addSourceDependency(BCC_APK_RESOURCE, pPath, sha1)) {
+ if (!pScript->addSourceDependencyInfo(BCC_APK_RESOURCE, pPath, sha1)) {
return false;
}
}
diff --git a/lib/ExecutionEngine/bcc_internal.h b/lib/ExecutionEngine/bcc_internal.h
index 553034c..d0f5766 100644
--- a/lib/ExecutionEngine/bcc_internal.h
+++ b/lib/ExecutionEngine/bcc_internal.h
@@ -35,7 +35,7 @@
}
namespace bcc {
- class RSScript;
+ class Script;
/* Function information struct */
struct FuncInfo {
@@ -44,7 +44,7 @@
size_t size;
};
- BCC_OPAQUE_TYPE_CONVERSION(bcc::RSScript *, BCCScriptRef);
+ BCC_OPAQUE_TYPE_CONVERSION(bcc::Script *, BCCScriptRef);
BCC_OPAQUE_TYPE_CONVERSION(llvm::Module *, LLVMModuleRef);
} // namespace bcc