diff options
| author | 2013-06-14 23:22:03 +0000 | |
|---|---|---|
| committer | 2013-06-14 23:22:03 +0000 | |
| commit | c81f00310cc28aa49e6f389791ed46df07b70cc7 (patch) | |
| tree | 88b7dfd7ac663b6e6bfb1e0de8296669aef5a49d | |
| parent | 9754368bff3103f47df0c31fd389af7bcca0c54c (diff) | |
| parent | 96391606d8adfc661e1c21703ded1e7a39377a76 (diff) | |
Merge "Move image class computation to the CompilerDriver" into dalvik-dev
| -rw-r--r-- | src/common_test.h | 10 | ||||
| -rw-r--r-- | src/compiler/driver/compiler_driver.cc | 267 | ||||
| -rw-r--r-- | src/compiler/driver/compiler_driver.h | 37 | ||||
| -rw-r--r-- | src/dex2oat.cc | 137 | ||||
| -rw-r--r-- | src/image_test.cc | 39 | ||||
| -rw-r--r-- | src/image_writer.cc | 66 | ||||
| -rw-r--r-- | src/image_writer.h | 17 | ||||
| -rw-r--r-- | src/oat_test.cc | 4 |
8 files changed, 343 insertions, 234 deletions
diff --git a/src/common_test.h b/src/common_test.h index 3baa77c55c..0c171a8a86 100644 --- a/src/common_test.h +++ b/src/common_test.h @@ -346,9 +346,11 @@ class CommonTest : public testing::Test { } } class_linker_->FixupDexCaches(runtime_->GetResolutionMethod()); - image_classes_.reset(new std::set<std::string>); - compiler_driver_.reset(new CompilerDriver(compiler_backend, instruction_set, true, 2, false, - image_classes_.get(), true, true)); + compiler_driver_.reset(new CompilerDriver(compiler_backend, instruction_set, + true, new CompilerDriver::DescriptorSet, + 2, false, true, true)); + // We typically don't generate an image in unit tests, disable this optimization by default. + compiler_driver_->SetSupportBootImageFixup(false); // Create the heap thread pool so that the GC runs in parallel for tests. Normally, the thread // pool is created by the runtime. @@ -389,7 +391,6 @@ class CommonTest : public testing::Test { (*icu_cleanup_fn)(); compiler_driver_.reset(); - image_classes_.reset(); STLDeleteElements(&opened_dex_files_); Runtime::Current()->GetHeap()->VerifyHeap(); // Check for heap corruption after the test @@ -522,7 +523,6 @@ class CommonTest : public testing::Test { // Owned by the runtime ClassLinker* class_linker_; UniquePtr<CompilerDriver> compiler_driver_; - UniquePtr<std::set<std::string> > image_classes_; private: std::vector<const DexFile*> opened_dex_files_; diff --git a/src/compiler/driver/compiler_driver.cc b/src/compiler/driver/compiler_driver.cc index 40cc4830d4..186cf0d4d3 100644 --- a/src/compiler/driver/compiler_driver.cc +++ b/src/compiler/driver/compiler_driver.cc @@ -324,8 +324,8 @@ static Fn FindFunction(const std::string& compiler_so_name, void* library, const } CompilerDriver::CompilerDriver(CompilerBackend compiler_backend, InstructionSet instruction_set, - bool image, size_t thread_count, bool support_debugging, - const std::set<std::string>* image_classes, + bool image, DescriptorSet* image_classes, + size_t thread_count, bool support_debugging, bool dump_stats, bool dump_timings) : compiler_backend_(compiler_backend), instruction_set_(instruction_set), @@ -333,19 +333,20 @@ CompilerDriver::CompilerDriver(CompilerBackend compiler_backend, InstructionSet compiled_classes_lock_("compiled classes lock"), compiled_methods_lock_("compiled method lock"), image_(image), + image_classes_(image_classes), thread_count_(thread_count), support_debugging_(support_debugging), start_ns_(0), stats_(new AOTCompilationStats), dump_stats_(dump_stats), dump_timings_(dump_timings), - image_classes_(image_classes), compiler_library_(NULL), compiler_(NULL), compiler_context_(NULL), jni_compiler_(NULL), compiler_enable_auto_elf_loading_(NULL), - compiler_get_method_code_addr_(NULL) + compiler_get_method_code_addr_(NULL), + support_boot_image_fixup_(true) { std::string compiler_so_name(MakeCompilerSoName(compiler_backend_)); compiler_library_ = dlopen(compiler_so_name.c_str(), RTLD_LAZY); @@ -380,7 +381,7 @@ CompilerDriver::CompilerDriver(CompilerBackend compiler_backend, InstructionSet CHECK(!Runtime::Current()->IsStarted()); if (!image_) { - CHECK(image_classes_ == NULL); + CHECK(image_classes_.get() == NULL); } } @@ -576,20 +577,199 @@ void CompilerDriver::Resolve(jobject class_loader, const std::vector<const DexFi void CompilerDriver::PreCompile(jobject class_loader, const std::vector<const DexFile*>& dex_files, ThreadPool& thread_pool, TimingLogger& timings) { + LoadImageClasses(timings); + Resolve(class_loader, dex_files, thread_pool, timings); Verify(class_loader, dex_files, thread_pool, timings); InitializeClasses(class_loader, dex_files, thread_pool, timings); + + UpdateImageClasses(timings); } bool CompilerDriver::IsImageClass(const char* descriptor) const { - if (image_classes_ == NULL) { - return false; + DCHECK(descriptor != NULL); + if (image_classes_.get() == NULL) { + return true; } return image_classes_->find(descriptor) != image_classes_->end(); } +static void ResolveExceptionsForMethod(MethodHelper* mh, + std::set<std::pair<uint16_t, const DexFile*> >& exceptions_to_resolve) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + const DexFile::CodeItem* code_item = mh->GetCodeItem(); + if (code_item == NULL) { + return; // native or abstract method + } + if (code_item->tries_size_ == 0) { + return; // nothing to process + } + const byte* encoded_catch_handler_list = DexFile::GetCatchHandlerData(*code_item, 0); + size_t num_encoded_catch_handlers = DecodeUnsignedLeb128(&encoded_catch_handler_list); + for (size_t i = 0; i < num_encoded_catch_handlers; i++) { + int32_t encoded_catch_handler_size = DecodeSignedLeb128(&encoded_catch_handler_list); + bool has_catch_all = false; + if (encoded_catch_handler_size <= 0) { + encoded_catch_handler_size = -encoded_catch_handler_size; + has_catch_all = true; + } + for (int32_t j = 0; j < encoded_catch_handler_size; j++) { + uint16_t encoded_catch_handler_handlers_type_idx = + DecodeUnsignedLeb128(&encoded_catch_handler_list); + // Add to set of types to resolve if not already in the dex cache resolved types + if (!mh->IsResolvedTypeIdx(encoded_catch_handler_handlers_type_idx)) { + exceptions_to_resolve.insert( + std::pair<uint16_t, const DexFile*>(encoded_catch_handler_handlers_type_idx, + &mh->GetDexFile())); + } + // ignore address associated with catch handler + DecodeUnsignedLeb128(&encoded_catch_handler_list); + } + if (has_catch_all) { + // ignore catch all address + DecodeUnsignedLeb128(&encoded_catch_handler_list); + } + } +} + +static bool ResolveCatchBlockExceptionsClassVisitor(mirror::Class* c, void* arg) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + std::set<std::pair<uint16_t, const DexFile*> >* exceptions_to_resolve = + reinterpret_cast<std::set<std::pair<uint16_t, const DexFile*> >*>(arg); + MethodHelper mh; + for (size_t i = 0; i < c->NumVirtualMethods(); ++i) { + mirror::AbstractMethod* m = c->GetVirtualMethod(i); + mh.ChangeMethod(m); + ResolveExceptionsForMethod(&mh, *exceptions_to_resolve); + } + for (size_t i = 0; i < c->NumDirectMethods(); ++i) { + mirror::AbstractMethod* m = c->GetDirectMethod(i); + mh.ChangeMethod(m); + ResolveExceptionsForMethod(&mh, *exceptions_to_resolve); + } + return true; +} + +static bool RecordImageClassesVisitor(mirror::Class* klass, void* arg) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + CompilerDriver::DescriptorSet* image_classes = + reinterpret_cast<CompilerDriver::DescriptorSet*>(arg); + image_classes->insert(ClassHelper(klass).GetDescriptor()); + return true; +} + +// Make a list of descriptors for classes to include in the image +void CompilerDriver::LoadImageClasses(TimingLogger& timings) + LOCKS_EXCLUDED(Locks::mutator_lock_) { + if (image_classes_.get() == NULL) { + return; + } + + // Make a first class to load all classes explicitly listed in the file + Thread* self = Thread::Current(); + ScopedObjectAccess soa(self); + ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); + typedef DescriptorSet::iterator It; // TODO: C++0x auto + for (It it = image_classes_->begin(), end = image_classes_->end(); it != end;) { + std::string descriptor(*it); + SirtRef<mirror::Class> klass(self, class_linker->FindSystemClass(descriptor.c_str())); + if (klass.get() == NULL) { + image_classes_->erase(it++); + LOG(WARNING) << "Failed to find class " << descriptor; + Thread::Current()->ClearException(); + } else { + ++it; + } + } + + // Resolve exception classes referenced by the loaded classes. The catch logic assumes + // exceptions are resolved by the verifier when there is a catch block in an interested method. + // Do this here so that exception classes appear to have been specified image classes. + std::set<std::pair<uint16_t, const DexFile*> > unresolved_exception_types; + SirtRef<mirror::Class> java_lang_Throwable(self, + class_linker->FindSystemClass("Ljava/lang/Throwable;")); + do { + unresolved_exception_types.clear(); + class_linker->VisitClasses(ResolveCatchBlockExceptionsClassVisitor, + &unresolved_exception_types); + typedef std::set<std::pair<uint16_t, const DexFile*> >::const_iterator It; // TODO: C++0x auto + for (It it = unresolved_exception_types.begin(), + end = unresolved_exception_types.end(); + it != end; ++it) { + uint16_t exception_type_idx = it->first; + const DexFile* dex_file = it->second; + mirror::DexCache* dex_cache = class_linker->FindDexCache(*dex_file); + mirror:: ClassLoader* class_loader = NULL; + SirtRef<mirror::Class> klass(self, class_linker->ResolveType(*dex_file, exception_type_idx, + dex_cache, class_loader)); + if (klass.get() == NULL) { + const DexFile::TypeId& type_id = dex_file->GetTypeId(exception_type_idx); + const char* descriptor = dex_file->GetTypeDescriptor(type_id); + LOG(FATAL) << "Failed to resolve class " << descriptor; + } + DCHECK(java_lang_Throwable->IsAssignableFrom(klass.get())); + } + // Resolving exceptions may load classes that reference more exceptions, iterate until no + // more are found + } while (!unresolved_exception_types.empty()); + + // We walk the roots looking for classes so that we'll pick up the + // above classes plus any classes them depend on such super + // classes, interfaces, and the required ClassLinker roots. + class_linker->VisitClasses(RecordImageClassesVisitor, image_classes_.get()); + + CHECK_NE(image_classes_->size(), 0U); + timings.AddSplit("LoadImageClasses"); +} + +static void MaybeAddToImageClasses(mirror::Class* klass, CompilerDriver::DescriptorSet* image_classes) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + while (!klass->IsObjectClass()) { + ClassHelper kh(klass); + const char* descriptor = kh.GetDescriptor(); + std::pair<CompilerDriver::DescriptorSet::iterator, bool> result = + image_classes->insert(descriptor); + if (result.second) { + LOG(INFO) << "Adding " << descriptor << " to image classes"; + } else { + return; + } + for (size_t i = 0; i < kh.NumDirectInterfaces(); ++i) { + MaybeAddToImageClasses(kh.GetDirectInterface(i), image_classes); + } + if (klass->IsArrayClass()) { + MaybeAddToImageClasses(klass->GetComponentType(), image_classes); + } + klass = klass->GetSuperClass(); + } +} + +void CompilerDriver::FindClinitImageClassesCallback(mirror::Object* object, void* arg) { + DCHECK(object != NULL); + DCHECK(arg != NULL); + CompilerDriver* compiler_driver = reinterpret_cast<CompilerDriver*>(arg); + MaybeAddToImageClasses(object->GetClass(), compiler_driver->image_classes_.get()); +} + +void CompilerDriver::UpdateImageClasses(TimingLogger& timings) { + if (image_classes_.get() == NULL) { + return; + } + + // Update image_classes_ with classes for objects created by <clinit> methods. + Thread* self = Thread::Current(); + const char* old_cause = self->StartAssertNoThreadSuspension("ImageWriter"); + Heap* heap = Runtime::Current()->GetHeap(); + // TODO: Image spaces only? + WriterMutexLock mu(self, *Locks::heap_bitmap_lock_); + heap->FlushAllocStack(); + heap->GetLiveBitmap()->Walk(FindClinitImageClassesCallback, this); + self->EndAssertNoThreadSuspension(old_cause); + timings.AddSplit("UpdateImageClasses"); +} + void CompilerDriver::RecordClassStatus(ClassReference ref, CompiledClass* compiled_class) { MutexLock mu(Thread::Current(), CompilerDriver::compiled_classes_lock_); compiled_classes_.Put(ref, compiled_class); @@ -914,8 +1094,7 @@ void CompilerDriver::GetCodeAndMethodForDirectCall(InvokeType type, InvokeType s } bool compiling_boot = Runtime::Current()->GetHeap()->GetSpaces().size() == 1; if (compiling_boot) { - const bool kSupportBootImageFixup = true; - if (kSupportBootImageFixup) { + if (support_boot_image_fixup_) { MethodHelper mh(method); if (IsImageClass(mh.GetDeclaringClassDescriptor())) { // We can only branch directly to Methods that are resolved in the DexCache. @@ -1617,10 +1796,13 @@ static const char* class_initializer_black_list[] = { "Ljava/io/ObjectStreamClass;", // Calls to Class.forName -> java.io.FileDescriptor. "Ljava/io/ObjectStreamConstants;", // Instance of non-image class SerializablePermission. "Ljava/lang/ClassLoader$SystemClassLoader;", // Calls System.getProperty -> OsConstants.initConstants. + "Ljava/lang/HexStringParser;", // Calls regex.Pattern.compile -..-> regex.Pattern.compileImpl. + "Ljava/lang/ProcessManager;", // Calls Thread.currentThread. "Ljava/lang/Runtime;", // Calls System.getProperty -> OsConstants.initConstants. "Ljava/lang/System;", // Calls OsConstants.initConstants. "Ljava/math/BigDecimal;", // Calls native ... -> java.math.NativeBN.BN_new(). "Ljava/math/BigInteger;", // Calls native ... -> java.math.NativeBN.BN_new(). + "Ljava/math/Primality;", // Calls native ... -> java.math.NativeBN.BN_new(). "Ljava/math/Multiplication;", // Calls native ... -> java.math.NativeBN.BN_new(). "Ljava/net/InetAddress;", // Requires libcore.io.OsConstants. "Ljava/net/Inet4Address;", // Sub-class of InetAddress. @@ -1629,23 +1811,57 @@ static const char* class_initializer_black_list[] = { "Ljava/nio/charset/Charset;", // Calls Charset.getDefaultCharset -> System.getProperty -> OsConstants.initConstants. "Ljava/nio/charset/CharsetICU;", // Sub-class of Charset. "Ljava/nio/charset/Charsets;", // Calls Charset.forName. + "Ljava/security/AlgorithmParameterGenerator;", // Calls OsConstants.initConstants. + "Ljava/security/KeyPairGenerator$KeyPairGeneratorImpl;", // Calls OsConstants.initConstants. "Ljava/security/KeyPairGenerator;", // Calls OsConstants.initConstants. "Ljava/security/Security;", // Tries to do disk IO for "security.properties". + "Ljava/security/spec/RSAKeyGenParameterSpec;", // java.math.NativeBN.BN_new() "Ljava/sql/Date;", // Calls OsConstants.initConstants. + "Ljava/sql/DriverManager;", // Calls OsConstants.initConstants. + "Ljava/sql/Time;", // Calls OsConstants.initConstants. + "Ljava/sql/Timestamp;", // Calls OsConstants.initConstants. "Ljava/util/Date;", // Calls Date.<init> -> System.currentTimeMillis -> OsConstants.initConstants. + "Ljava/util/ListResourceBundle;", // Calls OsConstants.initConstants. "Ljava/util/Locale;", // Calls System.getProperty -> OsConstants.initConstants. + "Ljava/util/PropertyResourceBundle;", // Calls OsConstants.initConstants. + "Ljava/util/ResourceBundle;", // Calls OsConstants.initConstants. + "Ljava/util/ResourceBundle$MissingBundle;", // Calls OsConstants.initConstants. + "Ljava/util/Scanner;", // regex.Pattern.compileImpl. "Ljava/util/SimpleTimeZone;", // Sub-class of TimeZone. "Ljava/util/TimeZone;", // Calls regex.Pattern.compile -..-> regex.Pattern.compileImpl. "Ljava/util/concurrent/ConcurrentHashMap$Segment;", // Calls Runtime.getRuntime().availableProcessors(). + "Ljava/util/concurrent/ConcurrentSkipListMap;", // Calls OsConstants.initConstants. + "Ljava/util/concurrent/Exchanger;", // Calls OsConstants.initConstants. + "Ljava/util/concurrent/ForkJoinPool;", // Calls OsConstants.initConstants. + "Ljava/util/concurrent/LinkedTransferQueue;", // Calls OsConstants.initConstants. + "Ljava/util/concurrent/Phaser;", // Calls OsConstants.initConstants. + "Ljava/util/concurrent/ScheduledThreadPoolExecutor;", // Calls AtomicLong.VMSupportsCS8() + "Ljava/util/concurrent/SynchronousQueue;", // Calls OsConstants.initConstants. + "Ljava/util/concurrent/atomic/AtomicLong;", // Calls AtomicLong.VMSupportsCS8() "Ljava/util/logging/LogManager;", // Calls System.getProperty -> OsConstants.initConstants. + "Ljava/util/prefs/AbstractPreferences;", // Calls OsConstants.initConstants. + "Ljava/util/prefs/FilePreferencesImpl;", // Calls OsConstants.initConstants. + "Ljava/util/prefs/FilePreferencesFactoryImpl;", // Calls OsConstants.initConstants. + "Ljava/util/prefs/Preferences;", // Calls OsConstants.initConstants. + "Ljavax/crypto/KeyAgreement;", // Calls OsConstants.initConstants. + "Ljavax/crypto/KeyGenerator;", // Calls OsConstants.initConstants. + "Ljavax/security/cert/X509Certificate;", // Calls VMClassLoader.getBootClassPathSize. + "Ljavax/security/cert/X509Certificate$1;", // Calls VMClassLoader.getBootClassPathSize. "Ljavax/microedition/khronos/egl/EGL10;", // Requires EGLContext. "Ljavax/microedition/khronos/egl/EGLContext;", // Requires com.google.android.gles_jni.EGLImpl. "Ljavax/net/ssl/HttpsURLConnection;", // Calls SSLSocketFactory.getDefault -> java.security.Security.getProperty. + "Ljavax/xml/datatype/DatatypeConstants;", // Calls OsConstants.initConstants. + "Ljavax/xml/datatype/FactoryFinder;", // Calls OsConstants.initConstants. + "Ljavax/xml/namespace/QName;", // Calls OsConstants.initConstants. + "Ljavax/xml/validation/SchemaFactoryFinder;", // Calls OsConstants.initConstants. + "Ljavax/xml/xpath/XPathConstants;", // Calls OsConstants.initConstants. + "Ljavax/xml/xpath/XPathFactoryFinder;", // Calls OsConstants.initConstants. "Llibcore/icu/LocaleData;", // Requires java.util.Locale. "Llibcore/icu/TimeZoneNames;", // Requires java.util.TimeZone. "Llibcore/io/IoUtils;", // Calls Random.<init> -> System.currentTimeMillis -> FileDescriptor -> OsConstants.initConstants. "Llibcore/io/OsConstants;", // Platform specific. "Llibcore/net/MimeUtils;", // Calls libcore.net.MimeUtils.getContentTypesPropertiesStream -> System.getProperty. + "Llibcore/reflect/Types;", // Calls OsConstants.initConstants. "Llibcore/util/ZoneInfo;", // Sub-class of TimeZone. "Llibcore/util/ZoneInfoDB;", // Calls System.getenv -> OsConstants.initConstants. "Lorg/apache/commons/logging/LogFactory;", // Calls System.getProperty. @@ -1653,17 +1869,40 @@ static const char* class_initializer_black_list[] = { "Lorg/apache/harmony/security/provider/cert/X509CertFactoryImpl;", // Requires java.nio.charsets.Charsets. "Lorg/apache/harmony/security/provider/crypto/RandomBitsSupplier;", // Requires java.io.File. "Lorg/apache/harmony/security/utils/AlgNameMapper;", // Requires java.util.Locale. + "Lorg/apache/harmony/security/pkcs10/CertificationRequest;", // Calls Thread.currentThread. + "Lorg/apache/harmony/security/pkcs10/CertificationRequestInfo;", // Calls Thread.currentThread. + "Lorg/apache/harmony/security/pkcs7/AuthenticatedAttributes;", // Calls Thread.currentThread. + "Lorg/apache/harmony/security/pkcs7/SignedData;", // Calls Thread.currentThread. + "Lorg/apache/harmony/security/pkcs7/SignerInfo;", // Calls Thread.currentThread. + "Lorg/apache/harmony/security/pkcs8/PrivateKeyInfo;", // Calls Thread.currentThread. + "Lorg/apache/harmony/security/provider/crypto/SHA1PRNG_SecureRandomImpl;", // Calls OsConstants.initConstants. "Lorg/apache/harmony/security/x501/AttributeTypeAndValue;", // Calls IntegralToString.convertInt -> Thread.currentThread. "Lorg/apache/harmony/security/x501/DirectoryString;", // Requires BigInteger. "Lorg/apache/harmony/security/x501/Name;", // Requires org.apache.harmony.security.x501.AttributeTypeAndValue. + "Lorg/apache/harmony/security/x509/AccessDescription;", // Calls Thread.currentThread. + "Lorg/apache/harmony/security/x509/AuthorityKeyIdentifier;", // Calls Thread.currentThread. + "Lorg/apache/harmony/security/x509/CRLDistributionPoints;", // Calls Thread.currentThread. "Lorg/apache/harmony/security/x509/Certificate;", // Requires org.apache.harmony.security.x509.TBSCertificate. - "Lorg/apache/harmony/security/x509/TBSCertificate;", // Requires org.apache.harmony.security.x501.Name. + "Lorg/apache/harmony/security/x509/CertificateIssuer;", // Calls Thread.currentThread. + "Lorg/apache/harmony/security/x509/CertificateList;", // Calls Thread.currentThread. + "Lorg/apache/harmony/security/x509/DistributionPoint;", // Calls Thread.currentThread. + "Lorg/apache/harmony/security/x509/DistributionPointName;", // Calls Thread.currentThread. "Lorg/apache/harmony/security/x509/EDIPartyName;", // Calls native ... -> java.math.NativeBN.BN_new(). "Lorg/apache/harmony/security/x509/GeneralName;", // Requires org.apache.harmony.security.x501.Name. "Lorg/apache/harmony/security/x509/GeneralNames;", // Requires GeneralName. + "Lorg/apache/harmony/security/x509/GeneralSubtree;", // Calls Thread.currentThread. + "Lorg/apache/harmony/security/x509/GeneralSubtrees;", // Calls Thread.currentThread. + "Lorg/apache/harmony/security/x509/InfoAccessSyntax;", // Calls Thread.currentThread. + "Lorg/apache/harmony/security/x509/IssuingDistributionPoint;", // Calls Thread.currentThread. + "Lorg/apache/harmony/security/x509/NameConstraints;", // Calls Thread.currentThread. + "Lorg/apache/harmony/security/x509/TBSCertList$RevokedCertificate;", // Calls NativeBN.BN_new(). + "Lorg/apache/harmony/security/x509/TBSCertList;", // Calls Thread.currentThread. + "Lorg/apache/harmony/security/x509/TBSCertificate;", // Requires org.apache.harmony.security.x501.Name. "Lorg/apache/harmony/security/x509/Time;", // Calls native ... -> java.math.NativeBN.BN_new(). "Lorg/apache/harmony/security/x509/Validity;", // Requires x509.Time. + "Lorg/apache/harmony/security/x509/tsp/TSTInfo;", // Calls Thread.currentThread. "Lorg/apache/harmony/xml/ExpatParser;", // Calls native ExpatParser.staticInitialize. + "Lorg/apache/harmony/xml/ExpatParser$EntityParser;", // Calls ExpatParser.staticInitialize. "Lorg/apache/http/conn/params/ConnRouteParams;", // Requires java.util.Locale. "Lorg/apache/http/conn/ssl/SSLSocketFactory;", // Calls java.security.Security.getProperty. "Lorg/apache/http/conn/util/InetAddressUtils;", // Calls regex.Pattern.compile -..-> regex.Pattern.compileImpl. @@ -1693,6 +1932,9 @@ static void InitializeClass(const ParallelCompilationManager* manager, size_t cl // Only try to initialize classes that were successfully verified. if (klass->IsVerified()) { manager->GetClassLinker()->EnsureInitialized(klass, false, can_init_static_fields); + if (soa.Self()->IsExceptionPending()) { + soa.Self()->GetException(NULL)->Dump(); + } if (!klass->IsInitialized()) { if (can_init_static_fields) { bool is_black_listed = false; @@ -1730,7 +1972,7 @@ static void InitializeClass(const ParallelCompilationManager* manager, size_t cl compiled_class = new CompiledClass(status); manager->GetCompiler()->RecordClassStatus(ref, compiled_class); } else { - DCHECK_EQ(status, compiled_class->GetStatus()); + DCHECK_GE(status, compiled_class->GetStatus()) << descriptor; } } // Clear any class not found or verification exceptions. @@ -1854,7 +2096,8 @@ void CompilerDriver::CompileMethod(const DexFile::CodeItem* code_item, uint32_t } else if ((access_flags & kAccAbstract) != 0) { } else { // In small mode we only compile image classes. - bool dont_compile = Runtime::Current()->IsSmallMode() && ((image_classes_ == NULL) || (image_classes_->size() == 0)); + bool dont_compile = (Runtime::Current()->IsSmallMode() && + ((image_classes_.get() == NULL) || (image_classes_->size() == 0))); // Don't compile class initializers, ever. if (((access_flags & kAccConstructor) != 0) && ((access_flags & kAccStatic) != 0)) { diff --git a/src/compiler/driver/compiler_driver.h b/src/compiler/driver/compiler_driver.h index 4f77bdb7a7..fbfcadb8dd 100644 --- a/src/compiler/driver/compiler_driver.h +++ b/src/compiler/driver/compiler_driver.h @@ -61,14 +61,16 @@ class CompilerTls { class CompilerDriver { public: + typedef std::set<std::string> DescriptorSet; + // Create a compiler targeting the requested "instruction_set". // "image" should be true if image specific optimizations should be // enabled. "image_classes" lets the compiler know what classes it // can assume will be in the image, with NULL implying all available // classes. - explicit CompilerDriver(CompilerBackend compiler_backend, InstructionSet instruction_set, bool image, + explicit CompilerDriver(CompilerBackend compiler_backend, InstructionSet instruction_set, + bool image, DescriptorSet* image_classes, size_t thread_count, bool support_debugging, - const std::set<std::string>* image_classes, bool dump_stats, bool dump_timings); ~CompilerDriver(); @@ -96,6 +98,10 @@ class CompilerDriver { return image_; } + DescriptorSet* GetImageClasses() const { + return image_classes_.get(); + } + CompilerTls* GetTls(); // Generate the trampolines that are invoked by unresolved direct methods. @@ -197,6 +203,15 @@ class CompilerDriver { void SetBitcodeFileName(std::string const& filename); + bool GetSupportBootImageFixup() const { + return support_boot_image_fixup_; + } + + void SetSupportBootImageFixup(bool support_boot_image_fixup) { + support_boot_image_fixup_ = support_boot_image_fixup; + } + + // TODO: remove these Elf wrappers when libart links against LLVM (when separate compiler library is gone) bool WriteElf(const std::string& android_root, bool is_host, @@ -298,6 +313,8 @@ class CompilerDriver { ThreadPool& thread_pool, TimingLogger& timings) LOCKS_EXCLUDED(Locks::mutator_lock_); + void LoadImageClasses(TimingLogger& timings); + // Attempt to resolve all type, methods, fields, and strings // referenced from code in the dex file following PathClassLoader // ordering semantics. @@ -321,6 +338,10 @@ class CompilerDriver { ThreadPool& thread_pool, TimingLogger& timings) LOCKS_EXCLUDED(Locks::mutator_lock_, compiled_classes_lock_); + void UpdateImageClasses(TimingLogger& timings); + static void FindClinitImageClassesCallback(mirror::Object* object, void* arg) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + void Compile(jobject class_loader, const std::vector<const DexFile*>& dex_files, ThreadPool& thread_pool, TimingLogger& timings); void CompileDexFile(jobject class_loader, const DexFile& dex_file, @@ -355,7 +376,13 @@ class CompilerDriver { mutable Mutex compiled_methods_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER; MethodTable compiled_methods_ GUARDED_BY(compiled_methods_lock_); - bool image_; + const bool image_; + + // If image_ is true, specifies the classes that will be included in + // the image. Note if image_classes_ is NULL, all classes are + // included in the image. + UniquePtr<DescriptorSet> image_classes_; + size_t thread_count_; bool support_debugging_; uint64_t start_ns_; @@ -365,8 +392,6 @@ class CompilerDriver { bool dump_stats_; bool dump_timings_; - const std::set<std::string>* image_classes_; - typedef void (*CompilerCallbackFn)(CompilerDriver& driver); typedef MutexLock* (*CompilerMutexLockFn)(CompilerDriver& driver); @@ -395,6 +420,8 @@ class CompilerDriver { (const CompilerDriver& driver, const CompiledMethod* cm, const mirror::AbstractMethod* method); CompilerGetMethodCodeAddrFn compiler_get_method_code_addr_; + bool support_boot_image_fixup_; + DISALLOW_COPY_AND_ASSIGN(CompilerDriver); }; diff --git a/src/dex2oat.cc b/src/dex2oat.cc index 235c068044..f678ee9438 100644 --- a/src/dex2oat.cc +++ b/src/dex2oat.cc @@ -161,18 +161,15 @@ class Dex2Oat { } - // Make a list of descriptors for classes to include in the image - std::set<std::string>* GetImageClassDescriptors(const char* image_classes_filename) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + // Reads the class names (java.lang.Object) and returns as set of class descriptors (Ljava/lang/Object;) + CompilerDriver::DescriptorSet* ReadImageClasses(const char* image_classes_filename) { UniquePtr<std::ifstream> image_classes_file(new std::ifstream(image_classes_filename, std::ifstream::in)); if (image_classes_file.get() == NULL) { LOG(ERROR) << "Failed to open image classes file " << image_classes_filename; return NULL; } - // Load all the classes specified in the file - ClassLinker* class_linker = runtime_->GetClassLinker(); - Thread* self = Thread::Current(); + UniquePtr<CompilerDriver::DescriptorSet> image_classes(new CompilerDriver::DescriptorSet); while (image_classes_file->good()) { std::string dot; std::getline(*image_classes_file.get(), dot); @@ -180,51 +177,9 @@ class Dex2Oat { continue; } std::string descriptor(DotToDescriptor(dot.c_str())); - SirtRef<mirror::Class> klass(self, class_linker->FindSystemClass(descriptor.c_str())); - if (klass.get() == NULL) { - LOG(WARNING) << "Failed to find class " << descriptor; - Thread::Current()->ClearException(); - } + image_classes->insert(descriptor); } image_classes_file->close(); - - // Resolve exception classes referenced by the loaded classes. The catch logic assumes - // exceptions are resolved by the verifier when there is a catch block in an interested method. - // Do this here so that exception classes appear to have been specified image classes. - std::set<std::pair<uint16_t, const DexFile*> > unresolved_exception_types; - SirtRef<mirror::Class> java_lang_Throwable(self, - class_linker->FindSystemClass("Ljava/lang/Throwable;")); - do { - unresolved_exception_types.clear(); - class_linker->VisitClasses(ResolveCatchBlockExceptionsClassVisitor, - &unresolved_exception_types); - typedef std::set<std::pair<uint16_t, const DexFile*> >::const_iterator It; // TODO: C++0x auto - for (It it = unresolved_exception_types.begin(), - end = unresolved_exception_types.end(); - it != end; ++it) { - uint16_t exception_type_idx = it->first; - const DexFile* dex_file = it->second; - mirror::DexCache* dex_cache = class_linker->FindDexCache(*dex_file); - mirror:: ClassLoader* class_loader = NULL; - SirtRef<mirror::Class> klass(self, class_linker->ResolveType(*dex_file, exception_type_idx, - dex_cache, class_loader)); - if (klass.get() == NULL) { - const DexFile::TypeId& type_id = dex_file->GetTypeId(exception_type_idx); - const char* descriptor = dex_file->GetTypeDescriptor(type_id); - LOG(FATAL) << "Failed to resolve class " << descriptor; - } - DCHECK(java_lang_Throwable->IsAssignableFrom(klass.get())); - } - // Resolving exceptions may load classes that reference more exceptions, iterate until no - // more are found - } while (!unresolved_exception_types.empty()); - - // We walk the roots looking for classes so that we'll pick up the - // above classes plus any classes them depend on such super - // classes, interfaces, and the required ClassLinker roots. - UniquePtr<ImageWriter::DescriptorSet> image_classes(new ImageWriter::DescriptorSet); - class_linker->VisitClasses(RecordImageClassesVisitor, image_classes.get()); - CHECK_NE(image_classes->size(), 0U); return image_classes.release(); } @@ -236,7 +191,7 @@ class Dex2Oat { File* oat_file, const std::string& bitcode_filename, bool image, - const ImageWriter::DescriptorSet* image_classes, + UniquePtr<CompilerDriver::DescriptorSet>& image_classes, bool dump_stats, bool dump_timings) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { @@ -260,9 +215,9 @@ class Dex2Oat { UniquePtr<CompilerDriver> driver(new CompilerDriver(compiler_backend_, instruction_set_, image, + image_classes.release(), thread_count_, support_debugging_, - image_classes, dump_stats, dump_timings)); @@ -320,7 +275,6 @@ class Dex2Oat { bool CreateImageFile(const std::string& image_filename, uintptr_t image_base, - ImageWriter::DescriptorSet* image_classes, const std::string& oat_filename, const std::string& oat_location, const CompilerDriver& compiler) @@ -328,8 +282,8 @@ class Dex2Oat { uintptr_t oat_data_begin; { // ImageWriter is scoped so it can free memory before doing FixupElf - ImageWriter image_writer(image_classes); - if (!image_writer.Write(image_filename, image_base, oat_filename, oat_location, compiler)) { + ImageWriter image_writer(compiler); + if (!image_writer.Write(image_filename, image_base, oat_filename, oat_location)) { LOG(ERROR) << "Failed to create image file " << image_filename; return false; } @@ -380,72 +334,6 @@ class Dex2Oat { return true; } - static void ResolveExceptionsForMethod(MethodHelper* mh, - std::set<std::pair<uint16_t, const DexFile*> >& exceptions_to_resolve) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - const DexFile::CodeItem* code_item = mh->GetCodeItem(); - if (code_item == NULL) { - return; // native or abstract method - } - if (code_item->tries_size_ == 0) { - return; // nothing to process - } - const byte* encoded_catch_handler_list = DexFile::GetCatchHandlerData(*code_item, 0); - size_t num_encoded_catch_handlers = DecodeUnsignedLeb128(&encoded_catch_handler_list); - for (size_t i = 0; i < num_encoded_catch_handlers; i++) { - int32_t encoded_catch_handler_size = DecodeSignedLeb128(&encoded_catch_handler_list); - bool has_catch_all = false; - if (encoded_catch_handler_size <= 0) { - encoded_catch_handler_size = -encoded_catch_handler_size; - has_catch_all = true; - } - for (int32_t j = 0; j < encoded_catch_handler_size; j++) { - uint16_t encoded_catch_handler_handlers_type_idx = - DecodeUnsignedLeb128(&encoded_catch_handler_list); - // Add to set of types to resolve if not already in the dex cache resolved types - if (!mh->IsResolvedTypeIdx(encoded_catch_handler_handlers_type_idx)) { - exceptions_to_resolve.insert( - std::pair<uint16_t, const DexFile*>(encoded_catch_handler_handlers_type_idx, - &mh->GetDexFile())); - } - // ignore address associated with catch handler - DecodeUnsignedLeb128(&encoded_catch_handler_list); - } - if (has_catch_all) { - // ignore catch all address - DecodeUnsignedLeb128(&encoded_catch_handler_list); - } - } - } - - static bool ResolveCatchBlockExceptionsClassVisitor(mirror::Class* c, void* arg) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - std::set<std::pair<uint16_t, const DexFile*> >* exceptions_to_resolve = - reinterpret_cast<std::set<std::pair<uint16_t, const DexFile*> >*>(arg); - MethodHelper mh; - for (size_t i = 0; i < c->NumVirtualMethods(); ++i) { - mirror::AbstractMethod* m = c->GetVirtualMethod(i); - mh.ChangeMethod(m); - ResolveExceptionsForMethod(&mh, *exceptions_to_resolve); - } - for (size_t i = 0; i < c->NumDirectMethods(); ++i) { - mirror::AbstractMethod* m = c->GetDirectMethod(i); - mh.ChangeMethod(m); - ResolveExceptionsForMethod(&mh, *exceptions_to_resolve); - } - return true; - } - - static bool RecordImageClassesVisitor(mirror::Class* klass, void* arg) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - ImageWriter::DescriptorSet* image_classes = reinterpret_cast<ImageWriter::DescriptorSet*>(arg); - if (klass->IsArrayClass() || klass->IsPrimitive()) { - return true; - } - image_classes->insert(ClassHelper(klass).GetDescriptor()); - return true; - } - // Appends to dex_files any elements of class_path that it doesn't already // contain. This will open those dex files as necessary. static void OpenClassPathFiles(const std::string& class_path, std::vector<const DexFile*>& dex_files) { @@ -929,7 +817,7 @@ static int dex2oat(int argc, char** argv) { #endif // ART_SMALL_MODE Dex2Oat* p_dex2oat; - if (!Dex2Oat::Create(&p_dex2oat, options, compiler_backend, instruction_set, thread_count, + if (!Dex2Oat::Create(&p_dex2oat, options, compiler_backend, instruction_set, thread_count, support_debugging)) { LOG(ERROR) << "Failed to create dex2oat"; return EXIT_FAILURE; @@ -943,9 +831,9 @@ static int dex2oat(int argc, char** argv) { ScopedObjectAccess soa(Thread::Current()); // If --image-classes was specified, calculate the full list of classes to include in the image - UniquePtr<ImageWriter::DescriptorSet> image_classes(NULL); + UniquePtr<CompilerDriver::DescriptorSet> image_classes(NULL); if (image_classes_filename != NULL) { - image_classes.reset(dex2oat->GetImageClassDescriptors(image_classes_filename)); + image_classes.reset(dex2oat->ReadImageClasses(image_classes_filename)); if (image_classes.get() == NULL) { LOG(ERROR) << "Failed to create list of image classes from " << image_classes_filename; return EXIT_FAILURE; @@ -1001,7 +889,7 @@ static int dex2oat(int argc, char** argv) { oat_file.get(), bitcode_filename, image, - image_classes.get(), + image_classes, dump_stats, dump_timings)); @@ -1066,7 +954,6 @@ static int dex2oat(int argc, char** argv) { Thread::Current()->TransitionFromRunnableToSuspended(kNative); bool image_creation_success = dex2oat->CreateImageFile(image_filename, image_base, - image_classes.get(), oat_unstripped, oat_location, *compiler.get()); diff --git a/src/image_test.cc b/src/image_test.cc index cd1a34fa56..0769e21f00 100644 --- a/src/image_test.cc +++ b/src/image_test.cc @@ -43,28 +43,19 @@ TEST_F(ImageTest, WriteRead) { { std::vector<uint8_t> oat_contents; { + jobject class_loader = NULL; + ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); + compiler_driver_->CompileAll(class_loader, class_linker->GetBootClassPath()); + ScopedObjectAccess soa(Thread::Current()); - std::vector<const DexFile*> dex_files; - dex_files.push_back(java_lang_dex_file_); - dex_files.push_back(conscrypt_file_); VectorOutputStream output_stream(tmp_elf.GetFilename(), oat_contents); - bool success_oat = OatWriter::Create(output_stream, dex_files, 0, 0, "", - *compiler_driver_.get()); + bool success_oat = OatWriter::Create(output_stream, class_linker->GetBootClassPath(), + 0, 0, "", *compiler_driver_.get()); ASSERT_TRUE(success_oat); - // Force all system classes into memory - for (size_t dex_file_index = 0; dex_file_index < dex_files.size(); ++dex_file_index) { - const DexFile* dex_file = dex_files[dex_file_index]; - for (size_t class_def_index = 0; class_def_index < dex_file->NumClassDefs(); ++class_def_index) { - const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_index); - const char* descriptor = dex_file->GetClassDescriptor(class_def); - mirror::Class* klass = class_linker_->FindSystemClass(descriptor); - EXPECT_TRUE(klass != NULL) << descriptor; - } - } bool success_elf = compiler_driver_->WriteElf(GetTestAndroidRoot(), !kIsTargetBuild, - dex_files, + class_linker->GetBootClassPath(), oat_contents, tmp_elf.GetFile()); ASSERT_TRUE(success_elf); @@ -77,10 +68,9 @@ TEST_F(ImageTest, WriteRead) { ScratchFile tmp_image; const uintptr_t requested_image_base = ART_BASE_ADDRESS; { - ImageWriter writer(NULL); + ImageWriter writer(*compiler_driver_.get()); bool success_image = writer.Write(tmp_image.GetFilename(), requested_image_base, - tmp_oat->GetPath(), tmp_oat->GetPath(), - *compiler_driver_.get()); + tmp_oat->GetPath(), tmp_oat->GetPath()); ASSERT_TRUE(success_image); bool success_fixup = compiler_driver_->FixupElf(tmp_oat.get(), writer.GetOatDataBegin()); ASSERT_TRUE(success_fixup); @@ -102,6 +92,9 @@ TEST_F(ImageTest, WriteRead) { ASSERT_GE(sizeof(image_header) + space->Size(), static_cast<size_t>(file->GetLength())); } + ASSERT_TRUE(compiler_driver_->GetImageClasses() != NULL); + CompilerDriver::DescriptorSet image_classes(*compiler_driver_->GetImageClasses()); + // Need to delete the compiler since it has worker threads which are attached to runtime. compiler_driver_.reset(); @@ -149,7 +142,13 @@ TEST_F(ImageTest, WriteRead) { mirror::Class* klass = class_linker_->FindSystemClass(descriptor); EXPECT_TRUE(klass != NULL) << descriptor; EXPECT_LT(image_begin, reinterpret_cast<byte*>(klass)) << descriptor; - EXPECT_LT(reinterpret_cast<byte*>(klass), image_end) << descriptor; + if (image_classes.find(descriptor) != image_classes.end()) { + // image classes should be located before the end of the image. + EXPECT_LT(reinterpret_cast<byte*>(klass), image_end) << descriptor; + } else { + // non image classes should be in a space after the image. + EXPECT_GT(reinterpret_cast<byte*>(klass), image_end) << descriptor; + } EXPECT_EQ(*klass->GetRawLockWordAddress(), 0); // address should have been removed from monitor } } diff --git a/src/image_writer.cc b/src/image_writer.cc index 4ba99fe3d0..5a1ebbbcfd 100644 --- a/src/image_writer.cc +++ b/src/image_writer.cc @@ -57,8 +57,7 @@ namespace art { bool ImageWriter::Write(const std::string& image_filename, uintptr_t image_begin, const std::string& oat_filename, - const std::string& oat_location, - const CompilerDriver& compiler_driver) { + const std::string& oat_location) { CHECK(!image_filename.empty()); CHECK_NE(image_begin, 0U); @@ -114,10 +113,10 @@ bool ImageWriter::Write(const std::string& image_filename, Thread::Current()->TransitionFromSuspendedToRunnable(); size_t oat_loaded_size = 0; size_t oat_data_offset = 0; - compiler_driver.GetOatElfInformation(oat_file.get(), oat_loaded_size, oat_data_offset); + compiler_driver_.GetOatElfInformation(oat_file.get(), oat_loaded_size, oat_data_offset); CalculateNewObjectOffsets(oat_loaded_size, oat_data_offset); CopyAndFixupObjects(); - PatchOatCodeAndMethods(compiler_driver); + PatchOatCodeAndMethods(); Thread::Current()->TransitionFromRunnableToSuspended(kNative); UniquePtr<File> image_file(OS::OpenFile(image_filename.c_str(), true)); @@ -199,42 +198,21 @@ void ImageWriter::ComputeEagerResolvedStrings() } bool ImageWriter::IsImageClass(const Class* klass) { - if (image_classes_ == NULL) { - return true; - } - while (klass->IsArrayClass()) { - klass = klass->GetComponentType(); - } - if (klass->IsPrimitive()) { - return true; - } - const std::string descriptor(ClassHelper(klass).GetDescriptor()); - return image_classes_->find(descriptor) != image_classes_->end(); + return compiler_driver_.IsImageClass(ClassHelper(klass).GetDescriptor()); } - struct NonImageClasses { ImageWriter* image_writer; std::set<std::string>* non_image_classes; }; void ImageWriter::PruneNonImageClasses() { - if (image_classes_ == NULL) { + if (compiler_driver_.GetImageClasses() == NULL) { return; } Runtime* runtime = Runtime::Current(); ClassLinker* class_linker = runtime->GetClassLinker(); - // Update image_classes_ with classes for objects created by <clinit> methods. - Thread* self = Thread::Current(); - const char* old_cause = self->StartAssertNoThreadSuspension("ImageWriter"); - Heap* heap = Runtime::Current()->GetHeap(); - // TODO: Image spaces only? - WriterMutexLock mu(self, *Locks::heap_bitmap_lock_); - heap->FlushAllocStack(); - heap->GetLiveBitmap()->Walk(FindClinitImageClassesCallback, this); - self->EndAssertNoThreadSuspension(old_cause); - // Make a list of classes we would like to prune. std::set<std::string> non_image_classes; NonImageClasses context; @@ -275,28 +253,6 @@ void ImageWriter::PruneNonImageClasses() { } } -void ImageWriter::FindClinitImageClassesCallback(Object* object, void* arg) { - DCHECK(object != NULL); - DCHECK(arg != NULL); - ImageWriter* image_writer = reinterpret_cast<ImageWriter*>(arg); - Class* klass = object->GetClass(); - while (klass->IsArrayClass()) { - klass = klass->GetComponentType(); - } - if (klass->IsPrimitive()) { - return; - } - while (!klass->IsObjectClass()) { - ClassHelper kh(klass); - const char* descriptor = kh.GetDescriptor(); - std::pair<DescriptorSet::iterator, bool> result = image_writer->image_classes_->insert(descriptor); - if (result.second) { - LOG(INFO) << "Adding " << descriptor << " to image classes"; - } - klass = klass->GetSuperClass(); - } -} - bool ImageWriter::NonImageClassesVisitor(Class* klass, void* arg) { NonImageClasses* context = reinterpret_cast<NonImageClasses*>(arg); if (!context->image_writer->IsImageClass(klass)) { @@ -307,7 +263,7 @@ bool ImageWriter::NonImageClassesVisitor(Class* klass, void* arg) { void ImageWriter::CheckNonImageClassesRemoved() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - if (image_classes_ == NULL) { + if (compiler_driver_.GetImageClasses() == NULL) { return; } @@ -336,8 +292,10 @@ void ImageWriter::CheckNonImageClassesRemovedCallback(Object* obj, void* arg) { } void ImageWriter::DumpImageClasses() { + CompilerDriver::DescriptorSet* image_classes = compiler_driver_.GetImageClasses(); + CHECK(image_classes != NULL); typedef std::set<std::string>::const_iterator It; // TODO: C++0x auto - for (It it = image_classes_->begin(), end = image_classes_->end(); it != end; ++it) { + for (It it = image_classes->begin(), end = image_classes->end(); it != end; ++it) { LOG(INFO) << " " << *it; } } @@ -659,13 +617,13 @@ static AbstractMethod* GetTargetMethod(const CompilerDriver::PatchInformation* p return method; } -void ImageWriter::PatchOatCodeAndMethods(const CompilerDriver& compiler) { +void ImageWriter::PatchOatCodeAndMethods() { Thread* self = Thread::Current(); ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); const char* old_cause = self->StartAssertNoThreadSuspension("ImageWriter"); typedef std::vector<const CompilerDriver::PatchInformation*> Patches; - const Patches& code_to_patch = compiler.GetCodeToPatch(); + const Patches& code_to_patch = compiler_driver_.GetCodeToPatch(); for (size_t i = 0; i < code_to_patch.size(); i++) { const CompilerDriver::PatchInformation* patch = code_to_patch[i]; AbstractMethod* target = GetTargetMethod(patch); @@ -675,7 +633,7 @@ void ImageWriter::PatchOatCodeAndMethods(const CompilerDriver& compiler) { SetPatchLocation(patch, reinterpret_cast<uint32_t>(GetOatAddress(code_offset))); } - const Patches& methods_to_patch = compiler.GetMethodsToPatch(); + const Patches& methods_to_patch = compiler_driver_.GetMethodsToPatch(); for (size_t i = 0; i < methods_to_patch.size(); i++) { const CompilerDriver::PatchInformation* patch = methods_to_patch[i]; AbstractMethod* target = GetTargetMethod(patch); diff --git a/src/image_writer.h b/src/image_writer.h index 4628e5a05f..4507592353 100644 --- a/src/image_writer.h +++ b/src/image_writer.h @@ -37,9 +37,8 @@ namespace art { // Write a Space built during compilation for use during execution. class ImageWriter { public: - typedef std::set<std::string> DescriptorSet; - explicit ImageWriter(DescriptorSet* image_classes) - : oat_file_(NULL), image_end_(0), image_begin_(NULL), image_classes_(image_classes), + explicit ImageWriter(const CompilerDriver& compiler_driver) + : compiler_driver_(compiler_driver), oat_file_(NULL), image_end_(0), image_begin_(NULL), oat_data_begin_(NULL), interpreter_to_interpreter_entry_offset_(0), interpreter_to_quick_entry_offset_(0), portable_resolution_trampoline_offset_(0), quick_resolution_trampoline_offset_(0) {} @@ -49,8 +48,7 @@ class ImageWriter { bool Write(const std::string& image_filename, uintptr_t image_begin, const std::string& oat_filename, - const std::string& oat_location, - const CompilerDriver& compiler_driver) + const std::string& oat_location) LOCKS_EXCLUDED(Locks::mutator_lock_); uintptr_t GetOatDataBegin() { @@ -132,8 +130,6 @@ class ImageWriter { // Remove unwanted classes from various roots. void PruneNonImageClasses() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - static void FindClinitImageClassesCallback(mirror::Object* object, void* arg) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); static bool NonImageClassesVisitor(mirror::Class* c, void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); @@ -172,12 +168,14 @@ class ImageWriter { SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Patches references in OatFile to expect runtime addresses. - void PatchOatCodeAndMethods(const CompilerDriver& compiler) + void PatchOatCodeAndMethods() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); void SetPatchLocation(const CompilerDriver::PatchInformation* patch, uint32_t value) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + const CompilerDriver& compiler_driver_; + // Map of Object to where it will be at runtime. SafeMap<const mirror::Object*, size_t> offsets_; @@ -193,9 +191,6 @@ class ImageWriter { // Beginning target image address for the output image. byte* image_begin_; - // Set of classes to be include in the image, or NULL for all. - DescriptorSet* image_classes_; - // Beginning target oat address for the pointers from the output image to its oat file. const byte* oat_data_begin_; diff --git a/src/oat_test.cc b/src/oat_test.cc index c7c063a9d1..29e2891b40 100644 --- a/src/oat_test.cc +++ b/src/oat_test.cc @@ -74,8 +74,8 @@ TEST_F(OatTest, WriteRead) { #else CompilerBackend compiler_backend = kQuick; #endif - compiler_driver_.reset(new CompilerDriver(compiler_backend, kThumb2, false, 2, false, - NULL, true, true)); + compiler_driver_.reset(new CompilerDriver(compiler_backend, kThumb2, false, NULL, 2, false, + true, true)); jobject class_loader = NULL; if (compile) { compiler_driver_->CompileAll(class_loader, class_linker->GetBootClassPath()); |