blob: 14d38bf29bf9ad5717a52b880a738a382803bf42 [file] [log] [blame]
Logancf3e5212010-12-29 01:44:55 +08001/*
Stephen Hinescc366e52012-02-21 17:22:04 -08002 * copyright 2010-2012, the android open source project
Logancf3e5212010-12-29 01:44:55 +08003 *
4 * licensed under the apache license, version 2.0 (the "license");
5 * you may not use this file except in compliance with the license.
6 * you may obtain a copy of the license at
7 *
8 * http://www.apache.org/licenses/license-2.0
9 *
10 * unless required by applicable law or agreed to in writing, software
11 * distributed under the license is distributed on an "as is" basis,
12 * without warranties or conditions of any kind, either express or implied.
13 * see the license for the specific language governing permissions and
14 * limitations under the license.
15 */
16
Logancf3e5212010-12-29 01:44:55 +080017#include "Script.h"
18
Logan35849002011-01-15 07:30:43 +080019#include "Config.h"
20
Logan Chiend2a5f302011-07-19 20:32:25 +080021#if USE_OLD_JIT
22#include "OldJIT/CacheReader.h"
23#include "OldJIT/CacheWriter.h"
24#endif
25
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -070026#include "MCCacheReader.h"
27#include "MCCacheWriter.h"
Zonr Chang2fcbd022012-01-06 21:04:31 +080028#include "CompilerOption.h"
Logan Chiend2a5f302011-07-19 20:32:25 +080029
30#if USE_OLD_JIT
31#include "OldJIT/ContextManager.h"
32#endif
33
Logan4dcd6792011-02-28 05:12:00 +080034#include "DebugHelper.h"
Logan04329712011-01-06 06:10:57 +080035#include "FileHandle.h"
Daniel Malea094881f2011-12-14 17:39:16 -050036#include "GDBJITRegistrar.h"
Logancf3e5212010-12-29 01:44:55 +080037#include "ScriptCompiled.h"
Logan9a5f8682011-01-07 06:09:57 +080038#include "ScriptCached.h"
39#include "Sha1Helper.h"
Logan474cbd22011-01-31 01:47:44 +080040#include "SourceInfo.h"
Logancf3e5212010-12-29 01:44:55 +080041
Logan89eb47f2011-01-07 10:45:16 +080042#include <errno.h>
Logan474cbd22011-01-31 01:47:44 +080043#include <sys/stat.h>
44#include <sys/types.h>
Bhanu Chetlapallieb4509b2012-01-08 20:42:56 -080045#include <unistd.h>
Logancf3e5212010-12-29 01:44:55 +080046
Logan89eb47f2011-01-07 10:45:16 +080047#include <new>
48#include <string.h>
Logan033f46e2011-01-06 05:51:24 +080049#include <cutils/properties.h>
50
Loganecf4cbd2011-01-06 05:34:11 +080051namespace {
52
Logan033f46e2011-01-06 05:51:24 +080053bool getBooleanProp(const char *str) {
Loganf340bf72011-01-14 17:51:40 +080054 char buf[PROPERTY_VALUE_MAX];
55 property_get(str, buf, "0");
56 return strcmp(buf, "0") != 0;
Logan033f46e2011-01-06 05:51:24 +080057}
58
Loganecf4cbd2011-01-06 05:34:11 +080059} // namespace anonymous
60
Logancf3e5212010-12-29 01:44:55 +080061namespace bcc {
62
63Script::~Script() {
Logan35849002011-01-15 07:30:43 +080064 switch (mStatus) {
65 case ScriptStatus::Compiled:
Logancf3e5212010-12-29 01:44:55 +080066 delete mCompiled;
Logan35849002011-01-15 07:30:43 +080067 break;
68
69#if USE_CACHE
70 case ScriptStatus::Cached:
Shih-wei Liaoc4cf6542011-01-13 01:43:01 -080071 delete mCached;
Logan35849002011-01-15 07:30:43 +080072 break;
73#endif
74
75 default:
76 break;
Logancf3e5212010-12-29 01:44:55 +080077 }
Logan474cbd22011-01-31 01:47:44 +080078
Shih-wei Liao6a60f4e2012-01-17 02:58:40 -080079 for (size_t i = 0; i < 2; ++i) {
Logan474cbd22011-01-31 01:47:44 +080080 delete mSourceList[i];
Shih-wei Liao6a60f4e2012-01-17 02:58:40 -080081 }
Logancf3e5212010-12-29 01:44:55 +080082}
83
84
Logan474cbd22011-01-31 01:47:44 +080085int Script::addSourceBC(size_t idx,
86 char const *resName,
87 const char *bitcode,
88 size_t bitcodeSize,
89 unsigned long flags) {
Shih-wei Liao898c5a92011-05-18 07:02:39 -070090
91 if (!resName) {
92 mErrorCode = BCC_INVALID_VALUE;
Steve Block10c14122012-01-08 10:15:06 +000093 ALOGE("Invalid argument: resName = NULL\n");
Shih-wei Liao898c5a92011-05-18 07:02:39 -070094 return 1;
95 }
96
Loganecf4cbd2011-01-06 05:34:11 +080097 if (mStatus != ScriptStatus::Unknown) {
Logancf3e5212010-12-29 01:44:55 +080098 mErrorCode = BCC_INVALID_OPERATION;
Steve Block10c14122012-01-08 10:15:06 +000099 ALOGE("Bad operation: Adding source after bccPrepareExecutable\n");
Logancf3e5212010-12-29 01:44:55 +0800100 return 1;
101 }
102
Logan474cbd22011-01-31 01:47:44 +0800103 if (!bitcode) {
104 mErrorCode = BCC_INVALID_VALUE;
Steve Block10c14122012-01-08 10:15:06 +0000105 ALOGE("Invalid argument: bitcode = NULL\n");
Logan474cbd22011-01-31 01:47:44 +0800106 return 1;
107 }
108
109 mSourceList[idx] = SourceInfo::createFromBuffer(resName,
110 bitcode, bitcodeSize,
111 flags);
112
113 if (!mSourceList[idx]) {
114 mErrorCode = BCC_OUT_OF_MEMORY;
Steve Block10c14122012-01-08 10:15:06 +0000115 ALOGE("Out of memory while adding source bitcode\n");
Logan474cbd22011-01-31 01:47:44 +0800116 return 1;
117 }
118
Loganecf4cbd2011-01-06 05:34:11 +0800119 return 0;
Logancf3e5212010-12-29 01:44:55 +0800120}
121
122
Logan474cbd22011-01-31 01:47:44 +0800123int Script::addSourceModule(size_t idx,
124 llvm::Module *module,
125 unsigned long flags) {
Logancf3e5212010-12-29 01:44:55 +0800126 if (mStatus != ScriptStatus::Unknown) {
127 mErrorCode = BCC_INVALID_OPERATION;
Steve Block10c14122012-01-08 10:15:06 +0000128 ALOGE("Bad operation: Adding source after bccPrepareExecutable\n");
Logancf3e5212010-12-29 01:44:55 +0800129 return 1;
130 }
131
Logan474cbd22011-01-31 01:47:44 +0800132 if (!module) {
133 mErrorCode = BCC_INVALID_VALUE;
Steve Block10c14122012-01-08 10:15:06 +0000134 ALOGE("Invalid argument: module = NULL\n");
Logan474cbd22011-01-31 01:47:44 +0800135 return 1;
136 }
137
138 mSourceList[idx] = SourceInfo::createFromModule(module, flags);
139
140 if (!mSourceList[idx]) {
141 mErrorCode = BCC_OUT_OF_MEMORY;
Steve Block10c14122012-01-08 10:15:06 +0000142 ALOGE("Out of memory when add source module\n");
Logan474cbd22011-01-31 01:47:44 +0800143 return 1;
144 }
145
Loganecf4cbd2011-01-06 05:34:11 +0800146 return 0;
Logancf3e5212010-12-29 01:44:55 +0800147}
148
149
Logan474cbd22011-01-31 01:47:44 +0800150int Script::addSourceFile(size_t idx,
151 char const *path,
152 unsigned long flags) {
Logan3133c412011-01-06 06:15:40 +0800153 if (mStatus != ScriptStatus::Unknown) {
Logancf3e5212010-12-29 01:44:55 +0800154 mErrorCode = BCC_INVALID_OPERATION;
Steve Block10c14122012-01-08 10:15:06 +0000155 ALOGE("Bad operation: Adding source after bccPrepareExecutable\n");
Logancf3e5212010-12-29 01:44:55 +0800156 return 1;
157 }
158
Logan474cbd22011-01-31 01:47:44 +0800159 if (!path) {
160 mErrorCode = BCC_INVALID_VALUE;
Steve Block10c14122012-01-08 10:15:06 +0000161 ALOGE("Invalid argument: path = NULL\n");
Logan474cbd22011-01-31 01:47:44 +0800162 return 1;
163 }
164
165 struct stat sb;
166 if (stat(path, &sb) != 0) {
167 mErrorCode = BCC_INVALID_VALUE;
Steve Block10c14122012-01-08 10:15:06 +0000168 ALOGE("File not found: %s\n", path);
Logan474cbd22011-01-31 01:47:44 +0800169 return 1;
170 }
171
172 mSourceList[idx] = SourceInfo::createFromFile(path, flags);
173
174 if (!mSourceList[idx]) {
175 mErrorCode = BCC_OUT_OF_MEMORY;
Steve Block10c14122012-01-08 10:15:06 +0000176 ALOGE("Out of memory while adding source file\n");
Logan474cbd22011-01-31 01:47:44 +0800177 return 1;
178 }
179
Logan3133c412011-01-06 06:15:40 +0800180 return 0;
Logancf3e5212010-12-29 01:44:55 +0800181}
182
Shih-wei Liao6a60f4e2012-01-17 02:58:40 -0800183int Script::prepareRelocatable(char const *cacheDir,
184 char const *cacheName,
185 llvm::Reloc::Model RelocModel,
186 unsigned long flags) {
Joseph Wen34c600a2011-07-25 17:59:17 -0700187#if USE_CACHE
Zonr Chang743dd712012-01-19 10:13:52 +0800188 if (internalLoadCache(cacheDir, cacheName,
Shih-wei Liao32ef88b2012-02-04 23:33:11 -0800189 ScriptObject::Relocatable, /* checkOnly */ true) == 0) {
Zonr Chang743dd712012-01-19 10:13:52 +0800190 return 0;
Shih-wei Liao32ef88b2012-02-04 23:33:11 -0800191 }
Joseph Wen34c600a2011-07-25 17:59:17 -0700192#endif
Zonr Chang2fcbd022012-01-06 21:04:31 +0800193
194 CompilerOption option;
Shih-wei Liao8afed382012-01-10 15:57:24 +0800195 option.RelocModelOpt = RelocModel;
Zonr Chang2fcbd022012-01-06 21:04:31 +0800196 option.LoadAfterCompile = false;
197 int status = internalCompile(option);
Joseph Wen34c600a2011-07-25 17:59:17 -0700198 if (status != 0) {
Steve Block10c14122012-01-08 10:15:06 +0000199 ALOGE("LLVM error message: %s\n", getCompilerErrorMessage());
Joseph Wen34c600a2011-07-25 17:59:17 -0700200 }
201 return status;
202}
203
Logancf3e5212010-12-29 01:44:55 +0800204
Shih-wei Liaoa471ebb2012-02-05 00:49:58 -0800205int Script::prepareSharedObject(char const *cacheDir,
206 char const *cacheName,
207 char const *objPath,
208 char const *dsoPath,
209 unsigned long flags) {
210 // TODO: Support cached shared object.
211 return 1;
212}
213
214
Logan Chien311c26f2011-07-11 14:30:34 +0800215int Script::prepareExecutable(char const *cacheDir,
216 char const *cacheName,
217 unsigned long flags) {
Loganecf4cbd2011-01-06 05:34:11 +0800218 if (mStatus != ScriptStatus::Unknown) {
Logancf3e5212010-12-29 01:44:55 +0800219 mErrorCode = BCC_INVALID_OPERATION;
Steve Block10c14122012-01-08 10:15:06 +0000220 ALOGE("Invalid operation: %s\n", __func__);
Logancf3e5212010-12-29 01:44:55 +0800221 return 1;
222 }
223
Daniel Malea094881f2011-12-14 17:39:16 -0500224 int status = -1;
Logan35849002011-01-15 07:30:43 +0800225#if USE_CACHE
Zonr Chang743dd712012-01-19 10:13:52 +0800226 if (internalLoadCache(cacheDir, cacheName,
Shih-wei Liao32ef88b2012-02-04 23:33:11 -0800227 ScriptObject::Executable, /* checkOnly */ false) == 0) {
Stephen Hinese0918ac2012-03-01 23:28:09 -0800228 status = 0;
Shih-wei Liao32ef88b2012-02-04 23:33:11 -0800229 }
Logan35849002011-01-15 07:30:43 +0800230#endif
Loganecf4cbd2011-01-06 05:34:11 +0800231
Stephen Hinese0918ac2012-03-01 23:28:09 -0800232 if (status != 0) {
233 CompilerOption option;
234 status = internalCompile(option);
235 }
236
Stephen Hines27b35102011-05-11 17:58:48 -0700237 if (status != 0) {
Steve Block10c14122012-01-08 10:15:06 +0000238 ALOGE("LLVM error message: %s\n", getCompilerErrorMessage());
Stephen Hines27b35102011-05-11 17:58:48 -0700239 }
Daniel Malea094881f2011-12-14 17:39:16 -0500240
241 // FIXME: Registration can be conditional on the presence of debug metadata
242 if (status == 0) {
243 registerObjectWithGDB(getELF(), getELFSize()); // thread-safe registration
Stephen Hines27b35102011-05-11 17:58:48 -0700244 }
245 return status;
Logan033f46e2011-01-06 05:51:24 +0800246}
247
Logan35849002011-01-15 07:30:43 +0800248#if USE_CACHE
Zonr Chang743dd712012-01-19 10:13:52 +0800249int Script::internalLoadCache(char const *cacheDir, char const *cacheName,
250 ScriptObject::ObjectType objectType,
251 bool checkOnly) {
252 mObjectType = objectType;
253
Shih-wei Liao32ef88b2012-02-04 23:33:11 -0800254 if ((cacheDir == NULL) || (cacheName == NULL)) {
Zonr Chang743dd712012-01-19 10:13:52 +0800255 return 1;
Shih-wei Liao32ef88b2012-02-04 23:33:11 -0800256 }
Zonr Chang743dd712012-01-19 10:13:52 +0800257
258 // Set cache file Name
259 mCacheName = cacheName;
260
Shih-wei Liao32ef88b2012-02-04 23:33:11 -0800261 // Santize mCacheDir. Ensure that mCacheDir ends with '/'.
Zonr Chang743dd712012-01-19 10:13:52 +0800262 mCacheDir = cacheDir;
Shih-wei Liao32ef88b2012-02-04 23:33:11 -0800263 if (!mCacheDir.empty() && *mCacheDir.rbegin() != '/') {
Zonr Chang743dd712012-01-19 10:13:52 +0800264 mCacheDir.push_back('/');
Shih-wei Liao32ef88b2012-02-04 23:33:11 -0800265 }
Zonr Chang743dd712012-01-19 10:13:52 +0800266
Shih-wei Liao32ef88b2012-02-04 23:33:11 -0800267 if (!isCacheable()) {
Logan033f46e2011-01-06 05:51:24 +0800268 return 1;
Shih-wei Liao32ef88b2012-02-04 23:33:11 -0800269 }
Logan04329712011-01-06 06:10:57 +0800270
Zonr Chang4ea08862012-01-17 17:26:49 +0800271 std::string objPath = getCachedObjectPath();
272 std::string infoPath = getCacheInfoPath();
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700273
Logan Chien311c26f2011-07-11 14:30:34 +0800274 FileHandle objFile;
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700275 if (objFile.open(objPath.c_str(), OpenMode::Read) < 0) {
Logan Chien03a2e302011-07-13 21:46:32 +0800276 // Unable to open the executable file in read mode.
Logan04329712011-01-06 06:10:57 +0800277 return 1;
278 }
279
Logan Chien311c26f2011-07-11 14:30:34 +0800280 FileHandle infoFile;
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700281 if (infoFile.open(infoPath.c_str(), OpenMode::Read) < 0) {
Logan Chien03a2e302011-07-13 21:46:32 +0800282 // Unable to open the metadata information file in read mode.
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700283 return 1;
284 }
285
Logan Chien311c26f2011-07-11 14:30:34 +0800286#if USE_OLD_JIT
287 CacheReader reader;
288#elif USE_MCJIT
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700289 MCCacheReader reader;
290
291 // Register symbol lookup function
292 if (mpExtSymbolLookupFn) {
293 reader.registerSymbolCallback(mpExtSymbolLookupFn,
294 mpExtSymbolLookupFnContext);
295 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700296#endif
Logan04329712011-01-06 06:10:57 +0800297
Logan9a5f8682011-01-07 06:09:57 +0800298 // Dependencies
Joseph Wen2ca6e572011-06-24 14:12:23 -0700299 reader.addDependency(BCC_FILE_RESOURCE, pathLibBCC_SHA1, sha1LibBCC_SHA1);
Joseph Wen76919072011-07-07 23:06:15 -0700300 reader.addDependency(BCC_FILE_RESOURCE, pathLibRS, sha1LibRS);
Logan9a5f8682011-01-07 06:09:57 +0800301
Logan474cbd22011-01-31 01:47:44 +0800302 for (size_t i = 0; i < 2; ++i) {
303 if (mSourceList[i]) {
304 mSourceList[i]->introDependency(reader);
305 }
Logan9a5f8682011-01-07 06:09:57 +0800306 }
307
Joseph Wen34c600a2011-07-25 17:59:17 -0700308 if (checkOnly)
Joseph Wen49281042011-07-26 10:04:09 -0700309 return !reader.checkCacheFile(&objFile, &infoFile, this);
Joseph Wen34c600a2011-07-25 17:59:17 -0700310
Logan9a5f8682011-01-07 06:09:57 +0800311 // Read cache file
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700312 ScriptCached *cached = reader.readCacheFile(&objFile, &infoFile, this);
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700313
Logan04329712011-01-06 06:10:57 +0800314 if (!cached) {
Logan42598052011-01-26 22:41:13 +0800315 mIsContextSlotNotAvail = reader.isContextSlotNotAvail();
Logan04329712011-01-06 06:10:57 +0800316 return 1;
317 }
318
319 mCached = cached;
320 mStatus = ScriptStatus::Cached;
Logan033f46e2011-01-06 05:51:24 +0800321
Loganf3c83ce2011-01-07 06:36:33 +0800322 // Dirty hack for libRS.
323 // TODO(all): This dirty hack should be removed in the future.
Shih-wei Liao8eb5fe92011-02-01 04:17:38 -0800324 if (!cached->isLibRSThreadable() && mpExtSymbolLookupFn) {
Loganf3c83ce2011-01-07 06:36:33 +0800325 mpExtSymbolLookupFn(mpExtSymbolLookupFnContext, "__clearThreadable");
326 }
327
Loganf7f0ac52011-01-07 03:53:43 +0800328 return 0;
Logan033f46e2011-01-06 05:51:24 +0800329}
Logan35849002011-01-15 07:30:43 +0800330#endif
Logan033f46e2011-01-06 05:51:24 +0800331
Shih-wei Liao9e81e372012-01-17 16:38:40 -0800332int Script::internalCompile(const CompilerOption &option) {
Logan033f46e2011-01-06 05:51:24 +0800333 // Create the ScriptCompiled object
Nowar Gu09b6c1c2011-05-24 23:49:07 +0800334 mCompiled = new (std::nothrow) ScriptCompiled(this);
Loganecf4cbd2011-01-06 05:34:11 +0800335
336 if (!mCompiled) {
337 mErrorCode = BCC_OUT_OF_MEMORY;
Steve Block10c14122012-01-08 10:15:06 +0000338 ALOGE("Out of memory: %s %d\n", __FILE__, __LINE__);
Loganecf4cbd2011-01-06 05:34:11 +0800339 return 1;
340 }
341
342 mStatus = ScriptStatus::Compiled;
343
Logan033f46e2011-01-06 05:51:24 +0800344 // Register symbol lookup function
Loganecf4cbd2011-01-06 05:34:11 +0800345 if (mpExtSymbolLookupFn) {
346 mCompiled->registerSymbolCallback(mpExtSymbolLookupFn,
347 mpExtSymbolLookupFnContext);
348 }
349
Zonr Changdf3fee42012-01-10 15:58:36 +0800350 if (!mSourceList[0]) {
351 ALOGE("Source bitcode is not set.\n");
Logan474cbd22011-01-31 01:47:44 +0800352 return 1;
353 }
354
Shih-wei Liaod88c0d12012-01-17 20:32:58 -0800355 // Parse Source bitcode file (if necessary)
356 if (mSourceList[0]->prepareModule() != 0) {
357 ALOGE("Unable to setup source module\n");
Zonr Changdf3fee42012-01-10 15:58:36 +0800358 return 1;
Shih-wei Liaod88c0d12012-01-17 20:32:58 -0800359 }
360
361 // Parse Library bitcode file (if necessary)
362 if (mSourceList[1]) {
363 if (mSourceList[1]->prepareModule(mSourceList[0]->getContext()) != 0) {
364 ALOGE("Unable to setup library module\n");
365 return 1;
366 }
367 }
Zonr Changdf3fee42012-01-10 15:58:36 +0800368
369 // Set the main source module
370 if (mCompiled->readModule(mSourceList[0]->getModule()) != 0) {
Steve Block10c14122012-01-08 10:15:06 +0000371 ALOGE("Unable to read source module\n");
Logan474cbd22011-01-31 01:47:44 +0800372 return 1;
Loganecf4cbd2011-01-06 05:34:11 +0800373 }
374
Logan3133c412011-01-06 06:15:40 +0800375 // Link the source module with the library module
Shih-wei Liaod88c0d12012-01-17 20:32:58 -0800376 if (mSourceList[1]) {
Zonr Changdf3fee42012-01-10 15:58:36 +0800377 if (mCompiled->linkModule(mSourceList[1]->getModule()) != 0) {
Steve Block10c14122012-01-08 10:15:06 +0000378 ALOGE("Unable to link library module\n");
Logan04329712011-01-06 06:10:57 +0800379 return 1;
380 }
381 }
Loganecf4cbd2011-01-06 05:34:11 +0800382
Logan3133c412011-01-06 06:15:40 +0800383 // Compile and JIT the code
Zonr Chang2fcbd022012-01-06 21:04:31 +0800384 if (mCompiled->compile(option) != 0) {
Steve Block10c14122012-01-08 10:15:06 +0000385 ALOGE("Unable to compile.\n");
Logan04329712011-01-06 06:10:57 +0800386 return 1;
387 }
388
Logan35849002011-01-15 07:30:43 +0800389#if USE_CACHE
Logan42598052011-01-26 22:41:13 +0800390 // Note: If we re-compile the script because the cached context slot not
391 // available, then we don't have to write the cache.
392
393 // Note: If the address of the context is not in the context slot, then
394 // we don't have to cache it.
395
Shih-wei Liaoabc7f512012-01-18 00:34:07 -0800396 if (
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700397#if USE_OLD_JIT
Logan1dc63142011-02-25 17:14:51 +0800398 !mIsContextSlotNotAvail &&
399 ContextManager::get().isManagingContext(getContext()) &&
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700400#endif
Shih-wei Liaoabc7f512012-01-18 00:34:07 -0800401 isCacheable()) {
Logan42598052011-01-26 22:41:13 +0800402
Zonr Chang4ea08862012-01-17 17:26:49 +0800403 std::string objPath = getCachedObjectPath();
404 std::string infoPath = getCacheInfoPath();
Logan Chien311c26f2011-07-11 14:30:34 +0800405
Jeff Brown937a0bc2011-01-26 23:20:14 -0800406 // Remove the file if it already exists before writing the new file.
407 // The old file may still be mapped elsewhere in memory and we do not want
408 // to modify its contents. (The same script may be running concurrently in
409 // the same process or a different process!)
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700410 ::unlink(objPath.c_str());
Logan Chien311c26f2011-07-11 14:30:34 +0800411#if !USE_OLD_JIT && USE_MCJIT
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700412 ::unlink(infoPath.c_str());
413#endif
Jeff Brown937a0bc2011-01-26 23:20:14 -0800414
Logan Chien03a2e302011-07-13 21:46:32 +0800415 FileHandle objFile;
416 FileHandle infoFile;
417
418 if (objFile.open(objPath.c_str(), OpenMode::Write) >= 0 &&
419 infoFile.open(infoPath.c_str(), OpenMode::Write) >= 0) {
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700420
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700421#if USE_OLD_JIT
Logan04329712011-01-06 06:10:57 +0800422 CacheWriter writer;
Logan Chien311c26f2011-07-11 14:30:34 +0800423#elif USE_MCJIT
424 MCCacheWriter writer;
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700425#endif
Logana27a83f2011-01-07 10:25:48 +0800426
Joseph Wen2ca6e572011-06-24 14:12:23 -0700427#ifdef TARGET_BUILD
Logana2e15af2011-01-07 11:46:08 +0800428 // Dependencies
Joseph Wen2ca6e572011-06-24 14:12:23 -0700429 writer.addDependency(BCC_FILE_RESOURCE, pathLibBCC_SHA1, sha1LibBCC_SHA1);
Joseph Wen76919072011-07-07 23:06:15 -0700430 writer.addDependency(BCC_FILE_RESOURCE, pathLibRS, sha1LibRS);
Logane1323992011-01-12 04:47:13 +0800431#endif
Logana2e15af2011-01-07 11:46:08 +0800432
Logan474cbd22011-01-31 01:47:44 +0800433 for (size_t i = 0; i < 2; ++i) {
Logan825c3b22011-02-28 05:05:48 +0800434 if (mSourceList[i]) {
435 mSourceList[i]->introDependency(writer);
436 }
Logana2e15af2011-01-07 11:46:08 +0800437 }
438
Logana27a83f2011-01-07 10:25:48 +0800439 // libRS is threadable dirty hack
440 // TODO: This should be removed in the future
441 uint32_t libRS_threadable = 0;
442 if (mpExtSymbolLookupFn) {
Logan89eb47f2011-01-07 10:45:16 +0800443 libRS_threadable =
444 (uint32_t)mpExtSymbolLookupFn(mpExtSymbolLookupFnContext,
445 "__isThreadable");
Logana27a83f2011-01-07 10:25:48 +0800446 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700447
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700448 if (!writer.writeCacheFile(&objFile, &infoFile, this, libRS_threadable)) {
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700449 objFile.truncate();
450 objFile.close();
Logana27a83f2011-01-07 10:25:48 +0800451
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700452 if (unlink(objPath.c_str()) != 0) {
Steve Block10c14122012-01-08 10:15:06 +0000453 ALOGE("Unable to remove the invalid cache file: %s. (reason: %s)\n",
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700454 objPath.c_str(), strerror(errno));
Logan89eb47f2011-01-07 10:45:16 +0800455 }
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700456
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700457 infoFile.truncate();
458 infoFile.close();
459
460 if (unlink(infoPath.c_str()) != 0) {
Steve Block10c14122012-01-08 10:15:06 +0000461 ALOGE("Unable to remove the invalid cache file: %s. (reason: %s)\n",
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700462 infoPath.c_str(), strerror(errno));
463 }
Logan89eb47f2011-01-07 10:45:16 +0800464 }
465 }
Logan04329712011-01-06 06:10:57 +0800466 }
Logan35849002011-01-15 07:30:43 +0800467#endif // USE_CACHE
Logan04329712011-01-06 06:10:57 +0800468
469 return 0;
Logancf3e5212010-12-29 01:44:55 +0800470}
471
472
473char const *Script::getCompilerErrorMessage() {
474 if (mStatus != ScriptStatus::Compiled) {
475 mErrorCode = BCC_INVALID_OPERATION;
476 return NULL;
477 }
478
479 return mCompiled->getCompilerErrorMessage();
480}
481
482
483void *Script::lookup(const char *name) {
Logan89eb47f2011-01-07 10:45:16 +0800484 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700485 case ScriptStatus::Compiled: {
486 return mCompiled->lookup(name);
487 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700488
Logan35849002011-01-15 07:30:43 +0800489#if USE_CACHE
Shih-wei Liaod50be322011-07-01 22:53:31 -0700490 case ScriptStatus::Cached: {
491 return mCached->lookup(name);
492 }
Logan35849002011-01-15 07:30:43 +0800493#endif
Logan89eb47f2011-01-07 10:45:16 +0800494
Shih-wei Liaod50be322011-07-01 22:53:31 -0700495 default: {
496 mErrorCode = BCC_INVALID_OPERATION;
497 return NULL;
498 }
Logancf3e5212010-12-29 01:44:55 +0800499 }
Logancf3e5212010-12-29 01:44:55 +0800500}
501
502
Loganbe79ada2011-01-13 01:33:45 +0800503size_t Script::getExportVarCount() const {
Logan89eb47f2011-01-07 10:45:16 +0800504 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700505 case ScriptStatus::Compiled: {
506 return mCompiled->getExportVarCount();
507 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700508
Logan35849002011-01-15 07:30:43 +0800509#if USE_CACHE
Shih-wei Liaod50be322011-07-01 22:53:31 -0700510 case ScriptStatus::Cached: {
511 return mCached->getExportVarCount();
512 }
Logan35849002011-01-15 07:30:43 +0800513#endif
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700514
Shih-wei Liaod50be322011-07-01 22:53:31 -0700515 default: {
516 return 0;
517 }
Loganbe79ada2011-01-13 01:33:45 +0800518 }
519}
520
521
522size_t Script::getExportFuncCount() const {
523 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700524 case ScriptStatus::Compiled: {
525 return mCompiled->getExportFuncCount();
526 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700527
Logan35849002011-01-15 07:30:43 +0800528#if USE_CACHE
Shih-wei Liaod50be322011-07-01 22:53:31 -0700529 case ScriptStatus::Cached: {
530 return mCached->getExportFuncCount();
531 }
Logan35849002011-01-15 07:30:43 +0800532#endif
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700533
Shih-wei Liaod50be322011-07-01 22:53:31 -0700534 default: {
535 return 0;
536 }
Loganbe79ada2011-01-13 01:33:45 +0800537 }
538}
539
540
Stephen Hinescc366e52012-02-21 17:22:04 -0800541size_t Script::getExportForEachCount() const {
542 switch (mStatus) {
543 case ScriptStatus::Compiled: {
544 return mCompiled->getExportForEachCount();
545 }
546
547#if USE_CACHE
548 case ScriptStatus::Cached: {
549 return mCached->getExportForEachCount();
550 }
551#endif
552
553 default: {
554 return 0;
555 }
556 }
557}
558
559
Loganbe79ada2011-01-13 01:33:45 +0800560size_t Script::getPragmaCount() const {
561 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700562 case ScriptStatus::Compiled: {
563 return mCompiled->getPragmaCount();
564 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700565
Logan35849002011-01-15 07:30:43 +0800566#if USE_CACHE
Shih-wei Liaod50be322011-07-01 22:53:31 -0700567 case ScriptStatus::Cached: {
568 return mCached->getPragmaCount();
569 }
Logan35849002011-01-15 07:30:43 +0800570#endif
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700571
Shih-wei Liaod50be322011-07-01 22:53:31 -0700572 default: {
573 return 0;
574 }
Loganbe79ada2011-01-13 01:33:45 +0800575 }
576}
577
578
579size_t Script::getFuncCount() const {
580 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700581 case ScriptStatus::Compiled: {
582 return mCompiled->getFuncCount();
583 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700584
Logan35849002011-01-15 07:30:43 +0800585#if USE_CACHE
Shih-wei Liaod50be322011-07-01 22:53:31 -0700586 case ScriptStatus::Cached: {
587 return mCached->getFuncCount();
588 }
Logan35849002011-01-15 07:30:43 +0800589#endif
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700590
Shih-wei Liaod50be322011-07-01 22:53:31 -0700591 default: {
592 return 0;
593 }
Loganbe79ada2011-01-13 01:33:45 +0800594 }
595}
596
597
Stephen Hines071288a2011-01-27 14:38:26 -0800598size_t Script::getObjectSlotCount() const {
599 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700600 case ScriptStatus::Compiled: {
601 return mCompiled->getObjectSlotCount();
602 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700603
Stephen Hines071288a2011-01-27 14:38:26 -0800604#if USE_CACHE
Shih-wei Liaod50be322011-07-01 22:53:31 -0700605 case ScriptStatus::Cached: {
606 return mCached->getObjectSlotCount();
607 }
Stephen Hines071288a2011-01-27 14:38:26 -0800608#endif
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700609
Shih-wei Liaod50be322011-07-01 22:53:31 -0700610 default: {
611 return 0;
612 }
Stephen Hines071288a2011-01-27 14:38:26 -0800613 }
614}
615
616
Loganbe79ada2011-01-13 01:33:45 +0800617void Script::getExportVarList(size_t varListSize, void **varList) {
618 switch (mStatus) {
619#define DELEGATE(STATUS) \
Shih-wei Liaod50be322011-07-01 22:53:31 -0700620 case ScriptStatus::STATUS: \
621 m##STATUS->getExportVarList(varListSize, varList); \
622 break;
Logancf3e5212010-12-29 01:44:55 +0800623
Logan35849002011-01-15 07:30:43 +0800624#if USE_CACHE
Shih-wei Liaod50be322011-07-01 22:53:31 -0700625 DELEGATE(Cached);
Logan35849002011-01-15 07:30:43 +0800626#endif
627
Shih-wei Liaod50be322011-07-01 22:53:31 -0700628 DELEGATE(Compiled);
Loganbe79ada2011-01-13 01:33:45 +0800629#undef DELEGATE
Logan89eb47f2011-01-07 10:45:16 +0800630
Shih-wei Liaod50be322011-07-01 22:53:31 -0700631 default: {
632 mErrorCode = BCC_INVALID_OPERATION;
633 }
Logan89eb47f2011-01-07 10:45:16 +0800634 }
Logancf3e5212010-12-29 01:44:55 +0800635}
636
Joseph Wenf36637f2011-07-06 18:27:12 -0700637void Script::getExportVarNameList(std::vector<std::string> &varList) {
638 switch (mStatus) {
639 case ScriptStatus::Compiled: {
640 return mCompiled->getExportVarNameList(varList);
641 }
642
643 default: {
644 mErrorCode = BCC_INVALID_OPERATION;
645 }
646 }
647}
648
Logancf3e5212010-12-29 01:44:55 +0800649
Loganbe79ada2011-01-13 01:33:45 +0800650void Script::getExportFuncList(size_t funcListSize, void **funcList) {
Logan89eb47f2011-01-07 10:45:16 +0800651 switch (mStatus) {
Loganbe79ada2011-01-13 01:33:45 +0800652#define DELEGATE(STATUS) \
Shih-wei Liaod50be322011-07-01 22:53:31 -0700653 case ScriptStatus::STATUS: \
654 m##STATUS->getExportFuncList(funcListSize, funcList); \
655 break;
Logancf3e5212010-12-29 01:44:55 +0800656
Logan35849002011-01-15 07:30:43 +0800657#if USE_CACHE
Shih-wei Liaod50be322011-07-01 22:53:31 -0700658 DELEGATE(Cached);
Logan35849002011-01-15 07:30:43 +0800659#endif
660
Shih-wei Liaod50be322011-07-01 22:53:31 -0700661 DELEGATE(Compiled);
Loganbe79ada2011-01-13 01:33:45 +0800662#undef DELEGATE
Logan89eb47f2011-01-07 10:45:16 +0800663
Shih-wei Liaod50be322011-07-01 22:53:31 -0700664 default: {
665 mErrorCode = BCC_INVALID_OPERATION;
666 }
Logan89eb47f2011-01-07 10:45:16 +0800667 }
Logancf3e5212010-12-29 01:44:55 +0800668}
669
Joseph Wenf36637f2011-07-06 18:27:12 -0700670void Script::getExportFuncNameList(std::vector<std::string> &funcList) {
671 switch (mStatus) {
672 case ScriptStatus::Compiled: {
673 return mCompiled->getExportFuncNameList(funcList);
674 }
675
676 default: {
677 mErrorCode = BCC_INVALID_OPERATION;
678 }
679 }
680}
681
Stephen Hinescc366e52012-02-21 17:22:04 -0800682void Script::getExportForEachList(size_t funcListSize, void **funcList) {
683 switch (mStatus) {
684#define DELEGATE(STATUS) \
685 case ScriptStatus::STATUS: \
686 m##STATUS->getExportForEachList(funcListSize, funcList); \
687 break;
688
689#if USE_CACHE
690 DELEGATE(Cached);
691#endif
692
693 DELEGATE(Compiled);
694#undef DELEGATE
695
696 default: {
697 mErrorCode = BCC_INVALID_OPERATION;
698 }
699 }
700}
701
702void Script::getExportForEachNameList(std::vector<std::string> &forEachList) {
703 switch (mStatus) {
704 case ScriptStatus::Compiled: {
705 return mCompiled->getExportForEachNameList(forEachList);
706 }
707
708 default: {
709 mErrorCode = BCC_INVALID_OPERATION;
710 }
711 }
712}
Logancf3e5212010-12-29 01:44:55 +0800713
Loganbe79ada2011-01-13 01:33:45 +0800714void Script::getPragmaList(size_t pragmaListSize,
715 char const **keyList,
716 char const **valueList) {
Logan89eb47f2011-01-07 10:45:16 +0800717 switch (mStatus) {
Loganbe79ada2011-01-13 01:33:45 +0800718#define DELEGATE(STATUS) \
Shih-wei Liaod50be322011-07-01 22:53:31 -0700719 case ScriptStatus::STATUS: \
720 m##STATUS->getPragmaList(pragmaListSize, keyList, valueList); \
721 break;
Logancf3e5212010-12-29 01:44:55 +0800722
Logan35849002011-01-15 07:30:43 +0800723#if USE_CACHE
Shih-wei Liaod50be322011-07-01 22:53:31 -0700724 DELEGATE(Cached);
Logan35849002011-01-15 07:30:43 +0800725#endif
726
Shih-wei Liaod50be322011-07-01 22:53:31 -0700727 DELEGATE(Compiled);
Loganbe79ada2011-01-13 01:33:45 +0800728#undef DELEGATE
Logan89eb47f2011-01-07 10:45:16 +0800729
Shih-wei Liaod50be322011-07-01 22:53:31 -0700730 default: {
731 mErrorCode = BCC_INVALID_OPERATION;
732 }
Logan89eb47f2011-01-07 10:45:16 +0800733 }
Logancf3e5212010-12-29 01:44:55 +0800734}
735
736
Loganf340bf72011-01-14 17:51:40 +0800737void Script::getFuncInfoList(size_t funcInfoListSize,
738 FuncInfo *funcInfoList) {
Logan89eb47f2011-01-07 10:45:16 +0800739 switch (mStatus) {
Loganbe79ada2011-01-13 01:33:45 +0800740#define DELEGATE(STATUS) \
Shih-wei Liaod50be322011-07-01 22:53:31 -0700741 case ScriptStatus::STATUS: \
742 m##STATUS->getFuncInfoList(funcInfoListSize, funcInfoList); \
743 break;
Logancf3e5212010-12-29 01:44:55 +0800744
Logan35849002011-01-15 07:30:43 +0800745#if USE_CACHE
Shih-wei Liaod50be322011-07-01 22:53:31 -0700746 DELEGATE(Cached);
Logan35849002011-01-15 07:30:43 +0800747#endif
748
Shih-wei Liaod50be322011-07-01 22:53:31 -0700749 DELEGATE(Compiled);
Loganbe79ada2011-01-13 01:33:45 +0800750#undef DELEGATE
Logan89eb47f2011-01-07 10:45:16 +0800751
Shih-wei Liaod50be322011-07-01 22:53:31 -0700752 default: {
753 mErrorCode = BCC_INVALID_OPERATION;
754 }
Logan89eb47f2011-01-07 10:45:16 +0800755 }
Logancf3e5212010-12-29 01:44:55 +0800756}
757
Stephen Hines071288a2011-01-27 14:38:26 -0800758
759void Script::getObjectSlotList(size_t objectSlotListSize,
760 uint32_t *objectSlotList) {
761 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700762#define DELEGATE(STATUS) \
763 case ScriptStatus::STATUS: \
764 m##STATUS->getObjectSlotList(objectSlotListSize, objectSlotList); \
765 break;
Stephen Hines071288a2011-01-27 14:38:26 -0800766
767#if USE_CACHE
Shih-wei Liaod50be322011-07-01 22:53:31 -0700768 DELEGATE(Cached);
Stephen Hines071288a2011-01-27 14:38:26 -0800769#endif
770
Shih-wei Liaod50be322011-07-01 22:53:31 -0700771 DELEGATE(Compiled);
Stephen Hines071288a2011-01-27 14:38:26 -0800772#undef DELEGATE
773
Shih-wei Liaod50be322011-07-01 22:53:31 -0700774 default: {
775 mErrorCode = BCC_INVALID_OPERATION;
776 }
Stephen Hines071288a2011-01-27 14:38:26 -0800777 }
778}
779
780
Logan Chiend2a5f302011-07-19 20:32:25 +0800781#if USE_OLD_JIT
Logana27a83f2011-01-07 10:25:48 +0800782char *Script::getContext() {
783 switch (mStatus) {
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700784
Logan35849002011-01-15 07:30:43 +0800785#if USE_CACHE
Shih-wei Liaod50be322011-07-01 22:53:31 -0700786 case ScriptStatus::Cached: {
787 return mCached->getContext();
788 }
Logan35849002011-01-15 07:30:43 +0800789#endif
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700790
Shih-wei Liaod50be322011-07-01 22:53:31 -0700791 case ScriptStatus::Compiled: {
792 return mCompiled->getContext();
793 }
Logana27a83f2011-01-07 10:25:48 +0800794
Shih-wei Liaod50be322011-07-01 22:53:31 -0700795 default: {
796 mErrorCode = BCC_INVALID_OPERATION;
797 return NULL;
798 }
Logan02286cb2011-01-07 00:30:47 +0800799 }
Logan02286cb2011-01-07 00:30:47 +0800800}
Logan Chiend2a5f302011-07-19 20:32:25 +0800801#endif
Logan02286cb2011-01-07 00:30:47 +0800802
Logancf3e5212010-12-29 01:44:55 +0800803
Shih-wei Liaoce82d492011-01-20 12:34:03 -0800804int Script::registerSymbolCallback(BCCSymbolLookupFn pFn, void *pContext) {
Logancf3e5212010-12-29 01:44:55 +0800805 mpExtSymbolLookupFn = pFn;
806 mpExtSymbolLookupFnContext = pContext;
807
Logan7d2219f2011-01-06 06:19:25 +0800808 if (mStatus != ScriptStatus::Unknown) {
Logancf3e5212010-12-29 01:44:55 +0800809 mErrorCode = BCC_INVALID_OPERATION;
Steve Block10c14122012-01-08 10:15:06 +0000810 ALOGE("Invalid operation: %s\n", __func__);
Shih-wei Liaoce82d492011-01-20 12:34:03 -0800811 return 1;
Logancf3e5212010-12-29 01:44:55 +0800812 }
Shih-wei Liaoce82d492011-01-20 12:34:03 -0800813 return 0;
Logancf3e5212010-12-29 01:44:55 +0800814}
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700815
Shih-wei Liaoabc7f512012-01-18 00:34:07 -0800816bool Script::isCacheable() const {
817#if USE_CACHE
818 if (getBooleanProp("debug.bcc.nocache")) {
819 // Android system environment property: Disables the cache mechanism by
820 // setting "debug.bcc.nocache". So we will not load the cache file any
821 // way.
822 return false;
823 }
824
825 if (mCacheDir.empty() || mCacheName.empty()) {
826 // The application developer has not specified the cachePath, so
827 // we don't know where to open the cache file.
828 return false;
829 }
830
831 return true;
832#else
833 return false;
834#endif
835}
836
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700837#if USE_MCJIT
838size_t Script::getELFSize() const {
839 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700840 case ScriptStatus::Compiled: {
841 return mCompiled->getELFSize();
842 }
Daniel Malea094881f2011-12-14 17:39:16 -0500843#if USE_CACHE
844 case ScriptStatus::Cached: {
845 return mCached->getELFSize();
846 }
847#endif
Shih-wei Liaod50be322011-07-01 22:53:31 -0700848 default: {
849 return 0;
850 }
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700851 }
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700852}
853
854const char *Script::getELF() const {
855 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700856 case ScriptStatus::Compiled: {
857 return mCompiled->getELF();
858 }
Daniel Malea094881f2011-12-14 17:39:16 -0500859#if USE_CACHE
860 case ScriptStatus::Cached: {
861 return mCached->getELF();
862 }
863#endif
Shih-wei Liaod50be322011-07-01 22:53:31 -0700864 default: {
865 return NULL;
866 }
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700867 }
868}
869#endif
Logancf3e5212010-12-29 01:44:55 +0800870
871} // namespace bcc