blob: 0c3c7a5eb80ac5903a8f63dd7ea09667f716cdda [file] [log] [blame]
Logancf3e5212010-12-29 01:44:55 +08001/*
Stephen Hines97c92c22012-05-03 12:30:24 -07002 * copyright 2010-2012, the android open source project
Logancf3e5212010-12-29 01:44:55 +08003 *
Stephen Hines97c92c22012-05-03 12:30:24 -07004 * 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
Logancf3e5212010-12-29 01:44:55 +08007 *
Stephen Hines97c92c22012-05-03 12:30:24 -07008 * http://www.apache.org/licenses/license-2.0
Logancf3e5212010-12-29 01:44:55 +08009 *
Stephen Hines97c92c22012-05-03 12:30:24 -070010 * 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.
Logancf3e5212010-12-29 01:44:55 +080015 */
16
Stephen Hines2f6a4932012-05-03 12:27:13 -070017#include "Script.h"
Logancf3e5212010-12-29 01:44:55 +080018
Stephen Hines97c92c22012-05-03 12:30:24 -070019#include "Config.h"
Stephen Hinesead5ccb2012-05-03 12:30:38 -070020#include "bcinfo/BitcodeWrapper.h"
Stephen Hines97c92c22012-05-03 12:30:24 -070021
22#include "MCCacheReader.h"
23#include "MCCacheWriter.h"
24#include "CompilerOption.h"
25
Stephen Hines97c92c22012-05-03 12:30:24 -070026#include "DebugHelper.h"
27#include "FileHandle.h"
28#include "GDBJITRegistrar.h"
29#include "ScriptCompiled.h"
30#include "ScriptCached.h"
31#include "Sha1Helper.h"
Stephen Hinesead5ccb2012-05-03 12:30:38 -070032#include "SourceInfo.h"
33
34#include <errno.h>
35#include <sys/stat.h>
36#include <sys/types.h>
37#include <unistd.h>
38
39#include <new>
40#include <string.h>
41#include <cutils/properties.h>
Logan033f46e2011-01-06 05:51:24 +080042
Stephen Hines97c92c22012-05-03 12:30:24 -070043namespace {
44
45bool getBooleanProp(const char *str) {
46 char buf[PROPERTY_VALUE_MAX];
47 property_get(str, buf, "0");
48 return strcmp(buf, "0") != 0;
49}
50
Stephen Hines32c56ec2012-06-01 15:26:30 -070051bool isSetProp(const char *str) {
52 char buf[PROPERTY_VALUE_MAX];
53 property_get(str, buf, "");
54 return buf[0] != '\0';
55}
56
Stephen Hines97c92c22012-05-03 12:30:24 -070057} // namespace anonymous
58
59namespace bcc {
60
Stephen Hines97c92c22012-05-03 12:30:24 -070061Script::~Script() {
62 switch (mStatus) {
63 case ScriptStatus::Compiled:
64 delete mCompiled;
65 break;
66
67 case ScriptStatus::Cached:
68 delete mCached;
69 break;
70
71 default:
72 break;
73 }
Stephen Hines97c92c22012-05-03 12:30:24 -070074
Stephen Hinesead5ccb2012-05-03 12:30:38 -070075 for (size_t i = 0; i < 2; ++i) {
76 delete mSourceList[i];
77 }
Stephen Hines97c92c22012-05-03 12:30:24 -070078}
79
80
Stephen Hinesead5ccb2012-05-03 12:30:38 -070081int Script::addSourceBC(size_t idx,
82 char const *resName,
83 const char *bitcode,
84 size_t bitcodeSize,
85 unsigned long flags) {
Logancf3e5212010-12-29 01:44:55 +080086
Stephen Hinesead5ccb2012-05-03 12:30:38 -070087 if (!resName) {
88 mErrorCode = BCC_INVALID_VALUE;
89 ALOGE("Invalid argument: resName = NULL\n");
90 return 1;
Logancf3e5212010-12-29 01:44:55 +080091 }
92
Stephen Hinesead5ccb2012-05-03 12:30:38 -070093 if (mStatus != ScriptStatus::Unknown) {
94 mErrorCode = BCC_INVALID_OPERATION;
95 ALOGE("Bad operation: Adding source after bccPrepareExecutable\n");
96 return 1;
Stephen Hines97c92c22012-05-03 12:30:24 -070097 }
98
Stephen Hinesead5ccb2012-05-03 12:30:38 -070099 if (!bitcode) {
100 mErrorCode = BCC_INVALID_VALUE;
101 ALOGE("Invalid argument: bitcode = NULL\n");
102 return 1;
103 }
104
105 bcinfo::BitcodeWrapper wrapper(bitcode, bitcodeSize);
106
107 mSourceList[idx] = SourceInfo::createFromBuffer(resName,
108 bitcode, bitcodeSize,
109 flags);
110
111 if (!mSourceList[idx]) {
112 mErrorCode = BCC_OUT_OF_MEMORY;
113 ALOGE("Out of memory while adding source bitcode\n");
114 return 1;
115 }
116
117 return 0;
118}
119
120
121int Script::addSourceModule(size_t idx,
122 llvm::Module *module,
123 unsigned long flags) {
124 if (mStatus != ScriptStatus::Unknown) {
125 mErrorCode = BCC_INVALID_OPERATION;
126 ALOGE("Bad operation: Adding source after bccPrepareExecutable\n");
127 return 1;
128 }
129
130 if (!module) {
131 mErrorCode = BCC_INVALID_VALUE;
132 ALOGE("Invalid argument: module = NULL\n");
133 return 1;
134 }
135
136 mSourceList[idx] = SourceInfo::createFromModule(module, flags);
137
138 if (!mSourceList[idx]) {
139 mErrorCode = BCC_OUT_OF_MEMORY;
140 ALOGE("Out of memory when add source module\n");
141 return 1;
142 }
143
144 return 0;
145}
146
147
148int Script::addSourceFile(size_t idx,
149 char const *path,
150 unsigned long flags) {
151 if (mStatus != ScriptStatus::Unknown) {
152 mErrorCode = BCC_INVALID_OPERATION;
153 ALOGE("Bad operation: Adding source after bccPrepareExecutable\n");
154 return 1;
155 }
156
157 if (!path) {
158 mErrorCode = BCC_INVALID_VALUE;
159 ALOGE("Invalid argument: path = NULL\n");
160 return 1;
161 }
162
163 struct stat sb;
164 if (stat(path, &sb) != 0) {
165 mErrorCode = BCC_INVALID_VALUE;
166 ALOGE("File not found: %s\n", path);
167 return 1;
168 }
169
170 mSourceList[idx] = SourceInfo::createFromFile(path, flags);
171
172 if (!mSourceList[idx]) {
173 mErrorCode = BCC_OUT_OF_MEMORY;
174 ALOGE("Out of memory while adding source file\n");
175 return 1;
176 }
177
178 return 0;
Stephen Hines97c92c22012-05-03 12:30:24 -0700179}
180
181int Script::prepareRelocatable(char const *objPath,
182 llvm::Reloc::Model RelocModel,
183 unsigned long flags) {
184 CompilerOption option;
185 option.RelocModelOpt = RelocModel;
Stephen Hines97c92c22012-05-03 12:30:24 -0700186 option.LoadAfterCompile = false;
187
188 int status = internalCompile(option);
189 if (status != 0) {
190 ALOGE("LLVM error message: %s\n", getCompilerErrorMessage());
191 return status;
192 }
193
194 FileHandle objFile;
195 if (objFile.open(objPath, OpenMode::Write) < 0) {
196 ALOGE("Failed to open %s for write.\n", objPath);
197 return 1;
198 }
199
200 if (static_cast<size_t>(objFile.write(getELF(),
201 getELFSize())) != getELFSize()) {
202 objFile.close();
203 ::unlink(objPath);
204 ALOGE("Unable to write ELF to file %s.\n", objPath);
205 return false;
206 }
207
208 mObjectType = ScriptObject::Relocatable;
209
210 return 0;
211}
212
213
214int Script::prepareSharedObject(char const *objPath,
215 char const *dsoPath,
216 unsigned long flags) {
217 // TODO: Support cached shared object.
218 return 1;
219}
220
221
222int Script::prepareExecutable(char const *cacheDir,
223 char const *cacheName,
224 unsigned long flags) {
225 if (mStatus != ScriptStatus::Unknown) {
226 mErrorCode = BCC_INVALID_OPERATION;
227 ALOGE("Invalid operation: %s\n", __func__);
228 return 1;
229 }
230
231 int status = internalLoadCache(cacheDir, cacheName, /* checkOnly */ false);
232
233 if (status != 0) {
234 CompilerOption option;
235 status = internalCompile(option);
236
237 if (status != 0) {
238 ALOGE("LLVM error message: %s\n", getCompilerErrorMessage());
239 return status;
240 }
241
242 status = writeCache();
243 if (status != 0) {
244 ALOGE("Failed to write the cache for %s\n", cacheName);
245 return status;
246 }
247 }
248
249 // FIXME: Registration can be conditional on the presence of debug metadata
250 registerObjectWithGDB(getELF(), getELFSize()); // thread-safe registration
251
252 mObjectType = ScriptObject::Executable;
253
254 return status;
255}
256
257int Script::internalLoadCache(char const *cacheDir, char const *cacheName,
258 bool checkOnly) {
259 if ((cacheDir == NULL) || (cacheName == NULL)) {
260 return 1;
261 }
262
263 // Set cache file Name
264 mCacheName = cacheName;
265
266 // Santize mCacheDir. Ensure that mCacheDir ends with '/'.
267 mCacheDir = cacheDir;
268 if (!mCacheDir.empty() && *mCacheDir.rbegin() != '/') {
269 mCacheDir.push_back('/');
270 }
271
272 if (!isCacheable()) {
273 return 1;
274 }
275
276 std::string objPath = getCachedObjectPath();
277 std::string infoPath = getCacheInfoPath();
278
279 FileHandle objFile;
280 if (objFile.open(objPath.c_str(), OpenMode::Read) < 0) {
281 // Unable to open the executable file in read mode.
282 return 1;
283 }
284
285 FileHandle infoFile;
286 if (infoFile.open(infoPath.c_str(), OpenMode::Read) < 0) {
287 // Unable to open the metadata information file in read mode.
288 return 1;
289 }
290
291 MCCacheReader reader;
292
293 // Register symbol lookup function
294 if (mpExtSymbolLookupFn) {
295 reader.registerSymbolCallback(mpExtSymbolLookupFn,
296 mpExtSymbolLookupFnContext);
297 }
298
299 // Dependencies
300 reader.addDependency(BCC_FILE_RESOURCE, pathLibBCC_SHA1, sha1LibBCC_SHA1);
301 reader.addDependency(BCC_FILE_RESOURCE, pathLibRS, sha1LibRS);
302
Stephen Hinesead5ccb2012-05-03 12:30:38 -0700303 for (size_t i = 0; i < 2; ++i) {
304 if (mSourceList[i]) {
305 mSourceList[i]->introDependency(reader);
306 }
Stephen Hines97c92c22012-05-03 12:30:24 -0700307 }
308
309 if (checkOnly)
310 return !reader.checkCacheFile(&objFile, &infoFile, this);
311
312 // Read cache file
313 ScriptCached *cached = reader.readCacheFile(&objFile, &infoFile, this);
314
315 if (!cached) {
316 mIsContextSlotNotAvail = reader.isContextSlotNotAvail();
317 return 1;
318 }
319
320 mCached = cached;
321 mStatus = ScriptStatus::Cached;
322
323 // Dirty hack for libRS.
324 // TODO(all): This dirty hack should be removed in the future.
325 if (!cached->isLibRSThreadable() && mpExtSymbolLookupFn) {
326 mpExtSymbolLookupFn(mpExtSymbolLookupFnContext, "__clearThreadable");
327 }
328
329 return 0;
330}
331
332int Script::internalCompile(const CompilerOption &option) {
333 // Create the ScriptCompiled object
334 mCompiled = new (std::nothrow) ScriptCompiled(this);
335
336 if (!mCompiled) {
337 mErrorCode = BCC_OUT_OF_MEMORY;
338 ALOGE("Out of memory: %s %d\n", __FILE__, __LINE__);
339 return 1;
340 }
341
342 mStatus = ScriptStatus::Compiled;
343
344 // Register symbol lookup function
345 if (mpExtSymbolLookupFn) {
346 mCompiled->registerSymbolCallback(mpExtSymbolLookupFn,
347 mpExtSymbolLookupFnContext);
348 }
349
Stephen Hinesead5ccb2012-05-03 12:30:38 -0700350 if (!mSourceList[0]) {
351 ALOGE("Source bitcode is not set.\n");
352 return 1;
353 }
354
355 // Parse Source bitcode file (if necessary)
Stephen Hines274926b2012-05-03 12:30:46 -0700356 if (mSourceList[0]->prepareModule() != 0) {
Stephen Hinesead5ccb2012-05-03 12:30:38 -0700357 ALOGE("Unable to setup source module\n");
358 return 1;
359 }
360
361 // Parse Library bitcode file (if necessary)
362 if (mSourceList[1]) {
Stephen Hines274926b2012-05-03 12:30:46 -0700363 if (mSourceList[1]->prepareModule(mSourceList[0]->getContext()) != 0) {
Stephen Hinesead5ccb2012-05-03 12:30:38 -0700364 ALOGE("Unable to setup library module\n");
365 return 1;
366 }
367 }
368
Stephen Hines97c92c22012-05-03 12:30:24 -0700369 // Set the main source module
Stephen Hinesead5ccb2012-05-03 12:30:38 -0700370 if (mCompiled->readModule(mSourceList[0]->getModule()) != 0) {
Stephen Hines97c92c22012-05-03 12:30:24 -0700371 ALOGE("Unable to read source module\n");
372 return 1;
373 }
374
Stephen Hinesead5ccb2012-05-03 12:30:38 -0700375 // Link the source module with the library module
376 if (mSourceList[1]) {
377 if (mCompiled->linkModule(mSourceList[1]->getModule()) != 0) {
378 ALOGE("Unable to link library module\n");
379 return 1;
380 }
381 }
382
Stephen Hines97c92c22012-05-03 12:30:24 -0700383 // Compile and JIT the code
384 if (mCompiled->compile(option) != 0) {
385 ALOGE("Unable to compile.\n");
386 return 1;
387 }
388
389 return 0;
390}
391
392int Script::writeCache() {
393 // Not compiled script or encountered error during the compilation.
394 if ((mStatus != ScriptStatus::Compiled) ||
395 (getCompilerErrorMessage() == NULL))
396 return 1;
397
398 // Note: If we re-compile the script because the cached context slot not
399 // available, then we don't have to write the cache.
400
401 // Note: If the address of the context is not in the context slot, then
402 // we don't have to cache it.
403
404 if (isCacheable()) {
405
406 std::string objPath = getCachedObjectPath();
407 std::string infoPath = getCacheInfoPath();
408
409 // Remove the file if it already exists before writing the new file.
410 // The old file may still be mapped elsewhere in memory and we do not want
411 // to modify its contents. (The same script may be running concurrently in
412 // the same process or a different process!)
413 ::unlink(objPath.c_str());
414 ::unlink(infoPath.c_str());
415
416 FileHandle objFile;
417 FileHandle infoFile;
418
419 if (objFile.open(objPath.c_str(), OpenMode::Write) >= 0 &&
420 infoFile.open(infoPath.c_str(), OpenMode::Write) >= 0) {
421
422 MCCacheWriter writer;
423
424#ifdef TARGET_BUILD
425 // Dependencies
426 writer.addDependency(BCC_FILE_RESOURCE, pathLibBCC_SHA1, sha1LibBCC_SHA1);
427 writer.addDependency(BCC_FILE_RESOURCE, pathLibRS, sha1LibRS);
428#endif
429
Stephen Hinesead5ccb2012-05-03 12:30:38 -0700430 for (size_t i = 0; i < 2; ++i) {
431 if (mSourceList[i]) {
432 mSourceList[i]->introDependency(writer);
433 }
Stephen Hines97c92c22012-05-03 12:30:24 -0700434 }
435
Stephen Hines97c92c22012-05-03 12:30:24 -0700436 // libRS is threadable dirty hack
437 // TODO: This should be removed in the future
438 uint32_t libRS_threadable = 0;
439 if (mpExtSymbolLookupFn) {
440 libRS_threadable =
441 (uint32_t)mpExtSymbolLookupFn(mpExtSymbolLookupFnContext,
442 "__isThreadable");
443 }
444
445 if (!writer.writeCacheFile(&objFile, &infoFile, this, libRS_threadable)) {
446 objFile.truncate();
447 objFile.close();
448
449 if (unlink(objPath.c_str()) != 0) {
450 ALOGE("Unable to remove the invalid cache file: %s. (reason: %s)\n",
451 objPath.c_str(), strerror(errno));
452 }
453
454 infoFile.truncate();
455 infoFile.close();
456
457 if (unlink(infoPath.c_str()) != 0) {
458 ALOGE("Unable to remove the invalid cache file: %s. (reason: %s)\n",
459 infoPath.c_str(), strerror(errno));
460 }
461 }
462 }
463 }
464
465 return 0;
466}
467
468
469char const *Script::getCompilerErrorMessage() {
470 if (mStatus != ScriptStatus::Compiled) {
471 mErrorCode = BCC_INVALID_OPERATION;
472 return NULL;
473 }
474
475 return mCompiled->getCompilerErrorMessage();
476}
477
478
479void *Script::lookup(const char *name) {
480 switch (mStatus) {
481 case ScriptStatus::Compiled: {
482 return mCompiled->lookup(name);
483 }
484
485 case ScriptStatus::Cached: {
486 return mCached->lookup(name);
487 }
488
489 default: {
490 mErrorCode = BCC_INVALID_OPERATION;
491 return NULL;
492 }
493 }
494}
495
496
497size_t Script::getExportVarCount() const {
498 switch (mStatus) {
499 case ScriptStatus::Compiled: {
500 return mCompiled->getExportVarCount();
501 }
502
503 case ScriptStatus::Cached: {
504 return mCached->getExportVarCount();
505 }
506
507 default: {
508 return 0;
509 }
510 }
511}
512
513
514size_t Script::getExportFuncCount() const {
515 switch (mStatus) {
516 case ScriptStatus::Compiled: {
517 return mCompiled->getExportFuncCount();
518 }
519
520 case ScriptStatus::Cached: {
521 return mCached->getExportFuncCount();
522 }
523
524 default: {
525 return 0;
526 }
527 }
528}
529
530
531size_t Script::getExportForEachCount() const {
532 switch (mStatus) {
533 case ScriptStatus::Compiled: {
534 return mCompiled->getExportForEachCount();
535 }
536
537 case ScriptStatus::Cached: {
538 return mCached->getExportForEachCount();
539 }
540
541 default: {
542 return 0;
543 }
544 }
545}
546
547
548size_t Script::getPragmaCount() const {
549 switch (mStatus) {
550 case ScriptStatus::Compiled: {
551 return mCompiled->getPragmaCount();
552 }
553
554 case ScriptStatus::Cached: {
555 return mCached->getPragmaCount();
556 }
557
558 default: {
559 return 0;
560 }
561 }
562}
563
564
565size_t Script::getFuncCount() const {
566 switch (mStatus) {
567 case ScriptStatus::Compiled: {
568 return mCompiled->getFuncCount();
569 }
570
571 case ScriptStatus::Cached: {
572 return mCached->getFuncCount();
573 }
574
575 default: {
576 return 0;
577 }
578 }
579}
580
581
582size_t Script::getObjectSlotCount() const {
583 switch (mStatus) {
584 case ScriptStatus::Compiled: {
585 return mCompiled->getObjectSlotCount();
586 }
587
588 case ScriptStatus::Cached: {
589 return mCached->getObjectSlotCount();
590 }
591
592 default: {
593 return 0;
594 }
595 }
596}
597
598
599void Script::getExportVarList(size_t varListSize, void **varList) {
600 switch (mStatus) {
601#define DELEGATE(STATUS) \
602 case ScriptStatus::STATUS: \
603 m##STATUS->getExportVarList(varListSize, varList); \
604 break;
605
606 DELEGATE(Cached);
607
608 DELEGATE(Compiled);
609#undef DELEGATE
610
611 default: {
612 mErrorCode = BCC_INVALID_OPERATION;
613 }
614 }
615}
616
617void Script::getExportVarNameList(std::vector<std::string> &varList) {
618 switch (mStatus) {
619 case ScriptStatus::Compiled: {
620 return mCompiled->getExportVarNameList(varList);
621 }
622
623 default: {
624 mErrorCode = BCC_INVALID_OPERATION;
625 }
626 }
627}
628
629
630void Script::getExportFuncList(size_t funcListSize, void **funcList) {
631 switch (mStatus) {
632#define DELEGATE(STATUS) \
633 case ScriptStatus::STATUS: \
634 m##STATUS->getExportFuncList(funcListSize, funcList); \
635 break;
636
637 DELEGATE(Cached);
638
639 DELEGATE(Compiled);
640#undef DELEGATE
641
642 default: {
643 mErrorCode = BCC_INVALID_OPERATION;
644 }
645 }
646}
647
648void Script::getExportFuncNameList(std::vector<std::string> &funcList) {
649 switch (mStatus) {
650 case ScriptStatus::Compiled: {
651 return mCompiled->getExportFuncNameList(funcList);
652 }
653
654 default: {
655 mErrorCode = BCC_INVALID_OPERATION;
656 }
657 }
658}
659
660void Script::getExportForEachList(size_t funcListSize, void **funcList) {
661 switch (mStatus) {
662#define DELEGATE(STATUS) \
663 case ScriptStatus::STATUS: \
664 m##STATUS->getExportForEachList(funcListSize, funcList); \
665 break;
666
667 DELEGATE(Cached);
668
669 DELEGATE(Compiled);
670#undef DELEGATE
671
672 default: {
673 mErrorCode = BCC_INVALID_OPERATION;
674 }
675 }
676}
677
678void Script::getExportForEachNameList(std::vector<std::string> &forEachList) {
679 switch (mStatus) {
680 case ScriptStatus::Compiled: {
681 return mCompiled->getExportForEachNameList(forEachList);
682 }
683
684 default: {
685 mErrorCode = BCC_INVALID_OPERATION;
686 }
687 }
688}
689
690void Script::getPragmaList(size_t pragmaListSize,
691 char const **keyList,
692 char const **valueList) {
693 switch (mStatus) {
694#define DELEGATE(STATUS) \
695 case ScriptStatus::STATUS: \
696 m##STATUS->getPragmaList(pragmaListSize, keyList, valueList); \
697 break;
698
699 DELEGATE(Cached);
700
701 DELEGATE(Compiled);
702#undef DELEGATE
703
704 default: {
705 mErrorCode = BCC_INVALID_OPERATION;
706 }
707 }
708}
709
710
711void Script::getFuncInfoList(size_t funcInfoListSize,
712 FuncInfo *funcInfoList) {
713 switch (mStatus) {
714#define DELEGATE(STATUS) \
715 case ScriptStatus::STATUS: \
716 m##STATUS->getFuncInfoList(funcInfoListSize, funcInfoList); \
717 break;
718
719 DELEGATE(Cached);
720
721 DELEGATE(Compiled);
722#undef DELEGATE
723
724 default: {
725 mErrorCode = BCC_INVALID_OPERATION;
726 }
727 }
728}
729
730
731void Script::getObjectSlotList(size_t objectSlotListSize,
732 uint32_t *objectSlotList) {
733 switch (mStatus) {
734#define DELEGATE(STATUS) \
735 case ScriptStatus::STATUS: \
736 m##STATUS->getObjectSlotList(objectSlotListSize, objectSlotList); \
737 break;
738
739 DELEGATE(Cached);
740
741 DELEGATE(Compiled);
742#undef DELEGATE
743
744 default: {
745 mErrorCode = BCC_INVALID_OPERATION;
746 }
747 }
748}
749
750
751int Script::registerSymbolCallback(BCCSymbolLookupFn pFn, void *pContext) {
752 mpExtSymbolLookupFn = pFn;
753 mpExtSymbolLookupFnContext = pContext;
754
755 if (mStatus != ScriptStatus::Unknown) {
756 mErrorCode = BCC_INVALID_OPERATION;
757 ALOGE("Invalid operation: %s\n", __func__);
758 return 1;
759 }
760 return 0;
761}
762
763bool Script::isCacheable() const {
764 if (getBooleanProp("debug.bcc.nocache")) {
765 // Android system environment property: Disables the cache mechanism by
766 // setting "debug.bcc.nocache". So we will not load the cache file any
767 // way.
768 return false;
769 }
770
Stephen Hines32c56ec2012-06-01 15:26:30 -0700771 if (isSetProp("debug.rs.precision")) {
772 // If we have a floating point precision override, don't use the cache.
773 return false;
774 }
775
Stephen Hines97c92c22012-05-03 12:30:24 -0700776 if (mCacheDir.empty() || mCacheName.empty()) {
777 // The application developer has not specified the cachePath, so
778 // we don't know where to open the cache file.
779 return false;
780 }
781
782 return true;
783}
784
785size_t Script::getELFSize() const {
786 switch (mStatus) {
787 case ScriptStatus::Compiled: {
788 return mCompiled->getELFSize();
789 }
790
791 case ScriptStatus::Cached: {
792 return mCached->getELFSize();
793 }
794
795 default: {
796 return 0;
797 }
798 }
799}
800
801const char *Script::getELF() const {
802 switch (mStatus) {
803 case ScriptStatus::Compiled: {
804 return mCompiled->getELF();
805 }
806
807 case ScriptStatus::Cached: {
808 return mCached->getELF();
809 }
810
811 default: {
812 return NULL;
813 }
814 }
815}
816
817} // namespace bcc