blob: 6e3774baf06e5a88c61d1d788df3411b9ac87714 [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 Liaod8ed6a92012-03-03 01:44:29 -0800183int Script::prepareRelocatable(char const *objPath,
Shih-wei Liao6a60f4e2012-01-17 02:58:40 -0800184 llvm::Reloc::Model RelocModel,
185 unsigned long flags) {
Zonr Chang2fcbd022012-01-06 21:04:31 +0800186 CompilerOption option;
Shih-wei Liao8afed382012-01-10 15:57:24 +0800187 option.RelocModelOpt = RelocModel;
Zonr Chang2fcbd022012-01-06 21:04:31 +0800188 option.LoadAfterCompile = false;
189 int status = internalCompile(option);
Joseph Wen34c600a2011-07-25 17:59:17 -0700190 if (status != 0) {
Steve Block10c14122012-01-08 10:15:06 +0000191 ALOGE("LLVM error message: %s\n", getCompilerErrorMessage());
Shih-wei Liaoa0ed34e2012-03-03 01:33:30 -0800192 return status;
193 }
Shih-wei Liaod8ed6a92012-03-03 01:44:29 -0800194
195 FileHandle objFile;
196 if (objFile.open(objPath, OpenMode::Write) < 0) {
197 ALOGE("Failed to open %s for write.\n", objPath);
198 return 1;
Joseph Wen34c600a2011-07-25 17:59:17 -0700199 }
Shih-wei Liaod8ed6a92012-03-03 01:44:29 -0800200
201 if (static_cast<size_t>(objFile.write(getELF(),
202 getELFSize())) != getELFSize()) {
203 objFile.close();
204 ::unlink(objPath);
205 ALOGE("Unable to write ELF to file %s.\n", objPath);
206 return false;
207 }
208
209 return 0;
Joseph Wen34c600a2011-07-25 17:59:17 -0700210}
211
Logancf3e5212010-12-29 01:44:55 +0800212
Shih-wei Liao69341742012-03-03 01:45:36 -0800213int Script::prepareSharedObject(char const *objPath,
Shih-wei Liaoa471ebb2012-02-05 00:49:58 -0800214 char const *dsoPath,
215 unsigned long flags) {
216 // TODO: Support cached shared object.
217 return 1;
218}
219
220
Logan Chien311c26f2011-07-11 14:30:34 +0800221int Script::prepareExecutable(char const *cacheDir,
222 char const *cacheName,
223 unsigned long flags) {
Loganecf4cbd2011-01-06 05:34:11 +0800224 if (mStatus != ScriptStatus::Unknown) {
Logancf3e5212010-12-29 01:44:55 +0800225 mErrorCode = BCC_INVALID_OPERATION;
Steve Block10c14122012-01-08 10:15:06 +0000226 ALOGE("Invalid operation: %s\n", __func__);
Logancf3e5212010-12-29 01:44:55 +0800227 return 1;
228 }
229
Daniel Malea094881f2011-12-14 17:39:16 -0500230 int status = -1;
Logan35849002011-01-15 07:30:43 +0800231#if USE_CACHE
Zonr Chang743dd712012-01-19 10:13:52 +0800232 if (internalLoadCache(cacheDir, cacheName,
Shih-wei Liao32ef88b2012-02-04 23:33:11 -0800233 ScriptObject::Executable, /* checkOnly */ false) == 0) {
Stephen Hinese0918ac2012-03-01 23:28:09 -0800234 status = 0;
Shih-wei Liao32ef88b2012-02-04 23:33:11 -0800235 }
Logan35849002011-01-15 07:30:43 +0800236#endif
Loganecf4cbd2011-01-06 05:34:11 +0800237
Stephen Hinese0918ac2012-03-01 23:28:09 -0800238 if (status != 0) {
239 CompilerOption option;
240 status = internalCompile(option);
Stephen Hinese0918ac2012-03-01 23:28:09 -0800241
Shih-wei Liaoa0ed34e2012-03-03 01:33:30 -0800242 if (status != 0) {
243 ALOGE("LLVM error message: %s\n", getCompilerErrorMessage());
244 return status;
245 }
246
247 status = writeCache();
248 if (status != 0) {
249 ALOGE("Failed to write the cache for %s\n", cacheName);
250 return status;
251 }
Stephen Hines27b35102011-05-11 17:58:48 -0700252 }
Daniel Malea094881f2011-12-14 17:39:16 -0500253
254 // FIXME: Registration can be conditional on the presence of debug metadata
Shih-wei Liaoa0ed34e2012-03-03 01:33:30 -0800255 registerObjectWithGDB(getELF(), getELFSize()); // thread-safe registration
256
Stephen Hines27b35102011-05-11 17:58:48 -0700257 return status;
Logan033f46e2011-01-06 05:51:24 +0800258}
259
Logan35849002011-01-15 07:30:43 +0800260#if USE_CACHE
Zonr Chang743dd712012-01-19 10:13:52 +0800261int Script::internalLoadCache(char const *cacheDir, char const *cacheName,
262 ScriptObject::ObjectType objectType,
263 bool checkOnly) {
264 mObjectType = objectType;
265
Shih-wei Liao32ef88b2012-02-04 23:33:11 -0800266 if ((cacheDir == NULL) || (cacheName == NULL)) {
Zonr Chang743dd712012-01-19 10:13:52 +0800267 return 1;
Shih-wei Liao32ef88b2012-02-04 23:33:11 -0800268 }
Zonr Chang743dd712012-01-19 10:13:52 +0800269
270 // Set cache file Name
271 mCacheName = cacheName;
272
Shih-wei Liao32ef88b2012-02-04 23:33:11 -0800273 // Santize mCacheDir. Ensure that mCacheDir ends with '/'.
Zonr Chang743dd712012-01-19 10:13:52 +0800274 mCacheDir = cacheDir;
Shih-wei Liao32ef88b2012-02-04 23:33:11 -0800275 if (!mCacheDir.empty() && *mCacheDir.rbegin() != '/') {
Zonr Chang743dd712012-01-19 10:13:52 +0800276 mCacheDir.push_back('/');
Shih-wei Liao32ef88b2012-02-04 23:33:11 -0800277 }
Zonr Chang743dd712012-01-19 10:13:52 +0800278
Shih-wei Liao32ef88b2012-02-04 23:33:11 -0800279 if (!isCacheable()) {
Logan033f46e2011-01-06 05:51:24 +0800280 return 1;
Shih-wei Liao32ef88b2012-02-04 23:33:11 -0800281 }
Logan04329712011-01-06 06:10:57 +0800282
Zonr Chang4ea08862012-01-17 17:26:49 +0800283 std::string objPath = getCachedObjectPath();
284 std::string infoPath = getCacheInfoPath();
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700285
Logan Chien311c26f2011-07-11 14:30:34 +0800286 FileHandle objFile;
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700287 if (objFile.open(objPath.c_str(), OpenMode::Read) < 0) {
Logan Chien03a2e302011-07-13 21:46:32 +0800288 // Unable to open the executable file in read mode.
Logan04329712011-01-06 06:10:57 +0800289 return 1;
290 }
291
Logan Chien311c26f2011-07-11 14:30:34 +0800292 FileHandle infoFile;
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700293 if (infoFile.open(infoPath.c_str(), OpenMode::Read) < 0) {
Logan Chien03a2e302011-07-13 21:46:32 +0800294 // Unable to open the metadata information file in read mode.
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700295 return 1;
296 }
297
Logan Chien311c26f2011-07-11 14:30:34 +0800298#if USE_OLD_JIT
299 CacheReader reader;
300#elif USE_MCJIT
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700301 MCCacheReader reader;
302
303 // Register symbol lookup function
304 if (mpExtSymbolLookupFn) {
305 reader.registerSymbolCallback(mpExtSymbolLookupFn,
306 mpExtSymbolLookupFnContext);
307 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700308#endif
Logan04329712011-01-06 06:10:57 +0800309
Logan9a5f8682011-01-07 06:09:57 +0800310 // Dependencies
Joseph Wen2ca6e572011-06-24 14:12:23 -0700311 reader.addDependency(BCC_FILE_RESOURCE, pathLibBCC_SHA1, sha1LibBCC_SHA1);
Joseph Wen76919072011-07-07 23:06:15 -0700312 reader.addDependency(BCC_FILE_RESOURCE, pathLibRS, sha1LibRS);
Logan9a5f8682011-01-07 06:09:57 +0800313
Logan474cbd22011-01-31 01:47:44 +0800314 for (size_t i = 0; i < 2; ++i) {
315 if (mSourceList[i]) {
316 mSourceList[i]->introDependency(reader);
317 }
Logan9a5f8682011-01-07 06:09:57 +0800318 }
319
Joseph Wen34c600a2011-07-25 17:59:17 -0700320 if (checkOnly)
Joseph Wen49281042011-07-26 10:04:09 -0700321 return !reader.checkCacheFile(&objFile, &infoFile, this);
Joseph Wen34c600a2011-07-25 17:59:17 -0700322
Logan9a5f8682011-01-07 06:09:57 +0800323 // Read cache file
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700324 ScriptCached *cached = reader.readCacheFile(&objFile, &infoFile, this);
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700325
Logan04329712011-01-06 06:10:57 +0800326 if (!cached) {
Logan42598052011-01-26 22:41:13 +0800327 mIsContextSlotNotAvail = reader.isContextSlotNotAvail();
Logan04329712011-01-06 06:10:57 +0800328 return 1;
329 }
330
331 mCached = cached;
332 mStatus = ScriptStatus::Cached;
Logan033f46e2011-01-06 05:51:24 +0800333
Loganf3c83ce2011-01-07 06:36:33 +0800334 // Dirty hack for libRS.
335 // TODO(all): This dirty hack should be removed in the future.
Shih-wei Liao8eb5fe92011-02-01 04:17:38 -0800336 if (!cached->isLibRSThreadable() && mpExtSymbolLookupFn) {
Loganf3c83ce2011-01-07 06:36:33 +0800337 mpExtSymbolLookupFn(mpExtSymbolLookupFnContext, "__clearThreadable");
338 }
339
Loganf7f0ac52011-01-07 03:53:43 +0800340 return 0;
Logan033f46e2011-01-06 05:51:24 +0800341}
Logan35849002011-01-15 07:30:43 +0800342#endif
Logan033f46e2011-01-06 05:51:24 +0800343
Shih-wei Liao9e81e372012-01-17 16:38:40 -0800344int Script::internalCompile(const CompilerOption &option) {
Logan033f46e2011-01-06 05:51:24 +0800345 // Create the ScriptCompiled object
Nowar Gu09b6c1c2011-05-24 23:49:07 +0800346 mCompiled = new (std::nothrow) ScriptCompiled(this);
Loganecf4cbd2011-01-06 05:34:11 +0800347
348 if (!mCompiled) {
349 mErrorCode = BCC_OUT_OF_MEMORY;
Steve Block10c14122012-01-08 10:15:06 +0000350 ALOGE("Out of memory: %s %d\n", __FILE__, __LINE__);
Loganecf4cbd2011-01-06 05:34:11 +0800351 return 1;
352 }
353
354 mStatus = ScriptStatus::Compiled;
355
Logan033f46e2011-01-06 05:51:24 +0800356 // Register symbol lookup function
Loganecf4cbd2011-01-06 05:34:11 +0800357 if (mpExtSymbolLookupFn) {
358 mCompiled->registerSymbolCallback(mpExtSymbolLookupFn,
359 mpExtSymbolLookupFnContext);
360 }
361
Zonr Changdf3fee42012-01-10 15:58:36 +0800362 if (!mSourceList[0]) {
363 ALOGE("Source bitcode is not set.\n");
Logan474cbd22011-01-31 01:47:44 +0800364 return 1;
365 }
366
Shih-wei Liaod88c0d12012-01-17 20:32:58 -0800367 // Parse Source bitcode file (if necessary)
368 if (mSourceList[0]->prepareModule() != 0) {
369 ALOGE("Unable to setup source module\n");
Zonr Changdf3fee42012-01-10 15:58:36 +0800370 return 1;
Shih-wei Liaod88c0d12012-01-17 20:32:58 -0800371 }
372
373 // Parse Library bitcode file (if necessary)
374 if (mSourceList[1]) {
375 if (mSourceList[1]->prepareModule(mSourceList[0]->getContext()) != 0) {
376 ALOGE("Unable to setup library module\n");
377 return 1;
378 }
379 }
Zonr Changdf3fee42012-01-10 15:58:36 +0800380
381 // Set the main source module
382 if (mCompiled->readModule(mSourceList[0]->getModule()) != 0) {
Steve Block10c14122012-01-08 10:15:06 +0000383 ALOGE("Unable to read source module\n");
Logan474cbd22011-01-31 01:47:44 +0800384 return 1;
Loganecf4cbd2011-01-06 05:34:11 +0800385 }
386
Logan3133c412011-01-06 06:15:40 +0800387 // Link the source module with the library module
Shih-wei Liaod88c0d12012-01-17 20:32:58 -0800388 if (mSourceList[1]) {
Zonr Changdf3fee42012-01-10 15:58:36 +0800389 if (mCompiled->linkModule(mSourceList[1]->getModule()) != 0) {
Steve Block10c14122012-01-08 10:15:06 +0000390 ALOGE("Unable to link library module\n");
Logan04329712011-01-06 06:10:57 +0800391 return 1;
392 }
393 }
Loganecf4cbd2011-01-06 05:34:11 +0800394
Logan3133c412011-01-06 06:15:40 +0800395 // Compile and JIT the code
Zonr Chang2fcbd022012-01-06 21:04:31 +0800396 if (mCompiled->compile(option) != 0) {
Steve Block10c14122012-01-08 10:15:06 +0000397 ALOGE("Unable to compile.\n");
Logan04329712011-01-06 06:10:57 +0800398 return 1;
399 }
400
Shih-wei Liaoa0ed34e2012-03-03 01:33:30 -0800401 return 0;
402}
403
404int Script::writeCache() {
405 // Not compiled script or encouter error during the compilation.
406 if ((mStatus != ScriptStatus::Compiled) ||
407 (getCompilerErrorMessage() == NULL))
408 return 1;
409
Logan35849002011-01-15 07:30:43 +0800410#if USE_CACHE
Logan42598052011-01-26 22:41:13 +0800411 // Note: If we re-compile the script because the cached context slot not
412 // available, then we don't have to write the cache.
413
414 // Note: If the address of the context is not in the context slot, then
415 // we don't have to cache it.
416
Shih-wei Liaoabc7f512012-01-18 00:34:07 -0800417 if (
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700418#if USE_OLD_JIT
Logan1dc63142011-02-25 17:14:51 +0800419 !mIsContextSlotNotAvail &&
420 ContextManager::get().isManagingContext(getContext()) &&
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700421#endif
Shih-wei Liaoabc7f512012-01-18 00:34:07 -0800422 isCacheable()) {
Logan42598052011-01-26 22:41:13 +0800423
Zonr Chang4ea08862012-01-17 17:26:49 +0800424 std::string objPath = getCachedObjectPath();
425 std::string infoPath = getCacheInfoPath();
Logan Chien311c26f2011-07-11 14:30:34 +0800426
Jeff Brown937a0bc2011-01-26 23:20:14 -0800427 // Remove the file if it already exists before writing the new file.
428 // The old file may still be mapped elsewhere in memory and we do not want
429 // to modify its contents. (The same script may be running concurrently in
430 // the same process or a different process!)
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700431 ::unlink(objPath.c_str());
Logan Chien311c26f2011-07-11 14:30:34 +0800432#if !USE_OLD_JIT && USE_MCJIT
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700433 ::unlink(infoPath.c_str());
434#endif
Jeff Brown937a0bc2011-01-26 23:20:14 -0800435
Logan Chien03a2e302011-07-13 21:46:32 +0800436 FileHandle objFile;
437 FileHandle infoFile;
438
439 if (objFile.open(objPath.c_str(), OpenMode::Write) >= 0 &&
440 infoFile.open(infoPath.c_str(), OpenMode::Write) >= 0) {
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700441
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700442#if USE_OLD_JIT
Logan04329712011-01-06 06:10:57 +0800443 CacheWriter writer;
Logan Chien311c26f2011-07-11 14:30:34 +0800444#elif USE_MCJIT
445 MCCacheWriter writer;
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700446#endif
Logana27a83f2011-01-07 10:25:48 +0800447
Joseph Wen2ca6e572011-06-24 14:12:23 -0700448#ifdef TARGET_BUILD
Logana2e15af2011-01-07 11:46:08 +0800449 // Dependencies
Joseph Wen2ca6e572011-06-24 14:12:23 -0700450 writer.addDependency(BCC_FILE_RESOURCE, pathLibBCC_SHA1, sha1LibBCC_SHA1);
Joseph Wen76919072011-07-07 23:06:15 -0700451 writer.addDependency(BCC_FILE_RESOURCE, pathLibRS, sha1LibRS);
Logane1323992011-01-12 04:47:13 +0800452#endif
Logana2e15af2011-01-07 11:46:08 +0800453
Logan474cbd22011-01-31 01:47:44 +0800454 for (size_t i = 0; i < 2; ++i) {
Logan825c3b22011-02-28 05:05:48 +0800455 if (mSourceList[i]) {
456 mSourceList[i]->introDependency(writer);
457 }
Logana2e15af2011-01-07 11:46:08 +0800458 }
459
Logana27a83f2011-01-07 10:25:48 +0800460 // libRS is threadable dirty hack
461 // TODO: This should be removed in the future
462 uint32_t libRS_threadable = 0;
463 if (mpExtSymbolLookupFn) {
Logan89eb47f2011-01-07 10:45:16 +0800464 libRS_threadable =
465 (uint32_t)mpExtSymbolLookupFn(mpExtSymbolLookupFnContext,
466 "__isThreadable");
Logana27a83f2011-01-07 10:25:48 +0800467 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700468
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700469 if (!writer.writeCacheFile(&objFile, &infoFile, this, libRS_threadable)) {
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700470 objFile.truncate();
471 objFile.close();
Logana27a83f2011-01-07 10:25:48 +0800472
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700473 if (unlink(objPath.c_str()) != 0) {
Steve Block10c14122012-01-08 10:15:06 +0000474 ALOGE("Unable to remove the invalid cache file: %s. (reason: %s)\n",
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700475 objPath.c_str(), strerror(errno));
Logan89eb47f2011-01-07 10:45:16 +0800476 }
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700477
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700478 infoFile.truncate();
479 infoFile.close();
480
481 if (unlink(infoPath.c_str()) != 0) {
Steve Block10c14122012-01-08 10:15:06 +0000482 ALOGE("Unable to remove the invalid cache file: %s. (reason: %s)\n",
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700483 infoPath.c_str(), strerror(errno));
484 }
Logan89eb47f2011-01-07 10:45:16 +0800485 }
486 }
Logan04329712011-01-06 06:10:57 +0800487 }
Logan35849002011-01-15 07:30:43 +0800488#endif // USE_CACHE
Logan04329712011-01-06 06:10:57 +0800489
490 return 0;
Logancf3e5212010-12-29 01:44:55 +0800491}
492
493
494char const *Script::getCompilerErrorMessage() {
495 if (mStatus != ScriptStatus::Compiled) {
496 mErrorCode = BCC_INVALID_OPERATION;
497 return NULL;
498 }
499
500 return mCompiled->getCompilerErrorMessage();
501}
502
503
504void *Script::lookup(const char *name) {
Logan89eb47f2011-01-07 10:45:16 +0800505 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700506 case ScriptStatus::Compiled: {
507 return mCompiled->lookup(name);
508 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700509
Logan35849002011-01-15 07:30:43 +0800510#if USE_CACHE
Shih-wei Liaod50be322011-07-01 22:53:31 -0700511 case ScriptStatus::Cached: {
512 return mCached->lookup(name);
513 }
Logan35849002011-01-15 07:30:43 +0800514#endif
Logan89eb47f2011-01-07 10:45:16 +0800515
Shih-wei Liaod50be322011-07-01 22:53:31 -0700516 default: {
517 mErrorCode = BCC_INVALID_OPERATION;
518 return NULL;
519 }
Logancf3e5212010-12-29 01:44:55 +0800520 }
Logancf3e5212010-12-29 01:44:55 +0800521}
522
523
Loganbe79ada2011-01-13 01:33:45 +0800524size_t Script::getExportVarCount() const {
Logan89eb47f2011-01-07 10:45:16 +0800525 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700526 case ScriptStatus::Compiled: {
527 return mCompiled->getExportVarCount();
528 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700529
Logan35849002011-01-15 07:30:43 +0800530#if USE_CACHE
Shih-wei Liaod50be322011-07-01 22:53:31 -0700531 case ScriptStatus::Cached: {
532 return mCached->getExportVarCount();
533 }
Logan35849002011-01-15 07:30:43 +0800534#endif
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700535
Shih-wei Liaod50be322011-07-01 22:53:31 -0700536 default: {
537 return 0;
538 }
Loganbe79ada2011-01-13 01:33:45 +0800539 }
540}
541
542
543size_t Script::getExportFuncCount() const {
544 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700545 case ScriptStatus::Compiled: {
546 return mCompiled->getExportFuncCount();
547 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700548
Logan35849002011-01-15 07:30:43 +0800549#if USE_CACHE
Shih-wei Liaod50be322011-07-01 22:53:31 -0700550 case ScriptStatus::Cached: {
551 return mCached->getExportFuncCount();
552 }
Logan35849002011-01-15 07:30:43 +0800553#endif
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700554
Shih-wei Liaod50be322011-07-01 22:53:31 -0700555 default: {
556 return 0;
557 }
Loganbe79ada2011-01-13 01:33:45 +0800558 }
559}
560
561
Stephen Hinescc366e52012-02-21 17:22:04 -0800562size_t Script::getExportForEachCount() const {
563 switch (mStatus) {
564 case ScriptStatus::Compiled: {
565 return mCompiled->getExportForEachCount();
566 }
567
568#if USE_CACHE
569 case ScriptStatus::Cached: {
570 return mCached->getExportForEachCount();
571 }
572#endif
573
574 default: {
575 return 0;
576 }
577 }
578}
579
580
Loganbe79ada2011-01-13 01:33:45 +0800581size_t Script::getPragmaCount() const {
582 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700583 case ScriptStatus::Compiled: {
584 return mCompiled->getPragmaCount();
585 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700586
Logan35849002011-01-15 07:30:43 +0800587#if USE_CACHE
Shih-wei Liaod50be322011-07-01 22:53:31 -0700588 case ScriptStatus::Cached: {
589 return mCached->getPragmaCount();
590 }
Logan35849002011-01-15 07:30:43 +0800591#endif
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700592
Shih-wei Liaod50be322011-07-01 22:53:31 -0700593 default: {
594 return 0;
595 }
Loganbe79ada2011-01-13 01:33:45 +0800596 }
597}
598
599
600size_t Script::getFuncCount() const {
601 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700602 case ScriptStatus::Compiled: {
603 return mCompiled->getFuncCount();
604 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700605
Logan35849002011-01-15 07:30:43 +0800606#if USE_CACHE
Shih-wei Liaod50be322011-07-01 22:53:31 -0700607 case ScriptStatus::Cached: {
608 return mCached->getFuncCount();
609 }
Logan35849002011-01-15 07:30:43 +0800610#endif
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700611
Shih-wei Liaod50be322011-07-01 22:53:31 -0700612 default: {
613 return 0;
614 }
Loganbe79ada2011-01-13 01:33:45 +0800615 }
616}
617
618
Stephen Hines071288a2011-01-27 14:38:26 -0800619size_t Script::getObjectSlotCount() const {
620 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700621 case ScriptStatus::Compiled: {
622 return mCompiled->getObjectSlotCount();
623 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700624
Stephen Hines071288a2011-01-27 14:38:26 -0800625#if USE_CACHE
Shih-wei Liaod50be322011-07-01 22:53:31 -0700626 case ScriptStatus::Cached: {
627 return mCached->getObjectSlotCount();
628 }
Stephen Hines071288a2011-01-27 14:38:26 -0800629#endif
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700630
Shih-wei Liaod50be322011-07-01 22:53:31 -0700631 default: {
632 return 0;
633 }
Stephen Hines071288a2011-01-27 14:38:26 -0800634 }
635}
636
637
Loganbe79ada2011-01-13 01:33:45 +0800638void Script::getExportVarList(size_t varListSize, void **varList) {
639 switch (mStatus) {
640#define DELEGATE(STATUS) \
Shih-wei Liaod50be322011-07-01 22:53:31 -0700641 case ScriptStatus::STATUS: \
642 m##STATUS->getExportVarList(varListSize, varList); \
643 break;
Logancf3e5212010-12-29 01:44:55 +0800644
Logan35849002011-01-15 07:30:43 +0800645#if USE_CACHE
Shih-wei Liaod50be322011-07-01 22:53:31 -0700646 DELEGATE(Cached);
Logan35849002011-01-15 07:30:43 +0800647#endif
648
Shih-wei Liaod50be322011-07-01 22:53:31 -0700649 DELEGATE(Compiled);
Loganbe79ada2011-01-13 01:33:45 +0800650#undef DELEGATE
Logan89eb47f2011-01-07 10:45:16 +0800651
Shih-wei Liaod50be322011-07-01 22:53:31 -0700652 default: {
653 mErrorCode = BCC_INVALID_OPERATION;
654 }
Logan89eb47f2011-01-07 10:45:16 +0800655 }
Logancf3e5212010-12-29 01:44:55 +0800656}
657
Joseph Wenf36637f2011-07-06 18:27:12 -0700658void Script::getExportVarNameList(std::vector<std::string> &varList) {
659 switch (mStatus) {
660 case ScriptStatus::Compiled: {
661 return mCompiled->getExportVarNameList(varList);
662 }
663
664 default: {
665 mErrorCode = BCC_INVALID_OPERATION;
666 }
667 }
668}
669
Logancf3e5212010-12-29 01:44:55 +0800670
Loganbe79ada2011-01-13 01:33:45 +0800671void Script::getExportFuncList(size_t funcListSize, void **funcList) {
Logan89eb47f2011-01-07 10:45:16 +0800672 switch (mStatus) {
Loganbe79ada2011-01-13 01:33:45 +0800673#define DELEGATE(STATUS) \
Shih-wei Liaod50be322011-07-01 22:53:31 -0700674 case ScriptStatus::STATUS: \
675 m##STATUS->getExportFuncList(funcListSize, funcList); \
676 break;
Logancf3e5212010-12-29 01:44:55 +0800677
Logan35849002011-01-15 07:30:43 +0800678#if USE_CACHE
Shih-wei Liaod50be322011-07-01 22:53:31 -0700679 DELEGATE(Cached);
Logan35849002011-01-15 07:30:43 +0800680#endif
681
Shih-wei Liaod50be322011-07-01 22:53:31 -0700682 DELEGATE(Compiled);
Loganbe79ada2011-01-13 01:33:45 +0800683#undef DELEGATE
Logan89eb47f2011-01-07 10:45:16 +0800684
Shih-wei Liaod50be322011-07-01 22:53:31 -0700685 default: {
686 mErrorCode = BCC_INVALID_OPERATION;
687 }
Logan89eb47f2011-01-07 10:45:16 +0800688 }
Logancf3e5212010-12-29 01:44:55 +0800689}
690
Joseph Wenf36637f2011-07-06 18:27:12 -0700691void Script::getExportFuncNameList(std::vector<std::string> &funcList) {
692 switch (mStatus) {
693 case ScriptStatus::Compiled: {
694 return mCompiled->getExportFuncNameList(funcList);
695 }
696
697 default: {
698 mErrorCode = BCC_INVALID_OPERATION;
699 }
700 }
701}
702
Stephen Hinescc366e52012-02-21 17:22:04 -0800703void Script::getExportForEachList(size_t funcListSize, void **funcList) {
704 switch (mStatus) {
705#define DELEGATE(STATUS) \
706 case ScriptStatus::STATUS: \
707 m##STATUS->getExportForEachList(funcListSize, funcList); \
708 break;
709
710#if USE_CACHE
711 DELEGATE(Cached);
712#endif
713
714 DELEGATE(Compiled);
715#undef DELEGATE
716
717 default: {
718 mErrorCode = BCC_INVALID_OPERATION;
719 }
720 }
721}
722
723void Script::getExportForEachNameList(std::vector<std::string> &forEachList) {
724 switch (mStatus) {
725 case ScriptStatus::Compiled: {
726 return mCompiled->getExportForEachNameList(forEachList);
727 }
728
729 default: {
730 mErrorCode = BCC_INVALID_OPERATION;
731 }
732 }
733}
Logancf3e5212010-12-29 01:44:55 +0800734
Loganbe79ada2011-01-13 01:33:45 +0800735void Script::getPragmaList(size_t pragmaListSize,
736 char const **keyList,
737 char const **valueList) {
Logan89eb47f2011-01-07 10:45:16 +0800738 switch (mStatus) {
Loganbe79ada2011-01-13 01:33:45 +0800739#define DELEGATE(STATUS) \
Shih-wei Liaod50be322011-07-01 22:53:31 -0700740 case ScriptStatus::STATUS: \
741 m##STATUS->getPragmaList(pragmaListSize, keyList, valueList); \
742 break;
Logancf3e5212010-12-29 01:44:55 +0800743
Logan35849002011-01-15 07:30:43 +0800744#if USE_CACHE
Shih-wei Liaod50be322011-07-01 22:53:31 -0700745 DELEGATE(Cached);
Logan35849002011-01-15 07:30:43 +0800746#endif
747
Shih-wei Liaod50be322011-07-01 22:53:31 -0700748 DELEGATE(Compiled);
Loganbe79ada2011-01-13 01:33:45 +0800749#undef DELEGATE
Logan89eb47f2011-01-07 10:45:16 +0800750
Shih-wei Liaod50be322011-07-01 22:53:31 -0700751 default: {
752 mErrorCode = BCC_INVALID_OPERATION;
753 }
Logan89eb47f2011-01-07 10:45:16 +0800754 }
Logancf3e5212010-12-29 01:44:55 +0800755}
756
757
Loganf340bf72011-01-14 17:51:40 +0800758void Script::getFuncInfoList(size_t funcInfoListSize,
759 FuncInfo *funcInfoList) {
Logan89eb47f2011-01-07 10:45:16 +0800760 switch (mStatus) {
Loganbe79ada2011-01-13 01:33:45 +0800761#define DELEGATE(STATUS) \
Shih-wei Liaod50be322011-07-01 22:53:31 -0700762 case ScriptStatus::STATUS: \
763 m##STATUS->getFuncInfoList(funcInfoListSize, funcInfoList); \
764 break;
Logancf3e5212010-12-29 01:44:55 +0800765
Logan35849002011-01-15 07:30:43 +0800766#if USE_CACHE
Shih-wei Liaod50be322011-07-01 22:53:31 -0700767 DELEGATE(Cached);
Logan35849002011-01-15 07:30:43 +0800768#endif
769
Shih-wei Liaod50be322011-07-01 22:53:31 -0700770 DELEGATE(Compiled);
Loganbe79ada2011-01-13 01:33:45 +0800771#undef DELEGATE
Logan89eb47f2011-01-07 10:45:16 +0800772
Shih-wei Liaod50be322011-07-01 22:53:31 -0700773 default: {
774 mErrorCode = BCC_INVALID_OPERATION;
775 }
Logan89eb47f2011-01-07 10:45:16 +0800776 }
Logancf3e5212010-12-29 01:44:55 +0800777}
778
Stephen Hines071288a2011-01-27 14:38:26 -0800779
780void Script::getObjectSlotList(size_t objectSlotListSize,
781 uint32_t *objectSlotList) {
782 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700783#define DELEGATE(STATUS) \
784 case ScriptStatus::STATUS: \
785 m##STATUS->getObjectSlotList(objectSlotListSize, objectSlotList); \
786 break;
Stephen Hines071288a2011-01-27 14:38:26 -0800787
788#if USE_CACHE
Shih-wei Liaod50be322011-07-01 22:53:31 -0700789 DELEGATE(Cached);
Stephen Hines071288a2011-01-27 14:38:26 -0800790#endif
791
Shih-wei Liaod50be322011-07-01 22:53:31 -0700792 DELEGATE(Compiled);
Stephen Hines071288a2011-01-27 14:38:26 -0800793#undef DELEGATE
794
Shih-wei Liaod50be322011-07-01 22:53:31 -0700795 default: {
796 mErrorCode = BCC_INVALID_OPERATION;
797 }
Stephen Hines071288a2011-01-27 14:38:26 -0800798 }
799}
800
801
Logan Chiend2a5f302011-07-19 20:32:25 +0800802#if USE_OLD_JIT
Logana27a83f2011-01-07 10:25:48 +0800803char *Script::getContext() {
804 switch (mStatus) {
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700805
Logan35849002011-01-15 07:30:43 +0800806#if USE_CACHE
Shih-wei Liaod50be322011-07-01 22:53:31 -0700807 case ScriptStatus::Cached: {
808 return mCached->getContext();
809 }
Logan35849002011-01-15 07:30:43 +0800810#endif
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700811
Shih-wei Liaod50be322011-07-01 22:53:31 -0700812 case ScriptStatus::Compiled: {
813 return mCompiled->getContext();
814 }
Logana27a83f2011-01-07 10:25:48 +0800815
Shih-wei Liaod50be322011-07-01 22:53:31 -0700816 default: {
817 mErrorCode = BCC_INVALID_OPERATION;
818 return NULL;
819 }
Logan02286cb2011-01-07 00:30:47 +0800820 }
Logan02286cb2011-01-07 00:30:47 +0800821}
Logan Chiend2a5f302011-07-19 20:32:25 +0800822#endif
Logan02286cb2011-01-07 00:30:47 +0800823
Logancf3e5212010-12-29 01:44:55 +0800824
Shih-wei Liaoce82d492011-01-20 12:34:03 -0800825int Script::registerSymbolCallback(BCCSymbolLookupFn pFn, void *pContext) {
Logancf3e5212010-12-29 01:44:55 +0800826 mpExtSymbolLookupFn = pFn;
827 mpExtSymbolLookupFnContext = pContext;
828
Logan7d2219f2011-01-06 06:19:25 +0800829 if (mStatus != ScriptStatus::Unknown) {
Logancf3e5212010-12-29 01:44:55 +0800830 mErrorCode = BCC_INVALID_OPERATION;
Steve Block10c14122012-01-08 10:15:06 +0000831 ALOGE("Invalid operation: %s\n", __func__);
Shih-wei Liaoce82d492011-01-20 12:34:03 -0800832 return 1;
Logancf3e5212010-12-29 01:44:55 +0800833 }
Shih-wei Liaoce82d492011-01-20 12:34:03 -0800834 return 0;
Logancf3e5212010-12-29 01:44:55 +0800835}
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700836
Shih-wei Liaoabc7f512012-01-18 00:34:07 -0800837bool Script::isCacheable() const {
838#if USE_CACHE
839 if (getBooleanProp("debug.bcc.nocache")) {
840 // Android system environment property: Disables the cache mechanism by
841 // setting "debug.bcc.nocache". So we will not load the cache file any
842 // way.
843 return false;
844 }
845
846 if (mCacheDir.empty() || mCacheName.empty()) {
847 // The application developer has not specified the cachePath, so
848 // we don't know where to open the cache file.
849 return false;
850 }
851
852 return true;
853#else
854 return false;
855#endif
856}
857
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700858#if USE_MCJIT
859size_t Script::getELFSize() const {
860 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700861 case ScriptStatus::Compiled: {
862 return mCompiled->getELFSize();
863 }
Daniel Malea094881f2011-12-14 17:39:16 -0500864#if USE_CACHE
865 case ScriptStatus::Cached: {
866 return mCached->getELFSize();
867 }
868#endif
Shih-wei Liaod50be322011-07-01 22:53:31 -0700869 default: {
870 return 0;
871 }
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700872 }
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700873}
874
875const char *Script::getELF() const {
876 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700877 case ScriptStatus::Compiled: {
878 return mCompiled->getELF();
879 }
Daniel Malea094881f2011-12-14 17:39:16 -0500880#if USE_CACHE
881 case ScriptStatus::Cached: {
882 return mCached->getELF();
883 }
884#endif
Shih-wei Liaod50be322011-07-01 22:53:31 -0700885 default: {
886 return NULL;
887 }
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700888 }
889}
890#endif
Logancf3e5212010-12-29 01:44:55 +0800891
892} // namespace bcc