Move image class computation to the CompilerDriver
Change-Id: Ia51cdc199cdeaf409755ab8da23323e204ce041e
diff --git a/src/compiler/driver/compiler_driver.cc b/src/compiler/driver/compiler_driver.cc
index 40cc483..186cf0d 100644
--- a/src/compiler/driver/compiler_driver.cc
+++ b/src/compiler/driver/compiler_driver.cc
@@ -324,8 +324,8 @@
}
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 @@
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 @@
CHECK(!Runtime::Current()->IsStarted());
if (!image_) {
- CHECK(image_classes_ == NULL);
+ CHECK(image_classes_.get() == NULL);
}
}
@@ -576,20 +577,199 @@
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 @@
}
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 @@
"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 @@
"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 @@
"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 @@
// 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 @@
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 @@
} 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)) {