| Elliott Hughes | 2faa5f1 | 2012-01-30 14:42:07 -0800 | [diff] [blame] | 1 | /* | 
 | 2 |  * Copyright (C) 2011 The Android Open Source Project | 
 | 3 |  * | 
 | 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 |  */ | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 16 |  | 
| Brian Carlstrom | 578bbdc | 2011-07-21 14:07:47 -0700 | [diff] [blame] | 17 | #include "class_linker.h" | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 18 |  | 
| Brian Carlstrom | dbc0525 | 2011-09-09 01:59:59 -0700 | [diff] [blame] | 19 | #include <deque> | 
| Ian Rogers | cf7f191 | 2014-10-22 22:06:39 -0700 | [diff] [blame] | 20 | #include <iostream> | 
| Ian Rogers | 700a402 | 2014-05-19 16:49:03 -0700 | [diff] [blame] | 21 | #include <memory> | 
| Fred Shih | 381e4ca | 2014-08-25 17:24:27 -0700 | [diff] [blame] | 22 | #include <queue> | 
| Ian Rogers | 0cfe1fb | 2011-08-26 03:29:44 -0700 | [diff] [blame] | 23 | #include <string> | 
| Andreas Gampe | a696c0a | 2014-12-10 20:51:45 -0800 | [diff] [blame] | 24 | #include <unistd.h> | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 25 | #include <utility> | 
| Elliott Hughes | 90a3369 | 2011-08-30 13:27:07 -0700 | [diff] [blame] | 26 | #include <vector> | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 27 |  | 
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 28 | #include "art_field-inl.h" | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 29 | #include "art_method-inl.h" | 
 | 30 | #include "base/arena_allocator.h" | 
| Elliott Hughes | 1aa246d | 2012-12-13 09:29:36 -0800 | [diff] [blame] | 31 | #include "base/casts.h" | 
| Elliott Hughes | 07ed66b | 2012-12-12 18:34:25 -0800 | [diff] [blame] | 32 | #include "base/logging.h" | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 33 | #include "base/scoped_arena_containers.h" | 
| Narayan Kamath | d1c606f | 2014-06-09 16:50:19 +0100 | [diff] [blame] | 34 | #include "base/scoped_flock.h" | 
| Elliott Hughes | 1aa246d | 2012-12-13 09:29:36 -0800 | [diff] [blame] | 35 | #include "base/stl_util.h" | 
| Vladimir Marko | 80afd02 | 2015-05-19 18:08:00 +0100 | [diff] [blame] | 36 | #include "base/time_utils.h" | 
| Elliott Hughes | 7616005 | 2012-12-12 16:31:20 -0800 | [diff] [blame] | 37 | #include "base/unix_file/fd_file.h" | 
| Andreas Gampe | b9aec2c | 2015-04-23 22:23:47 -0700 | [diff] [blame] | 38 | #include "base/value_object.h" | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 39 | #include "class_linker-inl.h" | 
| Mathieu Chartier | e4275c0 | 2015-08-06 15:34:15 -0700 | [diff] [blame] | 40 | #include "class_table-inl.h" | 
| Vladimir Marko | 2b5eaa2 | 2013-12-13 13:59:30 +0000 | [diff] [blame] | 41 | #include "compiler_callbacks.h" | 
| Elliott Hughes | 4740cdf | 2011-12-07 14:07:12 -0800 | [diff] [blame] | 42 | #include "debugger.h" | 
| Ian Rogers | 4f6ad8a | 2013-03-18 15:27:28 -0700 | [diff] [blame] | 43 | #include "dex_file-inl.h" | 
| Ian Rogers | 6f3dbba | 2014-10-14 17:41:57 -0700 | [diff] [blame] | 44 | #include "entrypoints/runtime_asm_entrypoints.h" | 
| Hiroshi Yamauchi | 94f7b49 | 2014-07-22 18:08:23 -0700 | [diff] [blame] | 45 | #include "gc_root-inl.h" | 
| Ian Rogers | 1d54e73 | 2013-05-02 21:10:01 -0700 | [diff] [blame] | 46 | #include "gc/accounting/card_table-inl.h" | 
 | 47 | #include "gc/accounting/heap_bitmap.h" | 
 | 48 | #include "gc/heap.h" | 
 | 49 | #include "gc/space/image_space.h" | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 50 | #include "handle_scope.h" | 
| Elliott Hughes | cf4c6c4 | 2011-09-01 15:16:42 -0700 | [diff] [blame] | 51 | #include "intern_table.h" | 
| Ian Rogers | 64b6d14 | 2012-10-29 16:34:15 -0700 | [diff] [blame] | 52 | #include "interpreter/interpreter.h" | 
| Mathieu Chartier | e5f13e5 | 2015-02-24 09:37:21 -0800 | [diff] [blame] | 53 | #include "jit/jit.h" | 
 | 54 | #include "jit/jit_code_cache.h" | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 55 | #include "leb128.h" | 
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 56 | #include "linear_alloc.h" | 
| Brian Carlstrom | 700c8d3 | 2012-11-05 10:42:02 -0800 | [diff] [blame] | 57 | #include "oat.h" | 
| Brian Carlstrom | 58ae941 | 2011-10-04 00:56:06 -0700 | [diff] [blame] | 58 | #include "oat_file.h" | 
| Nicolas Geoffray | c04c800 | 2015-07-14 11:37:54 +0100 | [diff] [blame] | 59 | #include "oat_file-inl.h" | 
| Richard Uhler | 66d874d | 2015-01-15 09:37:19 -0800 | [diff] [blame] | 60 | #include "oat_file_assistant.h" | 
| Ian Rogers | 22d5e73 | 2014-07-15 22:23:51 -0700 | [diff] [blame] | 61 | #include "object_lock.h" | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 62 | #include "mirror/class.h" | 
 | 63 | #include "mirror/class-inl.h" | 
 | 64 | #include "mirror/class_loader.h" | 
| Ian Rogers | 39ebcb8 | 2013-05-30 16:57:23 -0700 | [diff] [blame] | 65 | #include "mirror/dex_cache-inl.h" | 
| Mathieu Chartier | daaf326 | 2015-03-24 13:30:28 -0700 | [diff] [blame] | 66 | #include "mirror/field.h" | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 67 | #include "mirror/iftable-inl.h" | 
| Mathieu Chartier | fc58af4 | 2015-04-16 18:00:39 -0700 | [diff] [blame] | 68 | #include "mirror/method.h" | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 69 | #include "mirror/object-inl.h" | 
 | 70 | #include "mirror/object_array-inl.h" | 
 | 71 | #include "mirror/proxy.h" | 
| Fred Shih | 4ee7a66 | 2014-07-11 09:59:27 -0700 | [diff] [blame] | 72 | #include "mirror/reference-inl.h" | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 73 | #include "mirror/stack_trace_element.h" | 
| Mingyao Yang | 98d1cc8 | 2014-05-15 17:02:16 -0700 | [diff] [blame] | 74 | #include "mirror/string-inl.h" | 
| Brian Carlstrom | 5b332c8 | 2012-02-01 15:02:31 -0800 | [diff] [blame] | 75 | #include "os.h" | 
| Brian Carlstrom | 1f87008 | 2011-08-23 16:02:11 -0700 | [diff] [blame] | 76 | #include "runtime.h" | 
| Ian Rogers | 7655f29 | 2013-07-29 11:07:13 -0700 | [diff] [blame] | 77 | #include "entrypoints/entrypoint_utils.h" | 
| Elliott Hughes | 4d0207c | 2011-10-03 19:14:34 -0700 | [diff] [blame] | 78 | #include "ScopedLocalRef.h" | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 79 | #include "scoped_thread_state_change.h" | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 80 | #include "handle_scope-inl.h" | 
| Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 81 | #include "thread-inl.h" | 
| Brian Carlstrom | 578bbdc | 2011-07-21 14:07:47 -0700 | [diff] [blame] | 82 | #include "utils.h" | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 83 | #include "verifier/method_verifier.h" | 
| Elliott Hughes | eac7667 | 2012-05-24 21:56:51 -0700 | [diff] [blame] | 84 | #include "well_known_classes.h" | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 85 |  | 
 | 86 | namespace art { | 
 | 87 |  | 
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 88 | static constexpr bool kSanityCheckObjects = kIsDebugBuild; | 
 | 89 |  | 
| Andreas Gampe | 69b5d8f | 2015-06-03 15:43:16 -0700 | [diff] [blame] | 90 | // For b/21333911. | 
 | 91 | static constexpr bool kDuplicateClassesCheck = false; | 
 | 92 |  | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 93 | static void ThrowNoClassDefFoundError(const char* fmt, ...) | 
 | 94 |     __attribute__((__format__(__printf__, 1, 2))) | 
| Mathieu Chartier | 9044347 | 2015-07-16 20:32:27 -0700 | [diff] [blame] | 95 |     SHARED_REQUIRES(Locks::mutator_lock_); | 
| Elliott Hughes | 0512f02 | 2012-03-15 22:10:52 -0700 | [diff] [blame] | 96 | static void ThrowNoClassDefFoundError(const char* fmt, ...) { | 
| Elliott Hughes | 4a2b417 | 2011-09-20 17:08:25 -0700 | [diff] [blame] | 97 |   va_list args; | 
 | 98 |   va_start(args, fmt); | 
| Ian Rogers | 62d6c77 | 2013-02-27 08:32:07 -0800 | [diff] [blame] | 99 |   Thread* self = Thread::Current(); | 
| Nicolas Geoffray | 0aa50ce | 2015-03-10 11:03:29 +0000 | [diff] [blame] | 100 |   self->ThrowNewExceptionV("Ljava/lang/NoClassDefFoundError;", fmt, args); | 
| Ian Rogers | cab0101 | 2012-01-10 17:35:46 -0800 | [diff] [blame] | 101 |   va_end(args); | 
 | 102 | } | 
 | 103 |  | 
| Mathieu Chartier | 9044347 | 2015-07-16 20:32:27 -0700 | [diff] [blame] | 104 | bool ClassLinker::HasInitWithString(Thread* self, const char* descriptor) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 105 |   ArtMethod* method = self->GetCurrentMethod(nullptr); | 
| Andreas Gampe | bfdcdc1 | 2015-04-22 18:10:36 -0700 | [diff] [blame] | 106 |   StackHandleScope<1> hs(self); | 
 | 107 |   Handle<mirror::ClassLoader> class_loader(hs.NewHandle(method != nullptr ? | 
| Mathieu Chartier | 9044347 | 2015-07-16 20:32:27 -0700 | [diff] [blame] | 108 |       method->GetDeclaringClass()->GetClassLoader() : nullptr)); | 
 | 109 |   mirror::Class* exception_class = FindClass(self, descriptor, class_loader); | 
| Andreas Gampe | bfdcdc1 | 2015-04-22 18:10:36 -0700 | [diff] [blame] | 110 |  | 
 | 111 |   if (exception_class == nullptr) { | 
 | 112 |     // No exc class ~ no <init>-with-string. | 
 | 113 |     CHECK(self->IsExceptionPending()); | 
 | 114 |     self->ClearException(); | 
 | 115 |     return false; | 
 | 116 |   } | 
 | 117 |  | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 118 |   ArtMethod* exception_init_method = exception_class->FindDeclaredDirectMethod( | 
 | 119 |       "<init>", "(Ljava/lang/String;)V", image_pointer_size_); | 
| Andreas Gampe | bfdcdc1 | 2015-04-22 18:10:36 -0700 | [diff] [blame] | 120 |   return exception_init_method != nullptr; | 
 | 121 | } | 
 | 122 |  | 
 | 123 | void ClassLinker::ThrowEarlierClassFailure(mirror::Class* c) { | 
| Elliott Hughes | 5c59994 | 2012-06-13 16:45:05 -0700 | [diff] [blame] | 124 |   // The class failed to initialize on a previous attempt, so we want to throw | 
 | 125 |   // a NoClassDefFoundError (v2 2.17.5).  The exception to this rule is if we | 
 | 126 |   // failed in verification, in which case v2 5.4.1 says we need to re-throw | 
 | 127 |   // the previous error. | 
| Mathieu Chartier | e5f13e5 | 2015-02-24 09:37:21 -0800 | [diff] [blame] | 128 |   Runtime* const runtime = Runtime::Current(); | 
 | 129 |   if (!runtime->IsAotCompiler()) {  // Give info if this occurs at runtime. | 
| Ian Rogers | 87e552d | 2012-08-31 15:54:48 -0700 | [diff] [blame] | 130 |     LOG(INFO) << "Rejecting re-init on previously-failed class " << PrettyClass(c); | 
 | 131 |   } | 
| Elliott Hughes | 4a2b417 | 2011-09-20 17:08:25 -0700 | [diff] [blame] | 132 |  | 
| Elliott Hughes | 5c59994 | 2012-06-13 16:45:05 -0700 | [diff] [blame] | 133 |   CHECK(c->IsErroneous()) << PrettyClass(c) << " " << c->GetStatus(); | 
| Ian Rogers | 62d6c77 | 2013-02-27 08:32:07 -0800 | [diff] [blame] | 134 |   Thread* self = Thread::Current(); | 
| Mathieu Chartier | e5f13e5 | 2015-02-24 09:37:21 -0800 | [diff] [blame] | 135 |   if (runtime->IsAotCompiler()) { | 
| Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 136 |     // At compile time, accurate errors and NCDFE are disabled to speed compilation. | 
 | 137 |     mirror::Throwable* pre_allocated = runtime->GetPreAllocatedNoClassDefFoundError(); | 
| Nicolas Geoffray | 14691c5 | 2015-03-05 10:40:17 +0000 | [diff] [blame] | 138 |     self->SetException(pre_allocated); | 
| Elliott Hughes | 4a2b417 | 2011-09-20 17:08:25 -0700 | [diff] [blame] | 139 |   } else { | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 140 |     if (c->GetVerifyErrorClass() != nullptr) { | 
| Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 141 |       // TODO: change the verifier to store an _instance_, with a useful detail message? | 
| Andreas Gampe | bfdcdc1 | 2015-04-22 18:10:36 -0700 | [diff] [blame] | 142 |       // It's possible the exception doesn't have a <init>(String). | 
| Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 143 |       std::string temp; | 
| Andreas Gampe | bfdcdc1 | 2015-04-22 18:10:36 -0700 | [diff] [blame] | 144 |       const char* descriptor = c->GetVerifyErrorClass()->GetDescriptor(&temp); | 
 | 145 |  | 
| Mathieu Chartier | 9044347 | 2015-07-16 20:32:27 -0700 | [diff] [blame] | 146 |       if (HasInitWithString(self, descriptor)) { | 
| Andreas Gampe | bfdcdc1 | 2015-04-22 18:10:36 -0700 | [diff] [blame] | 147 |         self->ThrowNewException(descriptor, PrettyDescriptor(c).c_str()); | 
 | 148 |       } else { | 
 | 149 |         self->ThrowNewException(descriptor, nullptr); | 
 | 150 |       } | 
| Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 151 |     } else { | 
| Nicolas Geoffray | 0aa50ce | 2015-03-10 11:03:29 +0000 | [diff] [blame] | 152 |       self->ThrowNewException("Ljava/lang/NoClassDefFoundError;", | 
| Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 153 |                               PrettyDescriptor(c).c_str()); | 
 | 154 |     } | 
| Elliott Hughes | 4a2b417 | 2011-09-20 17:08:25 -0700 | [diff] [blame] | 155 |   } | 
 | 156 | } | 
 | 157 |  | 
| Brian Carlstrom | b23eab1 | 2014-10-08 17:55:21 -0700 | [diff] [blame] | 158 | static void VlogClassInitializationFailure(Handle<mirror::Class> klass) | 
| Mathieu Chartier | 9044347 | 2015-07-16 20:32:27 -0700 | [diff] [blame] | 159 |     SHARED_REQUIRES(Locks::mutator_lock_) { | 
| Brian Carlstrom | b23eab1 | 2014-10-08 17:55:21 -0700 | [diff] [blame] | 160 |   if (VLOG_IS_ON(class_linker)) { | 
 | 161 |     std::string temp; | 
 | 162 |     LOG(INFO) << "Failed to initialize class " << klass->GetDescriptor(&temp) << " from " | 
| Nicolas Geoffray | 14691c5 | 2015-03-05 10:40:17 +0000 | [diff] [blame] | 163 |               << klass->GetLocation() << "\n" << Thread::Current()->GetException()->Dump(); | 
| Brian Carlstrom | b23eab1 | 2014-10-08 17:55:21 -0700 | [diff] [blame] | 164 |   } | 
 | 165 | } | 
 | 166 |  | 
 | 167 | static void WrapExceptionInInitializer(Handle<mirror::Class> klass) | 
| Mathieu Chartier | 9044347 | 2015-07-16 20:32:27 -0700 | [diff] [blame] | 168 |     SHARED_REQUIRES(Locks::mutator_lock_) { | 
| Elliott Hughes | a4f9474 | 2012-05-29 16:28:38 -0700 | [diff] [blame] | 169 |   Thread* self = Thread::Current(); | 
 | 170 |   JNIEnv* env = self->GetJniEnv(); | 
| Elliott Hughes | 4d0207c | 2011-10-03 19:14:34 -0700 | [diff] [blame] | 171 |  | 
 | 172 |   ScopedLocalRef<jthrowable> cause(env, env->ExceptionOccurred()); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 173 |   CHECK(cause.get() != nullptr); | 
| Elliott Hughes | 4d0207c | 2011-10-03 19:14:34 -0700 | [diff] [blame] | 174 |  | 
 | 175 |   env->ExceptionClear(); | 
| Elliott Hughes | a4f9474 | 2012-05-29 16:28:38 -0700 | [diff] [blame] | 176 |   bool is_error = env->IsInstanceOf(cause.get(), WellKnownClasses::java_lang_Error); | 
 | 177 |   env->Throw(cause.get()); | 
| Elliott Hughes | 4d0207c | 2011-10-03 19:14:34 -0700 | [diff] [blame] | 178 |  | 
| Elliott Hughes | a4f9474 | 2012-05-29 16:28:38 -0700 | [diff] [blame] | 179 |   // We only wrap non-Error exceptions; an Error can just be used as-is. | 
 | 180 |   if (!is_error) { | 
| Nicolas Geoffray | 0aa50ce | 2015-03-10 11:03:29 +0000 | [diff] [blame] | 181 |     self->ThrowNewWrappedException("Ljava/lang/ExceptionInInitializerError;", nullptr); | 
| Elliott Hughes | 4d0207c | 2011-10-03 19:14:34 -0700 | [diff] [blame] | 182 |   } | 
| Brian Carlstrom | b23eab1 | 2014-10-08 17:55:21 -0700 | [diff] [blame] | 183 |   VlogClassInitializationFailure(klass); | 
| Elliott Hughes | 4d0207c | 2011-10-03 19:14:34 -0700 | [diff] [blame] | 184 | } | 
 | 185 |  | 
| Fred Shih | 381e4ca | 2014-08-25 17:24:27 -0700 | [diff] [blame] | 186 | // Gap between two fields in object layout. | 
 | 187 | struct FieldGap { | 
 | 188 |   uint32_t start_offset;  // The offset from the start of the object. | 
 | 189 |   uint32_t size;  // The gap size of 1, 2, or 4 bytes. | 
 | 190 | }; | 
 | 191 | struct FieldGapsComparator { | 
 | 192 |   explicit FieldGapsComparator() { | 
 | 193 |   } | 
 | 194 |   bool operator() (const FieldGap& lhs, const FieldGap& rhs) | 
 | 195 |       NO_THREAD_SAFETY_ANALYSIS { | 
| Andreas Gampe | f52857f | 2015-02-18 15:38:57 -0800 | [diff] [blame] | 196 |     // Sort by gap size, largest first. Secondary sort by starting offset. | 
| Richard Uhler | fab6788 | 2015-07-13 17:00:35 -0700 | [diff] [blame] | 197 |     // Note that the priority queue returns the largest element, so operator() | 
 | 198 |     // should return true if lhs is less than rhs. | 
 | 199 |     return lhs.size < rhs.size || (lhs.size == rhs.size && lhs.start_offset > rhs.start_offset); | 
| Fred Shih | 381e4ca | 2014-08-25 17:24:27 -0700 | [diff] [blame] | 200 |   } | 
 | 201 | }; | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 202 | typedef std::priority_queue<FieldGap, std::vector<FieldGap>, FieldGapsComparator> FieldGaps; | 
| Fred Shih | 381e4ca | 2014-08-25 17:24:27 -0700 | [diff] [blame] | 203 |  | 
 | 204 | // Adds largest aligned gaps to queue of gaps. | 
| Andreas Gampe | 277ccbd | 2014-11-03 21:36:10 -0800 | [diff] [blame] | 205 | static void AddFieldGap(uint32_t gap_start, uint32_t gap_end, FieldGaps* gaps) { | 
| Fred Shih | 381e4ca | 2014-08-25 17:24:27 -0700 | [diff] [blame] | 206 |   DCHECK(gaps != nullptr); | 
 | 207 |  | 
 | 208 |   uint32_t current_offset = gap_start; | 
 | 209 |   while (current_offset != gap_end) { | 
 | 210 |     size_t remaining = gap_end - current_offset; | 
 | 211 |     if (remaining >= sizeof(uint32_t) && IsAligned<4>(current_offset)) { | 
 | 212 |       gaps->push(FieldGap {current_offset, sizeof(uint32_t)}); | 
 | 213 |       current_offset += sizeof(uint32_t); | 
 | 214 |     } else if (remaining >= sizeof(uint16_t) && IsAligned<2>(current_offset)) { | 
 | 215 |       gaps->push(FieldGap {current_offset, sizeof(uint16_t)}); | 
 | 216 |       current_offset += sizeof(uint16_t); | 
 | 217 |     } else { | 
 | 218 |       gaps->push(FieldGap {current_offset, sizeof(uint8_t)}); | 
 | 219 |       current_offset += sizeof(uint8_t); | 
 | 220 |     } | 
 | 221 |     DCHECK_LE(current_offset, gap_end) << "Overran gap"; | 
 | 222 |   } | 
 | 223 | } | 
 | 224 | // Shuffle fields forward, making use of gaps whenever possible. | 
 | 225 | template<int n> | 
| Vladimir Marko | 76649e8 | 2014-11-10 18:32:59 +0000 | [diff] [blame] | 226 | static void ShuffleForward(size_t* current_field_idx, | 
| Fred Shih | 381e4ca | 2014-08-25 17:24:27 -0700 | [diff] [blame] | 227 |                            MemberOffset* field_offset, | 
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 228 |                            std::deque<ArtField*>* grouped_and_sorted_fields, | 
| Fred Shih | 381e4ca | 2014-08-25 17:24:27 -0700 | [diff] [blame] | 229 |                            FieldGaps* gaps) | 
| Mathieu Chartier | 9044347 | 2015-07-16 20:32:27 -0700 | [diff] [blame] | 230 |     SHARED_REQUIRES(Locks::mutator_lock_) { | 
| Fred Shih | 381e4ca | 2014-08-25 17:24:27 -0700 | [diff] [blame] | 231 |   DCHECK(current_field_idx != nullptr); | 
 | 232 |   DCHECK(grouped_and_sorted_fields != nullptr); | 
| Fred Shih | 381e4ca | 2014-08-25 17:24:27 -0700 | [diff] [blame] | 233 |   DCHECK(gaps != nullptr); | 
 | 234 |   DCHECK(field_offset != nullptr); | 
 | 235 |  | 
 | 236 |   DCHECK(IsPowerOfTwo(n)); | 
 | 237 |   while (!grouped_and_sorted_fields->empty()) { | 
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 238 |     ArtField* field = grouped_and_sorted_fields->front(); | 
| Fred Shih | 381e4ca | 2014-08-25 17:24:27 -0700 | [diff] [blame] | 239 |     Primitive::Type type = field->GetTypeAsPrimitiveType(); | 
 | 240 |     if (Primitive::ComponentSize(type) < n) { | 
 | 241 |       break; | 
 | 242 |     } | 
 | 243 |     if (!IsAligned<n>(field_offset->Uint32Value())) { | 
 | 244 |       MemberOffset old_offset = *field_offset; | 
 | 245 |       *field_offset = MemberOffset(RoundUp(field_offset->Uint32Value(), n)); | 
 | 246 |       AddFieldGap(old_offset.Uint32Value(), field_offset->Uint32Value(), gaps); | 
 | 247 |     } | 
 | 248 |     CHECK(type != Primitive::kPrimNot) << PrettyField(field);  // should be primitive types | 
 | 249 |     grouped_and_sorted_fields->pop_front(); | 
| Fred Shih | 381e4ca | 2014-08-25 17:24:27 -0700 | [diff] [blame] | 250 |     if (!gaps->empty() && gaps->top().size >= n) { | 
 | 251 |       FieldGap gap = gaps->top(); | 
 | 252 |       gaps->pop(); | 
| Roland Levillain | 14d9057 | 2015-07-16 10:52:26 +0100 | [diff] [blame] | 253 |       DCHECK_ALIGNED(gap.start_offset, n); | 
| Fred Shih | 381e4ca | 2014-08-25 17:24:27 -0700 | [diff] [blame] | 254 |       field->SetOffset(MemberOffset(gap.start_offset)); | 
 | 255 |       if (gap.size > n) { | 
 | 256 |         AddFieldGap(gap.start_offset + n, gap.start_offset + gap.size, gaps); | 
 | 257 |       } | 
 | 258 |     } else { | 
| Roland Levillain | 14d9057 | 2015-07-16 10:52:26 +0100 | [diff] [blame] | 259 |       DCHECK_ALIGNED(field_offset->Uint32Value(), n); | 
| Fred Shih | 381e4ca | 2014-08-25 17:24:27 -0700 | [diff] [blame] | 260 |       field->SetOffset(*field_offset); | 
 | 261 |       *field_offset = MemberOffset(field_offset->Uint32Value() + n); | 
 | 262 |     } | 
 | 263 |     ++(*current_field_idx); | 
 | 264 |   } | 
 | 265 | } | 
 | 266 |  | 
| Elliott Hughes | 4dd9b4d | 2011-12-12 18:29:24 -0800 | [diff] [blame] | 267 | ClassLinker::ClassLinker(InternTable* intern_table) | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 268 |     // dex_lock_ is recursive as it may be used in stack dumping. | 
| Ian Rogers | 1bf8d4d | 2013-05-30 00:18:49 -0700 | [diff] [blame] | 269 |     : dex_lock_("ClassLinker dex lock", kDefaultMutexLevel), | 
| Ian Rogers | 7dfb28c | 2013-08-22 08:18:36 -0700 | [diff] [blame] | 270 |       dex_cache_image_class_lookup_required_(false), | 
 | 271 |       failed_dex_cache_class_lookups_(0), | 
| Ian Rogers | 9837939 | 2014-02-24 16:53:16 -0800 | [diff] [blame] | 272 |       class_roots_(nullptr), | 
 | 273 |       array_iftable_(nullptr), | 
 | 274 |       find_array_class_cache_next_victim_(0), | 
| Elliott Hughes | cf4c6c4 | 2011-09-01 15:16:42 -0700 | [diff] [blame] | 275 |       init_done_(false), | 
| Mathieu Chartier | 893263b | 2014-03-04 11:07:42 -0800 | [diff] [blame] | 276 |       log_new_class_table_roots_(false), | 
| Jeff Hao | 0aba0ba | 2013-06-03 14:49:28 -0700 | [diff] [blame] | 277 |       intern_table_(intern_table), | 
| Ian Rogers | 9837939 | 2014-02-24 16:53:16 -0800 | [diff] [blame] | 278 |       quick_resolution_trampoline_(nullptr), | 
| Andreas Gampe | 2da8823 | 2014-02-27 12:26:20 -0800 | [diff] [blame] | 279 |       quick_imt_conflict_trampoline_(nullptr), | 
| Vladimir Marko | 8a63057 | 2014-04-09 18:45:35 +0100 | [diff] [blame] | 280 |       quick_generic_jni_trampoline_(nullptr), | 
| Mathieu Chartier | 2d72101 | 2014-11-10 11:08:06 -0800 | [diff] [blame] | 281 |       quick_to_interpreter_bridge_trampoline_(nullptr), | 
 | 282 |       image_pointer_size_(sizeof(void*)) { | 
| Mathieu Chartier | bb87e0f | 2015-04-03 11:21:55 -0700 | [diff] [blame] | 283 |   CHECK(intern_table_ != nullptr); | 
| Andreas Gampe | 8ac7595 | 2015-06-02 21:01:45 -0700 | [diff] [blame] | 284 |   static_assert(kFindArrayCacheSize == arraysize(find_array_class_cache_), | 
 | 285 |                 "Array cache size wrong."); | 
 | 286 |   std::fill_n(find_array_class_cache_, kFindArrayCacheSize, GcRoot<mirror::Class>(nullptr)); | 
| Brian Carlstrom | 9ea1cb1 | 2011-08-24 23:18:18 -0700 | [diff] [blame] | 287 | } | 
| Brian Carlstrom | a663ea5 | 2011-08-19 23:33:41 -0700 | [diff] [blame] | 288 |  | 
| Richard Uhler | fbef44d | 2014-12-23 09:48:51 -0800 | [diff] [blame] | 289 | void ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> boot_class_path) { | 
| Brian Carlstrom | a004aa9 | 2012-02-08 18:05:09 -0800 | [diff] [blame] | 290 |   VLOG(startup) << "ClassLinker::Init"; | 
| Brian Carlstrom | 0a5b14d | 2011-09-27 13:29:15 -0700 | [diff] [blame] | 291 |  | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 292 |   Thread* const self = Thread::Current(); | 
 | 293 |   Runtime* const runtime = Runtime::Current(); | 
 | 294 |   gc::Heap* const heap = runtime->GetHeap(); | 
 | 295 |  | 
 | 296 |   CHECK(!heap->HasImageSpace()) << "Runtime has image. We should use it."; | 
| Elliott Hughes | d8ddfd5 | 2011-08-15 14:32:53 -0700 | [diff] [blame] | 297 |   CHECK(!init_done_); | 
| Brian Carlstrom | 578bbdc | 2011-07-21 14:07:47 -0700 | [diff] [blame] | 298 |  | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 299 |   // Use the pointer size from the runtime since we are probably creating the image. | 
 | 300 |   image_pointer_size_ = InstructionSetPointerSize(runtime->GetInstructionSet()); | 
 | 301 |  | 
| Elliott Hughes | 3064683 | 2011-10-13 16:59:46 -0700 | [diff] [blame] | 302 |   // java_lang_Class comes first, it's needed for AllocClass | 
| Mathieu Chartier | 590fee9 | 2013-09-13 13:46:47 -0700 | [diff] [blame] | 303 |   // The GC can't handle an object with a null class since we can't get the size of this object. | 
| Mathieu Chartier | 1d27b34 | 2014-01-28 12:51:09 -0800 | [diff] [blame] | 304 |   heap->IncrementDisableMovingGC(self); | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 305 |   StackHandleScope<64> hs(self);  // 64 is picked arbitrarily. | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 306 |   auto class_class_size = mirror::Class::ClassClassSize(image_pointer_size_); | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 307 |   Handle<mirror::Class> java_lang_Class(hs.NewHandle(down_cast<mirror::Class*>( | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 308 |       heap->AllocNonMovableObject<true>(self, nullptr, class_class_size, VoidFunctor())))); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 309 |   CHECK(java_lang_Class.Get() != nullptr); | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 310 |   mirror::Class::SetClassClass(java_lang_Class.Get()); | 
 | 311 |   java_lang_Class->SetClass(java_lang_Class.Get()); | 
| Hiroshi Yamauchi | 624468c | 2014-03-31 15:14:47 -0700 | [diff] [blame] | 312 |   if (kUseBakerOrBrooksReadBarrier) { | 
 | 313 |     java_lang_Class->AssertReadBarrierPointer(); | 
| Hiroshi Yamauchi | 9d04a20 | 2014-01-31 13:35:49 -0800 | [diff] [blame] | 314 |   } | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 315 |   java_lang_Class->SetClassSize(class_class_size); | 
| Hiroshi Yamauchi | f0edfc3 | 2014-09-25 11:46:46 -0700 | [diff] [blame] | 316 |   java_lang_Class->SetPrimitiveType(Primitive::kPrimNot); | 
| Mathieu Chartier | 1d27b34 | 2014-01-28 12:51:09 -0800 | [diff] [blame] | 317 |   heap->DecrementDisableMovingGC(self); | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 318 |   // AllocClass(mirror::Class*) can now be used | 
| Brian Carlstrom | a080803 | 2011-07-18 00:39:23 -0700 | [diff] [blame] | 319 |  | 
| Elliott Hughes | 418d20f | 2011-09-22 14:00:39 -0700 | [diff] [blame] | 320 |   // Class[] is used for reflection support. | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 321 |   auto class_array_class_size = mirror::ObjectArray<mirror::Class>::ClassSize(image_pointer_size_); | 
| Mingyao Yang | 98d1cc8 | 2014-05-15 17:02:16 -0700 | [diff] [blame] | 322 |   Handle<mirror::Class> class_array_class(hs.NewHandle( | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 323 |       AllocClass(self, java_lang_Class.Get(), class_array_class_size))); | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 324 |   class_array_class->SetComponentType(java_lang_Class.Get()); | 
| Elliott Hughes | 418d20f | 2011-09-22 14:00:39 -0700 | [diff] [blame] | 325 |  | 
| Ian Rogers | 23435d0 | 2012-09-24 11:23:12 -0700 | [diff] [blame] | 326 |   // java_lang_Object comes next so that object_array_class can be created. | 
| Mingyao Yang | 98d1cc8 | 2014-05-15 17:02:16 -0700 | [diff] [blame] | 327 |   Handle<mirror::Class> java_lang_Object(hs.NewHandle( | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 328 |       AllocClass(self, java_lang_Class.Get(), mirror::Object::ClassSize(image_pointer_size_)))); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 329 |   CHECK(java_lang_Object.Get() != nullptr); | 
| Ian Rogers | 23435d0 | 2012-09-24 11:23:12 -0700 | [diff] [blame] | 330 |   // backfill Object as the super class of Class. | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 331 |   java_lang_Class->SetSuperClass(java_lang_Object.Get()); | 
| Hiroshi Yamauchi | 5b783e6 | 2015-03-18 17:20:11 -0700 | [diff] [blame] | 332 |   mirror::Class::SetStatus(java_lang_Object, mirror::Class::kStatusLoaded, self); | 
| Brian Carlstrom | a080803 | 2011-07-18 00:39:23 -0700 | [diff] [blame] | 333 |  | 
| Mathieu Chartier | 673ed3d | 2015-08-28 14:56:43 -0700 | [diff] [blame^] | 334 |   java_lang_Object->SetObjectSize(sizeof(mirror::Object)); | 
 | 335 |   runtime->SetSentinel(heap->AllocObject<true>(self, | 
 | 336 |                                                java_lang_Object.Get(), | 
 | 337 |                                                java_lang_Object->GetObjectSize(), | 
 | 338 |                                                VoidFunctor())); | 
 | 339 |  | 
| Ian Rogers | 23435d0 | 2012-09-24 11:23:12 -0700 | [diff] [blame] | 340 |   // Object[] next to hold class roots. | 
| Mingyao Yang | 98d1cc8 | 2014-05-15 17:02:16 -0700 | [diff] [blame] | 341 |   Handle<mirror::Class> object_array_class(hs.NewHandle( | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 342 |       AllocClass(self, java_lang_Class.Get(), | 
 | 343 |                  mirror::ObjectArray<mirror::Object>::ClassSize(image_pointer_size_)))); | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 344 |   object_array_class->SetComponentType(java_lang_Object.Get()); | 
| Brian Carlstrom | a080803 | 2011-07-18 00:39:23 -0700 | [diff] [blame] | 345 |  | 
| Mingyao Yang | 98d1cc8 | 2014-05-15 17:02:16 -0700 | [diff] [blame] | 346 |   // Setup the char (primitive) class to be used for char[]. | 
 | 347 |   Handle<mirror::Class> char_class(hs.NewHandle( | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 348 |       AllocClass(self, java_lang_Class.Get(), | 
 | 349 |                  mirror::Class::PrimitiveClassSize(image_pointer_size_)))); | 
| Hiroshi Yamauchi | f0edfc3 | 2014-09-25 11:46:46 -0700 | [diff] [blame] | 350 |   // The primitive char class won't be initialized by | 
 | 351 |   // InitializePrimitiveClass until line 459, but strings (and | 
 | 352 |   // internal char arrays) will be allocated before that and the | 
 | 353 |   // component size, which is computed from the primitive type, needs | 
 | 354 |   // to be set here. | 
 | 355 |   char_class->SetPrimitiveType(Primitive::kPrimChar); | 
| Brian Carlstrom | 5b8e4c8 | 2011-09-18 01:38:59 -0700 | [diff] [blame] | 356 |  | 
| Ian Rogers | 23435d0 | 2012-09-24 11:23:12 -0700 | [diff] [blame] | 357 |   // Setup the char[] class to be used for String. | 
| Mingyao Yang | 98d1cc8 | 2014-05-15 17:02:16 -0700 | [diff] [blame] | 358 |   Handle<mirror::Class> char_array_class(hs.NewHandle( | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 359 |       AllocClass(self, java_lang_Class.Get(), mirror::Array::ClassSize(image_pointer_size_)))); | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 360 |   char_array_class->SetComponentType(char_class.Get()); | 
 | 361 |   mirror::CharArray::SetArrayClass(char_array_class.Get()); | 
| Brian Carlstrom | 9cff8e1 | 2011-08-18 16:47:29 -0700 | [diff] [blame] | 362 |  | 
| Ian Rogers | 23435d0 | 2012-09-24 11:23:12 -0700 | [diff] [blame] | 363 |   // Setup String. | 
| Mingyao Yang | 98d1cc8 | 2014-05-15 17:02:16 -0700 | [diff] [blame] | 364 |   Handle<mirror::Class> java_lang_String(hs.NewHandle( | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 365 |       AllocClass(self, java_lang_Class.Get(), mirror::String::ClassSize(image_pointer_size_)))); | 
| Mathieu Chartier | 52a7f5c | 2015-08-18 18:35:52 -0700 | [diff] [blame] | 366 |   java_lang_String->SetStringClass(); | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 367 |   mirror::String::SetClass(java_lang_String.Get()); | 
| Hiroshi Yamauchi | 5b783e6 | 2015-03-18 17:20:11 -0700 | [diff] [blame] | 368 |   mirror::Class::SetStatus(java_lang_String, mirror::Class::kStatusResolved, self); | 
| Jesse Wilson | 1415074 | 2011-07-29 19:04:44 -0400 | [diff] [blame] | 369 |  | 
| Mathieu Chartier | daaf326 | 2015-03-24 13:30:28 -0700 | [diff] [blame] | 370 |   // Setup java.lang.ref.Reference. | 
| Fred Shih | 4ee7a66 | 2014-07-11 09:59:27 -0700 | [diff] [blame] | 371 |   Handle<mirror::Class> java_lang_ref_Reference(hs.NewHandle( | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 372 |       AllocClass(self, java_lang_Class.Get(), mirror::Reference::ClassSize(image_pointer_size_)))); | 
| Fred Shih | 4ee7a66 | 2014-07-11 09:59:27 -0700 | [diff] [blame] | 373 |   mirror::Reference::SetClass(java_lang_ref_Reference.Get()); | 
 | 374 |   java_lang_ref_Reference->SetObjectSize(mirror::Reference::InstanceSize()); | 
| Hiroshi Yamauchi | 5b783e6 | 2015-03-18 17:20:11 -0700 | [diff] [blame] | 375 |   mirror::Class::SetStatus(java_lang_ref_Reference, mirror::Class::kStatusResolved, self); | 
| Fred Shih | 4ee7a66 | 2014-07-11 09:59:27 -0700 | [diff] [blame] | 376 |  | 
| Ian Rogers | 23435d0 | 2012-09-24 11:23:12 -0700 | [diff] [blame] | 377 |   // Create storage for root classes, save away our work so far (requires descriptors). | 
| Mathieu Chartier | daaf326 | 2015-03-24 13:30:28 -0700 | [diff] [blame] | 378 |   class_roots_ = GcRoot<mirror::ObjectArray<mirror::Class>>( | 
| Hiroshi Yamauchi | 94f7b49 | 2014-07-22 18:08:23 -0700 | [diff] [blame] | 379 |       mirror::ObjectArray<mirror::Class>::Alloc(self, object_array_class.Get(), | 
 | 380 |                                                 kClassRootsMax)); | 
 | 381 |   CHECK(!class_roots_.IsNull()); | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 382 |   SetClassRoot(kJavaLangClass, java_lang_Class.Get()); | 
 | 383 |   SetClassRoot(kJavaLangObject, java_lang_Object.Get()); | 
 | 384 |   SetClassRoot(kClassArrayClass, class_array_class.Get()); | 
 | 385 |   SetClassRoot(kObjectArrayClass, object_array_class.Get()); | 
 | 386 |   SetClassRoot(kCharArrayClass, char_array_class.Get()); | 
 | 387 |   SetClassRoot(kJavaLangString, java_lang_String.Get()); | 
| Fred Shih | 4ee7a66 | 2014-07-11 09:59:27 -0700 | [diff] [blame] | 388 |   SetClassRoot(kJavaLangRefReference, java_lang_ref_Reference.Get()); | 
| Ian Rogers | 0cfe1fb | 2011-08-26 03:29:44 -0700 | [diff] [blame] | 389 |  | 
 | 390 |   // Setup the primitive type classes. | 
| Ian Rogers | 50b35e2 | 2012-10-04 10:09:15 -0700 | [diff] [blame] | 391 |   SetClassRoot(kPrimitiveBoolean, CreatePrimitiveClass(self, Primitive::kPrimBoolean)); | 
 | 392 |   SetClassRoot(kPrimitiveByte, CreatePrimitiveClass(self, Primitive::kPrimByte)); | 
 | 393 |   SetClassRoot(kPrimitiveShort, CreatePrimitiveClass(self, Primitive::kPrimShort)); | 
 | 394 |   SetClassRoot(kPrimitiveInt, CreatePrimitiveClass(self, Primitive::kPrimInt)); | 
 | 395 |   SetClassRoot(kPrimitiveLong, CreatePrimitiveClass(self, Primitive::kPrimLong)); | 
 | 396 |   SetClassRoot(kPrimitiveFloat, CreatePrimitiveClass(self, Primitive::kPrimFloat)); | 
 | 397 |   SetClassRoot(kPrimitiveDouble, CreatePrimitiveClass(self, Primitive::kPrimDouble)); | 
 | 398 |   SetClassRoot(kPrimitiveVoid, CreatePrimitiveClass(self, Primitive::kPrimVoid)); | 
| Ian Rogers | 0cfe1fb | 2011-08-26 03:29:44 -0700 | [diff] [blame] | 399 |  | 
| Ian Rogers | 23435d0 | 2012-09-24 11:23:12 -0700 | [diff] [blame] | 400 |   // Create array interface entries to populate once we can load system classes. | 
| Hiroshi Yamauchi | 94f7b49 | 2014-07-22 18:08:23 -0700 | [diff] [blame] | 401 |   array_iftable_ = GcRoot<mirror::IfTable>(AllocIfTable(self, 2)); | 
| Ian Rogers | 0cfe1fb | 2011-08-26 03:29:44 -0700 | [diff] [blame] | 402 |  | 
| Ian Rogers | 23435d0 | 2012-09-24 11:23:12 -0700 | [diff] [blame] | 403 |   // Create int array type for AllocDexCache (done in AppendToBootClassPath). | 
| Mingyao Yang | 98d1cc8 | 2014-05-15 17:02:16 -0700 | [diff] [blame] | 404 |   Handle<mirror::Class> int_array_class(hs.NewHandle( | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 405 |       AllocClass(self, java_lang_Class.Get(), mirror::Array::ClassSize(image_pointer_size_)))); | 
| Ian Rogers | 0cfe1fb | 2011-08-26 03:29:44 -0700 | [diff] [blame] | 406 |   int_array_class->SetComponentType(GetClassRoot(kPrimitiveInt)); | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 407 |   mirror::IntArray::SetArrayClass(int_array_class.Get()); | 
 | 408 |   SetClassRoot(kIntArrayClass, int_array_class.Get()); | 
| Ian Rogers | 0cfe1fb | 2011-08-26 03:29:44 -0700 | [diff] [blame] | 409 |  | 
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 410 |   // Create long array type for AllocDexCache (done in AppendToBootClassPath). | 
 | 411 |   Handle<mirror::Class> long_array_class(hs.NewHandle( | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 412 |       AllocClass(self, java_lang_Class.Get(), mirror::Array::ClassSize(image_pointer_size_)))); | 
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 413 |   long_array_class->SetComponentType(GetClassRoot(kPrimitiveLong)); | 
 | 414 |   mirror::LongArray::SetArrayClass(long_array_class.Get()); | 
 | 415 |   SetClassRoot(kLongArrayClass, long_array_class.Get()); | 
 | 416 |  | 
| Brian Carlstrom | 75cb3b4 | 2011-07-28 02:13:36 -0700 | [diff] [blame] | 417 |   // now that these are registered, we can use AllocClass() and AllocObjectArray | 
| Brian Carlstrom | a080803 | 2011-07-18 00:39:23 -0700 | [diff] [blame] | 418 |  | 
| Ian Rogers | 52813c9 | 2012-10-11 11:50:38 -0700 | [diff] [blame] | 419 |   // Set up DexCache. This cannot be done later since AppendToBootClassPath calls AllocDexCache. | 
| Mingyao Yang | 98d1cc8 | 2014-05-15 17:02:16 -0700 | [diff] [blame] | 420 |   Handle<mirror::Class> java_lang_DexCache(hs.NewHandle( | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 421 |       AllocClass(self, java_lang_Class.Get(), mirror::DexCache::ClassSize(image_pointer_size_)))); | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 422 |   SetClassRoot(kJavaLangDexCache, java_lang_DexCache.Get()); | 
| Mingyao Yang | 98d1cc8 | 2014-05-15 17:02:16 -0700 | [diff] [blame] | 423 |   java_lang_DexCache->SetObjectSize(mirror::DexCache::InstanceSize()); | 
| Hiroshi Yamauchi | 5b783e6 | 2015-03-18 17:20:11 -0700 | [diff] [blame] | 424 |   mirror::Class::SetStatus(java_lang_DexCache, mirror::Class::kStatusResolved, self); | 
| Ian Rogers | 0cfe1fb | 2011-08-26 03:29:44 -0700 | [diff] [blame] | 425 |  | 
| Mathieu Chartier | 66f1925 | 2012-09-18 08:57:04 -0700 | [diff] [blame] | 426 |   // Set up array classes for string, field, method | 
| Mingyao Yang | 98d1cc8 | 2014-05-15 17:02:16 -0700 | [diff] [blame] | 427 |   Handle<mirror::Class> object_array_string(hs.NewHandle( | 
 | 428 |       AllocClass(self, java_lang_Class.Get(), | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 429 |                  mirror::ObjectArray<mirror::String>::ClassSize(image_pointer_size_)))); | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 430 |   object_array_string->SetComponentType(java_lang_String.Get()); | 
 | 431 |   SetClassRoot(kJavaLangStringArrayClass, object_array_string.Get()); | 
| Mathieu Chartier | 66f1925 | 2012-09-18 08:57:04 -0700 | [diff] [blame] | 432 |  | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 433 |   // Create runtime resolution and imt conflict methods. | 
 | 434 |   runtime->SetResolutionMethod(runtime->CreateResolutionMethod()); | 
 | 435 |   runtime->SetImtConflictMethod(runtime->CreateImtConflictMethod()); | 
 | 436 |   runtime->SetImtUnimplementedMethod(runtime->CreateImtConflictMethod()); | 
| Ian Rogers | 4445a7e | 2012-10-05 17:19:13 -0700 | [diff] [blame] | 437 |  | 
| Ian Rogers | 23435d0 | 2012-09-24 11:23:12 -0700 | [diff] [blame] | 438 |   // Setup boot_class_path_ and register class_path now that we can use AllocObjectArray to create | 
 | 439 |   // DexCache instances. Needs to be after String, Field, Method arrays since AllocDexCache uses | 
 | 440 |   // these roots. | 
| Mathieu Chartier | 66f1925 | 2012-09-18 08:57:04 -0700 | [diff] [blame] | 441 |   CHECK_NE(0U, boot_class_path.size()); | 
| Richard Uhler | fbef44d | 2014-12-23 09:48:51 -0800 | [diff] [blame] | 442 |   for (auto& dex_file : boot_class_path) { | 
 | 443 |     CHECK(dex_file.get() != nullptr); | 
| Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 444 |     AppendToBootClassPath(self, *dex_file); | 
| Richard Uhler | fbef44d | 2014-12-23 09:48:51 -0800 | [diff] [blame] | 445 |     opened_dex_files_.push_back(std::move(dex_file)); | 
| Mathieu Chartier | 66f1925 | 2012-09-18 08:57:04 -0700 | [diff] [blame] | 446 |   } | 
| Ian Rogers | 0cfe1fb | 2011-08-26 03:29:44 -0700 | [diff] [blame] | 447 |  | 
 | 448 |   // now we can use FindSystemClass | 
 | 449 |  | 
| Brian Carlstrom | 5b8e4c8 | 2011-09-18 01:38:59 -0700 | [diff] [blame] | 450 |   // run char class through InitializePrimitiveClass to finish init | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 451 |   InitializePrimitiveClass(char_class.Get(), Primitive::kPrimChar); | 
 | 452 |   SetClassRoot(kPrimitiveChar, char_class.Get());  // needs descriptor | 
| Brian Carlstrom | 5b8e4c8 | 2011-09-18 01:38:59 -0700 | [diff] [blame] | 453 |  | 
| Dmitry Petrochenko | f0972a4 | 2014-05-16 17:43:39 +0700 | [diff] [blame] | 454 |   // Set up GenericJNI entrypoint. That is mainly a hack for common_compiler_test.h so that | 
 | 455 |   // we do not need friend classes or a publicly exposed setter. | 
| Ian Rogers | 6f3dbba | 2014-10-14 17:41:57 -0700 | [diff] [blame] | 456 |   quick_generic_jni_trampoline_ = GetQuickGenericJniStub(); | 
| Mathieu Chartier | e5f13e5 | 2015-02-24 09:37:21 -0800 | [diff] [blame] | 457 |   if (!runtime->IsAotCompiler()) { | 
| Alex Light | 64ad14d | 2014-08-19 14:23:13 -0700 | [diff] [blame] | 458 |     // We need to set up the generic trampolines since we don't have an image. | 
| Ian Rogers | 6f3dbba | 2014-10-14 17:41:57 -0700 | [diff] [blame] | 459 |     quick_resolution_trampoline_ = GetQuickResolutionStub(); | 
 | 460 |     quick_imt_conflict_trampoline_ = GetQuickImtConflictStub(); | 
 | 461 |     quick_to_interpreter_bridge_trampoline_ = GetQuickToInterpreterBridge(); | 
| Alex Light | 64ad14d | 2014-08-19 14:23:13 -0700 | [diff] [blame] | 462 |   } | 
| Dmitry Petrochenko | f0972a4 | 2014-05-16 17:43:39 +0700 | [diff] [blame] | 463 |  | 
| Mathieu Chartier | 66f1925 | 2012-09-18 08:57:04 -0700 | [diff] [blame] | 464 |   // Object, String and DexCache need to be rerun through FindSystemClass to finish init | 
| Hiroshi Yamauchi | 5b783e6 | 2015-03-18 17:20:11 -0700 | [diff] [blame] | 465 |   mirror::Class::SetStatus(java_lang_Object, mirror::Class::kStatusNotReady, self); | 
| Mathieu Chartier | fc58af4 | 2015-04-16 18:00:39 -0700 | [diff] [blame] | 466 |   CHECK_EQ(java_lang_Object.Get(), FindSystemClass(self, "Ljava/lang/Object;")); | 
| Mingyao Yang | 98d1cc8 | 2014-05-15 17:02:16 -0700 | [diff] [blame] | 467 |   CHECK_EQ(java_lang_Object->GetObjectSize(), mirror::Object::InstanceSize()); | 
| Hiroshi Yamauchi | 5b783e6 | 2015-03-18 17:20:11 -0700 | [diff] [blame] | 468 |   mirror::Class::SetStatus(java_lang_String, mirror::Class::kStatusNotReady, self); | 
| Ian Rogers | 9837939 | 2014-02-24 16:53:16 -0800 | [diff] [blame] | 469 |   mirror::Class* String_class = FindSystemClass(self, "Ljava/lang/String;"); | 
| Mathieu Chartier | fc58af4 | 2015-04-16 18:00:39 -0700 | [diff] [blame] | 470 |   if (java_lang_String.Get() != String_class) { | 
 | 471 |     std::ostringstream os1, os2; | 
 | 472 |     java_lang_String->DumpClass(os1, mirror::Class::kDumpClassFullDetail); | 
 | 473 |     String_class->DumpClass(os2, mirror::Class::kDumpClassFullDetail); | 
 | 474 |     LOG(FATAL) << os1.str() << "\n\n" << os2.str(); | 
 | 475 |   } | 
| Hiroshi Yamauchi | 5b783e6 | 2015-03-18 17:20:11 -0700 | [diff] [blame] | 476 |   mirror::Class::SetStatus(java_lang_DexCache, mirror::Class::kStatusNotReady, self); | 
| Mathieu Chartier | fc58af4 | 2015-04-16 18:00:39 -0700 | [diff] [blame] | 477 |   CHECK_EQ(java_lang_DexCache.Get(), FindSystemClass(self, "Ljava/lang/DexCache;")); | 
| Mingyao Yang | 98d1cc8 | 2014-05-15 17:02:16 -0700 | [diff] [blame] | 478 |   CHECK_EQ(java_lang_DexCache->GetObjectSize(), mirror::DexCache::InstanceSize()); | 
| Ian Rogers | 0cfe1fb | 2011-08-26 03:29:44 -0700 | [diff] [blame] | 479 |  | 
| Ian Rogers | 23435d0 | 2012-09-24 11:23:12 -0700 | [diff] [blame] | 480 |   // Setup the primitive array type classes - can't be done until Object has a vtable. | 
| Ian Rogers | 9837939 | 2014-02-24 16:53:16 -0800 | [diff] [blame] | 481 |   SetClassRoot(kBooleanArrayClass, FindSystemClass(self, "[Z")); | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 482 |   mirror::BooleanArray::SetArrayClass(GetClassRoot(kBooleanArrayClass)); | 
| Ian Rogers | 0cfe1fb | 2011-08-26 03:29:44 -0700 | [diff] [blame] | 483 |  | 
| Ian Rogers | 9837939 | 2014-02-24 16:53:16 -0800 | [diff] [blame] | 484 |   SetClassRoot(kByteArrayClass, FindSystemClass(self, "[B")); | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 485 |   mirror::ByteArray::SetArrayClass(GetClassRoot(kByteArrayClass)); | 
| Ian Rogers | 0cfe1fb | 2011-08-26 03:29:44 -0700 | [diff] [blame] | 486 |  | 
| Mathieu Chartier | fc58af4 | 2015-04-16 18:00:39 -0700 | [diff] [blame] | 487 |   CHECK_EQ(char_array_class.Get(), FindSystemClass(self, "[C")); | 
| Ian Rogers | 0cfe1fb | 2011-08-26 03:29:44 -0700 | [diff] [blame] | 488 |  | 
| Ian Rogers | 9837939 | 2014-02-24 16:53:16 -0800 | [diff] [blame] | 489 |   SetClassRoot(kShortArrayClass, FindSystemClass(self, "[S")); | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 490 |   mirror::ShortArray::SetArrayClass(GetClassRoot(kShortArrayClass)); | 
| Ian Rogers | 0cfe1fb | 2011-08-26 03:29:44 -0700 | [diff] [blame] | 491 |  | 
| Mathieu Chartier | fc58af4 | 2015-04-16 18:00:39 -0700 | [diff] [blame] | 492 |   CHECK_EQ(int_array_class.Get(), FindSystemClass(self, "[I")); | 
| Ian Rogers | 0cfe1fb | 2011-08-26 03:29:44 -0700 | [diff] [blame] | 493 |  | 
| Mathieu Chartier | fc58af4 | 2015-04-16 18:00:39 -0700 | [diff] [blame] | 494 |   CHECK_EQ(long_array_class.Get(), FindSystemClass(self, "[J")); | 
| Ian Rogers | 0cfe1fb | 2011-08-26 03:29:44 -0700 | [diff] [blame] | 495 |  | 
| Ian Rogers | 9837939 | 2014-02-24 16:53:16 -0800 | [diff] [blame] | 496 |   SetClassRoot(kFloatArrayClass, FindSystemClass(self, "[F")); | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 497 |   mirror::FloatArray::SetArrayClass(GetClassRoot(kFloatArrayClass)); | 
| Ian Rogers | 0cfe1fb | 2011-08-26 03:29:44 -0700 | [diff] [blame] | 498 |  | 
| Ian Rogers | 9837939 | 2014-02-24 16:53:16 -0800 | [diff] [blame] | 499 |   SetClassRoot(kDoubleArrayClass, FindSystemClass(self, "[D")); | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 500 |   mirror::DoubleArray::SetArrayClass(GetClassRoot(kDoubleArrayClass)); | 
| Ian Rogers | 0cfe1fb | 2011-08-26 03:29:44 -0700 | [diff] [blame] | 501 |  | 
| Mathieu Chartier | fc58af4 | 2015-04-16 18:00:39 -0700 | [diff] [blame] | 502 |   CHECK_EQ(class_array_class.Get(), FindSystemClass(self, "[Ljava/lang/Class;")); | 
| Elliott Hughes | 418d20f | 2011-09-22 14:00:39 -0700 | [diff] [blame] | 503 |  | 
| Mathieu Chartier | fc58af4 | 2015-04-16 18:00:39 -0700 | [diff] [blame] | 504 |   CHECK_EQ(object_array_class.Get(), FindSystemClass(self, "[Ljava/lang/Object;")); | 
| Ian Rogers | 0cfe1fb | 2011-08-26 03:29:44 -0700 | [diff] [blame] | 505 |  | 
| Ian Rogers | 23435d0 | 2012-09-24 11:23:12 -0700 | [diff] [blame] | 506 |   // Setup the single, global copy of "iftable". | 
| Mathieu Chartier | fc58af4 | 2015-04-16 18:00:39 -0700 | [diff] [blame] | 507 |   auto java_lang_Cloneable = hs.NewHandle(FindSystemClass(self, "Ljava/lang/Cloneable;")); | 
 | 508 |   CHECK(java_lang_Cloneable.Get() != nullptr); | 
 | 509 |   auto java_io_Serializable = hs.NewHandle(FindSystemClass(self, "Ljava/io/Serializable;")); | 
 | 510 |   CHECK(java_io_Serializable.Get() != nullptr); | 
| Ian Rogers | 23435d0 | 2012-09-24 11:23:12 -0700 | [diff] [blame] | 511 |   // We assume that Cloneable/Serializable don't have superinterfaces -- normally we'd have to | 
 | 512 |   // crawl up and explicitly list all of the supers as well. | 
| Mathieu Chartier | fc58af4 | 2015-04-16 18:00:39 -0700 | [diff] [blame] | 513 |   array_iftable_.Read()->SetInterface(0, java_lang_Cloneable.Get()); | 
 | 514 |   array_iftable_.Read()->SetInterface(1, java_io_Serializable.Get()); | 
| Ian Rogers | 0cfe1fb | 2011-08-26 03:29:44 -0700 | [diff] [blame] | 515 |  | 
| Mathieu Chartier | fc58af4 | 2015-04-16 18:00:39 -0700 | [diff] [blame] | 516 |   // Sanity check Class[] and Object[]'s interfaces. GetDirectInterface may cause thread | 
 | 517 |   // suspension. | 
 | 518 |   CHECK_EQ(java_lang_Cloneable.Get(), | 
 | 519 |            mirror::Class::GetDirectInterface(self, class_array_class, 0)); | 
 | 520 |   CHECK_EQ(java_io_Serializable.Get(), | 
 | 521 |            mirror::Class::GetDirectInterface(self, class_array_class, 1)); | 
 | 522 |   CHECK_EQ(java_lang_Cloneable.Get(), | 
 | 523 |            mirror::Class::GetDirectInterface(self, object_array_class, 0)); | 
 | 524 |   CHECK_EQ(java_io_Serializable.Get(), | 
 | 525 |            mirror::Class::GetDirectInterface(self, object_array_class, 1)); | 
| Brian Carlstrom | ea46f95 | 2013-07-30 01:26:50 -0700 | [diff] [blame] | 526 |   // Run Class, ArtField, and ArtMethod through FindSystemClass. This initializes their | 
| Ian Rogers | 7dfb28c | 2013-08-22 08:18:36 -0700 | [diff] [blame] | 527 |   // dex_cache_ fields and register them in class_table_. | 
| Mathieu Chartier | fc58af4 | 2015-04-16 18:00:39 -0700 | [diff] [blame] | 528 |   CHECK_EQ(java_lang_Class.Get(), FindSystemClass(self, "Ljava/lang/Class;")); | 
| Ian Rogers | 0cfe1fb | 2011-08-26 03:29:44 -0700 | [diff] [blame] | 529 |  | 
| Mathieu Chartier | fc58af4 | 2015-04-16 18:00:39 -0700 | [diff] [blame] | 530 |   CHECK_EQ(object_array_string.Get(), | 
 | 531 |            FindSystemClass(self, GetClassRootDescriptor(kJavaLangStringArrayClass))); | 
| Brian Carlstrom | 1f87008 | 2011-08-23 16:02:11 -0700 | [diff] [blame] | 532 |  | 
| Ian Rogers | 23435d0 | 2012-09-24 11:23:12 -0700 | [diff] [blame] | 533 |   // End of special init trickery, subsequent classes may be loaded via FindSystemClass. | 
| Ian Rogers | 466bb25 | 2011-10-14 03:29:56 -0700 | [diff] [blame] | 534 |  | 
| Ian Rogers | 23435d0 | 2012-09-24 11:23:12 -0700 | [diff] [blame] | 535 |   // Create java.lang.reflect.Proxy root. | 
| Mathieu Chartier | fc58af4 | 2015-04-16 18:00:39 -0700 | [diff] [blame] | 536 |   SetClassRoot(kJavaLangReflectProxy, FindSystemClass(self, "Ljava/lang/reflect/Proxy;")); | 
| Ian Rogers | 466bb25 | 2011-10-14 03:29:56 -0700 | [diff] [blame] | 537 |  | 
| Mathieu Chartier | daaf326 | 2015-03-24 13:30:28 -0700 | [diff] [blame] | 538 |   // Create java.lang.reflect.Field.class root. | 
| Mathieu Chartier | fc58af4 | 2015-04-16 18:00:39 -0700 | [diff] [blame] | 539 |   auto* class_root = FindSystemClass(self, "Ljava/lang/reflect/Field;"); | 
 | 540 |   CHECK(class_root != nullptr); | 
 | 541 |   SetClassRoot(kJavaLangReflectField, class_root); | 
 | 542 |   mirror::Field::SetClass(class_root); | 
| Mathieu Chartier | daaf326 | 2015-03-24 13:30:28 -0700 | [diff] [blame] | 543 |  | 
 | 544 |   // Create java.lang.reflect.Field array root. | 
| Mathieu Chartier | fc58af4 | 2015-04-16 18:00:39 -0700 | [diff] [blame] | 545 |   class_root = FindSystemClass(self, "[Ljava/lang/reflect/Field;"); | 
 | 546 |   CHECK(class_root != nullptr); | 
 | 547 |   SetClassRoot(kJavaLangReflectFieldArrayClass, class_root); | 
 | 548 |   mirror::Field::SetArrayClass(class_root); | 
 | 549 |  | 
 | 550 |   // Create java.lang.reflect.Constructor.class root and array root. | 
 | 551 |   class_root = FindSystemClass(self, "Ljava/lang/reflect/Constructor;"); | 
 | 552 |   CHECK(class_root != nullptr); | 
 | 553 |   SetClassRoot(kJavaLangReflectConstructor, class_root); | 
 | 554 |   mirror::Constructor::SetClass(class_root); | 
 | 555 |   class_root = FindSystemClass(self, "[Ljava/lang/reflect/Constructor;"); | 
 | 556 |   CHECK(class_root != nullptr); | 
 | 557 |   SetClassRoot(kJavaLangReflectConstructorArrayClass, class_root); | 
 | 558 |   mirror::Constructor::SetArrayClass(class_root); | 
 | 559 |  | 
 | 560 |   // Create java.lang.reflect.Method.class root and array root. | 
 | 561 |   class_root = FindSystemClass(self, "Ljava/lang/reflect/Method;"); | 
 | 562 |   CHECK(class_root != nullptr); | 
 | 563 |   SetClassRoot(kJavaLangReflectMethod, class_root); | 
 | 564 |   mirror::Method::SetClass(class_root); | 
 | 565 |   class_root = FindSystemClass(self, "[Ljava/lang/reflect/Method;"); | 
 | 566 |   CHECK(class_root != nullptr); | 
 | 567 |   SetClassRoot(kJavaLangReflectMethodArrayClass, class_root); | 
 | 568 |   mirror::Method::SetArrayClass(class_root); | 
| Mathieu Chartier | daaf326 | 2015-03-24 13:30:28 -0700 | [diff] [blame] | 569 |  | 
| Brian Carlstrom | 1f87008 | 2011-08-23 16:02:11 -0700 | [diff] [blame] | 570 |   // java.lang.ref classes need to be specially flagged, but otherwise are normal classes | 
| Fred Shih | 4ee7a66 | 2014-07-11 09:59:27 -0700 | [diff] [blame] | 571 |   // finish initializing Reference class | 
| Hiroshi Yamauchi | 5b783e6 | 2015-03-18 17:20:11 -0700 | [diff] [blame] | 572 |   mirror::Class::SetStatus(java_lang_ref_Reference, mirror::Class::kStatusNotReady, self); | 
| Mathieu Chartier | fc58af4 | 2015-04-16 18:00:39 -0700 | [diff] [blame] | 573 |   CHECK_EQ(java_lang_ref_Reference.Get(), FindSystemClass(self, "Ljava/lang/ref/Reference;")); | 
| Fred Shih | 4ee7a66 | 2014-07-11 09:59:27 -0700 | [diff] [blame] | 574 |   CHECK_EQ(java_lang_ref_Reference->GetObjectSize(), mirror::Reference::InstanceSize()); | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 575 |   CHECK_EQ(java_lang_ref_Reference->GetClassSize(), | 
 | 576 |            mirror::Reference::ClassSize(image_pointer_size_)); | 
| Mathieu Chartier | fc58af4 | 2015-04-16 18:00:39 -0700 | [diff] [blame] | 577 |   class_root = FindSystemClass(self, "Ljava/lang/ref/FinalizerReference;"); | 
| Mathieu Chartier | 66c2d2d | 2015-08-25 14:32:32 -0700 | [diff] [blame] | 578 |   CHECK_EQ(class_root->GetClassFlags(), mirror::kClassFlagNormal); | 
| Mathieu Chartier | 52a7f5c | 2015-08-18 18:35:52 -0700 | [diff] [blame] | 579 |   class_root->SetClassFlags(class_root->GetClassFlags() | mirror::kClassFlagFinalizerReference); | 
| Mathieu Chartier | fc58af4 | 2015-04-16 18:00:39 -0700 | [diff] [blame] | 580 |   class_root = FindSystemClass(self, "Ljava/lang/ref/PhantomReference;"); | 
| Mathieu Chartier | 66c2d2d | 2015-08-25 14:32:32 -0700 | [diff] [blame] | 581 |   CHECK_EQ(class_root->GetClassFlags(), mirror::kClassFlagNormal); | 
| Mathieu Chartier | 52a7f5c | 2015-08-18 18:35:52 -0700 | [diff] [blame] | 582 |   class_root->SetClassFlags(class_root->GetClassFlags() | mirror::kClassFlagPhantomReference); | 
| Mathieu Chartier | fc58af4 | 2015-04-16 18:00:39 -0700 | [diff] [blame] | 583 |   class_root = FindSystemClass(self, "Ljava/lang/ref/SoftReference;"); | 
| Mathieu Chartier | 66c2d2d | 2015-08-25 14:32:32 -0700 | [diff] [blame] | 584 |   CHECK_EQ(class_root->GetClassFlags(), mirror::kClassFlagNormal); | 
| Mathieu Chartier | 52a7f5c | 2015-08-18 18:35:52 -0700 | [diff] [blame] | 585 |   class_root->SetClassFlags(class_root->GetClassFlags() | mirror::kClassFlagSoftReference); | 
| Mathieu Chartier | fc58af4 | 2015-04-16 18:00:39 -0700 | [diff] [blame] | 586 |   class_root = FindSystemClass(self, "Ljava/lang/ref/WeakReference;"); | 
| Mathieu Chartier | 66c2d2d | 2015-08-25 14:32:32 -0700 | [diff] [blame] | 587 |   CHECK_EQ(class_root->GetClassFlags(), mirror::kClassFlagNormal); | 
| Mathieu Chartier | 52a7f5c | 2015-08-18 18:35:52 -0700 | [diff] [blame] | 588 |   class_root->SetClassFlags(class_root->GetClassFlags() | mirror::kClassFlagWeakReference); | 
| Brian Carlstrom | 1f87008 | 2011-08-23 16:02:11 -0700 | [diff] [blame] | 589 |  | 
| Ian Rogers | 23435d0 | 2012-09-24 11:23:12 -0700 | [diff] [blame] | 590 |   // Setup the ClassLoader, verifying the object_size_. | 
| Mathieu Chartier | fc58af4 | 2015-04-16 18:00:39 -0700 | [diff] [blame] | 591 |   class_root = FindSystemClass(self, "Ljava/lang/ClassLoader;"); | 
| Mathieu Chartier | e4275c0 | 2015-08-06 15:34:15 -0700 | [diff] [blame] | 592 |   class_root->SetClassLoaderClass(); | 
| Mathieu Chartier | fc58af4 | 2015-04-16 18:00:39 -0700 | [diff] [blame] | 593 |   CHECK_EQ(class_root->GetObjectSize(), mirror::ClassLoader::InstanceSize()); | 
 | 594 |   SetClassRoot(kJavaLangClassLoader, class_root); | 
| Ian Rogers | 0cfe1fb | 2011-08-26 03:29:44 -0700 | [diff] [blame] | 595 |  | 
| jeffhao | 8cd6dda | 2012-02-22 10:15:34 -0800 | [diff] [blame] | 596 |   // Set up java.lang.Throwable, java.lang.ClassNotFoundException, and | 
| Ian Rogers | 23435d0 | 2012-09-24 11:23:12 -0700 | [diff] [blame] | 597 |   // java.lang.StackTraceElement as a convenience. | 
| Ian Rogers | 9837939 | 2014-02-24 16:53:16 -0800 | [diff] [blame] | 598 |   SetClassRoot(kJavaLangThrowable, FindSystemClass(self, "Ljava/lang/Throwable;")); | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 599 |   mirror::Throwable::SetClass(GetClassRoot(kJavaLangThrowable)); | 
| Brian Carlstrom | f363283 | 2014-05-20 15:36:53 -0700 | [diff] [blame] | 600 |   SetClassRoot(kJavaLangClassNotFoundException, | 
 | 601 |                FindSystemClass(self, "Ljava/lang/ClassNotFoundException;")); | 
| Ian Rogers | 9837939 | 2014-02-24 16:53:16 -0800 | [diff] [blame] | 602 |   SetClassRoot(kJavaLangStackTraceElement, FindSystemClass(self, "Ljava/lang/StackTraceElement;")); | 
| Brian Carlstrom | f363283 | 2014-05-20 15:36:53 -0700 | [diff] [blame] | 603 |   SetClassRoot(kJavaLangStackTraceElementArrayClass, | 
 | 604 |                FindSystemClass(self, "[Ljava/lang/StackTraceElement;")); | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 605 |   mirror::StackTraceElement::SetClass(GetClassRoot(kJavaLangStackTraceElement)); | 
| Elliott Hughes | d8ddfd5 | 2011-08-15 14:32:53 -0700 | [diff] [blame] | 606 |  | 
| Andreas Gampe | 76bd880 | 2014-12-10 16:43:58 -0800 | [diff] [blame] | 607 |   // Ensure void type is resolved in the core's dex cache so java.lang.Void is correctly | 
 | 608 |   // initialized. | 
 | 609 |   { | 
 | 610 |     const DexFile& dex_file = java_lang_Object->GetDexFile(); | 
 | 611 |     const DexFile::StringId* void_string_id = dex_file.FindStringId("V"); | 
 | 612 |     CHECK(void_string_id != nullptr); | 
 | 613 |     uint32_t void_string_index = dex_file.GetIndexForStringId(*void_string_id); | 
 | 614 |     const DexFile::TypeId* void_type_id = dex_file.FindTypeId(void_string_index); | 
 | 615 |     CHECK(void_type_id != nullptr); | 
 | 616 |     uint16_t void_type_idx = dex_file.GetIndexForTypeId(*void_type_id); | 
 | 617 |     // Now we resolve void type so the dex cache contains it. We use java.lang.Object class | 
 | 618 |     // as referrer so the used dex cache is core's one. | 
 | 619 |     mirror::Class* resolved_type = ResolveType(dex_file, void_type_idx, java_lang_Object.Get()); | 
 | 620 |     CHECK_EQ(resolved_type, GetClassRoot(kPrimitiveVoid)); | 
 | 621 |     self->AssertNoPendingException(); | 
 | 622 |   } | 
 | 623 |  | 
| Ian Rogers | 9837939 | 2014-02-24 16:53:16 -0800 | [diff] [blame] | 624 |   FinishInit(self); | 
| Brian Carlstrom | 0a5b14d | 2011-09-27 13:29:15 -0700 | [diff] [blame] | 625 |  | 
| Brian Carlstrom | a004aa9 | 2012-02-08 18:05:09 -0800 | [diff] [blame] | 626 |   VLOG(startup) << "ClassLinker::InitFromCompiler exiting"; | 
| Brian Carlstrom | a663ea5 | 2011-08-19 23:33:41 -0700 | [diff] [blame] | 627 | } | 
 | 628 |  | 
| Ian Rogers | 9837939 | 2014-02-24 16:53:16 -0800 | [diff] [blame] | 629 | void ClassLinker::FinishInit(Thread* self) { | 
| Elliott Hughes | 4dd9b4d | 2011-12-12 18:29:24 -0800 | [diff] [blame] | 630 |   VLOG(startup) << "ClassLinker::FinishInit entering"; | 
| Brian Carlstrom | 1619286 | 2011-09-12 17:50:06 -0700 | [diff] [blame] | 631 |  | 
 | 632 |   // Let the heap know some key offsets into java.lang.ref instances | 
| Elliott Hughes | 20cde90 | 2011-10-04 17:37:27 -0700 | [diff] [blame] | 633 |   // Note: we hard code the field indexes here rather than using FindInstanceField | 
| Brian Carlstrom | 1619286 | 2011-09-12 17:50:06 -0700 | [diff] [blame] | 634 |   // as the types of the field can't be resolved prior to the runtime being | 
 | 635 |   // fully initialized | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 636 |   mirror::Class* java_lang_ref_Reference = GetClassRoot(kJavaLangRefReference); | 
| Ian Rogers | 8b2c0b9 | 2013-09-19 02:56:49 -0700 | [diff] [blame] | 637 |   mirror::Class* java_lang_ref_FinalizerReference = | 
| Ian Rogers | 9837939 | 2014-02-24 16:53:16 -0800 | [diff] [blame] | 638 |       FindSystemClass(self, "Ljava/lang/ref/FinalizerReference;"); | 
| Ian Rogers | 6d4d9fc | 2011-11-30 16:24:48 -0800 | [diff] [blame] | 639 |  | 
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 640 |   ArtField* pendingNext = java_lang_ref_Reference->GetInstanceField(0); | 
| Mathieu Chartier | 61c5ebc | 2014-06-05 17:42:53 -0700 | [diff] [blame] | 641 |   CHECK_STREQ(pendingNext->GetName(), "pendingNext"); | 
 | 642 |   CHECK_STREQ(pendingNext->GetTypeDescriptor(), "Ljava/lang/ref/Reference;"); | 
| Brian Carlstrom | 1619286 | 2011-09-12 17:50:06 -0700 | [diff] [blame] | 643 |  | 
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 644 |   ArtField* queue = java_lang_ref_Reference->GetInstanceField(1); | 
| Mathieu Chartier | 61c5ebc | 2014-06-05 17:42:53 -0700 | [diff] [blame] | 645 |   CHECK_STREQ(queue->GetName(), "queue"); | 
 | 646 |   CHECK_STREQ(queue->GetTypeDescriptor(), "Ljava/lang/ref/ReferenceQueue;"); | 
| Brian Carlstrom | 1619286 | 2011-09-12 17:50:06 -0700 | [diff] [blame] | 647 |  | 
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 648 |   ArtField* queueNext = java_lang_ref_Reference->GetInstanceField(2); | 
| Mathieu Chartier | 61c5ebc | 2014-06-05 17:42:53 -0700 | [diff] [blame] | 649 |   CHECK_STREQ(queueNext->GetName(), "queueNext"); | 
 | 650 |   CHECK_STREQ(queueNext->GetTypeDescriptor(), "Ljava/lang/ref/Reference;"); | 
| Brian Carlstrom | 1619286 | 2011-09-12 17:50:06 -0700 | [diff] [blame] | 651 |  | 
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 652 |   ArtField* referent = java_lang_ref_Reference->GetInstanceField(3); | 
| Mathieu Chartier | 61c5ebc | 2014-06-05 17:42:53 -0700 | [diff] [blame] | 653 |   CHECK_STREQ(referent->GetName(), "referent"); | 
 | 654 |   CHECK_STREQ(referent->GetTypeDescriptor(), "Ljava/lang/Object;"); | 
| Brian Carlstrom | 1619286 | 2011-09-12 17:50:06 -0700 | [diff] [blame] | 655 |  | 
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 656 |   ArtField* zombie = java_lang_ref_FinalizerReference->GetInstanceField(2); | 
| Mathieu Chartier | 61c5ebc | 2014-06-05 17:42:53 -0700 | [diff] [blame] | 657 |   CHECK_STREQ(zombie->GetName(), "zombie"); | 
 | 658 |   CHECK_STREQ(zombie->GetTypeDescriptor(), "Ljava/lang/Object;"); | 
| Brian Carlstrom | 1619286 | 2011-09-12 17:50:06 -0700 | [diff] [blame] | 659 |  | 
| Brian Carlstrom | a663ea5 | 2011-08-19 23:33:41 -0700 | [diff] [blame] | 660 |   // ensure all class_roots_ are initialized | 
| Brian Carlstrom | 75cb3b4 | 2011-07-28 02:13:36 -0700 | [diff] [blame] | 661 |   for (size_t i = 0; i < kClassRootsMax; i++) { | 
| Brian Carlstrom | a663ea5 | 2011-08-19 23:33:41 -0700 | [diff] [blame] | 662 |     ClassRoot class_root = static_cast<ClassRoot>(i); | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 663 |     mirror::Class* klass = GetClassRoot(class_root); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 664 |     CHECK(klass != nullptr); | 
 | 665 |     DCHECK(klass->IsArrayClass() || klass->IsPrimitive() || klass->GetDexCache() != nullptr); | 
| Brian Carlstrom | a663ea5 | 2011-08-19 23:33:41 -0700 | [diff] [blame] | 666 |     // note SetClassRoot does additional validation. | 
 | 667 |     // if possible add new checks there to catch errors early | 
| Brian Carlstrom | 75cb3b4 | 2011-07-28 02:13:36 -0700 | [diff] [blame] | 668 |   } | 
 | 669 |  | 
| Hiroshi Yamauchi | 94f7b49 | 2014-07-22 18:08:23 -0700 | [diff] [blame] | 670 |   CHECK(!array_iftable_.IsNull()); | 
| Elliott Hughes | 92f14b2 | 2011-10-06 12:29:54 -0700 | [diff] [blame] | 671 |  | 
| Brian Carlstrom | 75cb3b4 | 2011-07-28 02:13:36 -0700 | [diff] [blame] | 672 |   // disable the slow paths in FindClass and CreatePrimitiveClass now | 
 | 673 |   // that Object, Class, and Object[] are setup | 
 | 674 |   init_done_ = true; | 
| Brian Carlstrom | 0a5b14d | 2011-09-27 13:29:15 -0700 | [diff] [blame] | 675 |  | 
| Elliott Hughes | 4dd9b4d | 2011-12-12 18:29:24 -0800 | [diff] [blame] | 676 |   VLOG(startup) << "ClassLinker::FinishInit exiting"; | 
| Brian Carlstrom | 75cb3b4 | 2011-07-28 02:13:36 -0700 | [diff] [blame] | 677 | } | 
 | 678 |  | 
| Elliott Hughes | 2a20cfd | 2011-09-23 19:30:41 -0700 | [diff] [blame] | 679 | void ClassLinker::RunRootClinits() { | 
 | 680 |   Thread* self = Thread::Current(); | 
 | 681 |   for (size_t i = 0; i < ClassLinker::kClassRootsMax; ++i) { | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 682 |     mirror::Class* c = GetClassRoot(ClassRoot(i)); | 
| Elliott Hughes | 2a20cfd | 2011-09-23 19:30:41 -0700 | [diff] [blame] | 683 |     if (!c->IsArrayClass() && !c->IsPrimitive()) { | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 684 |       StackHandleScope<1> hs(self); | 
 | 685 |       Handle<mirror::Class> h_class(hs.NewHandle(GetClassRoot(ClassRoot(i)))); | 
| Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 686 |       EnsureInitialized(self, h_class, true, true); | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 687 |       self->AssertNoPendingException(); | 
| Elliott Hughes | 2a20cfd | 2011-09-23 19:30:41 -0700 | [diff] [blame] | 688 |     } | 
 | 689 |   } | 
 | 690 | } | 
 | 691 |  | 
| Ian Rogers | 8d31bbd | 2013-10-13 10:44:14 -0700 | [diff] [blame] | 692 | const OatFile* ClassLinker::RegisterOatFile(const OatFile* oat_file) { | 
| Ian Rogers | 1bf8d4d | 2013-05-30 00:18:49 -0700 | [diff] [blame] | 693 |   WriterMutexLock mu(Thread::Current(), dex_lock_); | 
| Brian Carlstrom | 0d6adac | 2014-02-05 17:39:16 -0800 | [diff] [blame] | 694 |   if (kIsDebugBuild) { | 
 | 695 |     for (size_t i = 0; i < oat_files_.size(); ++i) { | 
 | 696 |       CHECK_NE(oat_file, oat_files_[i]) << oat_file->GetLocation(); | 
| Ian Rogers | 1bf8d4d | 2013-05-30 00:18:49 -0700 | [diff] [blame] | 697 |     } | 
| Ian Rogers | 2bcb4a4 | 2012-11-08 10:39:18 -0800 | [diff] [blame] | 698 |   } | 
| Ian Rogers | 8d31bbd | 2013-10-13 10:44:14 -0700 | [diff] [blame] | 699 |   VLOG(class_linker) << "Registering " << oat_file->GetLocation(); | 
 | 700 |   oat_files_.push_back(oat_file); | 
 | 701 |   return oat_file; | 
| Brian Carlstrom | 866c862 | 2012-01-06 16:35:13 -0800 | [diff] [blame] | 702 | } | 
 | 703 |  | 
| Brian Carlstrom | 56d947f | 2013-07-15 13:14:23 -0700 | [diff] [blame] | 704 | OatFile& ClassLinker::GetImageOatFile(gc::space::ImageSpace* space) { | 
 | 705 |   VLOG(startup) << "ClassLinker::GetImageOatFile entering"; | 
| Ian Rogers | 8d31bbd | 2013-10-13 10:44:14 -0700 | [diff] [blame] | 706 |   OatFile* oat_file = space->ReleaseOatFile(); | 
 | 707 |   CHECK_EQ(RegisterOatFile(oat_file), oat_file); | 
| Brian Carlstrom | 56d947f | 2013-07-15 13:14:23 -0700 | [diff] [blame] | 708 |   VLOG(startup) << "ClassLinker::GetImageOatFile exiting"; | 
| Ian Rogers | 8d31bbd | 2013-10-13 10:44:14 -0700 | [diff] [blame] | 709 |   return *oat_file; | 
| Brian Carlstrom | 58ae941 | 2011-10-04 00:56:06 -0700 | [diff] [blame] | 710 | } | 
 | 711 |  | 
| Andreas Gampe | b9aec2c | 2015-04-23 22:23:47 -0700 | [diff] [blame] | 712 | class DexFileAndClassPair : ValueObject { | 
 | 713 |  public: | 
 | 714 |   DexFileAndClassPair(const DexFile* dex_file, size_t current_class_index, bool from_loaded_oat) | 
 | 715 |      : cached_descriptor_(GetClassDescriptor(dex_file, current_class_index)), | 
 | 716 |        dex_file_(dex_file), | 
 | 717 |        current_class_index_(current_class_index), | 
 | 718 |        from_loaded_oat_(from_loaded_oat) {} | 
 | 719 |  | 
 | 720 |   DexFileAndClassPair(const DexFileAndClassPair&) = default; | 
 | 721 |  | 
 | 722 |   DexFileAndClassPair& operator=(const DexFileAndClassPair& rhs) { | 
 | 723 |     cached_descriptor_ = rhs.cached_descriptor_; | 
 | 724 |     dex_file_ = rhs.dex_file_; | 
 | 725 |     current_class_index_ = rhs.current_class_index_; | 
 | 726 |     from_loaded_oat_ = rhs.from_loaded_oat_; | 
 | 727 |     return *this; | 
 | 728 |   } | 
 | 729 |  | 
 | 730 |   const char* GetCachedDescriptor() const { | 
 | 731 |     return cached_descriptor_; | 
 | 732 |   } | 
 | 733 |  | 
 | 734 |   bool operator<(const DexFileAndClassPair& rhs) const { | 
 | 735 |     const char* lhsDescriptor = cached_descriptor_; | 
 | 736 |     const char* rhsDescriptor = rhs.cached_descriptor_; | 
 | 737 |     int cmp = strcmp(lhsDescriptor, rhsDescriptor); | 
 | 738 |     if (cmp != 0) { | 
| Andreas Gampe | 0cba004 | 2015-04-29 20:47:16 -0700 | [diff] [blame] | 739 |       // Note that the order must be reversed. We want to iterate over the classes in dex files. | 
 | 740 |       // They are sorted lexicographically. Thus, the priority-queue must be a min-queue. | 
| Andreas Gampe | b9aec2c | 2015-04-23 22:23:47 -0700 | [diff] [blame] | 741 |       return cmp > 0; | 
 | 742 |     } | 
 | 743 |     return dex_file_ < rhs.dex_file_; | 
 | 744 |   } | 
 | 745 |  | 
 | 746 |   bool DexFileHasMoreClasses() const { | 
 | 747 |     return current_class_index_ + 1 < dex_file_->NumClassDefs(); | 
 | 748 |   } | 
 | 749 |  | 
 | 750 |   DexFileAndClassPair GetNext() const { | 
 | 751 |     return DexFileAndClassPair(dex_file_, current_class_index_ + 1, from_loaded_oat_); | 
 | 752 |   } | 
 | 753 |  | 
 | 754 |   size_t GetCurrentClassIndex() const { | 
 | 755 |     return current_class_index_; | 
 | 756 |   } | 
 | 757 |  | 
 | 758 |   bool FromLoadedOat() const { | 
 | 759 |     return from_loaded_oat_; | 
 | 760 |   } | 
 | 761 |  | 
 | 762 |   const DexFile* GetDexFile() const { | 
 | 763 |     return dex_file_; | 
 | 764 |   } | 
 | 765 |  | 
| Andreas Gampe | 0cba004 | 2015-04-29 20:47:16 -0700 | [diff] [blame] | 766 |   void DeleteDexFile() { | 
 | 767 |     delete dex_file_; | 
 | 768 |     dex_file_ = nullptr; | 
 | 769 |   } | 
 | 770 |  | 
| Andreas Gampe | b9aec2c | 2015-04-23 22:23:47 -0700 | [diff] [blame] | 771 |  private: | 
 | 772 |   static const char* GetClassDescriptor(const DexFile* dex_file, size_t index) { | 
 | 773 |     const DexFile::ClassDef& class_def = dex_file->GetClassDef(static_cast<uint16_t>(index)); | 
 | 774 |     return dex_file->StringByTypeIdx(class_def.class_idx_); | 
 | 775 |   } | 
 | 776 |  | 
 | 777 |   const char* cached_descriptor_; | 
 | 778 |   const DexFile* dex_file_; | 
 | 779 |   size_t current_class_index_; | 
 | 780 |   bool from_loaded_oat_;  // We only need to compare mismatches between what we load now | 
 | 781 |                           // and what was loaded before. Any old duplicates must have been | 
 | 782 |                           // OK, and any new "internal" duplicates are as well (they must | 
 | 783 |                           // be from multidex, which resolves correctly). | 
 | 784 | }; | 
 | 785 |  | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 786 | static void AddDexFilesFromOat(const OatFile* oat_file, bool already_loaded, | 
| Andreas Gampe | b9aec2c | 2015-04-23 22:23:47 -0700 | [diff] [blame] | 787 |                                std::priority_queue<DexFileAndClassPair>* heap) { | 
 | 788 |   const std::vector<const OatDexFile*>& oat_dex_files = oat_file->GetOatDexFiles(); | 
 | 789 |   for (const OatDexFile* oat_dex_file : oat_dex_files) { | 
 | 790 |     std::string error; | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 791 |     std::unique_ptr<const DexFile> dex_file = oat_dex_file->OpenDexFile(&error); | 
| Andreas Gampe | b9aec2c | 2015-04-23 22:23:47 -0700 | [diff] [blame] | 792 |     if (dex_file.get() == nullptr) { | 
 | 793 |       LOG(WARNING) << "Could not create dex file from oat file: " << error; | 
 | 794 |     } else { | 
 | 795 |       if (dex_file->NumClassDefs() > 0U) { | 
 | 796 |         heap->emplace(dex_file.release(), 0U, already_loaded); | 
 | 797 |       } | 
 | 798 |     } | 
 | 799 |   } | 
 | 800 | } | 
 | 801 |  | 
| Andreas Gampe | 0cba004 | 2015-04-29 20:47:16 -0700 | [diff] [blame] | 802 | static void AddNext(DexFileAndClassPair* original, | 
| Andreas Gampe | b9aec2c | 2015-04-23 22:23:47 -0700 | [diff] [blame] | 803 |                     std::priority_queue<DexFileAndClassPair>* heap) { | 
| Andreas Gampe | 0cba004 | 2015-04-29 20:47:16 -0700 | [diff] [blame] | 804 |   if (original->DexFileHasMoreClasses()) { | 
 | 805 |     heap->push(original->GetNext()); | 
| Andreas Gampe | b9aec2c | 2015-04-23 22:23:47 -0700 | [diff] [blame] | 806 |   } else { | 
 | 807 |     // Need to delete the dex file. | 
| Andreas Gampe | 0cba004 | 2015-04-29 20:47:16 -0700 | [diff] [blame] | 808 |     original->DeleteDexFile(); | 
| Andreas Gampe | b9aec2c | 2015-04-23 22:23:47 -0700 | [diff] [blame] | 809 |   } | 
 | 810 | } | 
 | 811 |  | 
 | 812 | static void FreeDexFilesInHeap(std::priority_queue<DexFileAndClassPair>* heap) { | 
 | 813 |   while (!heap->empty()) { | 
 | 814 |     delete heap->top().GetDexFile(); | 
 | 815 |     heap->pop(); | 
 | 816 |   } | 
 | 817 | } | 
 | 818 |  | 
| Sebastien Hertz | 0de1133 | 2015-05-13 12:14:05 +0200 | [diff] [blame] | 819 | const OatFile* ClassLinker::GetBootOatFile() { | 
| Andreas Gampe | 88da3b0 | 2015-06-12 20:38:49 -0700 | [diff] [blame] | 820 |   gc::space::ImageSpace* image_space = Runtime::Current()->GetHeap()->GetImageSpace(); | 
 | 821 |   if (image_space == nullptr) { | 
| Sebastien Hertz | 0de1133 | 2015-05-13 12:14:05 +0200 | [diff] [blame] | 822 |     return nullptr; | 
 | 823 |   } | 
| Andreas Gampe | 88da3b0 | 2015-06-12 20:38:49 -0700 | [diff] [blame] | 824 |   return image_space->GetOatFile(); | 
| Sebastien Hertz | 0de1133 | 2015-05-13 12:14:05 +0200 | [diff] [blame] | 825 | } | 
 | 826 |  | 
 | 827 | const OatFile* ClassLinker::GetPrimaryOatFile() { | 
 | 828 |   ReaderMutexLock mu(Thread::Current(), dex_lock_); | 
 | 829 |   const OatFile* boot_oat_file = GetBootOatFile(); | 
 | 830 |   if (boot_oat_file != nullptr) { | 
 | 831 |     for (const OatFile* oat_file : oat_files_) { | 
 | 832 |       if (oat_file != boot_oat_file) { | 
 | 833 |         return oat_file; | 
 | 834 |       } | 
 | 835 |     } | 
 | 836 |   } | 
 | 837 |   return nullptr; | 
 | 838 | } | 
 | 839 |  | 
| Andreas Gampe | 94329d3 | 2015-04-24 20:22:06 -0700 | [diff] [blame] | 840 | // Check for class-def collisions in dex files. | 
 | 841 | // | 
 | 842 | // This works by maintaining a heap with one class from each dex file, sorted by the class | 
 | 843 | // descriptor. Then a dex-file/class pair is continually removed from the heap and compared | 
 | 844 | // against the following top element. If the descriptor is the same, it is now checked whether | 
 | 845 | // the two elements agree on whether their dex file was from an already-loaded oat-file or the | 
 | 846 | // new oat file. Any disagreement indicates a collision. | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 847 | bool ClassLinker::HasCollisions(const OatFile* oat_file, std::string* error_msg) { | 
| Andreas Gampe | 69b5d8f | 2015-06-03 15:43:16 -0700 | [diff] [blame] | 848 |   if (!kDuplicateClassesCheck) { | 
 | 849 |     return false; | 
 | 850 |   } | 
 | 851 |  | 
| Andreas Gampe | b9aec2c | 2015-04-23 22:23:47 -0700 | [diff] [blame] | 852 |   // Dex files are registered late - once a class is actually being loaded. We have to compare | 
| Andreas Gampe | 0cba004 | 2015-04-29 20:47:16 -0700 | [diff] [blame] | 853 |   // against the open oat files. Take the dex_lock_ that protects oat_files_ accesses. | 
| Andreas Gampe | b9aec2c | 2015-04-23 22:23:47 -0700 | [diff] [blame] | 854 |   ReaderMutexLock mu(Thread::Current(), dex_lock_); | 
 | 855 |  | 
| Andreas Gampe | 0cba004 | 2015-04-29 20:47:16 -0700 | [diff] [blame] | 856 |   std::priority_queue<DexFileAndClassPair> queue; | 
| Andreas Gampe | b9aec2c | 2015-04-23 22:23:47 -0700 | [diff] [blame] | 857 |  | 
 | 858 |   // Add dex files from already loaded oat files, but skip boot. | 
 | 859 |   { | 
| Sebastien Hertz | 0de1133 | 2015-05-13 12:14:05 +0200 | [diff] [blame] | 860 |     const OatFile* boot_oat = GetBootOatFile(); | 
| Andreas Gampe | b9aec2c | 2015-04-23 22:23:47 -0700 | [diff] [blame] | 861 |     for (const OatFile* loaded_oat_file : oat_files_) { | 
 | 862 |       if (loaded_oat_file == boot_oat) { | 
 | 863 |         continue; | 
 | 864 |       } | 
| Andreas Gampe | 0cba004 | 2015-04-29 20:47:16 -0700 | [diff] [blame] | 865 |       AddDexFilesFromOat(loaded_oat_file, true, &queue); | 
| Andreas Gampe | b9aec2c | 2015-04-23 22:23:47 -0700 | [diff] [blame] | 866 |     } | 
 | 867 |   } | 
 | 868 |  | 
| Andreas Gampe | 0cba004 | 2015-04-29 20:47:16 -0700 | [diff] [blame] | 869 |   if (queue.empty()) { | 
| Andreas Gampe | b9aec2c | 2015-04-23 22:23:47 -0700 | [diff] [blame] | 870 |     // No other oat files, return early. | 
 | 871 |     return false; | 
 | 872 |   } | 
 | 873 |  | 
 | 874 |   // Add dex files from the oat file to check. | 
| Andreas Gampe | 0cba004 | 2015-04-29 20:47:16 -0700 | [diff] [blame] | 875 |   AddDexFilesFromOat(oat_file, false, &queue); | 
| Andreas Gampe | b9aec2c | 2015-04-23 22:23:47 -0700 | [diff] [blame] | 876 |  | 
| Andreas Gampe | 0cba004 | 2015-04-29 20:47:16 -0700 | [diff] [blame] | 877 |   // Now drain the queue. | 
 | 878 |   while (!queue.empty()) { | 
 | 879 |     DexFileAndClassPair compare_pop = queue.top(); | 
 | 880 |     queue.pop(); | 
| Andreas Gampe | b9aec2c | 2015-04-23 22:23:47 -0700 | [diff] [blame] | 881 |  | 
 | 882 |     // Compare against the following elements. | 
| Andreas Gampe | 0cba004 | 2015-04-29 20:47:16 -0700 | [diff] [blame] | 883 |     while (!queue.empty()) { | 
 | 884 |       DexFileAndClassPair top = queue.top(); | 
| Andreas Gampe | b9aec2c | 2015-04-23 22:23:47 -0700 | [diff] [blame] | 885 |  | 
 | 886 |       if (strcmp(compare_pop.GetCachedDescriptor(), top.GetCachedDescriptor()) == 0) { | 
 | 887 |         // Same descriptor. Check whether it's crossing old-oat-files to new-oat-files. | 
 | 888 |         if (compare_pop.FromLoadedOat() != top.FromLoadedOat()) { | 
 | 889 |           *error_msg = | 
 | 890 |               StringPrintf("Found duplicated class when checking oat files: '%s' in %s and %s", | 
 | 891 |                            compare_pop.GetCachedDescriptor(), | 
 | 892 |                            compare_pop.GetDexFile()->GetLocation().c_str(), | 
 | 893 |                            top.GetDexFile()->GetLocation().c_str()); | 
| Andreas Gampe | 0cba004 | 2015-04-29 20:47:16 -0700 | [diff] [blame] | 894 |           FreeDexFilesInHeap(&queue); | 
| Andreas Gampe | b9aec2c | 2015-04-23 22:23:47 -0700 | [diff] [blame] | 895 |           return true; | 
 | 896 |         } | 
 | 897 |         // Pop it. | 
| Andreas Gampe | 0cba004 | 2015-04-29 20:47:16 -0700 | [diff] [blame] | 898 |         queue.pop(); | 
 | 899 |         AddNext(&top, &queue); | 
| Andreas Gampe | b9aec2c | 2015-04-23 22:23:47 -0700 | [diff] [blame] | 900 |       } else { | 
 | 901 |         // Something else. Done here. | 
 | 902 |         break; | 
 | 903 |       } | 
 | 904 |     } | 
| Andreas Gampe | 0cba004 | 2015-04-29 20:47:16 -0700 | [diff] [blame] | 905 |     AddNext(&compare_pop, &queue); | 
| Andreas Gampe | b9aec2c | 2015-04-23 22:23:47 -0700 | [diff] [blame] | 906 |   } | 
 | 907 |  | 
 | 908 |   return false; | 
 | 909 | } | 
 | 910 |  | 
| Richard Uhler | 66d874d | 2015-01-15 09:37:19 -0800 | [diff] [blame] | 911 | std::vector<std::unique_ptr<const DexFile>> ClassLinker::OpenDexFilesFromOat( | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 912 |     const char* dex_location, const char* oat_location, | 
 | 913 |     std::vector<std::string>* error_msgs) { | 
 | 914 |   CHECK(error_msgs != nullptr); | 
 | 915 |  | 
| Richard Uhler | 66d874d | 2015-01-15 09:37:19 -0800 | [diff] [blame] | 916 |   // Verify we aren't holding the mutator lock, which could starve GC if we | 
 | 917 |   // have to generate or relocate an oat file. | 
 | 918 |   Locks::mutator_lock_->AssertNotHeld(Thread::Current()); | 
 | 919 |  | 
 | 920 |   OatFileAssistant oat_file_assistant(dex_location, oat_location, kRuntimeISA, | 
 | 921 |      !Runtime::Current()->IsAotCompiler()); | 
 | 922 |  | 
 | 923 |   // Lock the target oat location to avoid races generating and loading the | 
 | 924 |   // oat file. | 
 | 925 |   std::string error_msg; | 
 | 926 |   if (!oat_file_assistant.Lock(&error_msg)) { | 
 | 927 |     // Don't worry too much if this fails. If it does fail, it's unlikely we | 
 | 928 |     // can generate an oat file anyway. | 
 | 929 |     VLOG(class_linker) << "OatFileAssistant::Lock: " << error_msg; | 
| Andreas Gampe | 833a485 | 2014-05-21 18:46:59 -0700 | [diff] [blame] | 930 |   } | 
 | 931 |  | 
| Richard Uhler | 66d874d | 2015-01-15 09:37:19 -0800 | [diff] [blame] | 932 |   // Check if we already have an up-to-date oat file open. | 
 | 933 |   const OatFile* source_oat_file = nullptr; | 
 | 934 |   { | 
 | 935 |     ReaderMutexLock mu(Thread::Current(), dex_lock_); | 
 | 936 |     for (const OatFile* oat_file : oat_files_) { | 
 | 937 |       CHECK(oat_file != nullptr); | 
 | 938 |       if (oat_file_assistant.GivenOatFileIsUpToDate(*oat_file)) { | 
 | 939 |         source_oat_file = oat_file; | 
 | 940 |         break; | 
| Andreas Gampe | 833a485 | 2014-05-21 18:46:59 -0700 | [diff] [blame] | 941 |       } | 
 | 942 |     } | 
| Andreas Gampe | 833a485 | 2014-05-21 18:46:59 -0700 | [diff] [blame] | 943 |   } | 
 | 944 |  | 
| Richard Uhler | 66d874d | 2015-01-15 09:37:19 -0800 | [diff] [blame] | 945 |   // If we didn't have an up-to-date oat file open, try to load one from disk. | 
 | 946 |   if (source_oat_file == nullptr) { | 
 | 947 |     // Update the oat file on disk if we can. This may fail, but that's okay. | 
 | 948 |     // Best effort is all that matters here. | 
 | 949 |     if (!oat_file_assistant.MakeUpToDate(&error_msg)) { | 
 | 950 |       LOG(WARNING) << error_msg; | 
| Andreas Gampe | 833a485 | 2014-05-21 18:46:59 -0700 | [diff] [blame] | 951 |     } | 
| Andreas Gampe | 833a485 | 2014-05-21 18:46:59 -0700 | [diff] [blame] | 952 |  | 
| Richard Uhler | 66d874d | 2015-01-15 09:37:19 -0800 | [diff] [blame] | 953 |     // Get the oat file on disk. | 
 | 954 |     std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); | 
 | 955 |     if (oat_file.get() != nullptr) { | 
| Andreas Gampe | 0cba004 | 2015-04-29 20:47:16 -0700 | [diff] [blame] | 956 |       // Take the file only if it has no collisions, or we must take it because of preopting. | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 957 |       bool accept_oat_file = !HasCollisions(oat_file.get(), &error_msg); | 
| Andreas Gampe | 0cba004 | 2015-04-29 20:47:16 -0700 | [diff] [blame] | 958 |       if (!accept_oat_file) { | 
 | 959 |         // Failed the collision check. Print warning. | 
| Andreas Gampe | 94329d3 | 2015-04-24 20:22:06 -0700 | [diff] [blame] | 960 |         if (Runtime::Current()->IsDexFileFallbackEnabled()) { | 
 | 961 |           LOG(WARNING) << "Found duplicate classes, falling back to interpreter mode for " | 
 | 962 |                        << dex_location; | 
 | 963 |         } else { | 
 | 964 |           LOG(WARNING) << "Found duplicate classes, dex-file-fallback disabled, will be failing to " | 
 | 965 |                           " load classes for " << dex_location; | 
 | 966 |         } | 
| Andreas Gampe | b9aec2c | 2015-04-23 22:23:47 -0700 | [diff] [blame] | 967 |         LOG(WARNING) << error_msg; | 
| Andreas Gampe | 0cba004 | 2015-04-29 20:47:16 -0700 | [diff] [blame] | 968 |  | 
 | 969 |         // However, if the app was part of /system and preopted, there is no original dex file | 
 | 970 |         // available. In that case grudgingly accept the oat file. | 
 | 971 |         if (!DexFile::MaybeDex(dex_location)) { | 
 | 972 |           accept_oat_file = true; | 
 | 973 |           LOG(WARNING) << "Dex location " << dex_location << " does not seem to include dex file. " | 
 | 974 |                        << "Allow oat file use. This is potentially dangerous."; | 
 | 975 |         } | 
 | 976 |       } | 
 | 977 |  | 
 | 978 |       if (accept_oat_file) { | 
 | 979 |         source_oat_file = oat_file.release(); | 
 | 980 |         RegisterOatFile(source_oat_file); | 
| Andreas Gampe | b9aec2c | 2015-04-23 22:23:47 -0700 | [diff] [blame] | 981 |       } | 
| Andreas Gampe | 833a485 | 2014-05-21 18:46:59 -0700 | [diff] [blame] | 982 |     } | 
 | 983 |   } | 
 | 984 |  | 
| Richard Uhler | 66d874d | 2015-01-15 09:37:19 -0800 | [diff] [blame] | 985 |   std::vector<std::unique_ptr<const DexFile>> dex_files; | 
| Andreas Gampe | 833a485 | 2014-05-21 18:46:59 -0700 | [diff] [blame] | 986 |  | 
| Richard Uhler | 66d874d | 2015-01-15 09:37:19 -0800 | [diff] [blame] | 987 |   // Load the dex files from the oat file. | 
 | 988 |   if (source_oat_file != nullptr) { | 
 | 989 |     dex_files = oat_file_assistant.LoadDexFiles(*source_oat_file, dex_location); | 
 | 990 |     if (dex_files.empty()) { | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 991 |       error_msgs->push_back("Failed to open dex files from " | 
 | 992 |           + source_oat_file->GetLocation()); | 
| Andreas Gampe | 833a485 | 2014-05-21 18:46:59 -0700 | [diff] [blame] | 993 |     } | 
 | 994 |   } | 
 | 995 |  | 
| Richard Uhler | 66d874d | 2015-01-15 09:37:19 -0800 | [diff] [blame] | 996 |   // Fall back to running out of the original dex file if we couldn't load any | 
 | 997 |   // dex_files from the oat file. | 
 | 998 |   if (dex_files.empty()) { | 
| Richard Uhler | 9b994ea | 2015-06-24 08:44:19 -0700 | [diff] [blame] | 999 |     if (oat_file_assistant.HasOriginalDexFiles()) { | 
 | 1000 |       if (Runtime::Current()->IsDexFileFallbackEnabled()) { | 
 | 1001 |         if (!DexFile::Open(dex_location, dex_location, &error_msg, &dex_files)) { | 
 | 1002 |           LOG(WARNING) << error_msg; | 
 | 1003 |           error_msgs->push_back("Failed to open dex files from " + std::string(dex_location)); | 
 | 1004 |         } | 
 | 1005 |       } else { | 
 | 1006 |         error_msgs->push_back("Fallback mode disabled, skipping dex files."); | 
| Jean Christophe Beyler | 24e04aa | 2014-09-12 12:03:25 -0700 | [diff] [blame] | 1007 |       } | 
 | 1008 |     } else { | 
| Richard Uhler | 9b994ea | 2015-06-24 08:44:19 -0700 | [diff] [blame] | 1009 |       error_msgs->push_back("No original dex files found for dex location " | 
 | 1010 |           + std::string(dex_location)); | 
| Jean Christophe Beyler | 24e04aa | 2014-09-12 12:03:25 -0700 | [diff] [blame] | 1011 |     } | 
| Andreas Gampe | 833a485 | 2014-05-21 18:46:59 -0700 | [diff] [blame] | 1012 |   } | 
| Richard Uhler | 66d874d | 2015-01-15 09:37:19 -0800 | [diff] [blame] | 1013 |   return dex_files; | 
| Brian Carlstrom | aded5f7 | 2011-10-07 17:15:04 -0700 | [diff] [blame] | 1014 | } | 
 | 1015 |  | 
| Brian Carlstrom | ae82698 | 2011-11-09 01:33:42 -0800 | [diff] [blame] | 1016 | const OatFile* ClassLinker::FindOpenedOatFileFromOatLocation(const std::string& oat_location) { | 
| Ian Rogers | 8d31bbd | 2013-10-13 10:44:14 -0700 | [diff] [blame] | 1017 |   ReaderMutexLock mu(Thread::Current(), dex_lock_); | 
| Brian Carlstrom | aded5f7 | 2011-10-07 17:15:04 -0700 | [diff] [blame] | 1018 |   for (size_t i = 0; i < oat_files_.size(); i++) { | 
 | 1019 |     const OatFile* oat_file = oat_files_[i]; | 
| Ian Rogers | 8d31bbd | 2013-10-13 10:44:14 -0700 | [diff] [blame] | 1020 |     DCHECK(oat_file != nullptr); | 
| Brian Carlstrom | ae82698 | 2011-11-09 01:33:42 -0800 | [diff] [blame] | 1021 |     if (oat_file->GetLocation() == oat_location) { | 
| Brian Carlstrom | aded5f7 | 2011-10-07 17:15:04 -0700 | [diff] [blame] | 1022 |       return oat_file; | 
 | 1023 |     } | 
 | 1024 |   } | 
| Ian Rogers | 8d31bbd | 2013-10-13 10:44:14 -0700 | [diff] [blame] | 1025 |   return nullptr; | 
| Brian Carlstrom | fad7143 | 2011-10-16 20:25:10 -0700 | [diff] [blame] | 1026 | } | 
| Brian Carlstrom | aded5f7 | 2011-10-07 17:15:04 -0700 | [diff] [blame] | 1027 |  | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 1028 | static void SanityCheckArtMethod(ArtMethod* m, mirror::Class* expected_class, | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 1029 |                                  gc::space::ImageSpace* space) | 
| Mathieu Chartier | 9044347 | 2015-07-16 20:32:27 -0700 | [diff] [blame] | 1030 |     SHARED_REQUIRES(Locks::mutator_lock_) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 1031 |   if (m->IsRuntimeMethod()) { | 
 | 1032 |     CHECK(m->GetDeclaringClass() == nullptr) << PrettyMethod(m); | 
 | 1033 |   } else if (m->IsMiranda()) { | 
 | 1034 |     CHECK(m->GetDeclaringClass() != nullptr) << PrettyMethod(m); | 
 | 1035 |   } else if (expected_class != nullptr) { | 
 | 1036 |     CHECK_EQ(m->GetDeclaringClassUnchecked(), expected_class) << PrettyMethod(m); | 
 | 1037 |   } | 
 | 1038 |   if (space != nullptr) { | 
 | 1039 |     auto& header = space->GetImageHeader(); | 
 | 1040 |     auto& methods = header.GetMethodsSection(); | 
 | 1041 |     auto offset = reinterpret_cast<uint8_t*>(m) - space->Begin(); | 
 | 1042 |     CHECK(methods.Contains(offset)) << m << " not in " << methods; | 
 | 1043 |   } | 
 | 1044 | } | 
 | 1045 |  | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 1046 | static void SanityCheckArtMethodPointerArray( | 
 | 1047 |     mirror::PointerArray* arr, mirror::Class* expected_class, size_t pointer_size, | 
 | 1048 |     gc::space::ImageSpace* space) SHARED_REQUIRES(Locks::mutator_lock_) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 1049 |   CHECK(arr != nullptr); | 
 | 1050 |   for (int32_t j = 0; j < arr->GetLength(); ++j) { | 
 | 1051 |     auto* method = arr->GetElementPtrSize<ArtMethod*>(j, pointer_size); | 
 | 1052 |     // expected_class == null means we are a dex cache. | 
 | 1053 |     if (expected_class != nullptr) { | 
 | 1054 |       CHECK(method != nullptr); | 
 | 1055 |     } | 
 | 1056 |     if (method != nullptr) { | 
 | 1057 |       SanityCheckArtMethod(method, expected_class, space); | 
| Ian Rogers | 848871b | 2013-08-05 10:56:33 -0700 | [diff] [blame] | 1058 |     } | 
 | 1059 |   } | 
 | 1060 | } | 
 | 1061 |  | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 1062 | static void SanityCheckObjectsCallback(mirror::Object* obj, void* arg ATTRIBUTE_UNUSED) | 
| Mathieu Chartier | 9044347 | 2015-07-16 20:32:27 -0700 | [diff] [blame] | 1063 |     SHARED_REQUIRES(Locks::mutator_lock_) { | 
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 1064 |   DCHECK(obj != nullptr); | 
| Mathieu Chartier | d39645e | 2015-06-09 17:50:29 -0700 | [diff] [blame] | 1065 |   CHECK(obj->GetClass() != nullptr) << "Null class in object " << obj; | 
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 1066 |   CHECK(obj->GetClass()->GetClass() != nullptr) << "Null class class " << obj; | 
 | 1067 |   if (obj->IsClass()) { | 
 | 1068 |     auto klass = obj->AsClass(); | 
| Mathieu Chartier | 54d220e | 2015-07-30 16:20:06 -0700 | [diff] [blame] | 1069 |     for (ArtField& field : klass->GetIFields()) { | 
 | 1070 |       CHECK_EQ(field.GetDeclaringClass(), klass); | 
 | 1071 |     } | 
 | 1072 |     for (ArtField& field : klass->GetSFields()) { | 
 | 1073 |       CHECK_EQ(field.GetDeclaringClass(), klass); | 
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 1074 |     } | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 1075 |     auto* runtime = Runtime::Current(); | 
 | 1076 |     auto* image_space = runtime->GetHeap()->GetImageSpace(); | 
 | 1077 |     auto pointer_size = runtime->GetClassLinker()->GetImagePointerSize(); | 
 | 1078 |     for (auto& m : klass->GetDirectMethods(pointer_size)) { | 
 | 1079 |       SanityCheckArtMethod(&m, klass, image_space); | 
 | 1080 |     } | 
 | 1081 |     for (auto& m : klass->GetVirtualMethods(pointer_size)) { | 
 | 1082 |       SanityCheckArtMethod(&m, klass, image_space); | 
 | 1083 |     } | 
 | 1084 |     auto* vtable = klass->GetVTable(); | 
 | 1085 |     if (vtable != nullptr) { | 
 | 1086 |       SanityCheckArtMethodPointerArray(vtable, nullptr, pointer_size, image_space); | 
 | 1087 |     } | 
 | 1088 |     if (klass->ShouldHaveEmbeddedImtAndVTable()) { | 
 | 1089 |       for (size_t i = 0; i < mirror::Class::kImtSize; ++i) { | 
 | 1090 |         SanityCheckArtMethod(klass->GetEmbeddedImTableEntry(i, pointer_size), nullptr, image_space); | 
 | 1091 |       } | 
 | 1092 |       for (int32_t i = 0; i < klass->GetEmbeddedVTableLength(); ++i) { | 
 | 1093 |         SanityCheckArtMethod(klass->GetEmbeddedVTableEntry(i, pointer_size), nullptr, image_space); | 
 | 1094 |       } | 
 | 1095 |     } | 
 | 1096 |     auto* iftable = klass->GetIfTable(); | 
 | 1097 |     if (iftable != nullptr) { | 
 | 1098 |       for (int32_t i = 0; i < klass->GetIfTableCount(); ++i) { | 
 | 1099 |         if (iftable->GetMethodArrayCount(i) > 0) { | 
 | 1100 |           SanityCheckArtMethodPointerArray(iftable->GetMethodArray(i), nullptr, pointer_size, | 
 | 1101 |                                            image_space); | 
 | 1102 |         } | 
 | 1103 |       } | 
 | 1104 |     } | 
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 1105 |   } | 
 | 1106 | } | 
 | 1107 |  | 
| Sebastien Hertz | 46e857a | 2015-08-06 12:52:43 +0200 | [diff] [blame] | 1108 | // Set image methods' entry point to interpreter. | 
 | 1109 | class SetInterpreterEntrypointArtMethodVisitor : public ArtMethodVisitor { | 
 | 1110 |  public: | 
 | 1111 |   explicit SetInterpreterEntrypointArtMethodVisitor(size_t image_pointer_size) | 
 | 1112 |     : image_pointer_size_(image_pointer_size) {} | 
 | 1113 |  | 
 | 1114 |   void Visit(ArtMethod* method) OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) { | 
 | 1115 |     if (kIsDebugBuild && !method->IsRuntimeMethod()) { | 
 | 1116 |       CHECK(method->GetDeclaringClass() != nullptr); | 
 | 1117 |     } | 
 | 1118 |     if (!method->IsNative() && !method->IsRuntimeMethod() && !method->IsResolutionMethod()) { | 
 | 1119 |       method->SetEntryPointFromQuickCompiledCodePtrSize(GetQuickToInterpreterBridge(), | 
 | 1120 |                                                         image_pointer_size_); | 
 | 1121 |     } | 
 | 1122 |   } | 
 | 1123 |  | 
 | 1124 |  private: | 
 | 1125 |   const size_t image_pointer_size_; | 
 | 1126 |  | 
 | 1127 |   DISALLOW_COPY_AND_ASSIGN(SetInterpreterEntrypointArtMethodVisitor); | 
 | 1128 | }; | 
 | 1129 |  | 
| Brian Carlstrom | 58ae941 | 2011-10-04 00:56:06 -0700 | [diff] [blame] | 1130 | void ClassLinker::InitFromImage() { | 
| Elliott Hughes | 4dd9b4d | 2011-12-12 18:29:24 -0800 | [diff] [blame] | 1131 |   VLOG(startup) << "ClassLinker::InitFromImage entering"; | 
| Brian Carlstrom | a663ea5 | 2011-08-19 23:33:41 -0700 | [diff] [blame] | 1132 |   CHECK(!init_done_); | 
 | 1133 |  | 
| Mathieu Chartier | daaf326 | 2015-03-24 13:30:28 -0700 | [diff] [blame] | 1134 |   Runtime* const runtime = Runtime::Current(); | 
 | 1135 |   Thread* const self = Thread::Current(); | 
 | 1136 |   gc::Heap* const heap = runtime->GetHeap(); | 
 | 1137 |   gc::space::ImageSpace* const space = heap->GetImageSpace(); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 1138 |   CHECK(space != nullptr); | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 1139 |   image_pointer_size_ = space->GetImageHeader().GetPointerSize(); | 
 | 1140 |   dex_cache_image_class_lookup_required_ = true; | 
| Brian Carlstrom | 56d947f | 2013-07-15 13:14:23 -0700 | [diff] [blame] | 1141 |   OatFile& oat_file = GetImageOatFile(space); | 
 | 1142 |   CHECK_EQ(oat_file.GetOatHeader().GetImageFileLocationOatChecksum(), 0U); | 
 | 1143 |   CHECK_EQ(oat_file.GetOatHeader().GetImageFileLocationOatDataBegin(), 0U); | 
| Andreas Gampe | 22f8e5c | 2014-07-09 11:38:21 -0700 | [diff] [blame] | 1144 |   const char* image_file_location = oat_file.GetOatHeader(). | 
 | 1145 |       GetStoreValueByKey(OatHeader::kImageLocationKey); | 
 | 1146 |   CHECK(image_file_location == nullptr || *image_file_location == 0); | 
| Brian Carlstrom | 56d947f | 2013-07-15 13:14:23 -0700 | [diff] [blame] | 1147 |   quick_resolution_trampoline_ = oat_file.GetOatHeader().GetQuickResolutionTrampoline(); | 
| Jeff Hao | 88474b4 | 2013-10-23 16:24:40 -0700 | [diff] [blame] | 1148 |   quick_imt_conflict_trampoline_ = oat_file.GetOatHeader().GetQuickImtConflictTrampoline(); | 
| Andreas Gampe | 2da8823 | 2014-02-27 12:26:20 -0800 | [diff] [blame] | 1149 |   quick_generic_jni_trampoline_ = oat_file.GetOatHeader().GetQuickGenericJniTrampoline(); | 
| Vladimir Marko | 8a63057 | 2014-04-09 18:45:35 +0100 | [diff] [blame] | 1150 |   quick_to_interpreter_bridge_trampoline_ = oat_file.GetOatHeader().GetQuickToInterpreterBridge(); | 
| Mathieu Chartier | 673ed3d | 2015-08-28 14:56:43 -0700 | [diff] [blame^] | 1151 |   StackHandleScope<2> hs(self); | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 1152 |   mirror::Object* dex_caches_object = space->GetImageHeader().GetImageRoot(ImageHeader::kDexCaches); | 
| Mathieu Chartier | 673ed3d | 2015-08-28 14:56:43 -0700 | [diff] [blame^] | 1153 |   Handle<mirror::ObjectArray<mirror::DexCache>> dex_caches( | 
 | 1154 |       hs.NewHandle(dex_caches_object->AsObjectArray<mirror::DexCache>())); | 
| Brian Carlstrom | 58ae941 | 2011-10-04 00:56:06 -0700 | [diff] [blame] | 1155 |  | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 1156 |   Handle<mirror::ObjectArray<mirror::Class>> class_roots(hs.NewHandle( | 
 | 1157 |           space->GetImageHeader().GetImageRoot(ImageHeader::kClassRoots)-> | 
 | 1158 |           AsObjectArray<mirror::Class>())); | 
| Hiroshi Yamauchi | 94f7b49 | 2014-07-22 18:08:23 -0700 | [diff] [blame] | 1159 |   class_roots_ = GcRoot<mirror::ObjectArray<mirror::Class>>(class_roots.Get()); | 
| Mathieu Chartier | 02b6a78 | 2012-10-26 13:51:26 -0700 | [diff] [blame] | 1160 |  | 
| Brian Carlstrom | fddf6f6 | 2012-03-15 16:56:45 -0700 | [diff] [blame] | 1161 |   // Special case of setting up the String class early so that we can test arbitrary objects | 
 | 1162 |   // as being Strings or not | 
| Anwar Ghuloum | c4f105d | 2013-04-10 16:12:11 -0700 | [diff] [blame] | 1163 |   mirror::String::SetClass(GetClassRoot(kJavaLangString)); | 
| Ian Rogers | 6d4d9fc | 2011-11-30 16:24:48 -0800 | [diff] [blame] | 1164 |  | 
| Mathieu Chartier | 673ed3d | 2015-08-28 14:56:43 -0700 | [diff] [blame^] | 1165 |   mirror::Class* java_lang_Object = GetClassRoot(kJavaLangObject); | 
 | 1166 |   java_lang_Object->SetObjectSize(sizeof(mirror::Object)); | 
 | 1167 |   Runtime::Current()->SetSentinel(Runtime::Current()->GetHeap()->AllocObject<true>(self, | 
 | 1168 |                                                           java_lang_Object, | 
 | 1169 |                                                           java_lang_Object->GetObjectSize(), | 
 | 1170 |                                                           VoidFunctor())); | 
 | 1171 |  | 
| Brian Carlstrom | 56d947f | 2013-07-15 13:14:23 -0700 | [diff] [blame] | 1172 |   CHECK_EQ(oat_file.GetOatHeader().GetDexFileCount(), | 
| Brian Carlstrom | fddf6f6 | 2012-03-15 16:56:45 -0700 | [diff] [blame] | 1173 |            static_cast<uint32_t>(dex_caches->GetLength())); | 
| Ian Rogers | 7dfb28c | 2013-08-22 08:18:36 -0700 | [diff] [blame] | 1174 |   for (int32_t i = 0; i < dex_caches->GetLength(); i++) { | 
| Andreas Gampe | 277ccbd | 2014-11-03 21:36:10 -0800 | [diff] [blame] | 1175 |     StackHandleScope<1> hs2(self); | 
 | 1176 |     Handle<mirror::DexCache> dex_cache(hs2.NewHandle(dex_caches->Get(i))); | 
| Brian Carlstrom | fddf6f6 | 2012-03-15 16:56:45 -0700 | [diff] [blame] | 1177 |     const std::string& dex_file_location(dex_cache->GetLocation()->ToModifiedUtf8()); | 
| Ian Rogers | 8d31bbd | 2013-10-13 10:44:14 -0700 | [diff] [blame] | 1178 |     const OatFile::OatDexFile* oat_dex_file = oat_file.GetOatDexFile(dex_file_location.c_str(), | 
 | 1179 |                                                                      nullptr); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 1180 |     CHECK(oat_dex_file != nullptr) << oat_file.GetLocation() << " " << dex_file_location; | 
| Ian Rogers | 8d31bbd | 2013-10-13 10:44:14 -0700 | [diff] [blame] | 1181 |     std::string error_msg; | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 1182 |     std::unique_ptr<const DexFile> dex_file = oat_dex_file->OpenDexFile(&error_msg); | 
| Richard Uhler | fbef44d | 2014-12-23 09:48:51 -0800 | [diff] [blame] | 1183 |     if (dex_file.get() == nullptr) { | 
| Brian Carlstrom | fddf6f6 | 2012-03-15 16:56:45 -0700 | [diff] [blame] | 1184 |       LOG(FATAL) << "Failed to open dex file " << dex_file_location | 
| Ian Rogers | 8d31bbd | 2013-10-13 10:44:14 -0700 | [diff] [blame] | 1185 |                  << " from within oat file " << oat_file.GetLocation() | 
 | 1186 |                  << " error '" << error_msg << "'"; | 
| Ian Rogers | e0a02da | 2014-12-02 14:10:53 -0800 | [diff] [blame] | 1187 |       UNREACHABLE(); | 
| Brian Carlstrom | 58ae941 | 2011-10-04 00:56:06 -0700 | [diff] [blame] | 1188 |     } | 
| Brian Carlstrom | fddf6f6 | 2012-03-15 16:56:45 -0700 | [diff] [blame] | 1189 |  | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 1190 |     if (kSanityCheckObjects) { | 
 | 1191 |       SanityCheckArtMethodPointerArray(dex_cache->GetResolvedMethods(), nullptr, | 
 | 1192 |                                        image_pointer_size_, space); | 
 | 1193 |     } | 
 | 1194 |  | 
| Brian Carlstrom | fddf6f6 | 2012-03-15 16:56:45 -0700 | [diff] [blame] | 1195 |     CHECK_EQ(dex_file->GetLocationChecksum(), oat_dex_file->GetDexFileLocationChecksum()); | 
 | 1196 |  | 
| Richard Uhler | fbef44d | 2014-12-23 09:48:51 -0800 | [diff] [blame] | 1197 |     AppendToBootClassPath(*dex_file.get(), dex_cache); | 
 | 1198 |     opened_dex_files_.push_back(std::move(dex_file)); | 
| Brian Carlstrom | 58ae941 | 2011-10-04 00:56:06 -0700 | [diff] [blame] | 1199 |   } | 
 | 1200 |  | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 1201 |   CHECK(ValidPointerSize(image_pointer_size_)) << image_pointer_size_; | 
 | 1202 |  | 
| Anwar Ghuloum | c4f105d | 2013-04-10 16:12:11 -0700 | [diff] [blame] | 1203 |   // Set classes on AbstractMethod early so that IsMethod tests can be performed during the live | 
 | 1204 |   // bitmap walk. | 
| Mathieu Chartier | daaf326 | 2015-03-24 13:30:28 -0700 | [diff] [blame] | 1205 |   if (!runtime->IsAotCompiler()) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 1206 |     // Only the Aot compiler supports having an image with a different pointer size than the | 
 | 1207 |     // runtime. This happens on the host for compile 32 bit tests since we use a 64 bit libart | 
 | 1208 |     // compiler. We may also use 32 bit dex2oat on a system with 64 bit apps. | 
 | 1209 |     CHECK_EQ(image_pointer_size_, sizeof(void*)); | 
| Mathieu Chartier | 2d72101 | 2014-11-10 11:08:06 -0800 | [diff] [blame] | 1210 |   } | 
| Anwar Ghuloum | c4f105d | 2013-04-10 16:12:11 -0700 | [diff] [blame] | 1211 |  | 
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 1212 |   if (kSanityCheckObjects) { | 
 | 1213 |     for (int32_t i = 0; i < dex_caches->GetLength(); i++) { | 
 | 1214 |       auto* dex_cache = dex_caches->Get(i); | 
 | 1215 |       for (size_t j = 0; j < dex_cache->NumResolvedFields(); ++j) { | 
 | 1216 |         auto* field = dex_cache->GetResolvedField(j, image_pointer_size_); | 
 | 1217 |         if (field != nullptr) { | 
 | 1218 |           CHECK(field->GetDeclaringClass()->GetClass() != nullptr); | 
 | 1219 |         } | 
 | 1220 |       } | 
 | 1221 |     } | 
 | 1222 |     heap->VisitObjects(SanityCheckObjectsCallback, nullptr); | 
 | 1223 |   } | 
| Brian Carlstrom | a663ea5 | 2011-08-19 23:33:41 -0700 | [diff] [blame] | 1224 |  | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 1225 |   // Set entry point to interpreter if in InterpretOnly mode. | 
 | 1226 |   if (!runtime->IsAotCompiler() && runtime->GetInstrumentation()->InterpretOnly()) { | 
| Sebastien Hertz | 46e857a | 2015-08-06 12:52:43 +0200 | [diff] [blame] | 1227 |     const ImageHeader& header = space->GetImageHeader(); | 
 | 1228 |     const ImageSection& methods = header.GetMethodsSection(); | 
| Sebastien Hertz | 46e857a | 2015-08-06 12:52:43 +0200 | [diff] [blame] | 1229 |     SetInterpreterEntrypointArtMethodVisitor visitor(image_pointer_size_); | 
| Vladimir Marko | cf36d49 | 2015-08-12 19:27:26 +0100 | [diff] [blame] | 1230 |     methods.VisitPackedArtMethods(&visitor, space->Begin(), image_pointer_size_); | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 1231 |   } | 
 | 1232 |  | 
| Brian Carlstrom | a663ea5 | 2011-08-19 23:33:41 -0700 | [diff] [blame] | 1233 |   // reinit class_roots_ | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 1234 |   mirror::Class::SetClassClass(class_roots->Get(kJavaLangClass)); | 
| Hiroshi Yamauchi | 94f7b49 | 2014-07-22 18:08:23 -0700 | [diff] [blame] | 1235 |   class_roots_ = GcRoot<mirror::ObjectArray<mirror::Class>>(class_roots.Get()); | 
| Brian Carlstrom | a663ea5 | 2011-08-19 23:33:41 -0700 | [diff] [blame] | 1236 |  | 
| Ian Rogers | 6d4d9fc | 2011-11-30 16:24:48 -0800 | [diff] [blame] | 1237 |   // reinit array_iftable_ from any array class instance, they should be == | 
| Hiroshi Yamauchi | 94f7b49 | 2014-07-22 18:08:23 -0700 | [diff] [blame] | 1238 |   array_iftable_ = GcRoot<mirror::IfTable>(GetClassRoot(kObjectArrayClass)->GetIfTable()); | 
| Mathieu Chartier | 2d72101 | 2014-11-10 11:08:06 -0800 | [diff] [blame] | 1239 |   DCHECK_EQ(array_iftable_.Read(), GetClassRoot(kBooleanArrayClass)->GetIfTable()); | 
| Ian Rogers | 6d4d9fc | 2011-11-30 16:24:48 -0800 | [diff] [blame] | 1240 |   // String class root was set above | 
| Mathieu Chartier | daaf326 | 2015-03-24 13:30:28 -0700 | [diff] [blame] | 1241 |   mirror::Field::SetClass(GetClassRoot(kJavaLangReflectField)); | 
 | 1242 |   mirror::Field::SetArrayClass(GetClassRoot(kJavaLangReflectFieldArrayClass)); | 
| Mathieu Chartier | fc58af4 | 2015-04-16 18:00:39 -0700 | [diff] [blame] | 1243 |   mirror::Constructor::SetClass(GetClassRoot(kJavaLangReflectConstructor)); | 
 | 1244 |   mirror::Constructor::SetArrayClass(GetClassRoot(kJavaLangReflectConstructorArrayClass)); | 
 | 1245 |   mirror::Method::SetClass(GetClassRoot(kJavaLangReflectMethod)); | 
 | 1246 |   mirror::Method::SetArrayClass(GetClassRoot(kJavaLangReflectMethodArrayClass)); | 
| Fred Shih | 4ee7a66 | 2014-07-11 09:59:27 -0700 | [diff] [blame] | 1247 |   mirror::Reference::SetClass(GetClassRoot(kJavaLangRefReference)); | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 1248 |   mirror::BooleanArray::SetArrayClass(GetClassRoot(kBooleanArrayClass)); | 
 | 1249 |   mirror::ByteArray::SetArrayClass(GetClassRoot(kByteArrayClass)); | 
 | 1250 |   mirror::CharArray::SetArrayClass(GetClassRoot(kCharArrayClass)); | 
 | 1251 |   mirror::DoubleArray::SetArrayClass(GetClassRoot(kDoubleArrayClass)); | 
 | 1252 |   mirror::FloatArray::SetArrayClass(GetClassRoot(kFloatArrayClass)); | 
 | 1253 |   mirror::IntArray::SetArrayClass(GetClassRoot(kIntArrayClass)); | 
 | 1254 |   mirror::LongArray::SetArrayClass(GetClassRoot(kLongArrayClass)); | 
 | 1255 |   mirror::ShortArray::SetArrayClass(GetClassRoot(kShortArrayClass)); | 
 | 1256 |   mirror::Throwable::SetClass(GetClassRoot(kJavaLangThrowable)); | 
 | 1257 |   mirror::StackTraceElement::SetClass(GetClassRoot(kJavaLangStackTraceElement)); | 
| Brian Carlstrom | a663ea5 | 2011-08-19 23:33:41 -0700 | [diff] [blame] | 1258 |  | 
| Ian Rogers | 9837939 | 2014-02-24 16:53:16 -0800 | [diff] [blame] | 1259 |   FinishInit(self); | 
| Brian Carlstrom | 0a5b14d | 2011-09-27 13:29:15 -0700 | [diff] [blame] | 1260 |  | 
| Elliott Hughes | 4dd9b4d | 2011-12-12 18:29:24 -0800 | [diff] [blame] | 1261 |   VLOG(startup) << "ClassLinker::InitFromImage exiting"; | 
| Brian Carlstrom | a663ea5 | 2011-08-19 23:33:41 -0700 | [diff] [blame] | 1262 | } | 
 | 1263 |  | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 1264 | bool ClassLinker::ClassInClassTable(mirror::Class* klass) { | 
| Mathieu Chartier | cc5ebdf | 2015-07-27 11:19:43 -0700 | [diff] [blame] | 1265 |   ClassTable* const class_table = ClassTableForClassLoader(klass->GetClassLoader()); | 
 | 1266 |   return class_table != nullptr && class_table->Contains(klass); | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 1267 | } | 
 | 1268 |  | 
| Mathieu Chartier | bb87e0f | 2015-04-03 11:21:55 -0700 | [diff] [blame] | 1269 | void ClassLinker::VisitClassRoots(RootVisitor* visitor, VisitRootFlags flags) { | 
| Mathieu Chartier | 52e4b43 | 2014-06-10 11:22:31 -0700 | [diff] [blame] | 1270 |   WriterMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_); | 
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 1271 |   BufferedRootVisitor<kDefaultBufferedRootCount> buffered_visitor( | 
 | 1272 |       visitor, RootInfo(kRootStickyClass)); | 
| Mathieu Chartier | 52e4b43 | 2014-06-10 11:22:31 -0700 | [diff] [blame] | 1273 |   if ((flags & kVisitRootFlagAllRoots) != 0) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 1274 |     // Argument for how root visiting deals with ArtField and ArtMethod roots. | 
 | 1275 |     // There is 3 GC cases to handle: | 
 | 1276 |     // Non moving concurrent: | 
 | 1277 |     // This case is easy to handle since the reference members of ArtMethod and ArtFields are held | 
| Mathieu Chartier | da7c650 | 2015-07-23 16:01:26 -0700 | [diff] [blame] | 1278 |     // live by the class and class roots. | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 1279 |     // | 
 | 1280 |     // Moving non-concurrent: | 
 | 1281 |     // This case needs to call visit VisitNativeRoots in case the classes or dex cache arrays move. | 
 | 1282 |     // To prevent missing roots, this case needs to ensure that there is no | 
 | 1283 |     // suspend points between the point which we allocate ArtMethod arrays and place them in a | 
 | 1284 |     // class which is in the class table. | 
 | 1285 |     // | 
 | 1286 |     // Moving concurrent: | 
 | 1287 |     // Need to make sure to not copy ArtMethods without doing read barriers since the roots are | 
 | 1288 |     // marked concurrently and we don't hold the classlinker_classes_lock_ when we do the copy. | 
| Mathieu Chartier | e4275c0 | 2015-08-06 15:34:15 -0700 | [diff] [blame] | 1289 |     boot_class_table_.VisitRoots(buffered_visitor); | 
| Mathieu Chartier | 6b06953 | 2015-08-05 15:08:12 -0700 | [diff] [blame] | 1290 |     for (GcRoot<mirror::ClassLoader>& root : class_loaders_) { | 
 | 1291 |       // May be null for boot ClassLoader. | 
 | 1292 |       root.VisitRoot(visitor, RootInfo(kRootVMInternal)); | 
| Mathieu Chartier | c2e2062 | 2014-11-03 11:41:47 -0800 | [diff] [blame] | 1293 |     } | 
| Mathieu Chartier | 52e4b43 | 2014-06-10 11:22:31 -0700 | [diff] [blame] | 1294 |   } else if ((flags & kVisitRootFlagNewRoots) != 0) { | 
| Mathieu Chartier | c2e2062 | 2014-11-03 11:41:47 -0800 | [diff] [blame] | 1295 |     for (auto& root : new_class_roots_) { | 
 | 1296 |       mirror::Class* old_ref = root.Read<kWithoutReadBarrier>(); | 
| Mathieu Chartier | bb87e0f | 2015-04-03 11:21:55 -0700 | [diff] [blame] | 1297 |       root.VisitRoot(visitor, RootInfo(kRootStickyClass)); | 
| Mathieu Chartier | c2e2062 | 2014-11-03 11:41:47 -0800 | [diff] [blame] | 1298 |       mirror::Class* new_ref = root.Read<kWithoutReadBarrier>(); | 
| Mathieu Chartier | cc5ebdf | 2015-07-27 11:19:43 -0700 | [diff] [blame] | 1299 |       // Concurrent moving GC marked new roots through the to-space invariant. | 
 | 1300 |       CHECK_EQ(new_ref, old_ref); | 
| Mathieu Chartier | 52e4b43 | 2014-06-10 11:22:31 -0700 | [diff] [blame] | 1301 |     } | 
 | 1302 |   } | 
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 1303 |   buffered_visitor.Flush();  // Flush before clearing new_class_roots_. | 
| Mathieu Chartier | 52e4b43 | 2014-06-10 11:22:31 -0700 | [diff] [blame] | 1304 |   if ((flags & kVisitRootFlagClearRootLog) != 0) { | 
 | 1305 |     new_class_roots_.clear(); | 
 | 1306 |   } | 
 | 1307 |   if ((flags & kVisitRootFlagStartLoggingNewRoots) != 0) { | 
 | 1308 |     log_new_class_table_roots_ = true; | 
 | 1309 |   } else if ((flags & kVisitRootFlagStopLoggingNewRoots) != 0) { | 
 | 1310 |     log_new_class_table_roots_ = false; | 
 | 1311 |   } | 
 | 1312 |   // We deliberately ignore the class roots in the image since we | 
 | 1313 |   // handle image roots by using the MS/CMS rescanning of dirty cards. | 
 | 1314 | } | 
 | 1315 |  | 
| Brian Carlstrom | a663ea5 | 2011-08-19 23:33:41 -0700 | [diff] [blame] | 1316 | // Keep in sync with InitCallback. Anything we visit, we need to | 
 | 1317 | // reinit references to when reinitializing a ClassLinker from a | 
 | 1318 | // mapped image. | 
| Mathieu Chartier | bb87e0f | 2015-04-03 11:21:55 -0700 | [diff] [blame] | 1319 | void ClassLinker::VisitRoots(RootVisitor* visitor, VisitRootFlags flags) { | 
| Mathieu Chartier | 3100080 | 2015-06-14 14:14:37 -0700 | [diff] [blame] | 1320 |   class_roots_.VisitRootIfNonNull(visitor, RootInfo(kRootVMInternal)); | 
| Mathieu Chartier | bb87e0f | 2015-04-03 11:21:55 -0700 | [diff] [blame] | 1321 |   VisitClassRoots(visitor, flags); | 
| Mathieu Chartier | 3100080 | 2015-06-14 14:14:37 -0700 | [diff] [blame] | 1322 |   array_iftable_.VisitRootIfNonNull(visitor, RootInfo(kRootVMInternal)); | 
 | 1323 |   for (GcRoot<mirror::Class>& root : find_array_class_cache_) { | 
 | 1324 |     root.VisitRootIfNonNull(visitor, RootInfo(kRootVMInternal)); | 
| Ian Rogers | 9837939 | 2014-02-24 16:53:16 -0800 | [diff] [blame] | 1325 |   } | 
| Brian Carlstrom | 578bbdc | 2011-07-21 14:07:47 -0700 | [diff] [blame] | 1326 | } | 
 | 1327 |  | 
| Mathieu Chartier | e0671ce | 2015-07-28 17:23:28 -0700 | [diff] [blame] | 1328 | void ClassLinker::VisitClassesInternal(ClassVisitor* visitor) { | 
| Mathieu Chartier | 6b06953 | 2015-08-05 15:08:12 -0700 | [diff] [blame] | 1329 |   if (boot_class_table_.Visit(visitor)) { | 
 | 1330 |     for (GcRoot<mirror::ClassLoader>& root : class_loaders_) { | 
 | 1331 |       ClassTable* const class_table = root.Read()->GetClassTable(); | 
 | 1332 |       if (class_table != nullptr && !class_table->Visit(visitor)) { | 
 | 1333 |         return; | 
 | 1334 |       } | 
| Mathieu Chartier | cc5ebdf | 2015-07-27 11:19:43 -0700 | [diff] [blame] | 1335 |     } | 
 | 1336 |   } | 
 | 1337 | } | 
 | 1338 |  | 
| Mathieu Chartier | e0671ce | 2015-07-28 17:23:28 -0700 | [diff] [blame] | 1339 | void ClassLinker::VisitClasses(ClassVisitor* visitor) { | 
| Ian Rogers | 7dfb28c | 2013-08-22 08:18:36 -0700 | [diff] [blame] | 1340 |   if (dex_cache_image_class_lookup_required_) { | 
 | 1341 |     MoveImageClassesToClassTable(); | 
| Elliott Hughes | a215526 | 2011-11-16 16:26:58 -0800 | [diff] [blame] | 1342 |   } | 
| Mathieu Chartier | cc5ebdf | 2015-07-27 11:19:43 -0700 | [diff] [blame] | 1343 |   Thread* const self = Thread::Current(); | 
 | 1344 |   ReaderMutexLock mu(self, *Locks::classlinker_classes_lock_); | 
 | 1345 |   // Not safe to have thread suspension when we are holding a lock. | 
 | 1346 |   if (self != nullptr) { | 
 | 1347 |     ScopedAssertNoThreadSuspension nts(self, __FUNCTION__); | 
| Mathieu Chartier | e0671ce | 2015-07-28 17:23:28 -0700 | [diff] [blame] | 1348 |     VisitClassesInternal(visitor); | 
| Mathieu Chartier | cc5ebdf | 2015-07-27 11:19:43 -0700 | [diff] [blame] | 1349 |   } else { | 
| Mathieu Chartier | e0671ce | 2015-07-28 17:23:28 -0700 | [diff] [blame] | 1350 |     VisitClassesInternal(visitor); | 
| Elliott Hughes | a215526 | 2011-11-16 16:26:58 -0800 | [diff] [blame] | 1351 |   } | 
 | 1352 | } | 
 | 1353 |  | 
| Mathieu Chartier | e0671ce | 2015-07-28 17:23:28 -0700 | [diff] [blame] | 1354 | class GetClassesInToVector : public ClassVisitor { | 
 | 1355 |  public: | 
 | 1356 |   bool Visit(mirror::Class* klass) OVERRIDE { | 
 | 1357 |     classes_.push_back(klass); | 
 | 1358 |     return true; | 
 | 1359 |   } | 
 | 1360 |   std::vector<mirror::Class*> classes_; | 
| Ian Rogers | dbf3be0 | 2014-08-29 15:40:08 -0700 | [diff] [blame] | 1361 | }; | 
 | 1362 |  | 
| Mathieu Chartier | e0671ce | 2015-07-28 17:23:28 -0700 | [diff] [blame] | 1363 | class GetClassInToObjectArray : public ClassVisitor { | 
 | 1364 |  public: | 
 | 1365 |   explicit GetClassInToObjectArray(mirror::ObjectArray<mirror::Class>* arr) | 
 | 1366 |       : arr_(arr), index_(0) {} | 
 | 1367 |  | 
 | 1368 |   bool Visit(mirror::Class* klass) OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) { | 
 | 1369 |     ++index_; | 
 | 1370 |     if (index_ <= arr_->GetLength()) { | 
 | 1371 |       arr_->Set(index_ - 1, klass); | 
 | 1372 |       return true; | 
 | 1373 |     } | 
| Ian Rogers | dbf3be0 | 2014-08-29 15:40:08 -0700 | [diff] [blame] | 1374 |     return false; | 
 | 1375 |   } | 
| Ian Rogers | dbf3be0 | 2014-08-29 15:40:08 -0700 | [diff] [blame] | 1376 |  | 
| Mathieu Chartier | e0671ce | 2015-07-28 17:23:28 -0700 | [diff] [blame] | 1377 |   bool Succeeded() const SHARED_REQUIRES(Locks::mutator_lock_) { | 
 | 1378 |     return index_ <= arr_->GetLength(); | 
 | 1379 |   } | 
 | 1380 |  | 
 | 1381 |  private: | 
 | 1382 |   mirror::ObjectArray<mirror::Class>* const arr_; | 
 | 1383 |   int32_t index_; | 
 | 1384 | }; | 
 | 1385 |  | 
 | 1386 | void ClassLinker::VisitClassesWithoutClassesLock(ClassVisitor* visitor) { | 
| Ian Rogers | dbf3be0 | 2014-08-29 15:40:08 -0700 | [diff] [blame] | 1387 |   // TODO: it may be possible to avoid secondary storage if we iterate over dex caches. The problem | 
 | 1388 |   // is avoiding duplicates. | 
 | 1389 |   if (!kMovingClasses) { | 
| Mathieu Chartier | e0671ce | 2015-07-28 17:23:28 -0700 | [diff] [blame] | 1390 |     GetClassesInToVector accumulator; | 
 | 1391 |     VisitClasses(&accumulator); | 
 | 1392 |     for (mirror::Class* klass : accumulator.classes_) { | 
 | 1393 |       if (!visitor->Visit(klass)) { | 
| Ian Rogers | dbf3be0 | 2014-08-29 15:40:08 -0700 | [diff] [blame] | 1394 |         return; | 
 | 1395 |       } | 
 | 1396 |     } | 
 | 1397 |   } else { | 
| Mathieu Chartier | e0671ce | 2015-07-28 17:23:28 -0700 | [diff] [blame] | 1398 |     Thread* const self = Thread::Current(); | 
| Ian Rogers | dbf3be0 | 2014-08-29 15:40:08 -0700 | [diff] [blame] | 1399 |     StackHandleScope<1> hs(self); | 
| Mathieu Chartier | e0671ce | 2015-07-28 17:23:28 -0700 | [diff] [blame] | 1400 |     auto classes = hs.NewHandle<mirror::ObjectArray<mirror::Class>>(nullptr); | 
| Ian Rogers | dbf3be0 | 2014-08-29 15:40:08 -0700 | [diff] [blame] | 1401 |     // We size the array assuming classes won't be added to the class table during the visit. | 
 | 1402 |     // If this assumption fails we iterate again. | 
| Mathieu Chartier | e0671ce | 2015-07-28 17:23:28 -0700 | [diff] [blame] | 1403 |     while (true) { | 
| Ian Rogers | dbf3be0 | 2014-08-29 15:40:08 -0700 | [diff] [blame] | 1404 |       size_t class_table_size; | 
 | 1405 |       { | 
| Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 1406 |         ReaderMutexLock mu(self, *Locks::classlinker_classes_lock_); | 
| Mathieu Chartier | e0671ce | 2015-07-28 17:23:28 -0700 | [diff] [blame] | 1407 |         // Add 100 in case new classes get loaded when we are filling in the object array. | 
 | 1408 |         class_table_size = NumZygoteClasses() + NumNonZygoteClasses() + 100; | 
| Ian Rogers | dbf3be0 | 2014-08-29 15:40:08 -0700 | [diff] [blame] | 1409 |       } | 
 | 1410 |       mirror::Class* class_type = mirror::Class::GetJavaLangClass(); | 
 | 1411 |       mirror::Class* array_of_class = FindArrayClass(self, &class_type); | 
 | 1412 |       classes.Assign( | 
 | 1413 |           mirror::ObjectArray<mirror::Class>::Alloc(self, array_of_class, class_table_size)); | 
 | 1414 |       CHECK(classes.Get() != nullptr);  // OOME. | 
| Mathieu Chartier | e0671ce | 2015-07-28 17:23:28 -0700 | [diff] [blame] | 1415 |       GetClassInToObjectArray accumulator(classes.Get()); | 
 | 1416 |       VisitClasses(&accumulator); | 
 | 1417 |       if (accumulator.Succeeded()) { | 
 | 1418 |         break; | 
 | 1419 |       } | 
| Ian Rogers | dbf3be0 | 2014-08-29 15:40:08 -0700 | [diff] [blame] | 1420 |     } | 
 | 1421 |     for (int32_t i = 0; i < classes->GetLength(); ++i) { | 
 | 1422 |       // If the class table shrank during creation of the clases array we expect null elements. If | 
 | 1423 |       // the class table grew then the loop repeats. If classes are created after the loop has | 
 | 1424 |       // finished then we don't visit. | 
 | 1425 |       mirror::Class* klass = classes->Get(i); | 
| Mathieu Chartier | e0671ce | 2015-07-28 17:23:28 -0700 | [diff] [blame] | 1426 |       if (klass != nullptr && !visitor->Visit(klass)) { | 
| Ian Rogers | dbf3be0 | 2014-08-29 15:40:08 -0700 | [diff] [blame] | 1427 |         return; | 
 | 1428 |       } | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 1429 |     } | 
 | 1430 |   } | 
 | 1431 | } | 
 | 1432 |  | 
| Brian Carlstrom | 9ea1cb1 | 2011-08-24 23:18:18 -0700 | [diff] [blame] | 1433 | ClassLinker::~ClassLinker() { | 
| Mathieu Chartier | fc58af4 | 2015-04-16 18:00:39 -0700 | [diff] [blame] | 1434 |   mirror::Class::ResetClass(); | 
 | 1435 |   mirror::Constructor::ResetClass(); | 
| Mathieu Chartier | daaf326 | 2015-03-24 13:30:28 -0700 | [diff] [blame] | 1436 |   mirror::Field::ResetClass(); | 
| Mathieu Chartier | fc58af4 | 2015-04-16 18:00:39 -0700 | [diff] [blame] | 1437 |   mirror::Method::ResetClass(); | 
 | 1438 |   mirror::Reference::ResetClass(); | 
 | 1439 |   mirror::StackTraceElement::ResetClass(); | 
 | 1440 |   mirror::String::ResetClass(); | 
 | 1441 |   mirror::Throwable::ResetClass(); | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 1442 |   mirror::BooleanArray::ResetArrayClass(); | 
 | 1443 |   mirror::ByteArray::ResetArrayClass(); | 
 | 1444 |   mirror::CharArray::ResetArrayClass(); | 
| Mathieu Chartier | fc58af4 | 2015-04-16 18:00:39 -0700 | [diff] [blame] | 1445 |   mirror::Constructor::ResetArrayClass(); | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 1446 |   mirror::DoubleArray::ResetArrayClass(); | 
| Mathieu Chartier | fc58af4 | 2015-04-16 18:00:39 -0700 | [diff] [blame] | 1447 |   mirror::Field::ResetArrayClass(); | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 1448 |   mirror::FloatArray::ResetArrayClass(); | 
| Mathieu Chartier | fc58af4 | 2015-04-16 18:00:39 -0700 | [diff] [blame] | 1449 |   mirror::Method::ResetArrayClass(); | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 1450 |   mirror::IntArray::ResetArrayClass(); | 
 | 1451 |   mirror::LongArray::ResetArrayClass(); | 
 | 1452 |   mirror::ShortArray::ResetArrayClass(); | 
| Brian Carlstrom | 58ae941 | 2011-10-04 00:56:06 -0700 | [diff] [blame] | 1453 |   STLDeleteElements(&oat_files_); | 
| Mathieu Chartier | 6b06953 | 2015-08-05 15:08:12 -0700 | [diff] [blame] | 1454 |   for (GcRoot<mirror::ClassLoader>& root : class_loaders_) { | 
 | 1455 |     ClassTable* const class_table = root.Read()->GetClassTable(); | 
 | 1456 |     delete class_table; | 
 | 1457 |   } | 
| Brian Carlstrom | 9ea1cb1 | 2011-08-24 23:18:18 -0700 | [diff] [blame] | 1458 | } | 
 | 1459 |  | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 1460 | mirror::PointerArray* ClassLinker::AllocPointerArray(Thread* self, size_t length) { | 
 | 1461 |   return down_cast<mirror::PointerArray*>(image_pointer_size_ == 8u ? | 
 | 1462 |       static_cast<mirror::Array*>(mirror::LongArray::Alloc(self, length)) : | 
 | 1463 |       static_cast<mirror::Array*>(mirror::IntArray::Alloc(self, length))); | 
 | 1464 | } | 
 | 1465 |  | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 1466 | mirror::DexCache* ClassLinker::AllocDexCache(Thread* self, const DexFile& dex_file) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 1467 |   StackHandleScope<6> hs(self); | 
 | 1468 |   auto dex_cache(hs.NewHandle(down_cast<mirror::DexCache*>( | 
 | 1469 |       GetClassRoot(kJavaLangDexCache)->AllocObject(self)))); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 1470 |   if (dex_cache.Get() == nullptr) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 1471 |     self->AssertPendingOOMException(); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 1472 |     return nullptr; | 
| Elliott Hughes | 3064683 | 2011-10-13 16:59:46 -0700 | [diff] [blame] | 1473 |   } | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 1474 |   auto location(hs.NewHandle(intern_table_->InternStrong(dex_file.GetLocation().c_str()))); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 1475 |   if (location.Get() == nullptr) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 1476 |     self->AssertPendingOOMException(); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 1477 |     return nullptr; | 
| Elliott Hughes | 3064683 | 2011-10-13 16:59:46 -0700 | [diff] [blame] | 1478 |   } | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 1479 |   auto strings(hs.NewHandle(AllocStringArray(self, dex_file.NumStringIds()))); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 1480 |   if (strings.Get() == nullptr) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 1481 |     self->AssertPendingOOMException(); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 1482 |     return nullptr; | 
| Brian Carlstrom | 40381fb | 2011-10-19 14:13:40 -0700 | [diff] [blame] | 1483 |   } | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 1484 |   auto types(hs.NewHandle(AllocClassArray(self, dex_file.NumTypeIds()))); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 1485 |   if (types.Get() == nullptr) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 1486 |     self->AssertPendingOOMException(); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 1487 |     return nullptr; | 
| Brian Carlstrom | 40381fb | 2011-10-19 14:13:40 -0700 | [diff] [blame] | 1488 |   } | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 1489 |   auto methods(hs.NewHandle(AllocPointerArray(self, dex_file.NumMethodIds()))); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 1490 |   if (methods.Get() == nullptr) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 1491 |     self->AssertPendingOOMException(); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 1492 |     return nullptr; | 
| Brian Carlstrom | 40381fb | 2011-10-19 14:13:40 -0700 | [diff] [blame] | 1493 |   } | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 1494 |   auto fields(hs.NewHandle(AllocPointerArray(self, dex_file.NumFieldIds()))); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 1495 |   if (fields.Get() == nullptr) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 1496 |     self->AssertPendingOOMException(); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 1497 |     return nullptr; | 
| Brian Carlstrom | 40381fb | 2011-10-19 14:13:40 -0700 | [diff] [blame] | 1498 |   } | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 1499 |   dex_cache->Init(&dex_file, location.Get(), strings.Get(), types.Get(), methods.Get(), | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 1500 |                   fields.Get(), image_pointer_size_); | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 1501 |   return dex_cache.Get(); | 
| Brian Carlstrom | a080803 | 2011-07-18 00:39:23 -0700 | [diff] [blame] | 1502 | } | 
 | 1503 |  | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 1504 | mirror::Class* ClassLinker::AllocClass(Thread* self, mirror::Class* java_lang_Class, | 
| Ian Rogers | 6fac447 | 2014-02-25 17:01:10 -0800 | [diff] [blame] | 1505 |                                        uint32_t class_size) { | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 1506 |   DCHECK_GE(class_size, sizeof(mirror::Class)); | 
| Ian Rogers | 1d54e73 | 2013-05-02 21:10:01 -0700 | [diff] [blame] | 1507 |   gc::Heap* heap = Runtime::Current()->GetHeap(); | 
| Mingyao Yang | 98d1cc8 | 2014-05-15 17:02:16 -0700 | [diff] [blame] | 1508 |   mirror::Class::InitializeClassVisitor visitor(class_size); | 
| Mathieu Chartier | 52e4b43 | 2014-06-10 11:22:31 -0700 | [diff] [blame] | 1509 |   mirror::Object* k = kMovingClasses ? | 
| Brian Carlstrom | f363283 | 2014-05-20 15:36:53 -0700 | [diff] [blame] | 1510 |       heap->AllocObject<true>(self, java_lang_Class, class_size, visitor) : | 
 | 1511 |       heap->AllocNonMovableObject<true>(self, java_lang_Class, class_size, visitor); | 
| Ian Rogers | 6fac447 | 2014-02-25 17:01:10 -0800 | [diff] [blame] | 1512 |   if (UNLIKELY(k == nullptr)) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 1513 |     self->AssertPendingOOMException(); | 
| Ian Rogers | 6fac447 | 2014-02-25 17:01:10 -0800 | [diff] [blame] | 1514 |     return nullptr; | 
| Ian Rogers | a436fde | 2013-08-27 23:34:06 -0700 | [diff] [blame] | 1515 |   } | 
| Ian Rogers | 6fac447 | 2014-02-25 17:01:10 -0800 | [diff] [blame] | 1516 |   return k->AsClass(); | 
| Brian Carlstrom | 75cb3b4 | 2011-07-28 02:13:36 -0700 | [diff] [blame] | 1517 | } | 
 | 1518 |  | 
| Ian Rogers | 6fac447 | 2014-02-25 17:01:10 -0800 | [diff] [blame] | 1519 | mirror::Class* ClassLinker::AllocClass(Thread* self, uint32_t class_size) { | 
| Ian Rogers | 50b35e2 | 2012-10-04 10:09:15 -0700 | [diff] [blame] | 1520 |   return AllocClass(self, GetClassRoot(kJavaLangClass), class_size); | 
| Brian Carlstrom | a080803 | 2011-07-18 00:39:23 -0700 | [diff] [blame] | 1521 | } | 
 | 1522 |  | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 1523 | mirror::ObjectArray<mirror::StackTraceElement>* ClassLinker::AllocStackTraceElementArray( | 
 | 1524 |     Thread* self, size_t length) { | 
| Mathieu Chartier | 590fee9 | 2013-09-13 13:46:47 -0700 | [diff] [blame] | 1525 |   return mirror::ObjectArray<mirror::StackTraceElement>::Alloc( | 
 | 1526 |       self, GetClassRoot(kJavaLangStackTraceElementArrayClass), length); | 
| Shih-wei Liao | 55df06b | 2011-08-26 14:39:27 -0700 | [diff] [blame] | 1527 | } | 
 | 1528 |  | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 1529 | mirror::Class* ClassLinker::EnsureResolved(Thread* self, const char* descriptor, | 
| Mingyao Yang | 98d1cc8 | 2014-05-15 17:02:16 -0700 | [diff] [blame] | 1530 |                                            mirror::Class* klass) { | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 1531 |   DCHECK(klass != nullptr); | 
| Mingyao Yang | 98d1cc8 | 2014-05-15 17:02:16 -0700 | [diff] [blame] | 1532 |  | 
 | 1533 |   // For temporary classes we must wait for them to be retired. | 
 | 1534 |   if (init_done_ && klass->IsTemp()) { | 
 | 1535 |     CHECK(!klass->IsResolved()); | 
 | 1536 |     if (klass->IsErroneous()) { | 
 | 1537 |       ThrowEarlierClassFailure(klass); | 
 | 1538 |       return nullptr; | 
 | 1539 |     } | 
 | 1540 |     StackHandleScope<1> hs(self); | 
 | 1541 |     Handle<mirror::Class> h_class(hs.NewHandle(klass)); | 
 | 1542 |     ObjectLock<mirror::Class> lock(self, h_class); | 
 | 1543 |     // Loop and wait for the resolving thread to retire this class. | 
 | 1544 |     while (!h_class->IsRetired() && !h_class->IsErroneous()) { | 
 | 1545 |       lock.WaitIgnoringInterrupts(); | 
 | 1546 |     } | 
 | 1547 |     if (h_class->IsErroneous()) { | 
 | 1548 |       ThrowEarlierClassFailure(h_class.Get()); | 
 | 1549 |       return nullptr; | 
 | 1550 |     } | 
 | 1551 |     CHECK(h_class->IsRetired()); | 
 | 1552 |     // Get the updated class from class table. | 
| Mathieu Chartier | e7c9a8c | 2014-11-06 16:35:45 -0800 | [diff] [blame] | 1553 |     klass = LookupClass(self, descriptor, ComputeModifiedUtf8Hash(descriptor), | 
 | 1554 |                         h_class.Get()->GetClassLoader()); | 
| Mingyao Yang | 98d1cc8 | 2014-05-15 17:02:16 -0700 | [diff] [blame] | 1555 |   } | 
 | 1556 |  | 
| Brian Carlstrom | aded5f7 | 2011-10-07 17:15:04 -0700 | [diff] [blame] | 1557 |   // Wait for the class if it has not already been linked. | 
| Elliott Hughes | 5fe594f | 2011-09-08 12:33:17 -0700 | [diff] [blame] | 1558 |   if (!klass->IsResolved() && !klass->IsErroneous()) { | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 1559 |     StackHandleScope<1> hs(self); | 
| Mathieu Chartier | db2633c | 2014-05-16 09:59:29 -0700 | [diff] [blame] | 1560 |     HandleWrapper<mirror::Class> h_class(hs.NewHandleWrapper(&klass)); | 
 | 1561 |     ObjectLock<mirror::Class> lock(self, h_class); | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 1562 |     // Check for circular dependencies between classes. | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 1563 |     if (!h_class->IsResolved() && h_class->GetClinitThreadId() == self->GetTid()) { | 
 | 1564 |       ThrowClassCircularityError(h_class.Get()); | 
| Hiroshi Yamauchi | 5b783e6 | 2015-03-18 17:20:11 -0700 | [diff] [blame] | 1565 |       mirror::Class::SetStatus(h_class, mirror::Class::kStatusError, self); | 
| Mathieu Chartier | c528dba | 2013-11-26 12:00:11 -0800 | [diff] [blame] | 1566 |       return nullptr; | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 1567 |     } | 
 | 1568 |     // Wait for the pending initialization to complete. | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 1569 |     while (!h_class->IsResolved() && !h_class->IsErroneous()) { | 
| Ian Rogers | 05f3057 | 2013-02-20 12:13:11 -0800 | [diff] [blame] | 1570 |       lock.WaitIgnoringInterrupts(); | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 1571 |     } | 
 | 1572 |   } | 
| Mingyao Yang | 98d1cc8 | 2014-05-15 17:02:16 -0700 | [diff] [blame] | 1573 |  | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 1574 |   if (klass->IsErroneous()) { | 
| Elliott Hughes | 4a2b417 | 2011-09-20 17:08:25 -0700 | [diff] [blame] | 1575 |     ThrowEarlierClassFailure(klass); | 
| Mathieu Chartier | c528dba | 2013-11-26 12:00:11 -0800 | [diff] [blame] | 1576 |     return nullptr; | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 1577 |   } | 
 | 1578 |   // Return the loaded class.  No exceptions should be pending. | 
| Brian Carlstrom | aded5f7 | 2011-10-07 17:15:04 -0700 | [diff] [blame] | 1579 |   CHECK(klass->IsResolved()) << PrettyClass(klass); | 
| Ian Rogers | 62d6c77 | 2013-02-27 08:32:07 -0800 | [diff] [blame] | 1580 |   self->AssertNoPendingException(); | 
| Brian Carlstrom | aded5f7 | 2011-10-07 17:15:04 -0700 | [diff] [blame] | 1581 |   return klass; | 
 | 1582 | } | 
 | 1583 |  | 
| Ian Rogers | 68b5685 | 2014-08-29 20:19:11 -0700 | [diff] [blame] | 1584 | typedef std::pair<const DexFile*, const DexFile::ClassDef*> ClassPathEntry; | 
 | 1585 |  | 
 | 1586 | // Search a collection of DexFiles for a descriptor | 
| Mathieu Chartier | e7c9a8c | 2014-11-06 16:35:45 -0800 | [diff] [blame] | 1587 | ClassPathEntry FindInClassPath(const char* descriptor, | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 1588 |                                size_t hash, const std::vector<const DexFile*>& class_path) { | 
| Mathieu Chartier | e7c9a8c | 2014-11-06 16:35:45 -0800 | [diff] [blame] | 1589 |   for (const DexFile* dex_file : class_path) { | 
 | 1590 |     const DexFile::ClassDef* dex_class_def = dex_file->FindClassDef(descriptor, hash); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 1591 |     if (dex_class_def != nullptr) { | 
| Ian Rogers | 68b5685 | 2014-08-29 20:19:11 -0700 | [diff] [blame] | 1592 |       return ClassPathEntry(dex_file, dex_class_def); | 
 | 1593 |     } | 
 | 1594 |   } | 
| Mathieu Chartier | e7c9a8c | 2014-11-06 16:35:45 -0800 | [diff] [blame] | 1595 |   return ClassPathEntry(nullptr, nullptr); | 
| Ian Rogers | 68b5685 | 2014-08-29 20:19:11 -0700 | [diff] [blame] | 1596 | } | 
 | 1597 |  | 
| Andreas Gampe | f865ea9 | 2015-04-13 22:14:19 -0700 | [diff] [blame] | 1598 | static bool IsBootClassLoader(ScopedObjectAccessAlreadyRunnable& soa, | 
 | 1599 |                               mirror::ClassLoader* class_loader) | 
| Mathieu Chartier | 9044347 | 2015-07-16 20:32:27 -0700 | [diff] [blame] | 1600 |     SHARED_REQUIRES(Locks::mutator_lock_) { | 
| Andreas Gampe | f865ea9 | 2015-04-13 22:14:19 -0700 | [diff] [blame] | 1601 |   return class_loader == nullptr || | 
 | 1602 |       class_loader->GetClass() == | 
 | 1603 |           soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_BootClassLoader); | 
 | 1604 | } | 
 | 1605 |  | 
 | 1606 | bool ClassLinker::FindClassInPathClassLoader(ScopedObjectAccessAlreadyRunnable& soa, | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 1607 |                                              Thread* self, const char* descriptor, | 
| Andreas Gampe | f865ea9 | 2015-04-13 22:14:19 -0700 | [diff] [blame] | 1608 |                                              size_t hash, | 
 | 1609 |                                              Handle<mirror::ClassLoader> class_loader, | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 1610 |                                              mirror::Class** result) { | 
| Andreas Gampe | f865ea9 | 2015-04-13 22:14:19 -0700 | [diff] [blame] | 1611 |   // Termination case: boot class-loader. | 
 | 1612 |   if (IsBootClassLoader(soa, class_loader.Get())) { | 
 | 1613 |     // The boot class loader, search the boot class path. | 
 | 1614 |     ClassPathEntry pair = FindInClassPath(descriptor, hash, boot_class_path_); | 
 | 1615 |     if (pair.second != nullptr) { | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 1616 |       mirror::Class* klass = LookupClass(self, descriptor, hash, nullptr); | 
| Andreas Gampe | f865ea9 | 2015-04-13 22:14:19 -0700 | [diff] [blame] | 1617 |       if (klass != nullptr) { | 
 | 1618 |         *result = EnsureResolved(self, descriptor, klass); | 
 | 1619 |       } else { | 
 | 1620 |         *result = DefineClass(self, descriptor, hash, NullHandle<mirror::ClassLoader>(), | 
 | 1621 |                               *pair.first, *pair.second); | 
 | 1622 |       } | 
 | 1623 |       if (*result == nullptr) { | 
 | 1624 |         CHECK(self->IsExceptionPending()) << descriptor; | 
 | 1625 |         self->ClearException(); | 
 | 1626 |       } | 
| Ian Rogers | 3242729 | 2014-11-19 14:05:21 -0800 | [diff] [blame] | 1627 |     } else { | 
| Andreas Gampe | f865ea9 | 2015-04-13 22:14:19 -0700 | [diff] [blame] | 1628 |       *result = nullptr; | 
| Mathieu Chartier | ab0ed82 | 2014-09-11 14:21:41 -0700 | [diff] [blame] | 1629 |     } | 
| Andreas Gampe | f865ea9 | 2015-04-13 22:14:19 -0700 | [diff] [blame] | 1630 |     return true; | 
 | 1631 |   } | 
 | 1632 |  | 
 | 1633 |   // Unsupported class-loader? | 
 | 1634 |   if (class_loader->GetClass() != | 
 | 1635 |       soa.Decode<mirror::Class*>(WellKnownClasses::dalvik_system_PathClassLoader)) { | 
 | 1636 |     *result = nullptr; | 
 | 1637 |     return false; | 
 | 1638 |   } | 
 | 1639 |  | 
 | 1640 |   // Handles as RegisterDexFile may allocate dex caches (and cause thread suspension). | 
 | 1641 |   StackHandleScope<4> hs(self); | 
 | 1642 |   Handle<mirror::ClassLoader> h_parent(hs.NewHandle(class_loader->GetParent())); | 
 | 1643 |   bool recursive_result = FindClassInPathClassLoader(soa, self, descriptor, hash, h_parent, result); | 
 | 1644 |  | 
 | 1645 |   if (!recursive_result) { | 
 | 1646 |     // Something wrong up the chain. | 
 | 1647 |     return false; | 
 | 1648 |   } | 
 | 1649 |  | 
 | 1650 |   if (*result != nullptr) { | 
 | 1651 |     // Found the class up the chain. | 
 | 1652 |     return true; | 
 | 1653 |   } | 
 | 1654 |  | 
 | 1655 |   // Handle this step. | 
 | 1656 |   // Handle as if this is the child PathClassLoader. | 
 | 1657 |   // The class loader is a PathClassLoader which inherits from BaseDexClassLoader. | 
 | 1658 |   // We need to get the DexPathList and loop through it. | 
 | 1659 |   ArtField* const cookie_field = soa.DecodeField(WellKnownClasses::dalvik_system_DexFile_cookie); | 
 | 1660 |   ArtField* const dex_file_field = | 
 | 1661 |       soa.DecodeField(WellKnownClasses::dalvik_system_DexPathList__Element_dexFile); | 
 | 1662 |   mirror::Object* dex_path_list = | 
 | 1663 |       soa.DecodeField(WellKnownClasses::dalvik_system_PathClassLoader_pathList)-> | 
 | 1664 |       GetObject(class_loader.Get()); | 
 | 1665 |   if (dex_path_list != nullptr && dex_file_field != nullptr && cookie_field != nullptr) { | 
 | 1666 |     // DexPathList has an array dexElements of Elements[] which each contain a dex file. | 
 | 1667 |     mirror::Object* dex_elements_obj = | 
 | 1668 |         soa.DecodeField(WellKnownClasses::dalvik_system_DexPathList_dexElements)-> | 
 | 1669 |         GetObject(dex_path_list); | 
 | 1670 |     // Loop through each dalvik.system.DexPathList$Element's dalvik.system.DexFile and look | 
 | 1671 |     // at the mCookie which is a DexFile vector. | 
 | 1672 |     if (dex_elements_obj != nullptr) { | 
 | 1673 |       Handle<mirror::ObjectArray<mirror::Object>> dex_elements = | 
 | 1674 |           hs.NewHandle(dex_elements_obj->AsObjectArray<mirror::Object>()); | 
 | 1675 |       for (int32_t i = 0; i < dex_elements->GetLength(); ++i) { | 
 | 1676 |         mirror::Object* element = dex_elements->GetWithoutChecks(i); | 
 | 1677 |         if (element == nullptr) { | 
 | 1678 |           // Should never happen, fall back to java code to throw a NPE. | 
 | 1679 |           break; | 
 | 1680 |         } | 
 | 1681 |         mirror::Object* dex_file = dex_file_field->GetObject(element); | 
 | 1682 |         if (dex_file != nullptr) { | 
 | 1683 |           mirror::LongArray* long_array = cookie_field->GetObject(dex_file)->AsLongArray(); | 
 | 1684 |           if (long_array == nullptr) { | 
 | 1685 |             // This should never happen so log a warning. | 
 | 1686 |             LOG(WARNING) << "Null DexFile::mCookie for " << descriptor; | 
| Mathieu Chartier | ab0ed82 | 2014-09-11 14:21:41 -0700 | [diff] [blame] | 1687 |             break; | 
 | 1688 |           } | 
| Andreas Gampe | f865ea9 | 2015-04-13 22:14:19 -0700 | [diff] [blame] | 1689 |           int32_t long_array_size = long_array->GetLength(); | 
 | 1690 |           for (int32_t j = 0; j < long_array_size; ++j) { | 
 | 1691 |             const DexFile* cp_dex_file = reinterpret_cast<const DexFile*>(static_cast<uintptr_t>( | 
 | 1692 |                 long_array->GetWithoutChecks(j))); | 
 | 1693 |             const DexFile::ClassDef* dex_class_def = cp_dex_file->FindClassDef(descriptor, hash); | 
 | 1694 |             if (dex_class_def != nullptr) { | 
| Andreas Gampe | f865ea9 | 2015-04-13 22:14:19 -0700 | [diff] [blame] | 1695 |               mirror::Class* klass = DefineClass(self, descriptor, hash, class_loader, | 
 | 1696 |                                                  *cp_dex_file, *dex_class_def); | 
 | 1697 |               if (klass == nullptr) { | 
 | 1698 |                 CHECK(self->IsExceptionPending()) << descriptor; | 
 | 1699 |                 self->ClearException(); | 
 | 1700 |                 // TODO: Is it really right to break here, and not check the other dex files? | 
 | 1701 |                 return true; | 
| Mathieu Chartier | ab0ed82 | 2014-09-11 14:21:41 -0700 | [diff] [blame] | 1702 |               } | 
| Andreas Gampe | f865ea9 | 2015-04-13 22:14:19 -0700 | [diff] [blame] | 1703 |               *result = klass; | 
 | 1704 |               return true; | 
| Mathieu Chartier | ab0ed82 | 2014-09-11 14:21:41 -0700 | [diff] [blame] | 1705 |             } | 
 | 1706 |           } | 
 | 1707 |         } | 
 | 1708 |       } | 
 | 1709 |     } | 
| Ian Rogers | 3242729 | 2014-11-19 14:05:21 -0800 | [diff] [blame] | 1710 |     self->AssertNoPendingException(); | 
| Mathieu Chartier | ab0ed82 | 2014-09-11 14:21:41 -0700 | [diff] [blame] | 1711 |   } | 
| Andreas Gampe | f865ea9 | 2015-04-13 22:14:19 -0700 | [diff] [blame] | 1712 |  | 
 | 1713 |   // Result is still null from the parent call, no need to set it again... | 
 | 1714 |   return true; | 
| Mathieu Chartier | ab0ed82 | 2014-09-11 14:21:41 -0700 | [diff] [blame] | 1715 | } | 
 | 1716 |  | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 1717 | mirror::Class* ClassLinker::FindClass(Thread* self, const char* descriptor, | 
| Andreas Gampe | 5a4b8a2 | 2014-09-11 08:30:08 -0700 | [diff] [blame] | 1718 |                                       Handle<mirror::ClassLoader> class_loader) { | 
| Elliott Hughes | ba8eee1 | 2012-01-24 20:25:24 -0800 | [diff] [blame] | 1719 |   DCHECK_NE(*descriptor, '\0') << "descriptor is empty string"; | 
| Ian Rogers | 9837939 | 2014-02-24 16:53:16 -0800 | [diff] [blame] | 1720 |   DCHECK(self != nullptr); | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 1721 |   self->AssertNoPendingException(); | 
| Elliott Hughes | c3b77c7 | 2011-12-15 20:56:48 -0800 | [diff] [blame] | 1722 |   if (descriptor[1] == '\0') { | 
| Ian Rogers | 6d4d9fc | 2011-11-30 16:24:48 -0800 | [diff] [blame] | 1723 |     // only the descriptors of primitive types should be 1 character long, also avoid class lookup | 
 | 1724 |     // for primitive classes that aren't backed by dex files. | 
 | 1725 |     return FindPrimitiveClass(descriptor[0]); | 
 | 1726 |   } | 
| Mathieu Chartier | e7c9a8c | 2014-11-06 16:35:45 -0800 | [diff] [blame] | 1727 |   const size_t hash = ComputeModifiedUtf8Hash(descriptor); | 
| Brian Carlstrom | aded5f7 | 2011-10-07 17:15:04 -0700 | [diff] [blame] | 1728 |   // Find the class in the loaded classes table. | 
| Mathieu Chartier | e7c9a8c | 2014-11-06 16:35:45 -0800 | [diff] [blame] | 1729 |   mirror::Class* klass = LookupClass(self, descriptor, hash, class_loader.Get()); | 
| Ian Rogers | 68b5685 | 2014-08-29 20:19:11 -0700 | [diff] [blame] | 1730 |   if (klass != nullptr) { | 
| Mingyao Yang | 98d1cc8 | 2014-05-15 17:02:16 -0700 | [diff] [blame] | 1731 |     return EnsureResolved(self, descriptor, klass); | 
| Brian Carlstrom | aded5f7 | 2011-10-07 17:15:04 -0700 | [diff] [blame] | 1732 |   } | 
| Brian Carlstrom | aded5f7 | 2011-10-07 17:15:04 -0700 | [diff] [blame] | 1733 |   // Class is not yet loaded. | 
 | 1734 |   if (descriptor[0] == '[') { | 
| Mathieu Chartier | e7c9a8c | 2014-11-06 16:35:45 -0800 | [diff] [blame] | 1735 |     return CreateArrayClass(self, descriptor, hash, class_loader); | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 1736 |   } else if (class_loader.Get() == nullptr) { | 
| Ian Rogers | 6355745 | 2014-06-04 16:57:15 -0700 | [diff] [blame] | 1737 |     // The boot class loader, search the boot class path. | 
| Mathieu Chartier | e7c9a8c | 2014-11-06 16:35:45 -0800 | [diff] [blame] | 1738 |     ClassPathEntry pair = FindInClassPath(descriptor, hash, boot_class_path_); | 
| Ian Rogers | 68b5685 | 2014-08-29 20:19:11 -0700 | [diff] [blame] | 1739 |     if (pair.second != nullptr) { | 
| Mathieu Chartier | e7c9a8c | 2014-11-06 16:35:45 -0800 | [diff] [blame] | 1740 |       return DefineClass(self, descriptor, hash, NullHandle<mirror::ClassLoader>(), *pair.first, | 
| Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 1741 |                          *pair.second); | 
| Ian Rogers | 6355745 | 2014-06-04 16:57:15 -0700 | [diff] [blame] | 1742 |     } else { | 
 | 1743 |       // The boot class loader is searched ahead of the application class loader, failures are | 
 | 1744 |       // expected and will be wrapped in a ClassNotFoundException. Use the pre-allocated error to | 
 | 1745 |       // trigger the chaining with a proper stack trace. | 
 | 1746 |       mirror::Throwable* pre_allocated = Runtime::Current()->GetPreAllocatedNoClassDefFoundError(); | 
| Nicolas Geoffray | 14691c5 | 2015-03-05 10:40:17 +0000 | [diff] [blame] | 1747 |       self->SetException(pre_allocated); | 
| Ian Rogers | 6355745 | 2014-06-04 16:57:15 -0700 | [diff] [blame] | 1748 |       return nullptr; | 
| Jesse Wilson | 47daf87 | 2011-11-23 11:42:45 -0500 | [diff] [blame] | 1749 |     } | 
| Jesse Wilson | 47daf87 | 2011-11-23 11:42:45 -0500 | [diff] [blame] | 1750 |   } else { | 
| Ian Rogers | 9837939 | 2014-02-24 16:53:16 -0800 | [diff] [blame] | 1751 |     ScopedObjectAccessUnchecked soa(self); | 
| Andreas Gampe | f865ea9 | 2015-04-13 22:14:19 -0700 | [diff] [blame] | 1752 |     mirror::Class* cp_klass; | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 1753 |     if (FindClassInPathClassLoader(soa, self, descriptor, hash, class_loader, &cp_klass)) { | 
| Andreas Gampe | f865ea9 | 2015-04-13 22:14:19 -0700 | [diff] [blame] | 1754 |       // The chain was understood. So the value in cp_klass is either the class we were looking | 
 | 1755 |       // for, or not found. | 
 | 1756 |       if (cp_klass != nullptr) { | 
 | 1757 |         return cp_klass; | 
 | 1758 |       } | 
 | 1759 |       // TODO: We handle the boot classpath loader in FindClassInPathClassLoader. Try to unify this | 
 | 1760 |       //       and the branch above. TODO: throw the right exception here. | 
 | 1761 |  | 
 | 1762 |       // We'll let the Java-side rediscover all this and throw the exception with the right stack | 
 | 1763 |       // trace. | 
| Mathieu Chartier | 6bcae8f | 2014-09-04 18:33:17 -0700 | [diff] [blame] | 1764 |     } | 
| Andreas Gampe | 81c6f8d | 2015-03-25 17:19:53 -0700 | [diff] [blame] | 1765 |  | 
 | 1766 |     if (Runtime::Current()->IsAotCompiler()) { | 
 | 1767 |       // Oops, compile-time, can't run actual class-loader code. | 
 | 1768 |       mirror::Throwable* pre_allocated = Runtime::Current()->GetPreAllocatedNoClassDefFoundError(); | 
 | 1769 |       self->SetException(pre_allocated); | 
 | 1770 |       return nullptr; | 
 | 1771 |     } | 
 | 1772 |  | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 1773 |     ScopedLocalRef<jobject> class_loader_object(soa.Env(), | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 1774 |                                                 soa.AddLocalReference<jobject>(class_loader.Get())); | 
| Elliott Hughes | 9557241 | 2011-12-13 18:14:20 -0800 | [diff] [blame] | 1775 |     std::string class_name_string(DescriptorToDot(descriptor)); | 
| Ian Rogers | 68b5685 | 2014-08-29 20:19:11 -0700 | [diff] [blame] | 1776 |     ScopedLocalRef<jobject> result(soa.Env(), nullptr); | 
| Ian Rogers | 365c102 | 2012-06-22 15:05:28 -0700 | [diff] [blame] | 1777 |     { | 
 | 1778 |       ScopedThreadStateChange tsc(self, kNative); | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 1779 |       ScopedLocalRef<jobject> class_name_object(soa.Env(), | 
 | 1780 |                                                 soa.Env()->NewStringUTF(class_name_string.c_str())); | 
| Ian Rogers | 68b5685 | 2014-08-29 20:19:11 -0700 | [diff] [blame] | 1781 |       if (class_name_object.get() == nullptr) { | 
| Ian Rogers | 6355745 | 2014-06-04 16:57:15 -0700 | [diff] [blame] | 1782 |         DCHECK(self->IsExceptionPending());  // OOME. | 
| Ian Rogers | 68b5685 | 2014-08-29 20:19:11 -0700 | [diff] [blame] | 1783 |         return nullptr; | 
| Ian Rogers | 365c102 | 2012-06-22 15:05:28 -0700 | [diff] [blame] | 1784 |       } | 
| Ian Rogers | 68b5685 | 2014-08-29 20:19:11 -0700 | [diff] [blame] | 1785 |       CHECK(class_loader_object.get() != nullptr); | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 1786 |       result.reset(soa.Env()->CallObjectMethod(class_loader_object.get(), | 
 | 1787 |                                                WellKnownClasses::java_lang_ClassLoader_loadClass, | 
 | 1788 |                                                class_name_object.get())); | 
| Jesse Wilson | 47daf87 | 2011-11-23 11:42:45 -0500 | [diff] [blame] | 1789 |     } | 
| Ian Rogers | 9837939 | 2014-02-24 16:53:16 -0800 | [diff] [blame] | 1790 |     if (self->IsExceptionPending()) { | 
| Elliott Hughes | 748382f | 2012-01-26 18:07:38 -0800 | [diff] [blame] | 1791 |       // If the ClassLoader threw, pass that exception up. | 
| Ian Rogers | 68b5685 | 2014-08-29 20:19:11 -0700 | [diff] [blame] | 1792 |       return nullptr; | 
 | 1793 |     } else if (result.get() == nullptr) { | 
| Ian Rogers | cab0101 | 2012-01-10 17:35:46 -0800 | [diff] [blame] | 1794 |       // broken loader - throw NPE to be compatible with Dalvik | 
| Nicolas Geoffray | 0aa50ce | 2015-03-10 11:03:29 +0000 | [diff] [blame] | 1795 |       ThrowNullPointerException(StringPrintf("ClassLoader.loadClass returned null for %s", | 
 | 1796 |                                              class_name_string.c_str()).c_str()); | 
| Ian Rogers | 68b5685 | 2014-08-29 20:19:11 -0700 | [diff] [blame] | 1797 |       return nullptr; | 
| Ian Rogers | 761bfa8 | 2012-01-11 10:14:05 -0800 | [diff] [blame] | 1798 |     } else { | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 1799 |       // success, return mirror::Class* | 
 | 1800 |       return soa.Decode<mirror::Class*>(result.get()); | 
| Ian Rogers | 6b0870d | 2011-12-15 19:38:12 -0800 | [diff] [blame] | 1801 |     } | 
| Brian Carlstrom | aded5f7 | 2011-10-07 17:15:04 -0700 | [diff] [blame] | 1802 |   } | 
| Ian Rogers | 0714083 | 2014-09-30 15:43:59 -0700 | [diff] [blame] | 1803 |   UNREACHABLE(); | 
| Brian Carlstrom | aded5f7 | 2011-10-07 17:15:04 -0700 | [diff] [blame] | 1804 | } | 
 | 1805 |  | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 1806 | mirror::Class* ClassLinker::DefineClass(Thread* self, const char* descriptor, size_t hash, | 
| Andreas Gampe | 5a4b8a2 | 2014-09-11 08:30:08 -0700 | [diff] [blame] | 1807 |                                         Handle<mirror::ClassLoader> class_loader, | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 1808 |                                         const DexFile& dex_file, | 
 | 1809 |                                         const DexFile::ClassDef& dex_class_def) { | 
| Mingyao Yang | 98d1cc8 | 2014-05-15 17:02:16 -0700 | [diff] [blame] | 1810 |   StackHandleScope<3> hs(self); | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 1811 |   auto klass = hs.NewHandle<mirror::Class>(nullptr); | 
| Mingyao Yang | 98d1cc8 | 2014-05-15 17:02:16 -0700 | [diff] [blame] | 1812 |  | 
| Brian Carlstrom | aded5f7 | 2011-10-07 17:15:04 -0700 | [diff] [blame] | 1813 |   // Load the class from the dex file. | 
| Ian Rogers | 7dfb28c | 2013-08-22 08:18:36 -0700 | [diff] [blame] | 1814 |   if (UNLIKELY(!init_done_)) { | 
| Brian Carlstrom | aded5f7 | 2011-10-07 17:15:04 -0700 | [diff] [blame] | 1815 |     // finish up init of hand crafted class_roots_ | 
| Ian Rogers | 7dfb28c | 2013-08-22 08:18:36 -0700 | [diff] [blame] | 1816 |     if (strcmp(descriptor, "Ljava/lang/Object;") == 0) { | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 1817 |       klass.Assign(GetClassRoot(kJavaLangObject)); | 
| Ian Rogers | 7dfb28c | 2013-08-22 08:18:36 -0700 | [diff] [blame] | 1818 |     } else if (strcmp(descriptor, "Ljava/lang/Class;") == 0) { | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 1819 |       klass.Assign(GetClassRoot(kJavaLangClass)); | 
| Ian Rogers | 7dfb28c | 2013-08-22 08:18:36 -0700 | [diff] [blame] | 1820 |     } else if (strcmp(descriptor, "Ljava/lang/String;") == 0) { | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 1821 |       klass.Assign(GetClassRoot(kJavaLangString)); | 
| Fred Shih | 4ee7a66 | 2014-07-11 09:59:27 -0700 | [diff] [blame] | 1822 |     } else if (strcmp(descriptor, "Ljava/lang/ref/Reference;") == 0) { | 
 | 1823 |       klass.Assign(GetClassRoot(kJavaLangRefReference)); | 
| Ian Rogers | 7dfb28c | 2013-08-22 08:18:36 -0700 | [diff] [blame] | 1824 |     } else if (strcmp(descriptor, "Ljava/lang/DexCache;") == 0) { | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 1825 |       klass.Assign(GetClassRoot(kJavaLangDexCache)); | 
| Brian Carlstrom | aded5f7 | 2011-10-07 17:15:04 -0700 | [diff] [blame] | 1826 |     } | 
| Mingyao Yang | 98d1cc8 | 2014-05-15 17:02:16 -0700 | [diff] [blame] | 1827 |   } | 
 | 1828 |  | 
| Mathieu Chartier | e7c9a8c | 2014-11-06 16:35:45 -0800 | [diff] [blame] | 1829 |   if (klass.Get() == nullptr) { | 
| Mingyao Yang | 98d1cc8 | 2014-05-15 17:02:16 -0700 | [diff] [blame] | 1830 |     // Allocate a class with the status of not ready. | 
 | 1831 |     // Interface object should get the right size here. Regular class will | 
 | 1832 |     // figure out the right size later and be replaced with one of the right | 
 | 1833 |     // size when the class becomes resolved. | 
 | 1834 |     klass.Assign(AllocClass(self, SizeOfClassWithoutEmbeddedTables(dex_file, dex_class_def))); | 
| Brian Carlstrom | aded5f7 | 2011-10-07 17:15:04 -0700 | [diff] [blame] | 1835 |   } | 
| Ian Rogers | c114b5f | 2014-07-21 08:55:01 -0700 | [diff] [blame] | 1836 |   if (UNLIKELY(klass.Get() == nullptr)) { | 
| Mathieu Chartier | 673ed3d | 2015-08-28 14:56:43 -0700 | [diff] [blame^] | 1837 |     self->AssertPendingOOMException(); | 
| Ian Rogers | c114b5f | 2014-07-21 08:55:01 -0700 | [diff] [blame] | 1838 |     return nullptr; | 
| Ian Rogers | a436fde | 2013-08-27 23:34:06 -0700 | [diff] [blame] | 1839 |   } | 
| Mathieu Chartier | 673ed3d | 2015-08-28 14:56:43 -0700 | [diff] [blame^] | 1840 |   mirror::DexCache* dex_cache = RegisterDexFile(dex_file); | 
 | 1841 |   if (dex_cache == nullptr) { | 
 | 1842 |     self->AssertPendingOOMException(); | 
 | 1843 |     return nullptr; | 
 | 1844 |   } | 
 | 1845 |   klass->SetDexCache(dex_cache); | 
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 1846 |   SetupClass(dex_file, dex_class_def, klass, class_loader.Get()); | 
 | 1847 |  | 
| Jeff Hao | 848f70a | 2014-01-15 13:49:50 -0800 | [diff] [blame] | 1848 |   // Mark the string class by setting its access flag. | 
 | 1849 |   if (UNLIKELY(!init_done_)) { | 
 | 1850 |     if (strcmp(descriptor, "Ljava/lang/String;") == 0) { | 
 | 1851 |       klass->SetStringClass(); | 
 | 1852 |     } | 
 | 1853 |   } | 
 | 1854 |  | 
| Mathieu Chartier | db2633c | 2014-05-16 09:59:29 -0700 | [diff] [blame] | 1855 |   ObjectLock<mirror::Class> lock(self, klass); | 
| Brian Carlstrom | aded5f7 | 2011-10-07 17:15:04 -0700 | [diff] [blame] | 1856 |   klass->SetClinitThreadId(self->GetTid()); | 
| Mingyao Yang | 98d1cc8 | 2014-05-15 17:02:16 -0700 | [diff] [blame] | 1857 |  | 
| Mathieu Chartier | 590fee9 | 2013-09-13 13:46:47 -0700 | [diff] [blame] | 1858 |   // Add the newly loaded class to the loaded classes table. | 
| Mathieu Chartier | e7c9a8c | 2014-11-06 16:35:45 -0800 | [diff] [blame] | 1859 |   mirror::Class* existing = InsertClass(descriptor, klass.Get(), hash); | 
| Ian Rogers | c114b5f | 2014-07-21 08:55:01 -0700 | [diff] [blame] | 1860 |   if (existing != nullptr) { | 
| Mathieu Chartier | 590fee9 | 2013-09-13 13:46:47 -0700 | [diff] [blame] | 1861 |     // We failed to insert because we raced with another thread. Calling EnsureResolved may cause | 
 | 1862 |     // this thread to block. | 
| Mingyao Yang | 98d1cc8 | 2014-05-15 17:02:16 -0700 | [diff] [blame] | 1863 |     return EnsureResolved(self, descriptor, existing); | 
| Brian Carlstrom | aded5f7 | 2011-10-07 17:15:04 -0700 | [diff] [blame] | 1864 |   } | 
| Mingyao Yang | 98d1cc8 | 2014-05-15 17:02:16 -0700 | [diff] [blame] | 1865 |  | 
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 1866 |   // Load the fields and other things after we are inserted in the table. This is so that we don't | 
 | 1867 |   // end up allocating unfree-able linear alloc resources and then lose the race condition. The | 
 | 1868 |   // other reason is that the field roots are only visited from the class table. So we need to be | 
 | 1869 |   // inserted before we allocate / fill in these fields. | 
 | 1870 |   LoadClass(self, dex_file, dex_class_def, klass); | 
 | 1871 |   if (self->IsExceptionPending()) { | 
 | 1872 |     // An exception occured during load, set status to erroneous while holding klass' lock in case | 
 | 1873 |     // notification is necessary. | 
 | 1874 |     if (!klass->IsErroneous()) { | 
 | 1875 |       mirror::Class::SetStatus(klass, mirror::Class::kStatusError, self); | 
 | 1876 |     } | 
 | 1877 |     return nullptr; | 
 | 1878 |   } | 
 | 1879 |  | 
| Brian Carlstrom | aded5f7 | 2011-10-07 17:15:04 -0700 | [diff] [blame] | 1880 |   // Finish loading (if necessary) by finding parents | 
 | 1881 |   CHECK(!klass->IsLoaded()); | 
 | 1882 |   if (!LoadSuperAndInterfaces(klass, dex_file)) { | 
 | 1883 |     // Loading failed. | 
| Ian Rogers | ecd4d9a | 2014-07-22 00:59:52 -0700 | [diff] [blame] | 1884 |     if (!klass->IsErroneous()) { | 
| Hiroshi Yamauchi | 5b783e6 | 2015-03-18 17:20:11 -0700 | [diff] [blame] | 1885 |       mirror::Class::SetStatus(klass, mirror::Class::kStatusError, self); | 
| Ian Rogers | ecd4d9a | 2014-07-22 00:59:52 -0700 | [diff] [blame] | 1886 |     } | 
| Ian Rogers | c114b5f | 2014-07-21 08:55:01 -0700 | [diff] [blame] | 1887 |     return nullptr; | 
| Brian Carlstrom | aded5f7 | 2011-10-07 17:15:04 -0700 | [diff] [blame] | 1888 |   } | 
 | 1889 |   CHECK(klass->IsLoaded()); | 
 | 1890 |   // Link the class (if necessary) | 
 | 1891 |   CHECK(!klass->IsResolved()); | 
| Mathieu Chartier | 590fee9 | 2013-09-13 13:46:47 -0700 | [diff] [blame] | 1892 |   // TODO: Use fast jobjects? | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 1893 |   auto interfaces = hs.NewHandle<mirror::ObjectArray<mirror::Class>>(nullptr); | 
| Mingyao Yang | 98d1cc8 | 2014-05-15 17:02:16 -0700 | [diff] [blame] | 1894 |  | 
| Hiroshi Yamauchi | 679b1cf | 2015-05-21 12:05:27 -0700 | [diff] [blame] | 1895 |   MutableHandle<mirror::Class> h_new_class = hs.NewHandle<mirror::Class>(nullptr); | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 1896 |   if (!LinkClass(self, descriptor, klass, interfaces, &h_new_class)) { | 
| Brian Carlstrom | aded5f7 | 2011-10-07 17:15:04 -0700 | [diff] [blame] | 1897 |     // Linking failed. | 
| Ian Rogers | ecd4d9a | 2014-07-22 00:59:52 -0700 | [diff] [blame] | 1898 |     if (!klass->IsErroneous()) { | 
| Hiroshi Yamauchi | 5b783e6 | 2015-03-18 17:20:11 -0700 | [diff] [blame] | 1899 |       mirror::Class::SetStatus(klass, mirror::Class::kStatusError, self); | 
| Ian Rogers | ecd4d9a | 2014-07-22 00:59:52 -0700 | [diff] [blame] | 1900 |     } | 
| Ian Rogers | c114b5f | 2014-07-21 08:55:01 -0700 | [diff] [blame] | 1901 |     return nullptr; | 
| Brian Carlstrom | aded5f7 | 2011-10-07 17:15:04 -0700 | [diff] [blame] | 1902 |   } | 
| Mathieu Chartier | 524507a | 2014-08-27 15:28:28 -0700 | [diff] [blame] | 1903 |   self->AssertNoPendingException(); | 
| Hiroshi Yamauchi | 679b1cf | 2015-05-21 12:05:27 -0700 | [diff] [blame] | 1904 |   CHECK(h_new_class.Get() != nullptr) << descriptor; | 
 | 1905 |   CHECK(h_new_class->IsResolved()) << descriptor; | 
| Elliott Hughes | 4740cdf | 2011-12-07 14:07:12 -0800 | [diff] [blame] | 1906 |  | 
| Sebastien Hertz | a8a697f | 2015-01-15 12:28:47 +0100 | [diff] [blame] | 1907 |   // Instrumentation may have updated entrypoints for all methods of all | 
 | 1908 |   // classes. However it could not update methods of this class while we | 
 | 1909 |   // were loading it. Now the class is resolved, we can update entrypoints | 
 | 1910 |   // as required by instrumentation. | 
 | 1911 |   if (Runtime::Current()->GetInstrumentation()->AreExitStubsInstalled()) { | 
 | 1912 |     // We must be in the kRunnable state to prevent instrumentation from | 
 | 1913 |     // suspending all threads to update entrypoints while we are doing it | 
 | 1914 |     // for this class. | 
 | 1915 |     DCHECK_EQ(self->GetState(), kRunnable); | 
| Hiroshi Yamauchi | 679b1cf | 2015-05-21 12:05:27 -0700 | [diff] [blame] | 1916 |     Runtime::Current()->GetInstrumentation()->InstallStubsForClass(h_new_class.Get()); | 
| Sebastien Hertz | a8a697f | 2015-01-15 12:28:47 +0100 | [diff] [blame] | 1917 |   } | 
 | 1918 |  | 
| Elliott Hughes | 4740cdf | 2011-12-07 14:07:12 -0800 | [diff] [blame] | 1919 |   /* | 
 | 1920 |    * We send CLASS_PREPARE events to the debugger from here.  The | 
 | 1921 |    * definition of "preparation" is creating the static fields for a | 
 | 1922 |    * class and initializing them to the standard default values, but not | 
 | 1923 |    * executing any code (that comes later, during "initialization"). | 
 | 1924 |    * | 
 | 1925 |    * We did the static preparation in LinkClass. | 
 | 1926 |    * | 
 | 1927 |    * The class has been prepared and resolved but possibly not yet verified | 
 | 1928 |    * at this point. | 
 | 1929 |    */ | 
| Hiroshi Yamauchi | 679b1cf | 2015-05-21 12:05:27 -0700 | [diff] [blame] | 1930 |   Dbg::PostClassPrepare(h_new_class.Get()); | 
| Elliott Hughes | 4740cdf | 2011-12-07 14:07:12 -0800 | [diff] [blame] | 1931 |  | 
| Hiroshi Yamauchi | 679b1cf | 2015-05-21 12:05:27 -0700 | [diff] [blame] | 1932 |   return h_new_class.Get(); | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 1933 | } | 
 | 1934 |  | 
| Mingyao Yang | 98d1cc8 | 2014-05-15 17:02:16 -0700 | [diff] [blame] | 1935 | uint32_t ClassLinker::SizeOfClassWithoutEmbeddedTables(const DexFile& dex_file, | 
 | 1936 |                                                        const DexFile::ClassDef& dex_class_def) { | 
| Ian Rogers | 1373595 | 2014-10-08 12:43:28 -0700 | [diff] [blame] | 1937 |   const uint8_t* class_data = dex_file.GetClassData(dex_class_def); | 
| Brian Carlstrom | 4873d46 | 2011-08-21 15:23:39 -0700 | [diff] [blame] | 1938 |   size_t num_ref = 0; | 
| Fred Shih | 37f05ef | 2014-07-16 18:38:08 -0700 | [diff] [blame] | 1939 |   size_t num_8 = 0; | 
 | 1940 |   size_t num_16 = 0; | 
| Brian Carlstrom | 4873d46 | 2011-08-21 15:23:39 -0700 | [diff] [blame] | 1941 |   size_t num_32 = 0; | 
 | 1942 |   size_t num_64 = 0; | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 1943 |   if (class_data != nullptr) { | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 1944 |     for (ClassDataItemIterator it(dex_file, class_data); it.HasNextStaticField(); it.Next()) { | 
 | 1945 |       const DexFile::FieldId& field_id = dex_file.GetFieldId(it.GetMemberIndex()); | 
| Brian Carlstrom | 6b4ef02 | 2011-10-23 14:59:04 -0700 | [diff] [blame] | 1946 |       const char* descriptor = dex_file.GetFieldTypeDescriptor(field_id); | 
| Brian Carlstrom | 4873d46 | 2011-08-21 15:23:39 -0700 | [diff] [blame] | 1947 |       char c = descriptor[0]; | 
| Fred Shih | 37f05ef | 2014-07-16 18:38:08 -0700 | [diff] [blame] | 1948 |       switch (c) { | 
 | 1949 |         case 'L': | 
 | 1950 |         case '[': | 
 | 1951 |           num_ref++; | 
 | 1952 |           break; | 
 | 1953 |         case 'J': | 
 | 1954 |         case 'D': | 
 | 1955 |           num_64++; | 
 | 1956 |           break; | 
 | 1957 |         case 'I': | 
 | 1958 |         case 'F': | 
 | 1959 |           num_32++; | 
 | 1960 |           break; | 
 | 1961 |         case 'S': | 
 | 1962 |         case 'C': | 
 | 1963 |           num_16++; | 
 | 1964 |           break; | 
 | 1965 |         case 'B': | 
 | 1966 |         case 'Z': | 
 | 1967 |           num_8++; | 
 | 1968 |           break; | 
 | 1969 |         default: | 
 | 1970 |           LOG(FATAL) << "Unknown descriptor: " << c; | 
| Ian Rogers | e0a02da | 2014-12-02 14:10:53 -0800 | [diff] [blame] | 1971 |           UNREACHABLE(); | 
| Brian Carlstrom | 4873d46 | 2011-08-21 15:23:39 -0700 | [diff] [blame] | 1972 |       } | 
 | 1973 |     } | 
 | 1974 |   } | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 1975 |   return mirror::Class::ComputeClassSize(false, 0, num_8, num_16, num_32, num_64, num_ref, | 
 | 1976 |                                          image_pointer_size_); | 
| Brian Carlstrom | 4873d46 | 2011-08-21 15:23:39 -0700 | [diff] [blame] | 1977 | } | 
 | 1978 |  | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 1979 | OatFile::OatClass ClassLinker::FindOatClass(const DexFile& dex_file, uint16_t class_def_idx, | 
 | 1980 |                                             bool* found) { | 
| Ian Rogers | 8b2c0b9 | 2013-09-19 02:56:49 -0700 | [diff] [blame] | 1981 |   DCHECK_NE(class_def_idx, DexFile::kDexNoIndex16); | 
| Richard Uhler | 07b3c23 | 2015-03-31 15:57:54 -0700 | [diff] [blame] | 1982 |   const OatFile::OatDexFile* oat_dex_file = dex_file.GetOatDexFile(); | 
| Vladimir Marko | aa4497d | 2014-09-05 14:01:17 +0100 | [diff] [blame] | 1983 |   if (oat_dex_file == nullptr) { | 
| Ian Rogers | 97b52f8 | 2014-08-14 11:34:07 -0700 | [diff] [blame] | 1984 |     *found = false; | 
 | 1985 |     return OatFile::OatClass::Invalid(); | 
| Nicolas Geoffray | 4fcdc94 | 2014-07-22 10:48:00 +0100 | [diff] [blame] | 1986 |   } | 
| Ian Rogers | 97b52f8 | 2014-08-14 11:34:07 -0700 | [diff] [blame] | 1987 |   *found = true; | 
 | 1988 |   return oat_dex_file->GetOatClass(class_def_idx); | 
| Ian Rogers | 1984651 | 2012-02-24 11:42:47 -0800 | [diff] [blame] | 1989 | } | 
 | 1990 |  | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 1991 | static uint32_t GetOatMethodIndexFromMethodIndex(const DexFile& dex_file, uint16_t class_def_idx, | 
| Ian Rogers | 8b2c0b9 | 2013-09-19 02:56:49 -0700 | [diff] [blame] | 1992 |                                                  uint32_t method_idx) { | 
 | 1993 |   const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_idx); | 
| Ian Rogers | 1373595 | 2014-10-08 12:43:28 -0700 | [diff] [blame] | 1994 |   const uint8_t* class_data = dex_file.GetClassData(class_def); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 1995 |   CHECK(class_data != nullptr); | 
| Mathieu Chartier | e35517a | 2012-10-30 18:49:55 -0700 | [diff] [blame] | 1996 |   ClassDataItemIterator it(dex_file, class_data); | 
 | 1997 |   // Skip fields | 
 | 1998 |   while (it.HasNextStaticField()) { | 
 | 1999 |     it.Next(); | 
 | 2000 |   } | 
 | 2001 |   while (it.HasNextInstanceField()) { | 
 | 2002 |     it.Next(); | 
 | 2003 |   } | 
 | 2004 |   // Process methods | 
 | 2005 |   size_t class_def_method_index = 0; | 
 | 2006 |   while (it.HasNextDirectMethod()) { | 
 | 2007 |     if (it.GetMemberIndex() == method_idx) { | 
 | 2008 |       return class_def_method_index; | 
 | 2009 |     } | 
 | 2010 |     class_def_method_index++; | 
 | 2011 |     it.Next(); | 
 | 2012 |   } | 
 | 2013 |   while (it.HasNextVirtualMethod()) { | 
 | 2014 |     if (it.GetMemberIndex() == method_idx) { | 
 | 2015 |       return class_def_method_index; | 
 | 2016 |     } | 
 | 2017 |     class_def_method_index++; | 
 | 2018 |     it.Next(); | 
 | 2019 |   } | 
 | 2020 |   DCHECK(!it.HasNext()); | 
 | 2021 |   LOG(FATAL) << "Failed to find method index " << method_idx << " in " << dex_file.GetLocation(); | 
| Ian Rogers | e0a02da | 2014-12-02 14:10:53 -0800 | [diff] [blame] | 2022 |   UNREACHABLE(); | 
| Mathieu Chartier | e35517a | 2012-10-30 18:49:55 -0700 | [diff] [blame] | 2023 | } | 
 | 2024 |  | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 2025 | const OatFile::OatMethod ClassLinker::FindOatMethodFor(ArtMethod* method, bool* found) { | 
| Ian Rogers | 1984651 | 2012-02-24 11:42:47 -0800 | [diff] [blame] | 2026 |   // Although we overwrite the trampoline of non-static methods, we may get here via the resolution | 
| Ian Rogers | fb6adba | 2012-03-04 21:51:51 -0800 | [diff] [blame] | 2027 |   // method for direct methods (or virtual methods made direct). | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 2028 |   mirror::Class* declaring_class = method->GetDeclaringClass(); | 
| Ian Rogers | fb6adba | 2012-03-04 21:51:51 -0800 | [diff] [blame] | 2029 |   size_t oat_method_index; | 
 | 2030 |   if (method->IsStatic() || method->IsDirect()) { | 
 | 2031 |     // Simple case where the oat method index was stashed at load time. | 
 | 2032 |     oat_method_index = method->GetMethodIndex(); | 
 | 2033 |   } else { | 
 | 2034 |     // We're invoking a virtual method directly (thanks to sharpening), compute the oat_method_index | 
 | 2035 |     // by search for its position in the declared virtual methods. | 
 | 2036 |     oat_method_index = declaring_class->NumDirectMethods(); | 
 | 2037 |     size_t end = declaring_class->NumVirtualMethods(); | 
| Andreas Gampe | 277ccbd | 2014-11-03 21:36:10 -0800 | [diff] [blame] | 2038 |     bool found_virtual = false; | 
| Ian Rogers | fb6adba | 2012-03-04 21:51:51 -0800 | [diff] [blame] | 2039 |     for (size_t i = 0; i < end; i++) { | 
| Jeff Hao | 68caf9e | 2014-09-03 13:48:16 -0700 | [diff] [blame] | 2040 |       // Check method index instead of identity in case of duplicate method definitions. | 
 | 2041 |       if (method->GetDexMethodIndex() == | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 2042 |           declaring_class->GetVirtualMethod(i, image_pointer_size_)->GetDexMethodIndex()) { | 
| Andreas Gampe | 277ccbd | 2014-11-03 21:36:10 -0800 | [diff] [blame] | 2043 |         found_virtual = true; | 
| Ian Rogers | fb6adba | 2012-03-04 21:51:51 -0800 | [diff] [blame] | 2044 |         break; | 
 | 2045 |       } | 
| Ian Rogers | f320b63 | 2012-03-13 18:47:47 -0700 | [diff] [blame] | 2046 |       oat_method_index++; | 
| Ian Rogers | fb6adba | 2012-03-04 21:51:51 -0800 | [diff] [blame] | 2047 |     } | 
| Andreas Gampe | 277ccbd | 2014-11-03 21:36:10 -0800 | [diff] [blame] | 2048 |     CHECK(found_virtual) << "Didn't find oat method index for virtual method: " | 
 | 2049 |                          << PrettyMethod(method); | 
| Ian Rogers | fb6adba | 2012-03-04 21:51:51 -0800 | [diff] [blame] | 2050 |   } | 
| Mathieu Chartier | e35517a | 2012-10-30 18:49:55 -0700 | [diff] [blame] | 2051 |   DCHECK_EQ(oat_method_index, | 
 | 2052 |             GetOatMethodIndexFromMethodIndex(*declaring_class->GetDexCache()->GetDexFile(), | 
| Ian Rogers | 8b2c0b9 | 2013-09-19 02:56:49 -0700 | [diff] [blame] | 2053 |                                              method->GetDeclaringClass()->GetDexClassDefIndex(), | 
| Mathieu Chartier | e35517a | 2012-10-30 18:49:55 -0700 | [diff] [blame] | 2054 |                                              method->GetDexMethodIndex())); | 
| Ian Rogers | 97b52f8 | 2014-08-14 11:34:07 -0700 | [diff] [blame] | 2055 |   OatFile::OatClass oat_class = FindOatClass(*declaring_class->GetDexCache()->GetDexFile(), | 
 | 2056 |                                              declaring_class->GetDexClassDefIndex(), | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 2057 |                                              found); | 
| Andreas Gampe | 277ccbd | 2014-11-03 21:36:10 -0800 | [diff] [blame] | 2058 |   if (!(*found)) { | 
| Ian Rogers | 97b52f8 | 2014-08-14 11:34:07 -0700 | [diff] [blame] | 2059 |     return OatFile::OatMethod::Invalid(); | 
| Nicolas Geoffray | 4fcdc94 | 2014-07-22 10:48:00 +0100 | [diff] [blame] | 2060 |   } | 
| Ian Rogers | 97b52f8 | 2014-08-14 11:34:07 -0700 | [diff] [blame] | 2061 |   return oat_class.GetOatMethod(oat_method_index); | 
| TDYa127 | 8532191 | 2012-04-01 15:24:56 -0700 | [diff] [blame] | 2062 | } | 
 | 2063 |  | 
 | 2064 | // Special case to get oat code without overwriting a trampoline. | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 2065 | const void* ClassLinker::GetQuickOatCodeFor(ArtMethod* method) { | 
| Ian Rogers | 62d6c77 | 2013-02-27 08:32:07 -0800 | [diff] [blame] | 2066 |   CHECK(!method->IsAbstract()) << PrettyMethod(method); | 
| Jeff Hao | 8df6cea | 2013-07-29 13:54:48 -0700 | [diff] [blame] | 2067 |   if (method->IsProxyMethod()) { | 
| Ian Rogers | ef7d42f | 2014-01-06 12:55:46 -0800 | [diff] [blame] | 2068 |     return GetQuickProxyInvokeHandler(); | 
| Jeff Hao | 8df6cea | 2013-07-29 13:54:48 -0700 | [diff] [blame] | 2069 |   } | 
| Ian Rogers | 97b52f8 | 2014-08-14 11:34:07 -0700 | [diff] [blame] | 2070 |   bool found; | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 2071 |   OatFile::OatMethod oat_method = FindOatMethodFor(method, &found); | 
| Mathieu Chartier | c0d5f89 | 2015-02-25 13:22:57 -0800 | [diff] [blame] | 2072 |   if (found) { | 
 | 2073 |     auto* code = oat_method.GetQuickCode(); | 
| Mathieu Chartier | e5f13e5 | 2015-02-24 09:37:21 -0800 | [diff] [blame] | 2074 |     if (code != nullptr) { | 
 | 2075 |       return code; | 
| Mathieu Chartier | 2535abe | 2015-02-17 10:38:49 -0800 | [diff] [blame] | 2076 |     } | 
 | 2077 |   } | 
| Mathieu Chartier | c0d5f89 | 2015-02-25 13:22:57 -0800 | [diff] [blame] | 2078 |   jit::Jit* const jit = Runtime::Current()->GetJit(); | 
 | 2079 |   if (jit != nullptr) { | 
 | 2080 |     auto* code = jit->GetCodeCache()->GetCodeFor(method); | 
| Mathieu Chartier | e5f13e5 | 2015-02-24 09:37:21 -0800 | [diff] [blame] | 2081 |     if (code != nullptr) { | 
 | 2082 |       return code; | 
 | 2083 |     } | 
 | 2084 |   } | 
 | 2085 |   if (method->IsNative()) { | 
 | 2086 |     // No code and native? Use generic trampoline. | 
 | 2087 |     return GetQuickGenericJniStub(); | 
 | 2088 |   } | 
 | 2089 |   return GetQuickToInterpreterBridge(); | 
| TDYa127 | 8532191 | 2012-04-01 15:24:56 -0700 | [diff] [blame] | 2090 | } | 
 | 2091 |  | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 2092 | const void* ClassLinker::GetOatMethodQuickCodeFor(ArtMethod* method) { | 
| Hiroshi Yamauchi | 9bdec88 | 2014-08-15 17:11:12 -0700 | [diff] [blame] | 2093 |   if (method->IsNative() || method->IsAbstract() || method->IsProxyMethod()) { | 
 | 2094 |     return nullptr; | 
 | 2095 |   } | 
| Mathieu Chartier | c0d5f89 | 2015-02-25 13:22:57 -0800 | [diff] [blame] | 2096 |   bool found; | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 2097 |   OatFile::OatMethod oat_method = FindOatMethodFor(method, &found); | 
| Mathieu Chartier | c0d5f89 | 2015-02-25 13:22:57 -0800 | [diff] [blame] | 2098 |   if (found) { | 
 | 2099 |     return oat_method.GetQuickCode(); | 
 | 2100 |   } | 
| Mathieu Chartier | e5f13e5 | 2015-02-24 09:37:21 -0800 | [diff] [blame] | 2101 |   jit::Jit* jit = Runtime::Current()->GetJit(); | 
 | 2102 |   if (jit != nullptr) { | 
 | 2103 |     auto* code = jit->GetCodeCache()->GetCodeFor(method); | 
 | 2104 |     if (code != nullptr) { | 
 | 2105 |       return code; | 
 | 2106 |     } | 
 | 2107 |   } | 
| Mathieu Chartier | e5f13e5 | 2015-02-24 09:37:21 -0800 | [diff] [blame] | 2108 |   return nullptr; | 
| Hiroshi Yamauchi | 9bdec88 | 2014-08-15 17:11:12 -0700 | [diff] [blame] | 2109 | } | 
 | 2110 |  | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 2111 | const void* ClassLinker::GetQuickOatCodeFor(const DexFile& dex_file, uint16_t class_def_idx, | 
| Ian Rogers | ef7d42f | 2014-01-06 12:55:46 -0800 | [diff] [blame] | 2112 |                                             uint32_t method_idx) { | 
| Ian Rogers | 97b52f8 | 2014-08-14 11:34:07 -0700 | [diff] [blame] | 2113 |   bool found; | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 2114 |   OatFile::OatClass oat_class = FindOatClass(dex_file, class_def_idx, &found); | 
| Ian Rogers | 97b52f8 | 2014-08-14 11:34:07 -0700 | [diff] [blame] | 2115 |   if (!found) { | 
| Nicolas Geoffray | 4fcdc94 | 2014-07-22 10:48:00 +0100 | [diff] [blame] | 2116 |     return nullptr; | 
 | 2117 |   } | 
| Ian Rogers | 8b2c0b9 | 2013-09-19 02:56:49 -0700 | [diff] [blame] | 2118 |   uint32_t oat_method_idx = GetOatMethodIndexFromMethodIndex(dex_file, class_def_idx, method_idx); | 
| Vladimir Marko | d3c5beb | 2014-04-11 16:32:51 +0100 | [diff] [blame] | 2119 |   return oat_class.GetOatMethod(oat_method_idx).GetQuickCode(); | 
| Ian Rogers | ef7d42f | 2014-01-06 12:55:46 -0800 | [diff] [blame] | 2120 | } | 
 | 2121 |  | 
| Sebastien Hertz | 7d658cf | 2013-07-09 10:56:11 +0200 | [diff] [blame] | 2122 | // Returns true if the method must run with interpreter, false otherwise. | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 2123 | static bool NeedsInterpreter(ArtMethod* method, const void* quick_code) | 
| Mathieu Chartier | 9044347 | 2015-07-16 20:32:27 -0700 | [diff] [blame] | 2124 |     SHARED_REQUIRES(Locks::mutator_lock_) { | 
| Elliott Hughes | 956af0f | 2014-12-11 14:34:28 -0800 | [diff] [blame] | 2125 |   if (quick_code == nullptr) { | 
| Sebastien Hertz | 7d658cf | 2013-07-09 10:56:11 +0200 | [diff] [blame] | 2126 |     // No code: need interpreter. | 
| Andreas Gampe | 2da8823 | 2014-02-27 12:26:20 -0800 | [diff] [blame] | 2127 |     // May return true for native code, in the case of generic JNI | 
 | 2128 |     // DCHECK(!method->IsNative()); | 
| Sebastien Hertz | 7d658cf | 2013-07-09 10:56:11 +0200 | [diff] [blame] | 2129 |     return true; | 
 | 2130 |   } | 
 | 2131 |   // If interpreter mode is enabled, every method (except native and proxy) must | 
 | 2132 |   // be run with interpreter. | 
 | 2133 |   return Runtime::Current()->GetInstrumentation()->InterpretOnly() && | 
 | 2134 |          !method->IsNative() && !method->IsProxyMethod(); | 
 | 2135 | } | 
 | 2136 |  | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 2137 | void ClassLinker::FixupStaticTrampolines(mirror::Class* klass) { | 
| Brian Carlstrom | 073278c | 2014-02-19 15:21:21 -0800 | [diff] [blame] | 2138 |   DCHECK(klass->IsInitialized()) << PrettyDescriptor(klass); | 
| Ian Rogers | 1c82982 | 2013-09-30 18:18:50 -0700 | [diff] [blame] | 2139 |   if (klass->NumDirectMethods() == 0) { | 
 | 2140 |     return;  // No direct methods => no static methods. | 
| Ian Rogers | 1984651 | 2012-02-24 11:42:47 -0800 | [diff] [blame] | 2141 |   } | 
| Ian Rogers | 62d6c77 | 2013-02-27 08:32:07 -0800 | [diff] [blame] | 2142 |   Runtime* runtime = Runtime::Current(); | 
| Andreas Gampe | 81c6f8d | 2015-03-25 17:19:53 -0700 | [diff] [blame] | 2143 |   if (!runtime->IsStarted()) { | 
| Mathieu Chartier | e5f13e5 | 2015-02-24 09:37:21 -0800 | [diff] [blame] | 2144 |     if (runtime->IsAotCompiler() || runtime->GetHeap()->HasImageSpace()) { | 
| Alex Light | 64ad14d | 2014-08-19 14:23:13 -0700 | [diff] [blame] | 2145 |       return;  // OAT file unavailable. | 
 | 2146 |     } | 
| Ian Rogers | 1984651 | 2012-02-24 11:42:47 -0800 | [diff] [blame] | 2147 |   } | 
| Alex Light | 64ad14d | 2014-08-19 14:23:13 -0700 | [diff] [blame] | 2148 |  | 
| Mathieu Chartier | f832284 | 2014-05-16 10:59:25 -0700 | [diff] [blame] | 2149 |   const DexFile& dex_file = klass->GetDexFile(); | 
 | 2150 |   const DexFile::ClassDef* dex_class_def = klass->GetClassDef(); | 
| Ian Rogers | 1c82982 | 2013-09-30 18:18:50 -0700 | [diff] [blame] | 2151 |   CHECK(dex_class_def != nullptr); | 
| Ian Rogers | 1373595 | 2014-10-08 12:43:28 -0700 | [diff] [blame] | 2152 |   const uint8_t* class_data = dex_file.GetClassData(*dex_class_def); | 
| Ian Rogers | 1c82982 | 2013-09-30 18:18:50 -0700 | [diff] [blame] | 2153 |   // There should always be class data if there were direct methods. | 
 | 2154 |   CHECK(class_data != nullptr) << PrettyDescriptor(klass); | 
| Ian Rogers | 1984651 | 2012-02-24 11:42:47 -0800 | [diff] [blame] | 2155 |   ClassDataItemIterator it(dex_file, class_data); | 
 | 2156 |   // Skip fields | 
 | 2157 |   while (it.HasNextStaticField()) { | 
 | 2158 |     it.Next(); | 
 | 2159 |   } | 
 | 2160 |   while (it.HasNextInstanceField()) { | 
 | 2161 |     it.Next(); | 
 | 2162 |   } | 
| Ian Rogers | 97b52f8 | 2014-08-14 11:34:07 -0700 | [diff] [blame] | 2163 |   bool has_oat_class; | 
 | 2164 |   OatFile::OatClass oat_class = FindOatClass(dex_file, klass->GetDexClassDefIndex(), | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 2165 |                                              &has_oat_class); | 
| Ian Rogers | 1c82982 | 2013-09-30 18:18:50 -0700 | [diff] [blame] | 2166 |   // Link the code of methods skipped by LinkCode. | 
| Sebastien Hertz | 7d658cf | 2013-07-09 10:56:11 +0200 | [diff] [blame] | 2167 |   for (size_t method_index = 0; it.HasNextDirectMethod(); ++method_index, it.Next()) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 2168 |     ArtMethod* method = klass->GetDirectMethod(method_index, image_pointer_size_); | 
| Sebastien Hertz | 7d658cf | 2013-07-09 10:56:11 +0200 | [diff] [blame] | 2169 |     if (!method->IsStatic()) { | 
 | 2170 |       // Only update static methods. | 
 | 2171 |       continue; | 
| Ian Rogers | 1984651 | 2012-02-24 11:42:47 -0800 | [diff] [blame] | 2172 |     } | 
| Nicolas Geoffray | 4fcdc94 | 2014-07-22 10:48:00 +0100 | [diff] [blame] | 2173 |     const void* quick_code = nullptr; | 
 | 2174 |     if (has_oat_class) { | 
 | 2175 |       OatFile::OatMethod oat_method = oat_class.GetOatMethod(method_index); | 
| Nicolas Geoffray | 4fcdc94 | 2014-07-22 10:48:00 +0100 | [diff] [blame] | 2176 |       quick_code = oat_method.GetQuickCode(); | 
 | 2177 |     } | 
| Elliott Hughes | 956af0f | 2014-12-11 14:34:28 -0800 | [diff] [blame] | 2178 |     const bool enter_interpreter = NeedsInterpreter(method, quick_code); | 
| Sebastien Hertz | 7d658cf | 2013-07-09 10:56:11 +0200 | [diff] [blame] | 2179 |     if (enter_interpreter) { | 
 | 2180 |       // Use interpreter entry point. | 
| Ian Rogers | 1a57066 | 2014-03-12 01:02:21 -0700 | [diff] [blame] | 2181 |       // Check whether the method is native, in which case it's generic JNI. | 
| Elliott Hughes | 956af0f | 2014-12-11 14:34:28 -0800 | [diff] [blame] | 2182 |       if (quick_code == nullptr && method->IsNative()) { | 
| Ian Rogers | 6f3dbba | 2014-10-14 17:41:57 -0700 | [diff] [blame] | 2183 |         quick_code = GetQuickGenericJniStub(); | 
| Andreas Gampe | 2da8823 | 2014-02-27 12:26:20 -0800 | [diff] [blame] | 2184 |       } else { | 
 | 2185 |         quick_code = GetQuickToInterpreterBridge(); | 
 | 2186 |       } | 
| Sebastien Hertz | 7d658cf | 2013-07-09 10:56:11 +0200 | [diff] [blame] | 2187 |     } | 
| Elliott Hughes | 956af0f | 2014-12-11 14:34:28 -0800 | [diff] [blame] | 2188 |     runtime->GetInstrumentation()->UpdateMethodsCode(method, quick_code); | 
| Ian Rogers | 1984651 | 2012-02-24 11:42:47 -0800 | [diff] [blame] | 2189 |   } | 
| Ian Rogers | 62d6c77 | 2013-02-27 08:32:07 -0800 | [diff] [blame] | 2190 |   // Ignore virtual methods on the iterator. | 
| Ian Rogers | 1984651 | 2012-02-24 11:42:47 -0800 | [diff] [blame] | 2191 | } | 
 | 2192 |  | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 2193 | void ClassLinker::LinkCode(ArtMethod* method, const OatFile::OatClass* oat_class, | 
| Ian Rogers | 6a3c1fc | 2014-10-31 00:33:20 -0700 | [diff] [blame] | 2194 |                            uint32_t class_def_method_index) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 2195 |   Runtime* const runtime = Runtime::Current(); | 
| Mathieu Chartier | e5f13e5 | 2015-02-24 09:37:21 -0800 | [diff] [blame] | 2196 |   if (runtime->IsAotCompiler()) { | 
| Nicolas Geoffray | 4fcdc94 | 2014-07-22 10:48:00 +0100 | [diff] [blame] | 2197 |     // The following code only applies to a non-compiler runtime. | 
 | 2198 |     return; | 
 | 2199 |   } | 
| Ian Rogers | 62d6c77 | 2013-02-27 08:32:07 -0800 | [diff] [blame] | 2200 |   // Method shouldn't have already been linked. | 
| Ian Rogers | ef7d42f | 2014-01-06 12:55:46 -0800 | [diff] [blame] | 2201 |   DCHECK(method->GetEntryPointFromQuickCompiledCode() == nullptr); | 
| Nicolas Geoffray | 4fcdc94 | 2014-07-22 10:48:00 +0100 | [diff] [blame] | 2202 |   if (oat_class != nullptr) { | 
 | 2203 |     // Every kind of method should at least get an invoke stub from the oat_method. | 
 | 2204 |     // non-abstract methods also get their code pointers. | 
| Ian Rogers | 6a3c1fc | 2014-10-31 00:33:20 -0700 | [diff] [blame] | 2205 |     const OatFile::OatMethod oat_method = oat_class->GetOatMethod(class_def_method_index); | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 2206 |     oat_method.LinkMethod(method); | 
| Nicolas Geoffray | 4fcdc94 | 2014-07-22 10:48:00 +0100 | [diff] [blame] | 2207 |   } | 
| Brian Carlstrom | 92827a5 | 2011-10-10 15:50:01 -0700 | [diff] [blame] | 2208 |  | 
| Jeff Hao | 1674363 | 2013-05-08 10:59:04 -0700 | [diff] [blame] | 2209 |   // Install entry point from interpreter. | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 2210 |   bool enter_interpreter = NeedsInterpreter(method, method->GetEntryPointFromQuickCompiledCode()); | 
| Jeff Hao | 1674363 | 2013-05-08 10:59:04 -0700 | [diff] [blame] | 2211 |  | 
| Brian Carlstrom | 92827a5 | 2011-10-10 15:50:01 -0700 | [diff] [blame] | 2212 |   if (method->IsAbstract()) { | 
| Ian Rogers | ef7d42f | 2014-01-06 12:55:46 -0800 | [diff] [blame] | 2213 |     method->SetEntryPointFromQuickCompiledCode(GetQuickToInterpreterBridge()); | 
| Brian Carlstrom | 92827a5 | 2011-10-10 15:50:01 -0700 | [diff] [blame] | 2214 |     return; | 
 | 2215 |   } | 
| Ian Rogers | 1984651 | 2012-02-24 11:42:47 -0800 | [diff] [blame] | 2216 |  | 
 | 2217 |   if (method->IsStatic() && !method->IsConstructor()) { | 
| Ian Rogers | 62d6c77 | 2013-02-27 08:32:07 -0800 | [diff] [blame] | 2218 |     // For static methods excluding the class initializer, install the trampoline. | 
| Sebastien Hertz | 7d658cf | 2013-07-09 10:56:11 +0200 | [diff] [blame] | 2219 |     // It will be replaced by the proper entry point by ClassLinker::FixupStaticTrampolines | 
 | 2220 |     // after initializing class (see ClassLinker::InitializeClass method). | 
| Ian Rogers | 6f3dbba | 2014-10-14 17:41:57 -0700 | [diff] [blame] | 2221 |     method->SetEntryPointFromQuickCompiledCode(GetQuickResolutionStub()); | 
| Sebastien Hertz | 7d658cf | 2013-07-09 10:56:11 +0200 | [diff] [blame] | 2222 |   } else if (enter_interpreter) { | 
| Andreas Gampe | bf6b92a | 2014-03-05 16:11:04 -0800 | [diff] [blame] | 2223 |     if (!method->IsNative()) { | 
 | 2224 |       // Set entry point from compiled code if there's no code or in interpreter only mode. | 
 | 2225 |       method->SetEntryPointFromQuickCompiledCode(GetQuickToInterpreterBridge()); | 
| Andreas Gampe | bf6b92a | 2014-03-05 16:11:04 -0800 | [diff] [blame] | 2226 |     } else { | 
| Ian Rogers | 6f3dbba | 2014-10-14 17:41:57 -0700 | [diff] [blame] | 2227 |       method->SetEntryPointFromQuickCompiledCode(GetQuickGenericJniStub()); | 
| Andreas Gampe | bf6b92a | 2014-03-05 16:11:04 -0800 | [diff] [blame] | 2228 |     } | 
| Ian Rogers | 0d6de04 | 2012-02-29 08:50:26 -0800 | [diff] [blame] | 2229 |   } | 
| jeffhao | 26c0a1a | 2012-01-17 16:28:33 -0800 | [diff] [blame] | 2230 |  | 
| Ian Rogers | 62d6c77 | 2013-02-27 08:32:07 -0800 | [diff] [blame] | 2231 |   if (method->IsNative()) { | 
 | 2232 |     // Unregistering restores the dlsym lookup stub. | 
| Ian Rogers | 6f3dbba | 2014-10-14 17:41:57 -0700 | [diff] [blame] | 2233 |     method->UnregisterNative(); | 
| Andreas Gampe | 9054683 | 2014-03-12 18:07:19 -0700 | [diff] [blame] | 2234 |  | 
 | 2235 |     if (enter_interpreter) { | 
| Ian Rogers | 6f3dbba | 2014-10-14 17:41:57 -0700 | [diff] [blame] | 2236 |       // We have a native method here without code. Then it should have either the generic JNI | 
 | 2237 |       // trampoline as entrypoint (non-static), or the resolution trampoline (static). | 
 | 2238 |       // TODO: this doesn't handle all the cases where trampolines may be installed. | 
 | 2239 |       const void* entry_point = method->GetEntryPointFromQuickCompiledCode(); | 
 | 2240 |       DCHECK(IsQuickGenericJniStub(entry_point) || IsQuickResolutionStub(entry_point)); | 
| Andreas Gampe | 9054683 | 2014-03-12 18:07:19 -0700 | [diff] [blame] | 2241 |     } | 
| Brian Carlstrom | 92827a5 | 2011-10-10 15:50:01 -0700 | [diff] [blame] | 2242 |   } | 
 | 2243 | } | 
 | 2244 |  | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 2245 | void ClassLinker::SetupClass(const DexFile& dex_file, const DexFile::ClassDef& dex_class_def, | 
 | 2246 |                              Handle<mirror::Class> klass, mirror::ClassLoader* class_loader) { | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 2247 |   CHECK(klass.Get() != nullptr); | 
 | 2248 |   CHECK(klass->GetDexCache() != nullptr); | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 2249 |   CHECK_EQ(mirror::Class::kStatusNotReady, klass->GetStatus()); | 
| Brian Carlstrom | f615a61 | 2011-07-23 12:50:34 -0700 | [diff] [blame] | 2250 |   const char* descriptor = dex_file.GetClassDescriptor(dex_class_def); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 2251 |   CHECK(descriptor != nullptr); | 
| Brian Carlstrom | 934486c | 2011-07-12 23:42:50 -0700 | [diff] [blame] | 2252 |  | 
| Ian Rogers | 0cfe1fb | 2011-08-26 03:29:44 -0700 | [diff] [blame] | 2253 |   klass->SetClass(GetClassRoot(kJavaLangClass)); | 
| Andreas Gampe | 5182932 | 2014-08-25 15:05:04 -0700 | [diff] [blame] | 2254 |   uint32_t access_flags = dex_class_def.GetJavaAccessFlags(); | 
| Brian Carlstrom | 8e3fb14 | 2013-10-09 21:00:27 -0700 | [diff] [blame] | 2255 |   CHECK_EQ(access_flags & ~kAccJavaFlagsMask, 0U); | 
| Ian Rogers | 0cfe1fb | 2011-08-26 03:29:44 -0700 | [diff] [blame] | 2256 |   klass->SetAccessFlags(access_flags); | 
 | 2257 |   klass->SetClassLoader(class_loader); | 
| Ian Rogers | c2b4447 | 2011-12-14 21:17:17 -0800 | [diff] [blame] | 2258 |   DCHECK_EQ(klass->GetPrimitiveType(), Primitive::kPrimNot); | 
| Hiroshi Yamauchi | 5b783e6 | 2015-03-18 17:20:11 -0700 | [diff] [blame] | 2259 |   mirror::Class::SetStatus(klass, mirror::Class::kStatusIdx, nullptr); | 
| Brian Carlstrom | 934486c | 2011-07-12 23:42:50 -0700 | [diff] [blame] | 2260 |  | 
| Ian Rogers | 8b2c0b9 | 2013-09-19 02:56:49 -0700 | [diff] [blame] | 2261 |   klass->SetDexClassDefIndex(dex_file.GetIndexForClassDef(dex_class_def)); | 
| Ian Rogers | 6d4d9fc | 2011-11-30 16:24:48 -0800 | [diff] [blame] | 2262 |   klass->SetDexTypeIndex(dex_class_def.class_idx_); | 
| Mathieu Chartier | 91a6dc4 | 2014-12-01 10:31:15 -0800 | [diff] [blame] | 2263 |   CHECK(klass->GetDexCacheStrings() != nullptr); | 
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 2264 | } | 
| Brian Carlstrom | 934486c | 2011-07-12 23:42:50 -0700 | [diff] [blame] | 2265 |  | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 2266 | void ClassLinker::LoadClass(Thread* self, const DexFile& dex_file, | 
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 2267 |                             const DexFile::ClassDef& dex_class_def, | 
 | 2268 |                             Handle<mirror::Class> klass) { | 
| Ian Rogers | 1373595 | 2014-10-08 12:43:28 -0700 | [diff] [blame] | 2269 |   const uint8_t* class_data = dex_file.GetClassData(dex_class_def); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 2270 |   if (class_data == nullptr) { | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 2271 |     return;  // no fields or methods - for example a marker interface | 
| Brian Carlstrom | 934486c | 2011-07-12 23:42:50 -0700 | [diff] [blame] | 2272 |   } | 
| Ian Rogers | 97b52f8 | 2014-08-14 11:34:07 -0700 | [diff] [blame] | 2273 |   bool has_oat_class = false; | 
| Andreas Gampe | 81c6f8d | 2015-03-25 17:19:53 -0700 | [diff] [blame] | 2274 |   if (Runtime::Current()->IsStarted() && !Runtime::Current()->IsAotCompiler()) { | 
| Ian Rogers | 97b52f8 | 2014-08-14 11:34:07 -0700 | [diff] [blame] | 2275 |     OatFile::OatClass oat_class = FindOatClass(dex_file, klass->GetDexClassDefIndex(), | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 2276 |                                                &has_oat_class); | 
| Ian Rogers | 97b52f8 | 2014-08-14 11:34:07 -0700 | [diff] [blame] | 2277 |     if (has_oat_class) { | 
| Ian Rogers | 6a3c1fc | 2014-10-31 00:33:20 -0700 | [diff] [blame] | 2278 |       LoadClassMembers(self, dex_file, class_data, klass, &oat_class); | 
| Ian Rogers | 97b52f8 | 2014-08-14 11:34:07 -0700 | [diff] [blame] | 2279 |     } | 
 | 2280 |   } | 
 | 2281 |   if (!has_oat_class) { | 
| Ian Rogers | 6a3c1fc | 2014-10-31 00:33:20 -0700 | [diff] [blame] | 2282 |     LoadClassMembers(self, dex_file, class_data, klass, nullptr); | 
| Vladimir Marko | d3c5beb | 2014-04-11 16:32:51 +0100 | [diff] [blame] | 2283 |   } | 
 | 2284 | } | 
 | 2285 |  | 
| Mathieu Chartier | 54d220e | 2015-07-30 16:20:06 -0700 | [diff] [blame] | 2286 | LengthPrefixedArray<ArtField>* ClassLinker::AllocArtFieldArray(Thread* self, size_t length) { | 
 | 2287 |   if (length == 0) { | 
 | 2288 |     return nullptr; | 
 | 2289 |   } | 
| Vladimir Marko | cf36d49 | 2015-08-12 19:27:26 +0100 | [diff] [blame] | 2290 |   // If the ArtField alignment changes, review all uses of LengthPrefixedArray<ArtField>. | 
 | 2291 |   static_assert(alignof(ArtField) == 4, "ArtField alignment is expected to be 4."); | 
 | 2292 |   size_t storage_size = LengthPrefixedArray<ArtField>::ComputeSize(length); | 
 | 2293 |   void* array_storage = Runtime::Current()->GetLinearAlloc()->Alloc(self, storage_size); | 
 | 2294 |   auto* ret = new(array_storage) LengthPrefixedArray<ArtField>(length); | 
| Mathieu Chartier | 54d220e | 2015-07-30 16:20:06 -0700 | [diff] [blame] | 2295 |   CHECK(ret != nullptr); | 
 | 2296 |   std::uninitialized_fill_n(&ret->At(0), length, ArtField()); | 
 | 2297 |   return ret; | 
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 2298 | } | 
 | 2299 |  | 
| Mathieu Chartier | 54d220e | 2015-07-30 16:20:06 -0700 | [diff] [blame] | 2300 | LengthPrefixedArray<ArtMethod>* ClassLinker::AllocArtMethodArray(Thread* self, size_t length) { | 
 | 2301 |   if (length == 0) { | 
 | 2302 |     return nullptr; | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 2303 |   } | 
| Vladimir Marko | 1463285 | 2015-08-17 12:07:23 +0100 | [diff] [blame] | 2304 |   const size_t method_alignment = ArtMethod::Alignment(image_pointer_size_); | 
 | 2305 |   const size_t method_size = ArtMethod::Size(image_pointer_size_); | 
| Vladimir Marko | cf36d49 | 2015-08-12 19:27:26 +0100 | [diff] [blame] | 2306 |   const size_t storage_size = | 
 | 2307 |       LengthPrefixedArray<ArtMethod>::ComputeSize(length, method_size, method_alignment); | 
 | 2308 |   void* array_storage = Runtime::Current()->GetLinearAlloc()->Alloc(self, storage_size); | 
 | 2309 |   auto* ret = new (array_storage) LengthPrefixedArray<ArtMethod>(length); | 
| Mathieu Chartier | 54d220e | 2015-07-30 16:20:06 -0700 | [diff] [blame] | 2310 |   CHECK(ret != nullptr); | 
 | 2311 |   for (size_t i = 0; i < length; ++i) { | 
| Vladimir Marko | cf36d49 | 2015-08-12 19:27:26 +0100 | [diff] [blame] | 2312 |     new(reinterpret_cast<void*>(&ret->At(i, method_size, method_alignment))) ArtMethod; | 
| Mathieu Chartier | 54d220e | 2015-07-30 16:20:06 -0700 | [diff] [blame] | 2313 |   } | 
 | 2314 |   return ret; | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 2315 | } | 
 | 2316 |  | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 2317 | void ClassLinker::LoadClassMembers(Thread* self, const DexFile& dex_file, | 
| Ian Rogers | 1373595 | 2014-10-08 12:43:28 -0700 | [diff] [blame] | 2318 |                                    const uint8_t* class_data, | 
| Andreas Gampe | 5a4b8a2 | 2014-09-11 08:30:08 -0700 | [diff] [blame] | 2319 |                                    Handle<mirror::Class> klass, | 
| Vladimir Marko | d3c5beb | 2014-04-11 16:32:51 +0100 | [diff] [blame] | 2320 |                                    const OatFile::OatClass* oat_class) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 2321 |   { | 
 | 2322 |     // Note: We cannot have thread suspension until the field and method arrays are setup or else | 
 | 2323 |     // Class::VisitFieldRoots may miss some fields or methods. | 
 | 2324 |     ScopedAssertNoThreadSuspension nts(self, __FUNCTION__); | 
 | 2325 |     // Load static fields. | 
| Vladimir Marko | 23682bf | 2015-06-24 14:28:03 +0100 | [diff] [blame] | 2326 |     // We allow duplicate definitions of the same field in a class_data_item | 
 | 2327 |     // but ignore the repeated indexes here, b/21868015. | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 2328 |     ClassDataItemIterator it(dex_file, class_data); | 
| Mathieu Chartier | 54d220e | 2015-07-30 16:20:06 -0700 | [diff] [blame] | 2329 |     LengthPrefixedArray<ArtField>* sfields = AllocArtFieldArray(self, it.NumStaticFields()); | 
| Vladimir Marko | 23682bf | 2015-06-24 14:28:03 +0100 | [diff] [blame] | 2330 |     size_t num_sfields = 0; | 
 | 2331 |     uint32_t last_field_idx = 0u; | 
 | 2332 |     for (; it.HasNextStaticField(); it.Next()) { | 
 | 2333 |       uint32_t field_idx = it.GetMemberIndex(); | 
 | 2334 |       DCHECK_GE(field_idx, last_field_idx);  // Ordering enforced by DexFileVerifier. | 
 | 2335 |       if (num_sfields == 0 || LIKELY(field_idx > last_field_idx)) { | 
 | 2336 |         DCHECK_LT(num_sfields, it.NumStaticFields()); | 
| Mathieu Chartier | 54d220e | 2015-07-30 16:20:06 -0700 | [diff] [blame] | 2337 |         LoadField(it, klass, &sfields->At(num_sfields)); | 
| Vladimir Marko | 23682bf | 2015-06-24 14:28:03 +0100 | [diff] [blame] | 2338 |         ++num_sfields; | 
 | 2339 |         last_field_idx = field_idx; | 
 | 2340 |       } | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 2341 |     } | 
| Mathieu Chartier | 54d220e | 2015-07-30 16:20:06 -0700 | [diff] [blame] | 2342 |     klass->SetSFieldsPtr(sfields); | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 2343 |     DCHECK_EQ(klass->NumStaticFields(), num_sfields); | 
 | 2344 |     // Load instance fields. | 
| Mathieu Chartier | 54d220e | 2015-07-30 16:20:06 -0700 | [diff] [blame] | 2345 |     LengthPrefixedArray<ArtField>* ifields = AllocArtFieldArray(self, it.NumInstanceFields()); | 
| Vladimir Marko | 23682bf | 2015-06-24 14:28:03 +0100 | [diff] [blame] | 2346 |     size_t num_ifields = 0u; | 
 | 2347 |     last_field_idx = 0u; | 
 | 2348 |     for (; it.HasNextInstanceField(); it.Next()) { | 
 | 2349 |       uint32_t field_idx = it.GetMemberIndex(); | 
 | 2350 |       DCHECK_GE(field_idx, last_field_idx);  // Ordering enforced by DexFileVerifier. | 
 | 2351 |       if (num_ifields == 0 || LIKELY(field_idx > last_field_idx)) { | 
 | 2352 |         DCHECK_LT(num_ifields, it.NumInstanceFields()); | 
| Mathieu Chartier | 54d220e | 2015-07-30 16:20:06 -0700 | [diff] [blame] | 2353 |         LoadField(it, klass, &ifields->At(num_ifields)); | 
| Vladimir Marko | 23682bf | 2015-06-24 14:28:03 +0100 | [diff] [blame] | 2354 |         ++num_ifields; | 
 | 2355 |         last_field_idx = field_idx; | 
 | 2356 |       } | 
 | 2357 |     } | 
 | 2358 |     if (UNLIKELY(num_sfields != it.NumStaticFields()) || | 
 | 2359 |         UNLIKELY(num_ifields != it.NumInstanceFields())) { | 
 | 2360 |       LOG(WARNING) << "Duplicate fields in class " << PrettyDescriptor(klass.Get()) | 
 | 2361 |           << " (unique static fields: " << num_sfields << "/" << it.NumStaticFields() | 
 | 2362 |           << ", unique instance fields: " << num_ifields << "/" << it.NumInstanceFields() << ")"; | 
 | 2363 |       // NOTE: Not shrinking the over-allocated sfields/ifields. | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 2364 |     } | 
| Mathieu Chartier | 54d220e | 2015-07-30 16:20:06 -0700 | [diff] [blame] | 2365 |     klass->SetIFieldsPtr(ifields); | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 2366 |     DCHECK_EQ(klass->NumInstanceFields(), num_ifields); | 
 | 2367 |     // Load methods. | 
| Mathieu Chartier | 54d220e | 2015-07-30 16:20:06 -0700 | [diff] [blame] | 2368 |     klass->SetDirectMethodsPtr(AllocArtMethodArray(self, it.NumDirectMethods())); | 
 | 2369 |     klass->SetVirtualMethodsPtr(AllocArtMethodArray(self, it.NumVirtualMethods())); | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 2370 |     size_t class_def_method_index = 0; | 
 | 2371 |     uint32_t last_dex_method_index = DexFile::kDexNoIndex; | 
 | 2372 |     size_t last_class_def_method_index = 0; | 
 | 2373 |     for (size_t i = 0; it.HasNextDirectMethod(); i++, it.Next()) { | 
 | 2374 |       ArtMethod* method = klass->GetDirectMethodUnchecked(i, image_pointer_size_); | 
 | 2375 |       LoadMethod(self, dex_file, it, klass, method); | 
 | 2376 |       LinkCode(method, oat_class, class_def_method_index); | 
 | 2377 |       uint32_t it_method_index = it.GetMemberIndex(); | 
 | 2378 |       if (last_dex_method_index == it_method_index) { | 
 | 2379 |         // duplicate case | 
 | 2380 |         method->SetMethodIndex(last_class_def_method_index); | 
 | 2381 |       } else { | 
 | 2382 |         method->SetMethodIndex(class_def_method_index); | 
 | 2383 |         last_dex_method_index = it_method_index; | 
 | 2384 |         last_class_def_method_index = class_def_method_index; | 
 | 2385 |       } | 
 | 2386 |       class_def_method_index++; | 
 | 2387 |     } | 
 | 2388 |     for (size_t i = 0; it.HasNextVirtualMethod(); i++, it.Next()) { | 
 | 2389 |       ArtMethod* method = klass->GetVirtualMethodUnchecked(i, image_pointer_size_); | 
 | 2390 |       LoadMethod(self, dex_file, it, klass, method); | 
 | 2391 |       DCHECK_EQ(class_def_method_index, it.NumDirectMethods() + i); | 
 | 2392 |       LinkCode(method, oat_class, class_def_method_index); | 
 | 2393 |       class_def_method_index++; | 
 | 2394 |     } | 
 | 2395 |     DCHECK(!it.HasNext()); | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 2396 |   } | 
| Mathieu Chartier | eb837eb | 2015-07-29 17:25:41 -0700 | [diff] [blame] | 2397 |   // Ensure that the card is marked so that remembered sets pick up native roots. | 
 | 2398 |   Runtime::Current()->GetHeap()->WriteBarrierEveryFieldOf(klass.Get()); | 
| Mathieu Chartier | f3f2a7a | 2015-04-14 15:43:10 -0700 | [diff] [blame] | 2399 |   self->AllowThreadSuspension(); | 
| Brian Carlstrom | 934486c | 2011-07-12 23:42:50 -0700 | [diff] [blame] | 2400 | } | 
 | 2401 |  | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 2402 | void ClassLinker::LoadField(const ClassDataItemIterator& it, Handle<mirror::Class> klass, | 
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 2403 |                             ArtField* dst) { | 
 | 2404 |   const uint32_t field_idx = it.GetMemberIndex(); | 
| Ian Rogers | 6d4d9fc | 2011-11-30 16:24:48 -0800 | [diff] [blame] | 2405 |   dst->SetDexFieldIndex(field_idx); | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 2406 |   dst->SetDeclaringClass(klass.Get()); | 
| Andreas Gampe | 5182932 | 2014-08-25 15:05:04 -0700 | [diff] [blame] | 2407 |   dst->SetAccessFlags(it.GetFieldAccessFlags()); | 
| Brian Carlstrom | 934486c | 2011-07-12 23:42:50 -0700 | [diff] [blame] | 2408 | } | 
 | 2409 |  | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 2410 | void ClassLinker::LoadMethod(Thread* self, const DexFile& dex_file, const ClassDataItemIterator& it, | 
 | 2411 |                              Handle<mirror::Class> klass, ArtMethod* dst) { | 
| Ian Rogers | 1984651 | 2012-02-24 11:42:47 -0800 | [diff] [blame] | 2412 |   uint32_t dex_method_idx = it.GetMemberIndex(); | 
| Ian Rogers | 1984651 | 2012-02-24 11:42:47 -0800 | [diff] [blame] | 2413 |   const DexFile::MethodId& method_id = dex_file.GetMethodId(dex_method_idx); | 
| Ian Rogers | dfb325e | 2013-10-30 01:00:44 -0700 | [diff] [blame] | 2414 |   const char* method_name = dex_file.StringDataByIdx(method_id.name_idx_); | 
| Mathieu Chartier | 66f1925 | 2012-09-18 08:57:04 -0700 | [diff] [blame] | 2415 |  | 
| Mathieu Chartier | 2d5f39e | 2014-09-19 17:52:37 -0700 | [diff] [blame] | 2416 |   ScopedAssertNoThreadSuspension ants(self, "LoadMethod"); | 
| Mathieu Chartier | 66f1925 | 2012-09-18 08:57:04 -0700 | [diff] [blame] | 2417 |   dst->SetDexMethodIndex(dex_method_idx); | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 2418 |   dst->SetDeclaringClass(klass.Get()); | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 2419 |   dst->SetCodeItemOffset(it.GetMethodCodeItemOffset()); | 
| Brian Carlstrom | 934486c | 2011-07-12 23:42:50 -0700 | [diff] [blame] | 2420 |  | 
| Ian Rogers | 1984651 | 2012-02-24 11:42:47 -0800 | [diff] [blame] | 2421 |   dst->SetDexCacheResolvedMethods(klass->GetDexCache()->GetResolvedMethods()); | 
| Ian Rogers | 0cfe1fb | 2011-08-26 03:29:44 -0700 | [diff] [blame] | 2422 |   dst->SetDexCacheResolvedTypes(klass->GetDexCache()->GetResolvedTypes()); | 
| Mathieu Chartier | 66f1925 | 2012-09-18 08:57:04 -0700 | [diff] [blame] | 2423 |  | 
| Andreas Gampe | 5182932 | 2014-08-25 15:05:04 -0700 | [diff] [blame] | 2424 |   uint32_t access_flags = it.GetMethodAccessFlags(); | 
| Ian Rogers | 241b5de | 2013-10-09 17:58:57 -0700 | [diff] [blame] | 2425 |  | 
| Ian Rogers | dfb325e | 2013-10-30 01:00:44 -0700 | [diff] [blame] | 2426 |   if (UNLIKELY(strcmp("finalize", method_name) == 0)) { | 
| Ian Rogers | 241b5de | 2013-10-09 17:58:57 -0700 | [diff] [blame] | 2427 |     // Set finalizable flag on declaring class. | 
| Ian Rogers | dfb325e | 2013-10-30 01:00:44 -0700 | [diff] [blame] | 2428 |     if (strcmp("V", dex_file.GetShorty(method_id.proto_idx_)) == 0) { | 
 | 2429 |       // Void return type. | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 2430 |       if (klass->GetClassLoader() != nullptr) {  // All non-boot finalizer methods are flagged. | 
| Ian Rogers | dfb325e | 2013-10-30 01:00:44 -0700 | [diff] [blame] | 2431 |         klass->SetFinalizable(); | 
 | 2432 |       } else { | 
| Ian Rogers | 1ff3c98 | 2014-08-12 02:30:58 -0700 | [diff] [blame] | 2433 |         std::string temp; | 
 | 2434 |         const char* klass_descriptor = klass->GetDescriptor(&temp); | 
| Ian Rogers | dfb325e | 2013-10-30 01:00:44 -0700 | [diff] [blame] | 2435 |         // The Enum class declares a "final" finalize() method to prevent subclasses from | 
 | 2436 |         // introducing a finalizer. We don't want to set the finalizable flag for Enum or its | 
 | 2437 |         // subclasses, so we exclude it here. | 
 | 2438 |         // We also want to avoid setting the flag on Object, where we know that finalize() is | 
 | 2439 |         // empty. | 
| Ian Rogers | 1ff3c98 | 2014-08-12 02:30:58 -0700 | [diff] [blame] | 2440 |         if (strcmp(klass_descriptor, "Ljava/lang/Object;") != 0 && | 
 | 2441 |             strcmp(klass_descriptor, "Ljava/lang/Enum;") != 0) { | 
| Ian Rogers | 241b5de | 2013-10-09 17:58:57 -0700 | [diff] [blame] | 2442 |           klass->SetFinalizable(); | 
| Ian Rogers | 241b5de | 2013-10-09 17:58:57 -0700 | [diff] [blame] | 2443 |         } | 
 | 2444 |       } | 
 | 2445 |     } | 
 | 2446 |   } else if (method_name[0] == '<') { | 
 | 2447 |     // Fix broken access flags for initializers. Bug 11157540. | 
| Ian Rogers | dfb325e | 2013-10-30 01:00:44 -0700 | [diff] [blame] | 2448 |     bool is_init = (strcmp("<init>", method_name) == 0); | 
 | 2449 |     bool is_clinit = !is_init && (strcmp("<clinit>", method_name) == 0); | 
| Ian Rogers | 241b5de | 2013-10-09 17:58:57 -0700 | [diff] [blame] | 2450 |     if (UNLIKELY(!is_init && !is_clinit)) { | 
 | 2451 |       LOG(WARNING) << "Unexpected '<' at start of method name " << method_name; | 
 | 2452 |     } else { | 
 | 2453 |       if (UNLIKELY((access_flags & kAccConstructor) == 0)) { | 
 | 2454 |         LOG(WARNING) << method_name << " didn't have expected constructor access flag in class " | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 2455 |             << PrettyDescriptor(klass.Get()) << " in dex file " << dex_file.GetLocation(); | 
| Ian Rogers | 241b5de | 2013-10-09 17:58:57 -0700 | [diff] [blame] | 2456 |         access_flags |= kAccConstructor; | 
 | 2457 |       } | 
 | 2458 |     } | 
 | 2459 |   } | 
 | 2460 |   dst->SetAccessFlags(access_flags); | 
| Brian Carlstrom | 934486c | 2011-07-12 23:42:50 -0700 | [diff] [blame] | 2461 | } | 
 | 2462 |  | 
| Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 2463 | void ClassLinker::AppendToBootClassPath(Thread* self, const DexFile& dex_file) { | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 2464 |   StackHandleScope<1> hs(self); | 
 | 2465 |   Handle<mirror::DexCache> dex_cache(hs.NewHandle(AllocDexCache(self, dex_file))); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 2466 |   CHECK(dex_cache.Get() != nullptr) << "Failed to allocate dex cache for " | 
 | 2467 |                                     << dex_file.GetLocation(); | 
| Brian Carlstrom | 40381fb | 2011-10-19 14:13:40 -0700 | [diff] [blame] | 2468 |   AppendToBootClassPath(dex_file, dex_cache); | 
| Brian Carlstrom | a663ea5 | 2011-08-19 23:33:41 -0700 | [diff] [blame] | 2469 | } | 
 | 2470 |  | 
| Mathieu Chartier | c528dba | 2013-11-26 12:00:11 -0800 | [diff] [blame] | 2471 | void ClassLinker::AppendToBootClassPath(const DexFile& dex_file, | 
| Andreas Gampe | 5a4b8a2 | 2014-09-11 08:30:08 -0700 | [diff] [blame] | 2472 |                                         Handle<mirror::DexCache> dex_cache) { | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 2473 |   CHECK(dex_cache.Get() != nullptr) << dex_file.GetLocation(); | 
| Brian Carlstrom | 9ea1cb1 | 2011-08-24 23:18:18 -0700 | [diff] [blame] | 2474 |   boot_class_path_.push_back(&dex_file); | 
| Brian Carlstrom | a663ea5 | 2011-08-19 23:33:41 -0700 | [diff] [blame] | 2475 |   RegisterDexFile(dex_file, dex_cache); | 
| Brian Carlstrom | 578bbdc | 2011-07-21 14:07:47 -0700 | [diff] [blame] | 2476 | } | 
 | 2477 |  | 
| Mathieu Chartier | c528dba | 2013-11-26 12:00:11 -0800 | [diff] [blame] | 2478 | void ClassLinker::RegisterDexFileLocked(const DexFile& dex_file, | 
| Andreas Gampe | 5a4b8a2 | 2014-09-11 08:30:08 -0700 | [diff] [blame] | 2479 |                                         Handle<mirror::DexCache> dex_cache) { | 
| Mathieu Chartier | 673ed3d | 2015-08-28 14:56:43 -0700 | [diff] [blame^] | 2480 |   Thread* const self = Thread::Current(); | 
 | 2481 |   dex_lock_.AssertExclusiveHeld(self); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 2482 |   CHECK(dex_cache.Get() != nullptr) << dex_file.GetLocation(); | 
| Brian Carlstrom | 7c3d13a | 2013-09-04 17:15:11 -0700 | [diff] [blame] | 2483 |   CHECK(dex_cache->GetLocation()->Equals(dex_file.GetLocation())) | 
 | 2484 |       << dex_cache->GetLocation()->ToModifiedUtf8() << " " << dex_file.GetLocation(); | 
| Mathieu Chartier | 673ed3d | 2015-08-28 14:56:43 -0700 | [diff] [blame^] | 2485 |   // Clean up pass to remove null dex caches. | 
 | 2486 |   // Null dex caches can occur due to class unloading and we are lazily removing null entries. | 
 | 2487 |   JavaVMExt* const vm = self->GetJniEnv()->vm; | 
 | 2488 |   for (auto it = dex_caches_.begin(); it != dex_caches_.end();) { | 
 | 2489 |     mirror::Object* dex_cache_root = self->DecodeJObject(*it); | 
 | 2490 |     if (dex_cache_root == nullptr) { | 
 | 2491 |       vm->DeleteWeakGlobalRef(self, *it); | 
 | 2492 |       it = dex_caches_.erase(it); | 
 | 2493 |     } else { | 
 | 2494 |       ++it; | 
 | 2495 |     } | 
| Brian Carlstrom | 81a9087 | 2015-08-28 09:07:14 -0700 | [diff] [blame] | 2496 |   } | 
| Mathieu Chartier | 673ed3d | 2015-08-28 14:56:43 -0700 | [diff] [blame^] | 2497 |   dex_caches_.push_back(vm->AddWeakGlobalRef(self, dex_cache.Get())); | 
 | 2498 |   dex_cache->SetDexFile(&dex_file); | 
| Brian Carlstrom | 578bbdc | 2011-07-21 14:07:47 -0700 | [diff] [blame] | 2499 | } | 
 | 2500 |  | 
| Mathieu Chartier | 673ed3d | 2015-08-28 14:56:43 -0700 | [diff] [blame^] | 2501 | mirror::DexCache* ClassLinker::RegisterDexFile(const DexFile& dex_file) { | 
| Ian Rogers | 1f53934 | 2012-10-03 21:09:42 -0700 | [diff] [blame] | 2502 |   Thread* self = Thread::Current(); | 
| Brian Carlstrom | 47d237a | 2011-10-18 15:08:33 -0700 | [diff] [blame] | 2503 |   { | 
| Ian Rogers | 1bf8d4d | 2013-05-30 00:18:49 -0700 | [diff] [blame] | 2504 |     ReaderMutexLock mu(self, dex_lock_); | 
| Mathieu Chartier | 673ed3d | 2015-08-28 14:56:43 -0700 | [diff] [blame^] | 2505 |     mirror::DexCache* dex_cache = FindDexCacheLocked(self, dex_file, true); | 
 | 2506 |     if (dex_cache != nullptr) { | 
 | 2507 |       return dex_cache; | 
| Brian Carlstrom | 47d237a | 2011-10-18 15:08:33 -0700 | [diff] [blame] | 2508 |     } | 
| Brian Carlstrom | aded5f7 | 2011-10-07 17:15:04 -0700 | [diff] [blame] | 2509 |   } | 
| Brian Carlstrom | 47d237a | 2011-10-18 15:08:33 -0700 | [diff] [blame] | 2510 |   // Don't alloc while holding the lock, since allocation may need to | 
 | 2511 |   // suspend all threads and another thread may need the dex_lock_ to | 
 | 2512 |   // get to a suspend point. | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 2513 |   StackHandleScope<1> hs(self); | 
| Mathieu Chartier | 673ed3d | 2015-08-28 14:56:43 -0700 | [diff] [blame^] | 2514 |   Handle<mirror::DexCache> h_dex_cache(hs.NewHandle(AllocDexCache(self, dex_file))); | 
 | 2515 |   WriterMutexLock mu(self, dex_lock_); | 
 | 2516 |   mirror::DexCache* dex_cache = FindDexCacheLocked(self, dex_file, true); | 
 | 2517 |   if (dex_cache != nullptr) { | 
 | 2518 |     return dex_cache; | 
| Brian Carlstrom | 47d237a | 2011-10-18 15:08:33 -0700 | [diff] [blame] | 2519 |   } | 
| Mathieu Chartier | 673ed3d | 2015-08-28 14:56:43 -0700 | [diff] [blame^] | 2520 |   if (h_dex_cache.Get() == nullptr) { | 
 | 2521 |     self->AssertPendingOOMException(); | 
 | 2522 |     return nullptr; | 
 | 2523 |   } | 
 | 2524 |   RegisterDexFileLocked(dex_file, h_dex_cache); | 
 | 2525 |   return h_dex_cache.Get(); | 
| Brian Carlstrom | aded5f7 | 2011-10-07 17:15:04 -0700 | [diff] [blame] | 2526 | } | 
 | 2527 |  | 
| Mathieu Chartier | c528dba | 2013-11-26 12:00:11 -0800 | [diff] [blame] | 2528 | void ClassLinker::RegisterDexFile(const DexFile& dex_file, | 
| Andreas Gampe | 5a4b8a2 | 2014-09-11 08:30:08 -0700 | [diff] [blame] | 2529 |                                   Handle<mirror::DexCache> dex_cache) { | 
| Ian Rogers | 1bf8d4d | 2013-05-30 00:18:49 -0700 | [diff] [blame] | 2530 |   WriterMutexLock mu(Thread::Current(), dex_lock_); | 
| Brian Carlstrom | aded5f7 | 2011-10-07 17:15:04 -0700 | [diff] [blame] | 2531 |   RegisterDexFileLocked(dex_file, dex_cache); | 
 | 2532 | } | 
 | 2533 |  | 
| Mathieu Chartier | 673ed3d | 2015-08-28 14:56:43 -0700 | [diff] [blame^] | 2534 | mirror::DexCache* ClassLinker::FindDexCache(Thread* self, | 
 | 2535 |                                             const DexFile& dex_file, | 
 | 2536 |                                             bool allow_failure) { | 
 | 2537 |   ReaderMutexLock mu(self, dex_lock_); | 
 | 2538 |   return FindDexCacheLocked(self, dex_file, allow_failure); | 
 | 2539 | } | 
 | 2540 |  | 
 | 2541 | mirror::DexCache* ClassLinker::FindDexCacheLocked(Thread* self, | 
 | 2542 |                                                   const DexFile& dex_file, | 
 | 2543 |                                                   bool allow_failure) { | 
| Ian Rogers | 2bcb4a4 | 2012-11-08 10:39:18 -0800 | [diff] [blame] | 2544 |   // Search assuming unique-ness of dex file. | 
| Mathieu Chartier | 673ed3d | 2015-08-28 14:56:43 -0700 | [diff] [blame^] | 2545 |   JavaVMExt* const vm = self->GetJniEnv()->vm; | 
 | 2546 |   { | 
 | 2547 |     MutexLock mu(self, vm->WeakGlobalsLock()); | 
 | 2548 |     for (jobject weak_root : dex_caches_) { | 
 | 2549 |       DCHECK_EQ(GetIndirectRefKind(weak_root), kWeakGlobal); | 
 | 2550 |       mirror::DexCache* dex_cache = down_cast<mirror::DexCache*>( | 
 | 2551 |           vm->DecodeWeakGlobalLocked(self, weak_root)); | 
 | 2552 |       if (dex_cache != nullptr && dex_cache->GetDexFile() == &dex_file) { | 
 | 2553 |         return dex_cache; | 
 | 2554 |       } | 
| Brian Carlstrom | 578bbdc | 2011-07-21 14:07:47 -0700 | [diff] [blame] | 2555 |     } | 
 | 2556 |   } | 
| Mathieu Chartier | 673ed3d | 2015-08-28 14:56:43 -0700 | [diff] [blame^] | 2557 |   if (allow_failure) { | 
 | 2558 |     return nullptr; | 
 | 2559 |   } | 
| Mathieu Chartier | ac8f439 | 2015-08-27 13:54:20 -0700 | [diff] [blame] | 2560 |   std::string location(dex_file.GetLocation()); | 
| Brian Carlstrom | 81a9087 | 2015-08-28 09:07:14 -0700 | [diff] [blame] | 2561 |   // Failure, dump diagnostic and abort. | 
| Mathieu Chartier | 673ed3d | 2015-08-28 14:56:43 -0700 | [diff] [blame^] | 2562 |   for (jobject weak_root : dex_caches_) { | 
 | 2563 |     mirror::DexCache* dex_cache = down_cast<mirror::DexCache*>(self->DecodeJObject(weak_root)); | 
 | 2564 |     if (dex_cache != nullptr) { | 
 | 2565 |       LOG(ERROR) << "Registered dex file " << dex_cache->GetDexFile()->GetLocation(); | 
 | 2566 |     } | 
| Brian Carlstrom | 81a9087 | 2015-08-28 09:07:14 -0700 | [diff] [blame] | 2567 |   } | 
| Ian Rogers | 2bcb4a4 | 2012-11-08 10:39:18 -0800 | [diff] [blame] | 2568 |   LOG(FATAL) << "Failed to find DexCache for DexFile " << location; | 
| Ian Rogers | e0a02da | 2014-12-02 14:10:53 -0800 | [diff] [blame] | 2569 |   UNREACHABLE(); | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 2570 | } | 
 | 2571 |  | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 2572 | void ClassLinker::FixupDexCaches(ArtMethod* resolution_method) { | 
| Mathieu Chartier | 673ed3d | 2015-08-28 14:56:43 -0700 | [diff] [blame^] | 2573 |   Thread* const self = Thread::Current(); | 
 | 2574 |   ReaderMutexLock mu(self, dex_lock_); | 
 | 2575 |   for (jobject weak_root : dex_caches_) { | 
 | 2576 |     mirror::DexCache* dex_cache = down_cast<mirror::DexCache*>(self->DecodeJObject(weak_root)); | 
 | 2577 |     if (dex_cache != nullptr) { | 
 | 2578 |       dex_cache->Fixup(resolution_method, image_pointer_size_); | 
 | 2579 |     } | 
| Ian Rogers | 1984651 | 2012-02-24 11:42:47 -0800 | [diff] [blame] | 2580 |   } | 
 | 2581 | } | 
 | 2582 |  | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 2583 | mirror::Class* ClassLinker::CreatePrimitiveClass(Thread* self, Primitive::Type type) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 2584 |   mirror::Class* klass = AllocClass(self, mirror::Class::PrimitiveClassSize(image_pointer_size_)); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 2585 |   if (UNLIKELY(klass == nullptr)) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 2586 |     self->AssertPendingOOMException(); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 2587 |     return nullptr; | 
| Ian Rogers | a436fde | 2013-08-27 23:34:06 -0700 | [diff] [blame] | 2588 |   } | 
 | 2589 |   return InitializePrimitiveClass(klass, type); | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 2590 | } | 
 | 2591 |  | 
| Mathieu Chartier | c528dba | 2013-11-26 12:00:11 -0800 | [diff] [blame] | 2592 | mirror::Class* ClassLinker::InitializePrimitiveClass(mirror::Class* primitive_class, | 
 | 2593 |                                                      Primitive::Type type) { | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 2594 |   CHECK(primitive_class != nullptr); | 
| Ian Rogers | 1f53934 | 2012-10-03 21:09:42 -0700 | [diff] [blame] | 2595 |   // Must hold lock on object when initializing. | 
| Ian Rogers | 7dfb28c | 2013-08-22 08:18:36 -0700 | [diff] [blame] | 2596 |   Thread* self = Thread::Current(); | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 2597 |   StackHandleScope<1> hs(self); | 
 | 2598 |   Handle<mirror::Class> h_class(hs.NewHandle(primitive_class)); | 
| Mathieu Chartier | db2633c | 2014-05-16 09:59:29 -0700 | [diff] [blame] | 2599 |   ObjectLock<mirror::Class> lock(self, h_class); | 
| Hiroshi Yamauchi | 5b783e6 | 2015-03-18 17:20:11 -0700 | [diff] [blame] | 2600 |   h_class->SetAccessFlags(kAccPublic | kAccFinal | kAccAbstract); | 
 | 2601 |   h_class->SetPrimitiveType(type); | 
 | 2602 |   mirror::Class::SetStatus(h_class, mirror::Class::kStatusInitialized, self); | 
| Ian Rogers | 7dfb28c | 2013-08-22 08:18:36 -0700 | [diff] [blame] | 2603 |   const char* descriptor = Primitive::Descriptor(type); | 
| Hiroshi Yamauchi | 5b783e6 | 2015-03-18 17:20:11 -0700 | [diff] [blame] | 2604 |   mirror::Class* existing = InsertClass(descriptor, h_class.Get(), | 
| Mathieu Chartier | e7c9a8c | 2014-11-06 16:35:45 -0800 | [diff] [blame] | 2605 |                                         ComputeModifiedUtf8Hash(descriptor)); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 2606 |   CHECK(existing == nullptr) << "InitPrimitiveClass(" << type << ") failed"; | 
| Hiroshi Yamauchi | 5b783e6 | 2015-03-18 17:20:11 -0700 | [diff] [blame] | 2607 |   return h_class.Get(); | 
| Carl Shapiro | 565f507 | 2011-07-10 13:39:43 -0700 | [diff] [blame] | 2608 | } | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 2609 |  | 
| Brian Carlstrom | be97785 | 2011-07-19 14:54:54 -0700 | [diff] [blame] | 2610 | // Create an array class (i.e. the class object for the array, not the | 
 | 2611 | // array itself).  "descriptor" looks like "[C" or "[[[[B" or | 
 | 2612 | // "[Ljava/lang/String;". | 
 | 2613 | // | 
 | 2614 | // If "descriptor" refers to an array of primitives, look up the | 
 | 2615 | // primitive type's internally-generated class object. | 
 | 2616 | // | 
| Brian Carlstrom | 5b8e4c8 | 2011-09-18 01:38:59 -0700 | [diff] [blame] | 2617 | // "class_loader" is the class loader of the class that's referring to | 
 | 2618 | // us.  It's used to ensure that we're looking for the element type in | 
 | 2619 | // the right context.  It does NOT become the class loader for the | 
 | 2620 | // array class; that always comes from the base element class. | 
| Brian Carlstrom | be97785 | 2011-07-19 14:54:54 -0700 | [diff] [blame] | 2621 | // | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 2622 | // Returns null with an exception raised on failure. | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 2623 | mirror::Class* ClassLinker::CreateArrayClass(Thread* self, const char* descriptor, size_t hash, | 
| Andreas Gampe | 5a4b8a2 | 2014-09-11 08:30:08 -0700 | [diff] [blame] | 2624 |                                              Handle<mirror::ClassLoader> class_loader) { | 
| Brian Carlstrom | 5b8e4c8 | 2011-09-18 01:38:59 -0700 | [diff] [blame] | 2625 |   // Identify the underlying component type | 
| Ian Rogers | 7dfb28c | 2013-08-22 08:18:36 -0700 | [diff] [blame] | 2626 |   CHECK_EQ('[', descriptor[0]); | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 2627 |   StackHandleScope<2> hs(self); | 
| Andreas Gampe | 5a4b8a2 | 2014-09-11 08:30:08 -0700 | [diff] [blame] | 2628 |   MutableHandle<mirror::Class> component_type(hs.NewHandle(FindClass(self, descriptor + 1, | 
 | 2629 |                                                                      class_loader))); | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 2630 |   if (component_type.Get() == nullptr) { | 
| Mathieu Chartier | c0a9ea4 | 2014-02-03 16:36:49 -0800 | [diff] [blame] | 2631 |     DCHECK(self->IsExceptionPending()); | 
| Andreas Gampe | dc13d7d | 2014-07-23 20:18:36 -0700 | [diff] [blame] | 2632 |     // We need to accept erroneous classes as component types. | 
| Mathieu Chartier | e7c9a8c | 2014-11-06 16:35:45 -0800 | [diff] [blame] | 2633 |     const size_t component_hash = ComputeModifiedUtf8Hash(descriptor + 1); | 
 | 2634 |     component_type.Assign(LookupClass(self, descriptor + 1, component_hash, class_loader.Get())); | 
| Andreas Gampe | dc13d7d | 2014-07-23 20:18:36 -0700 | [diff] [blame] | 2635 |     if (component_type.Get() == nullptr) { | 
 | 2636 |       DCHECK(self->IsExceptionPending()); | 
 | 2637 |       return nullptr; | 
 | 2638 |     } else { | 
 | 2639 |       self->ClearException(); | 
 | 2640 |     } | 
| Brian Carlstrom | 74eb46a | 2011-08-02 20:10:14 -0700 | [diff] [blame] | 2641 |   } | 
| Ian Rogers | 2d10b20 | 2014-05-12 19:15:18 -0700 | [diff] [blame] | 2642 |   if (UNLIKELY(component_type->IsPrimitiveVoid())) { | 
 | 2643 |     ThrowNoClassDefFoundError("Attempt to create array of void primitive type"); | 
 | 2644 |     return nullptr; | 
 | 2645 |   } | 
| Brian Carlstrom | 74eb46a | 2011-08-02 20:10:14 -0700 | [diff] [blame] | 2646 |   // See if the component type is already loaded.  Array classes are | 
 | 2647 |   // always associated with the class loader of their underlying | 
 | 2648 |   // element type -- an array of Strings goes with the loader for | 
 | 2649 |   // java/lang/String -- so we need to look for it there.  (The | 
 | 2650 |   // caller should have checked for the existence of the class | 
 | 2651 |   // before calling here, but they did so with *their* class loader, | 
 | 2652 |   // not the component type's loader.) | 
 | 2653 |   // | 
 | 2654 |   // If we find it, the caller adds "loader" to the class' initiating | 
 | 2655 |   // loader list, which should prevent us from going through this again. | 
 | 2656 |   // | 
| Ian Rogers | 0cfe1fb | 2011-08-26 03:29:44 -0700 | [diff] [blame] | 2657 |   // This call is unnecessary if "loader" and "component_type->GetClassLoader()" | 
| Brian Carlstrom | 74eb46a | 2011-08-02 20:10:14 -0700 | [diff] [blame] | 2658 |   // are the same, because our caller (FindClass) just did the | 
 | 2659 |   // lookup.  (Even if we get this wrong we still have correct behavior, | 
 | 2660 |   // because we effectively do this lookup again when we add the new | 
 | 2661 |   // class to the hash table --- necessary because of possible races with | 
 | 2662 |   // other threads.) | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 2663 |   if (class_loader.Get() != component_type->GetClassLoader()) { | 
| Mathieu Chartier | e7c9a8c | 2014-11-06 16:35:45 -0800 | [diff] [blame] | 2664 |     mirror::Class* new_class = LookupClass(self, descriptor, hash, component_type->GetClassLoader()); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 2665 |     if (new_class != nullptr) { | 
| Brian Carlstrom | a331b3c | 2011-07-18 17:47:56 -0700 | [diff] [blame] | 2666 |       return new_class; | 
 | 2667 |     } | 
| Brian Carlstrom | 74eb46a | 2011-08-02 20:10:14 -0700 | [diff] [blame] | 2668 |   } | 
| Brian Carlstrom | a331b3c | 2011-07-18 17:47:56 -0700 | [diff] [blame] | 2669 |  | 
| Brian Carlstrom | 74eb46a | 2011-08-02 20:10:14 -0700 | [diff] [blame] | 2670 |   // Fill out the fields in the Class. | 
 | 2671 |   // | 
 | 2672 |   // It is possible to execute some methods against arrays, because | 
 | 2673 |   // all arrays are subclasses of java_lang_Object_, so we need to set | 
 | 2674 |   // up a vtable.  We can just point at the one in java_lang_Object_. | 
 | 2675 |   // | 
 | 2676 |   // Array classes are simple enough that we don't need to do a full | 
 | 2677 |   // link step. | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 2678 |   auto new_class = hs.NewHandle<mirror::Class>(nullptr); | 
| Ian Rogers | 7dfb28c | 2013-08-22 08:18:36 -0700 | [diff] [blame] | 2679 |   if (UNLIKELY(!init_done_)) { | 
| Ian Rogers | 0cfe1fb | 2011-08-26 03:29:44 -0700 | [diff] [blame] | 2680 |     // Classes that were hand created, ie not by FindSystemClass | 
| Ian Rogers | 7dfb28c | 2013-08-22 08:18:36 -0700 | [diff] [blame] | 2681 |     if (strcmp(descriptor, "[Ljava/lang/Class;") == 0) { | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 2682 |       new_class.Assign(GetClassRoot(kClassArrayClass)); | 
| Ian Rogers | 7dfb28c | 2013-08-22 08:18:36 -0700 | [diff] [blame] | 2683 |     } else if (strcmp(descriptor, "[Ljava/lang/Object;") == 0) { | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 2684 |       new_class.Assign(GetClassRoot(kObjectArrayClass)); | 
| Ian Rogers | 6f3dbba | 2014-10-14 17:41:57 -0700 | [diff] [blame] | 2685 |     } else if (strcmp(descriptor, GetClassRootDescriptor(kJavaLangStringArrayClass)) == 0) { | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 2686 |       new_class.Assign(GetClassRoot(kJavaLangStringArrayClass)); | 
| Ian Rogers | 7dfb28c | 2013-08-22 08:18:36 -0700 | [diff] [blame] | 2687 |     } else if (strcmp(descriptor, "[C") == 0) { | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 2688 |       new_class.Assign(GetClassRoot(kCharArrayClass)); | 
| Ian Rogers | 7dfb28c | 2013-08-22 08:18:36 -0700 | [diff] [blame] | 2689 |     } else if (strcmp(descriptor, "[I") == 0) { | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 2690 |       new_class.Assign(GetClassRoot(kIntArrayClass)); | 
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 2691 |     } else if (strcmp(descriptor, "[J") == 0) { | 
 | 2692 |       new_class.Assign(GetClassRoot(kLongArrayClass)); | 
| Brian Carlstrom | 74eb46a | 2011-08-02 20:10:14 -0700 | [diff] [blame] | 2693 |     } | 
 | 2694 |   } | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 2695 |   if (new_class.Get() == nullptr) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 2696 |     new_class.Assign(AllocClass(self, mirror::Array::ClassSize(image_pointer_size_))); | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 2697 |     if (new_class.Get() == nullptr) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 2698 |       self->AssertPendingOOMException(); | 
| Mathieu Chartier | c0a9ea4 | 2014-02-03 16:36:49 -0800 | [diff] [blame] | 2699 |       return nullptr; | 
| Brian Carlstrom | 74eb46a | 2011-08-02 20:10:14 -0700 | [diff] [blame] | 2700 |     } | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 2701 |     new_class->SetComponentType(component_type.Get()); | 
| Brian Carlstrom | 74eb46a | 2011-08-02 20:10:14 -0700 | [diff] [blame] | 2702 |   } | 
| Mathieu Chartier | db2633c | 2014-05-16 09:59:29 -0700 | [diff] [blame] | 2703 |   ObjectLock<mirror::Class> lock(self, new_class);  // Must hold lock on object when initializing. | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 2704 |   DCHECK(new_class->GetComponentType() != nullptr); | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 2705 |   mirror::Class* java_lang_Object = GetClassRoot(kJavaLangObject); | 
| Ian Rogers | 0cfe1fb | 2011-08-26 03:29:44 -0700 | [diff] [blame] | 2706 |   new_class->SetSuperClass(java_lang_Object); | 
 | 2707 |   new_class->SetVTable(java_lang_Object->GetVTable()); | 
| Brian Carlstrom | 6b4ef02 | 2011-10-23 14:59:04 -0700 | [diff] [blame] | 2708 |   new_class->SetPrimitiveType(Primitive::kPrimNot); | 
| Ian Rogers | 0cfe1fb | 2011-08-26 03:29:44 -0700 | [diff] [blame] | 2709 |   new_class->SetClassLoader(component_type->GetClassLoader()); | 
| Mathieu Chartier | 52a7f5c | 2015-08-18 18:35:52 -0700 | [diff] [blame] | 2710 |   if (component_type->IsPrimitive()) { | 
 | 2711 |     new_class->SetClassFlags(mirror::kClassFlagNoReferenceFields); | 
 | 2712 |   } else { | 
 | 2713 |     new_class->SetClassFlags(mirror::kClassFlagObjectArray); | 
 | 2714 |   } | 
| Hiroshi Yamauchi | 5b783e6 | 2015-03-18 17:20:11 -0700 | [diff] [blame] | 2715 |   mirror::Class::SetStatus(new_class, mirror::Class::kStatusLoaded, self); | 
| Mathieu Chartier | 2d2621a | 2014-10-23 16:48:06 -0700 | [diff] [blame] | 2716 |   { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 2717 |     ArtMethod* imt[mirror::Class::kImtSize]; | 
 | 2718 |     std::fill_n(imt, arraysize(imt), Runtime::Current()->GetImtUnimplementedMethod()); | 
 | 2719 |     new_class->PopulateEmbeddedImtAndVTable(imt, image_pointer_size_); | 
| Mathieu Chartier | 2d2621a | 2014-10-23 16:48:06 -0700 | [diff] [blame] | 2720 |   } | 
| Hiroshi Yamauchi | 5b783e6 | 2015-03-18 17:20:11 -0700 | [diff] [blame] | 2721 |   mirror::Class::SetStatus(new_class, mirror::Class::kStatusInitialized, self); | 
| Ian Rogers | 0cfe1fb | 2011-08-26 03:29:44 -0700 | [diff] [blame] | 2722 |   // don't need to set new_class->SetObjectSize(..) | 
| Brian Carlstrom | 9cff8e1 | 2011-08-18 16:47:29 -0700 | [diff] [blame] | 2723 |   // because Object::SizeOf delegates to Array::SizeOf | 
| Brian Carlstrom | 74eb46a | 2011-08-02 20:10:14 -0700 | [diff] [blame] | 2724 |  | 
 | 2725 |  | 
 | 2726 |   // All arrays have java/lang/Cloneable and java/io/Serializable as | 
 | 2727 |   // interfaces.  We need to set that up here, so that stuff like | 
 | 2728 |   // "instanceof" works right. | 
 | 2729 |   // | 
 | 2730 |   // Note: The GC could run during the call to FindSystemClass, | 
 | 2731 |   // so we need to make sure the class object is GC-valid while we're in | 
 | 2732 |   // there.  Do this by clearing the interface list so the GC will just | 
 | 2733 |   // think that the entries are null. | 
 | 2734 |  | 
 | 2735 |  | 
 | 2736 |   // Use the single, global copies of "interfaces" and "iftable" | 
 | 2737 |   // (remember not to free them for arrays). | 
| Hiroshi Yamauchi | e9e3e69 | 2014-06-24 14:31:37 -0700 | [diff] [blame] | 2738 |   { | 
| Hiroshi Yamauchi | 94f7b49 | 2014-07-22 18:08:23 -0700 | [diff] [blame] | 2739 |     mirror::IfTable* array_iftable = array_iftable_.Read(); | 
| Hiroshi Yamauchi | e9e3e69 | 2014-06-24 14:31:37 -0700 | [diff] [blame] | 2740 |     CHECK(array_iftable != nullptr); | 
 | 2741 |     new_class->SetIfTable(array_iftable); | 
 | 2742 |   } | 
| Brian Carlstrom | 74eb46a | 2011-08-02 20:10:14 -0700 | [diff] [blame] | 2743 |  | 
| Elliott Hughes | 00626c2 | 2013-06-14 15:04:14 -0700 | [diff] [blame] | 2744 |   // Inherit access flags from the component type. | 
 | 2745 |   int access_flags = new_class->GetComponentType()->GetAccessFlags(); | 
 | 2746 |   // Lose any implementation detail flags; in particular, arrays aren't finalizable. | 
 | 2747 |   access_flags &= kAccJavaFlagsMask; | 
 | 2748 |   // Arrays can't be used as a superclass or interface, so we want to add "abstract final" | 
| Brian Carlstrom | 74eb46a | 2011-08-02 20:10:14 -0700 | [diff] [blame] | 2749 |   // and remove "interface". | 
| Elliott Hughes | 00626c2 | 2013-06-14 15:04:14 -0700 | [diff] [blame] | 2750 |   access_flags |= kAccAbstract | kAccFinal; | 
 | 2751 |   access_flags &= ~kAccInterface; | 
 | 2752 |  | 
 | 2753 |   new_class->SetAccessFlags(access_flags); | 
| Brian Carlstrom | 74eb46a | 2011-08-02 20:10:14 -0700 | [diff] [blame] | 2754 |  | 
| Mathieu Chartier | e7c9a8c | 2014-11-06 16:35:45 -0800 | [diff] [blame] | 2755 |   mirror::Class* existing = InsertClass(descriptor, new_class.Get(), hash); | 
| Mathieu Chartier | c0a9ea4 | 2014-02-03 16:36:49 -0800 | [diff] [blame] | 2756 |   if (existing == nullptr) { | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 2757 |     return new_class.Get(); | 
| Brian Carlstrom | 74eb46a | 2011-08-02 20:10:14 -0700 | [diff] [blame] | 2758 |   } | 
 | 2759 |   // Another thread must have loaded the class after we | 
 | 2760 |   // started but before we finished.  Abandon what we've | 
 | 2761 |   // done. | 
 | 2762 |   // | 
 | 2763 |   // (Yes, this happens.) | 
 | 2764 |  | 
| Brian Carlstrom | 07bb855 | 2012-01-18 22:10:50 -0800 | [diff] [blame] | 2765 |   return existing; | 
| Brian Carlstrom | a331b3c | 2011-07-18 17:47:56 -0700 | [diff] [blame] | 2766 | } | 
 | 2767 |  | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 2768 | mirror::Class* ClassLinker::FindPrimitiveClass(char type) { | 
| Ian Rogers | 62f0512 | 2014-03-21 11:21:29 -0700 | [diff] [blame] | 2769 |   switch (type) { | 
 | 2770 |     case 'B': | 
| Brian Carlstrom | 74eb46a | 2011-08-02 20:10:14 -0700 | [diff] [blame] | 2771 |       return GetClassRoot(kPrimitiveByte); | 
| Ian Rogers | 62f0512 | 2014-03-21 11:21:29 -0700 | [diff] [blame] | 2772 |     case 'C': | 
| Brian Carlstrom | 74eb46a | 2011-08-02 20:10:14 -0700 | [diff] [blame] | 2773 |       return GetClassRoot(kPrimitiveChar); | 
| Ian Rogers | 62f0512 | 2014-03-21 11:21:29 -0700 | [diff] [blame] | 2774 |     case 'D': | 
| Brian Carlstrom | 74eb46a | 2011-08-02 20:10:14 -0700 | [diff] [blame] | 2775 |       return GetClassRoot(kPrimitiveDouble); | 
| Ian Rogers | 62f0512 | 2014-03-21 11:21:29 -0700 | [diff] [blame] | 2776 |     case 'F': | 
| Brian Carlstrom | 74eb46a | 2011-08-02 20:10:14 -0700 | [diff] [blame] | 2777 |       return GetClassRoot(kPrimitiveFloat); | 
| Ian Rogers | 62f0512 | 2014-03-21 11:21:29 -0700 | [diff] [blame] | 2778 |     case 'I': | 
| Brian Carlstrom | 74eb46a | 2011-08-02 20:10:14 -0700 | [diff] [blame] | 2779 |       return GetClassRoot(kPrimitiveInt); | 
| Ian Rogers | 62f0512 | 2014-03-21 11:21:29 -0700 | [diff] [blame] | 2780 |     case 'J': | 
| Brian Carlstrom | 74eb46a | 2011-08-02 20:10:14 -0700 | [diff] [blame] | 2781 |       return GetClassRoot(kPrimitiveLong); | 
| Ian Rogers | 62f0512 | 2014-03-21 11:21:29 -0700 | [diff] [blame] | 2782 |     case 'S': | 
| Brian Carlstrom | 74eb46a | 2011-08-02 20:10:14 -0700 | [diff] [blame] | 2783 |       return GetClassRoot(kPrimitiveShort); | 
| Ian Rogers | 62f0512 | 2014-03-21 11:21:29 -0700 | [diff] [blame] | 2784 |     case 'Z': | 
| Brian Carlstrom | 74eb46a | 2011-08-02 20:10:14 -0700 | [diff] [blame] | 2785 |       return GetClassRoot(kPrimitiveBoolean); | 
| Ian Rogers | 62f0512 | 2014-03-21 11:21:29 -0700 | [diff] [blame] | 2786 |     case 'V': | 
| Brian Carlstrom | 74eb46a | 2011-08-02 20:10:14 -0700 | [diff] [blame] | 2787 |       return GetClassRoot(kPrimitiveVoid); | 
| Ian Rogers | 62f0512 | 2014-03-21 11:21:29 -0700 | [diff] [blame] | 2788 |     default: | 
| Brian Carlstrom | 6b4ef02 | 2011-10-23 14:59:04 -0700 | [diff] [blame] | 2789 |       break; | 
| Carl Shapiro | 744ad05 | 2011-08-06 15:53:36 -0700 | [diff] [blame] | 2790 |   } | 
| Elliott Hughes | bd93599 | 2011-08-22 11:59:34 -0700 | [diff] [blame] | 2791 |   std::string printable_type(PrintableChar(type)); | 
| Elliott Hughes | 4a2b417 | 2011-09-20 17:08:25 -0700 | [diff] [blame] | 2792 |   ThrowNoClassDefFoundError("Not a primitive type: %s", printable_type.c_str()); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 2793 |   return nullptr; | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 2794 | } | 
 | 2795 |  | 
| Mathieu Chartier | cc5ebdf | 2015-07-27 11:19:43 -0700 | [diff] [blame] | 2796 | mirror::Class* ClassLinker::InsertClass(const char* descriptor, mirror::Class* klass, size_t hash) { | 
| Elliott Hughes | 4dd9b4d | 2011-12-12 18:29:24 -0800 | [diff] [blame] | 2797 |   if (VLOG_IS_ON(class_linker)) { | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 2798 |     mirror::DexCache* dex_cache = klass->GetDexCache(); | 
| Brian Carlstrom | ae82698 | 2011-11-09 01:33:42 -0800 | [diff] [blame] | 2799 |     std::string source; | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 2800 |     if (dex_cache != nullptr) { | 
| Brian Carlstrom | ae82698 | 2011-11-09 01:33:42 -0800 | [diff] [blame] | 2801 |       source += " from "; | 
 | 2802 |       source += dex_cache->GetLocation()->ToModifiedUtf8(); | 
 | 2803 |     } | 
 | 2804 |     LOG(INFO) << "Loaded class " << descriptor << source; | 
 | 2805 |   } | 
| Ian Rogers | 1bf8d4d | 2013-05-30 00:18:49 -0700 | [diff] [blame] | 2806 |   WriterMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_); | 
| Mathieu Chartier | cc5ebdf | 2015-07-27 11:19:43 -0700 | [diff] [blame] | 2807 |   mirror::ClassLoader* const class_loader = klass->GetClassLoader(); | 
 | 2808 |   ClassTable* const class_table = InsertClassTableForClassLoader(class_loader); | 
 | 2809 |   mirror::Class* existing = class_table->Lookup(descriptor, hash); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 2810 |   if (existing != nullptr) { | 
| Brian Carlstrom | 07bb855 | 2012-01-18 22:10:50 -0800 | [diff] [blame] | 2811 |     return existing; | 
| Ian Rogers | 5d76c43 | 2011-10-31 21:42:49 -0700 | [diff] [blame] | 2812 |   } | 
| Mathieu Chartier | cc5ebdf | 2015-07-27 11:19:43 -0700 | [diff] [blame] | 2813 |   if (kIsDebugBuild && !klass->IsTemp() && class_loader == nullptr && | 
| Mingyao Yang | 98d1cc8 | 2014-05-15 17:02:16 -0700 | [diff] [blame] | 2814 |       dex_cache_image_class_lookup_required_) { | 
| Ian Rogers | 7dfb28c | 2013-08-22 08:18:36 -0700 | [diff] [blame] | 2815 |     // Check a class loaded with the system class loader matches one in the image if the class | 
 | 2816 |     // is in the image. | 
 | 2817 |     existing = LookupClassFromImage(descriptor); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 2818 |     if (existing != nullptr) { | 
| Mathieu Chartier | c2e2062 | 2014-11-03 11:41:47 -0800 | [diff] [blame] | 2819 |       CHECK_EQ(klass, existing); | 
| Ian Rogers | 7dfb28c | 2013-08-22 08:18:36 -0700 | [diff] [blame] | 2820 |     } | 
 | 2821 |   } | 
| Mathieu Chartier | 4e30541 | 2014-02-19 10:54:44 -0800 | [diff] [blame] | 2822 |   VerifyObject(klass); | 
| Mathieu Chartier | cc5ebdf | 2015-07-27 11:19:43 -0700 | [diff] [blame] | 2823 |   class_table->InsertWithHash(klass, hash); | 
| Mathieu Chartier | e4275c0 | 2015-08-06 15:34:15 -0700 | [diff] [blame] | 2824 |   if (class_loader != nullptr) { | 
 | 2825 |     // This is necessary because we need to have the card dirtied for remembered sets. | 
 | 2826 |     Runtime::Current()->GetHeap()->WriteBarrierEveryFieldOf(class_loader); | 
 | 2827 |   } | 
| Mathieu Chartier | 893263b | 2014-03-04 11:07:42 -0800 | [diff] [blame] | 2828 |   if (log_new_class_table_roots_) { | 
| Mathieu Chartier | c2e2062 | 2014-11-03 11:41:47 -0800 | [diff] [blame] | 2829 |     new_class_roots_.push_back(GcRoot<mirror::Class>(klass)); | 
| Mathieu Chartier | 893263b | 2014-03-04 11:07:42 -0800 | [diff] [blame] | 2830 |   } | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 2831 |   return nullptr; | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 2832 | } | 
 | 2833 |  | 
| Mathieu Chartier | 54d220e | 2015-07-30 16:20:06 -0700 | [diff] [blame] | 2834 | void ClassLinker::UpdateClassVirtualMethods(mirror::Class* klass, | 
 | 2835 |                                             LengthPrefixedArray<ArtMethod>* new_methods) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 2836 |   klass->SetVirtualMethodsPtr(new_methods); | 
| Mathieu Chartier | 54d220e | 2015-07-30 16:20:06 -0700 | [diff] [blame] | 2837 |   // Need to mark the card so that the remembered sets and mod union tables get updated. | 
| Mathieu Chartier | eb837eb | 2015-07-29 17:25:41 -0700 | [diff] [blame] | 2838 |   Runtime::Current()->GetHeap()->WriteBarrierEveryFieldOf(klass); | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 2839 | } | 
 | 2840 |  | 
| Mathieu Chartier | c2e2062 | 2014-11-03 11:41:47 -0800 | [diff] [blame] | 2841 | bool ClassLinker::RemoveClass(const char* descriptor, mirror::ClassLoader* class_loader) { | 
| Ian Rogers | 1bf8d4d | 2013-05-30 00:18:49 -0700 | [diff] [blame] | 2842 |   WriterMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_); | 
| Mathieu Chartier | cc5ebdf | 2015-07-27 11:19:43 -0700 | [diff] [blame] | 2843 |   ClassTable* const class_table = ClassTableForClassLoader(class_loader); | 
 | 2844 |   return class_table != nullptr && class_table->Remove(descriptor); | 
| Brian Carlstrom | ae82698 | 2011-11-09 01:33:42 -0800 | [diff] [blame] | 2845 | } | 
 | 2846 |  | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 2847 | mirror::Class* ClassLinker::LookupClass(Thread* self, const char* descriptor, size_t hash, | 
| Mathieu Chartier | c2e2062 | 2014-11-03 11:41:47 -0800 | [diff] [blame] | 2848 |                                         mirror::ClassLoader* class_loader) { | 
| Ian Rogers | 7dfb28c | 2013-08-22 08:18:36 -0700 | [diff] [blame] | 2849 |   { | 
| Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 2850 |     ReaderMutexLock mu(self, *Locks::classlinker_classes_lock_); | 
| Mathieu Chartier | cc5ebdf | 2015-07-27 11:19:43 -0700 | [diff] [blame] | 2851 |     ClassTable* const class_table = ClassTableForClassLoader(class_loader); | 
 | 2852 |     if (class_table != nullptr) { | 
 | 2853 |       mirror::Class* result = class_table->Lookup(descriptor, hash); | 
 | 2854 |       if (result != nullptr) { | 
 | 2855 |         return result; | 
 | 2856 |       } | 
| Ian Rogers | 7dfb28c | 2013-08-22 08:18:36 -0700 | [diff] [blame] | 2857 |     } | 
| Sameer Abu Asal | 2c6de22 | 2013-05-02 17:38:59 -0700 | [diff] [blame] | 2858 |   } | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 2859 |   if (class_loader != nullptr || !dex_cache_image_class_lookup_required_) { | 
 | 2860 |     return nullptr; | 
| Mathieu Chartier | cc5ebdf | 2015-07-27 11:19:43 -0700 | [diff] [blame] | 2861 |   } | 
 | 2862 |   // Lookup failed but need to search dex_caches_. | 
 | 2863 |   mirror::Class* result = LookupClassFromImage(descriptor); | 
 | 2864 |   if (result != nullptr) { | 
 | 2865 |     result = InsertClass(descriptor, result, hash); | 
| Ian Rogers | 7dfb28c | 2013-08-22 08:18:36 -0700 | [diff] [blame] | 2866 |   } else { | 
| Mathieu Chartier | cc5ebdf | 2015-07-27 11:19:43 -0700 | [diff] [blame] | 2867 |     // Searching the image dex files/caches failed, we don't want to get into this situation | 
 | 2868 |     // often as map searches are faster, so after kMaxFailedDexCacheLookups move all image | 
 | 2869 |     // classes into the class table. | 
 | 2870 |     constexpr uint32_t kMaxFailedDexCacheLookups = 1000; | 
 | 2871 |     if (++failed_dex_cache_class_lookups_ > kMaxFailedDexCacheLookups) { | 
 | 2872 |       MoveImageClassesToClassTable(); | 
| Ian Rogers | 5d76c43 | 2011-10-31 21:42:49 -0700 | [diff] [blame] | 2873 |     } | 
 | 2874 |   } | 
| Mathieu Chartier | cc5ebdf | 2015-07-27 11:19:43 -0700 | [diff] [blame] | 2875 |   return result; | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 2876 | } | 
 | 2877 |  | 
| Ian Rogers | 7dfb28c | 2013-08-22 08:18:36 -0700 | [diff] [blame] | 2878 | static mirror::ObjectArray<mirror::DexCache>* GetImageDexCaches() | 
| Mathieu Chartier | 9044347 | 2015-07-16 20:32:27 -0700 | [diff] [blame] | 2879 |     SHARED_REQUIRES(Locks::mutator_lock_) { | 
| Ian Rogers | 7dfb28c | 2013-08-22 08:18:36 -0700 | [diff] [blame] | 2880 |   gc::space::ImageSpace* image = Runtime::Current()->GetHeap()->GetImageSpace(); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 2881 |   CHECK(image != nullptr); | 
| Ian Rogers | 7dfb28c | 2013-08-22 08:18:36 -0700 | [diff] [blame] | 2882 |   mirror::Object* root = image->GetImageHeader().GetImageRoot(ImageHeader::kDexCaches); | 
 | 2883 |   return root->AsObjectArray<mirror::DexCache>(); | 
 | 2884 | } | 
 | 2885 |  | 
 | 2886 | void ClassLinker::MoveImageClassesToClassTable() { | 
 | 2887 |   Thread* self = Thread::Current(); | 
 | 2888 |   WriterMutexLock mu(self, *Locks::classlinker_classes_lock_); | 
 | 2889 |   if (!dex_cache_image_class_lookup_required_) { | 
 | 2890 |     return;  // All dex cache classes are already in the class table. | 
 | 2891 |   } | 
| Mathieu Chartier | 2d5f39e | 2014-09-19 17:52:37 -0700 | [diff] [blame] | 2892 |   ScopedAssertNoThreadSuspension ants(self, "Moving image classes to class table"); | 
| Ian Rogers | 7dfb28c | 2013-08-22 08:18:36 -0700 | [diff] [blame] | 2893 |   mirror::ObjectArray<mirror::DexCache>* dex_caches = GetImageDexCaches(); | 
| Ian Rogers | 1ff3c98 | 2014-08-12 02:30:58 -0700 | [diff] [blame] | 2894 |   std::string temp; | 
| Mathieu Chartier | cc5ebdf | 2015-07-27 11:19:43 -0700 | [diff] [blame] | 2895 |   ClassTable* const class_table = InsertClassTableForClassLoader(nullptr); | 
| Ian Rogers | 7dfb28c | 2013-08-22 08:18:36 -0700 | [diff] [blame] | 2896 |   for (int32_t i = 0; i < dex_caches->GetLength(); i++) { | 
 | 2897 |     mirror::DexCache* dex_cache = dex_caches->Get(i); | 
 | 2898 |     mirror::ObjectArray<mirror::Class>* types = dex_cache->GetResolvedTypes(); | 
 | 2899 |     for (int32_t j = 0; j < types->GetLength(); j++) { | 
 | 2900 |       mirror::Class* klass = types->Get(j); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 2901 |       if (klass != nullptr) { | 
 | 2902 |         DCHECK(klass->GetClassLoader() == nullptr); | 
| Ian Rogers | 1ff3c98 | 2014-08-12 02:30:58 -0700 | [diff] [blame] | 2903 |         const char* descriptor = klass->GetDescriptor(&temp); | 
| Mathieu Chartier | e7c9a8c | 2014-11-06 16:35:45 -0800 | [diff] [blame] | 2904 |         size_t hash = ComputeModifiedUtf8Hash(descriptor); | 
| Mathieu Chartier | cc5ebdf | 2015-07-27 11:19:43 -0700 | [diff] [blame] | 2905 |         mirror::Class* existing = class_table->Lookup(descriptor, hash); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 2906 |         if (existing != nullptr) { | 
| Mathieu Chartier | c2e2062 | 2014-11-03 11:41:47 -0800 | [diff] [blame] | 2907 |           CHECK_EQ(existing, klass) << PrettyClassAndClassLoader(existing) << " != " | 
| Ian Rogers | 7dfb28c | 2013-08-22 08:18:36 -0700 | [diff] [blame] | 2908 |               << PrettyClassAndClassLoader(klass); | 
 | 2909 |         } else { | 
| Mathieu Chartier | cc5ebdf | 2015-07-27 11:19:43 -0700 | [diff] [blame] | 2910 |           class_table->Insert(klass); | 
| Mathieu Chartier | 893263b | 2014-03-04 11:07:42 -0800 | [diff] [blame] | 2911 |           if (log_new_class_table_roots_) { | 
| Mathieu Chartier | c2e2062 | 2014-11-03 11:41:47 -0800 | [diff] [blame] | 2912 |             new_class_roots_.push_back(GcRoot<mirror::Class>(klass)); | 
| Mathieu Chartier | 893263b | 2014-03-04 11:07:42 -0800 | [diff] [blame] | 2913 |           } | 
| Ian Rogers | 7dfb28c | 2013-08-22 08:18:36 -0700 | [diff] [blame] | 2914 |         } | 
 | 2915 |       } | 
| Elliott Hughes | 6fa602d | 2011-12-02 17:54:25 -0800 | [diff] [blame] | 2916 |     } | 
 | 2917 |   } | 
| Ian Rogers | 7dfb28c | 2013-08-22 08:18:36 -0700 | [diff] [blame] | 2918 |   dex_cache_image_class_lookup_required_ = false; | 
| Ian Rogers | 7dfb28c | 2013-08-22 08:18:36 -0700 | [diff] [blame] | 2919 | } | 
 | 2920 |  | 
| Mathieu Chartier | c2e2062 | 2014-11-03 11:41:47 -0800 | [diff] [blame] | 2921 | void ClassLinker::MoveClassTableToPreZygote() { | 
 | 2922 |   WriterMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_); | 
| Mathieu Chartier | 6b06953 | 2015-08-05 15:08:12 -0700 | [diff] [blame] | 2923 |   boot_class_table_.FreezeSnapshot(); | 
 | 2924 |   for (GcRoot<mirror::ClassLoader>& root : class_loaders_) { | 
 | 2925 |     ClassTable* const class_table = root.Read()->GetClassTable(); | 
 | 2926 |     if (class_table != nullptr) { | 
 | 2927 |       class_table->FreezeSnapshot(); | 
 | 2928 |     } | 
| Mathieu Chartier | cc5ebdf | 2015-07-27 11:19:43 -0700 | [diff] [blame] | 2929 |   } | 
| Mathieu Chartier | c2e2062 | 2014-11-03 11:41:47 -0800 | [diff] [blame] | 2930 | } | 
 | 2931 |  | 
| Ian Rogers | 7dfb28c | 2013-08-22 08:18:36 -0700 | [diff] [blame] | 2932 | mirror::Class* ClassLinker::LookupClassFromImage(const char* descriptor) { | 
| Mathieu Chartier | 2d5f39e | 2014-09-19 17:52:37 -0700 | [diff] [blame] | 2933 |   ScopedAssertNoThreadSuspension ants(Thread::Current(), "Image class lookup"); | 
| Ian Rogers | 7dfb28c | 2013-08-22 08:18:36 -0700 | [diff] [blame] | 2934 |   mirror::ObjectArray<mirror::DexCache>* dex_caches = GetImageDexCaches(); | 
 | 2935 |   for (int32_t i = 0; i < dex_caches->GetLength(); ++i) { | 
 | 2936 |     mirror::DexCache* dex_cache = dex_caches->Get(i); | 
 | 2937 |     const DexFile* dex_file = dex_cache->GetDexFile(); | 
| Vladimir Marko | 801a811 | 2014-01-06 14:28:16 +0000 | [diff] [blame] | 2938 |     // Try binary searching the string/type index. | 
| Ian Rogers | 7dfb28c | 2013-08-22 08:18:36 -0700 | [diff] [blame] | 2939 |     const DexFile::StringId* string_id = dex_file->FindStringId(descriptor); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 2940 |     if (string_id != nullptr) { | 
| Ian Rogers | 7dfb28c | 2013-08-22 08:18:36 -0700 | [diff] [blame] | 2941 |       const DexFile::TypeId* type_id = | 
 | 2942 |           dex_file->FindTypeId(dex_file->GetIndexForStringId(*string_id)); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 2943 |       if (type_id != nullptr) { | 
| Ian Rogers | 7dfb28c | 2013-08-22 08:18:36 -0700 | [diff] [blame] | 2944 |         uint16_t type_idx = dex_file->GetIndexForTypeId(*type_id); | 
 | 2945 |         mirror::Class* klass = dex_cache->GetResolvedType(type_idx); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 2946 |         if (klass != nullptr) { | 
| Ian Rogers | 7dfb28c | 2013-08-22 08:18:36 -0700 | [diff] [blame] | 2947 |           return klass; | 
 | 2948 |         } | 
 | 2949 |       } | 
 | 2950 |     } | 
 | 2951 |   } | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 2952 |   return nullptr; | 
| Ian Rogers | 7dfb28c | 2013-08-22 08:18:36 -0700 | [diff] [blame] | 2953 | } | 
 | 2954 |  | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 2955 | void ClassLinker::LookupClasses(const char* descriptor, std::vector<mirror::Class*>& result) { | 
| Ian Rogers | 7dfb28c | 2013-08-22 08:18:36 -0700 | [diff] [blame] | 2956 |   result.clear(); | 
 | 2957 |   if (dex_cache_image_class_lookup_required_) { | 
 | 2958 |     MoveImageClassesToClassTable(); | 
 | 2959 |   } | 
| Mathieu Chartier | c2e2062 | 2014-11-03 11:41:47 -0800 | [diff] [blame] | 2960 |   WriterMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_); | 
| Mathieu Chartier | 6b06953 | 2015-08-05 15:08:12 -0700 | [diff] [blame] | 2961 |   const size_t hash = ComputeModifiedUtf8Hash(descriptor); | 
 | 2962 |   mirror::Class* klass = boot_class_table_.Lookup(descriptor, hash); | 
 | 2963 |   if (klass != nullptr) { | 
 | 2964 |     result.push_back(klass); | 
 | 2965 |   } | 
 | 2966 |   for (GcRoot<mirror::ClassLoader>& root : class_loaders_) { | 
| Mathieu Chartier | cc5ebdf | 2015-07-27 11:19:43 -0700 | [diff] [blame] | 2967 |     // There can only be one class with the same descriptor per class loader. | 
| Mathieu Chartier | 6b06953 | 2015-08-05 15:08:12 -0700 | [diff] [blame] | 2968 |     ClassTable* const class_table = root.Read()->GetClassTable(); | 
 | 2969 |     klass = class_table->Lookup(descriptor, hash); | 
| Mathieu Chartier | cc5ebdf | 2015-07-27 11:19:43 -0700 | [diff] [blame] | 2970 |     if (klass != nullptr) { | 
 | 2971 |       result.push_back(klass); | 
| Elliott Hughes | 6fa602d | 2011-12-02 17:54:25 -0800 | [diff] [blame] | 2972 |     } | 
 | 2973 |   } | 
 | 2974 | } | 
 | 2975 |  | 
| Andreas Gampe | 5a4b8a2 | 2014-09-11 08:30:08 -0700 | [diff] [blame] | 2976 | void ClassLinker::VerifyClass(Thread* self, Handle<mirror::Class> klass) { | 
| Brian Carlstrom | 9b5ee88 | 2012-02-28 09:48:54 -0800 | [diff] [blame] | 2977 |   // TODO: assert that the monitor on the Class is held | 
| Mathieu Chartier | db2633c | 2014-05-16 09:59:29 -0700 | [diff] [blame] | 2978 |   ObjectLock<mirror::Class> lock(self, klass); | 
| Elliott Hughes | d9c67be | 2012-02-02 19:54:06 -0800 | [diff] [blame] | 2979 |  | 
| Ian Rogers | 9ffb039 | 2012-09-10 11:56:50 -0700 | [diff] [blame] | 2980 |   // Don't attempt to re-verify if already sufficiently verified. | 
| Andreas Gampe | bb0c7f6 | 2014-09-11 10:59:33 -0700 | [diff] [blame] | 2981 |   if (klass->IsVerified()) { | 
| Andreas Gampe | 4849859 | 2014-09-10 19:48:05 -0700 | [diff] [blame] | 2982 |     EnsurePreverifiedMethods(klass); | 
| jeffhao | 98eacac | 2011-09-14 16:11:53 -0700 | [diff] [blame] | 2983 |     return; | 
 | 2984 |   } | 
| Mathieu Chartier | e5f13e5 | 2015-02-24 09:37:21 -0800 | [diff] [blame] | 2985 |   if (klass->IsCompileTimeVerified() && Runtime::Current()->IsAotCompiler()) { | 
| Andreas Gampe | bb0c7f6 | 2014-09-11 10:59:33 -0700 | [diff] [blame] | 2986 |     return; | 
 | 2987 |   } | 
| jeffhao | 98eacac | 2011-09-14 16:11:53 -0700 | [diff] [blame] | 2988 |  | 
| Ian Rogers | 9ffb039 | 2012-09-10 11:56:50 -0700 | [diff] [blame] | 2989 |   // The class might already be erroneous, for example at compile time if we attempted to verify | 
 | 2990 |   // this class as a parent to another. | 
| Brian Carlstrom | 9b5ee88 | 2012-02-28 09:48:54 -0800 | [diff] [blame] | 2991 |   if (klass->IsErroneous()) { | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 2992 |     ThrowEarlierClassFailure(klass.Get()); | 
| Brian Carlstrom | 9b5ee88 | 2012-02-28 09:48:54 -0800 | [diff] [blame] | 2993 |     return; | 
 | 2994 |   } | 
 | 2995 |  | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 2996 |   if (klass->GetStatus() == mirror::Class::kStatusResolved) { | 
| Hiroshi Yamauchi | 5b783e6 | 2015-03-18 17:20:11 -0700 | [diff] [blame] | 2997 |     mirror::Class::SetStatus(klass, mirror::Class::kStatusVerifying, self); | 
| Ian Rogers | 9ffb039 | 2012-09-10 11:56:50 -0700 | [diff] [blame] | 2998 |   } else { | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 2999 |     CHECK_EQ(klass->GetStatus(), mirror::Class::kStatusRetryVerificationAtRuntime) | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 3000 |         << PrettyClass(klass.Get()); | 
| Mathieu Chartier | e5f13e5 | 2015-02-24 09:37:21 -0800 | [diff] [blame] | 3001 |     CHECK(!Runtime::Current()->IsAotCompiler()); | 
| Hiroshi Yamauchi | 5b783e6 | 2015-03-18 17:20:11 -0700 | [diff] [blame] | 3002 |     mirror::Class::SetStatus(klass, mirror::Class::kStatusVerifyingAtRuntime, self); | 
| Ian Rogers | 9ffb039 | 2012-09-10 11:56:50 -0700 | [diff] [blame] | 3003 |   } | 
| jeffhao | 98eacac | 2011-09-14 16:11:53 -0700 | [diff] [blame] | 3004 |  | 
| Igor Murashkin | 7617abd | 2015-07-10 18:27:47 -0700 | [diff] [blame] | 3005 |   // Skip verification if we are forcing a soft fail. | 
 | 3006 |   // This has to be before the normal verification enabled check, | 
 | 3007 |   // since technically verification is disabled in this mode. | 
 | 3008 |   if (UNLIKELY(Runtime::Current()->IsVerificationSoftFail())) { | 
 | 3009 |     // Force verification to be a 'soft failure'. | 
 | 3010 |     mirror::Class::SetStatus(klass, mirror::Class::kStatusVerified, self); | 
 | 3011 |     // As this is a fake verified status, make sure the methods are _not_ marked preverified | 
 | 3012 |     // later. | 
 | 3013 |     klass->SetPreverified(); | 
 | 3014 |     return; | 
 | 3015 |   } | 
 | 3016 |  | 
| Jeff Hao | 4a200f5 | 2014-04-01 14:58:49 -0700 | [diff] [blame] | 3017 |   // Skip verification if disabled. | 
 | 3018 |   if (!Runtime::Current()->IsVerificationEnabled()) { | 
| Hiroshi Yamauchi | 5b783e6 | 2015-03-18 17:20:11 -0700 | [diff] [blame] | 3019 |     mirror::Class::SetStatus(klass, mirror::Class::kStatusVerified, self); | 
| Andreas Gampe | 4849859 | 2014-09-10 19:48:05 -0700 | [diff] [blame] | 3020 |     EnsurePreverifiedMethods(klass); | 
| Jeff Hao | 4a200f5 | 2014-04-01 14:58:49 -0700 | [diff] [blame] | 3021 |     return; | 
 | 3022 |   } | 
 | 3023 |  | 
| Ian Rogers | 9ffb039 | 2012-09-10 11:56:50 -0700 | [diff] [blame] | 3024 |   // Verify super class. | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 3025 |   StackHandleScope<2> hs(self); | 
 | 3026 |   Handle<mirror::Class> super(hs.NewHandle(klass->GetSuperClass())); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 3027 |   if (super.Get() != nullptr) { | 
| Ian Rogers | 9ffb039 | 2012-09-10 11:56:50 -0700 | [diff] [blame] | 3028 |     // Acquire lock to prevent races on verifying the super class. | 
| Andreas Gampe | 277ccbd | 2014-11-03 21:36:10 -0800 | [diff] [blame] | 3029 |     ObjectLock<mirror::Class> super_lock(self, super); | 
| Ian Rogers | 1c5eb70 | 2012-02-01 09:18:34 -0800 | [diff] [blame] | 3030 |  | 
 | 3031 |     if (!super->IsVerified() && !super->IsErroneous()) { | 
| Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 3032 |       VerifyClass(self, super); | 
| Ian Rogers | 1c5eb70 | 2012-02-01 09:18:34 -0800 | [diff] [blame] | 3033 |     } | 
| jeffhao | f1e6b7c | 2012-06-05 18:33:30 -0700 | [diff] [blame] | 3034 |     if (!super->IsCompileTimeVerified()) { | 
| Brian Carlstrom | f363283 | 2014-05-20 15:36:53 -0700 | [diff] [blame] | 3035 |       std::string error_msg( | 
 | 3036 |           StringPrintf("Rejecting class %s that attempts to sub-class erroneous class %s", | 
 | 3037 |                        PrettyDescriptor(klass.Get()).c_str(), | 
 | 3038 |                        PrettyDescriptor(super.Get()).c_str())); | 
| Andreas Gampe | e4301ff | 2015-02-17 19:25:29 -0800 | [diff] [blame] | 3039 |       LOG(WARNING) << error_msg  << " in " << klass->GetDexCache()->GetLocation()->ToModifiedUtf8(); | 
| Nicolas Geoffray | 14691c5 | 2015-03-05 10:40:17 +0000 | [diff] [blame] | 3040 |       Handle<mirror::Throwable> cause(hs.NewHandle(self->GetException())); | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 3041 |       if (cause.Get() != nullptr) { | 
| Ian Rogers | 1c5eb70 | 2012-02-01 09:18:34 -0800 | [diff] [blame] | 3042 |         self->ClearException(); | 
 | 3043 |       } | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 3044 |       ThrowVerifyError(klass.Get(), "%s", error_msg.c_str()); | 
 | 3045 |       if (cause.Get() != nullptr) { | 
| Nicolas Geoffray | 14691c5 | 2015-03-05 10:40:17 +0000 | [diff] [blame] | 3046 |         self->GetException()->SetCause(cause.Get()); | 
| Ian Rogers | 1c5eb70 | 2012-02-01 09:18:34 -0800 | [diff] [blame] | 3047 |       } | 
| Jeff Hao | 22cb09b | 2013-12-12 14:29:15 -0800 | [diff] [blame] | 3048 |       ClassReference ref(klass->GetDexCache()->GetDexFile(), klass->GetDexClassDefIndex()); | 
| Mathieu Chartier | e5f13e5 | 2015-02-24 09:37:21 -0800 | [diff] [blame] | 3049 |       if (Runtime::Current()->IsAotCompiler()) { | 
| Vladimir Marko | 2b5eaa2 | 2013-12-13 13:59:30 +0000 | [diff] [blame] | 3050 |         Runtime::Current()->GetCompilerCallbacks()->ClassRejected(ref); | 
 | 3051 |       } | 
| Hiroshi Yamauchi | 5b783e6 | 2015-03-18 17:20:11 -0700 | [diff] [blame] | 3052 |       mirror::Class::SetStatus(klass, mirror::Class::kStatusError, self); | 
| Ian Rogers | 1c5eb70 | 2012-02-01 09:18:34 -0800 | [diff] [blame] | 3053 |       return; | 
 | 3054 |     } | 
 | 3055 |   } | 
 | 3056 |  | 
| Elliott Hughes | 634eb2e | 2012-03-22 16:06:28 -0700 | [diff] [blame] | 3057 |   // Try to use verification information from the oat file, otherwise do runtime verification. | 
| Ian Rogers | 4445a7e | 2012-10-05 17:19:13 -0700 | [diff] [blame] | 3058 |   const DexFile& dex_file = *klass->GetDexCache()->GetDexFile(); | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 3059 |   mirror::Class::Status oat_file_class_status(mirror::Class::kStatusNotReady); | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 3060 |   bool preverified = VerifyClassUsingOatFile(dex_file, klass.Get(), oat_file_class_status); | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 3061 |   if (oat_file_class_status == mirror::Class::kStatusError) { | 
| Ian Rogers | e6bb3b2 | 2013-08-19 21:51:45 -0700 | [diff] [blame] | 3062 |     VLOG(class_linker) << "Skipping runtime verification of erroneous class " | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 3063 |         << PrettyDescriptor(klass.Get()) << " in " | 
| Ian Rogers | e6bb3b2 | 2013-08-19 21:51:45 -0700 | [diff] [blame] | 3064 |         << klass->GetDexCache()->GetLocation()->ToModifiedUtf8(); | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 3065 |     ThrowVerifyError(klass.Get(), "Rejecting class %s because it failed compile-time verification", | 
 | 3066 |                      PrettyDescriptor(klass.Get()).c_str()); | 
| Hiroshi Yamauchi | 5b783e6 | 2015-03-18 17:20:11 -0700 | [diff] [blame] | 3067 |     mirror::Class::SetStatus(klass, mirror::Class::kStatusError, self); | 
| jeffhao | ec01423 | 2012-09-05 10:42:25 -0700 | [diff] [blame] | 3068 |     return; | 
 | 3069 |   } | 
| Sebastien Hertz | 233ea8e | 2013-06-06 11:57:09 +0200 | [diff] [blame] | 3070 |   verifier::MethodVerifier::FailureKind verifier_failure = verifier::MethodVerifier::kNoFailure; | 
| Ian Rogers | 62d6c77 | 2013-02-27 08:32:07 -0800 | [diff] [blame] | 3071 |   std::string error_msg; | 
| jeffhao | f1e6b7c | 2012-06-05 18:33:30 -0700 | [diff] [blame] | 3072 |   if (!preverified) { | 
| Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 3073 |     verifier_failure = verifier::MethodVerifier::VerifyClass(self, klass.Get(), | 
| Mathieu Chartier | e5f13e5 | 2015-02-24 09:37:21 -0800 | [diff] [blame] | 3074 |                                                              Runtime::Current()->IsAotCompiler(), | 
| Ian Rogers | 8b2c0b9 | 2013-09-19 02:56:49 -0700 | [diff] [blame] | 3075 |                                                              &error_msg); | 
| jeffhao | f1e6b7c | 2012-06-05 18:33:30 -0700 | [diff] [blame] | 3076 |   } | 
 | 3077 |   if (preverified || verifier_failure != verifier::MethodVerifier::kHardFailure) { | 
| Ian Rogers | 529781d | 2012-07-23 17:24:29 -0700 | [diff] [blame] | 3078 |     if (!preverified && verifier_failure != verifier::MethodVerifier::kNoFailure) { | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 3079 |       VLOG(class_linker) << "Soft verification failure in class " << PrettyDescriptor(klass.Get()) | 
| Ian Rogers | 529781d | 2012-07-23 17:24:29 -0700 | [diff] [blame] | 3080 |           << " in " << klass->GetDexCache()->GetLocation()->ToModifiedUtf8() | 
 | 3081 |           << " because: " << error_msg; | 
 | 3082 |     } | 
| Ian Rogers | 1f53934 | 2012-10-03 21:09:42 -0700 | [diff] [blame] | 3083 |     self->AssertNoPendingException(); | 
| jeffhao | e4f0b2a | 2012-08-30 11:18:57 -0700 | [diff] [blame] | 3084 |     // Make sure all classes referenced by catch blocks are resolved. | 
| Brian Carlstrom | e7d856b | 2012-01-11 18:10:55 -0800 | [diff] [blame] | 3085 |     ResolveClassExceptionHandlerTypes(dex_file, klass); | 
| jeffhao | e4f0b2a | 2012-08-30 11:18:57 -0700 | [diff] [blame] | 3086 |     if (verifier_failure == verifier::MethodVerifier::kNoFailure) { | 
| Ian Rogers | 8f3c9ae | 2013-08-20 17:26:41 -0700 | [diff] [blame] | 3087 |       // Even though there were no verifier failures we need to respect whether the super-class | 
 | 3088 |       // was verified or requiring runtime reverification. | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 3089 |       if (super.Get() == nullptr || super->IsVerified()) { | 
| Hiroshi Yamauchi | 5b783e6 | 2015-03-18 17:20:11 -0700 | [diff] [blame] | 3090 |         mirror::Class::SetStatus(klass, mirror::Class::kStatusVerified, self); | 
| Ian Rogers | 8f3c9ae | 2013-08-20 17:26:41 -0700 | [diff] [blame] | 3091 |       } else { | 
 | 3092 |         CHECK_EQ(super->GetStatus(), mirror::Class::kStatusRetryVerificationAtRuntime); | 
| Hiroshi Yamauchi | 5b783e6 | 2015-03-18 17:20:11 -0700 | [diff] [blame] | 3093 |         mirror::Class::SetStatus(klass, mirror::Class::kStatusRetryVerificationAtRuntime, self); | 
| Brian Carlstrom | 6d3f72c | 2013-08-21 18:06:34 -0700 | [diff] [blame] | 3094 |         // Pretend a soft failure occured so that we don't consider the class verified below. | 
 | 3095 |         verifier_failure = verifier::MethodVerifier::kSoftFailure; | 
| Ian Rogers | 8f3c9ae | 2013-08-20 17:26:41 -0700 | [diff] [blame] | 3096 |       } | 
| jeffhao | e4f0b2a | 2012-08-30 11:18:57 -0700 | [diff] [blame] | 3097 |     } else { | 
 | 3098 |       CHECK_EQ(verifier_failure, verifier::MethodVerifier::kSoftFailure); | 
 | 3099 |       // Soft failures at compile time should be retried at runtime. Soft | 
 | 3100 |       // failures at runtime will be handled by slow paths in the generated | 
 | 3101 |       // code. Set status accordingly. | 
| Mathieu Chartier | e5f13e5 | 2015-02-24 09:37:21 -0800 | [diff] [blame] | 3102 |       if (Runtime::Current()->IsAotCompiler()) { | 
| Hiroshi Yamauchi | 5b783e6 | 2015-03-18 17:20:11 -0700 | [diff] [blame] | 3103 |         mirror::Class::SetStatus(klass, mirror::Class::kStatusRetryVerificationAtRuntime, self); | 
| jeffhao | e4f0b2a | 2012-08-30 11:18:57 -0700 | [diff] [blame] | 3104 |       } else { | 
| Hiroshi Yamauchi | 5b783e6 | 2015-03-18 17:20:11 -0700 | [diff] [blame] | 3105 |         mirror::Class::SetStatus(klass, mirror::Class::kStatusVerified, self); | 
| Andreas Gampe | bb0c7f6 | 2014-09-11 10:59:33 -0700 | [diff] [blame] | 3106 |         // As this is a fake verified status, make sure the methods are _not_ marked preverified | 
 | 3107 |         // later. | 
| Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 3108 |         klass->SetPreverified(); | 
| jeffhao | e4f0b2a | 2012-08-30 11:18:57 -0700 | [diff] [blame] | 3109 |       } | 
 | 3110 |     } | 
| jeffhao | 5cfd6fb | 2011-09-27 13:54:29 -0700 | [diff] [blame] | 3111 |   } else { | 
| Andreas Gampe | e4301ff | 2015-02-17 19:25:29 -0800 | [diff] [blame] | 3112 |     LOG(WARNING) << "Verification failed on class " << PrettyDescriptor(klass.Get()) | 
| Ian Rogers | 1c5eb70 | 2012-02-01 09:18:34 -0800 | [diff] [blame] | 3113 |         << " in " << klass->GetDexCache()->GetLocation()->ToModifiedUtf8() | 
 | 3114 |         << " because: " << error_msg; | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 3115 |     self->AssertNoPendingException(); | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 3116 |     ThrowVerifyError(klass.Get(), "%s", error_msg.c_str()); | 
| Hiroshi Yamauchi | 5b783e6 | 2015-03-18 17:20:11 -0700 | [diff] [blame] | 3117 |     mirror::Class::SetStatus(klass, mirror::Class::kStatusError, self); | 
| jeffhao | 5cfd6fb | 2011-09-27 13:54:29 -0700 | [diff] [blame] | 3118 |   } | 
| Sebastien Hertz | 233ea8e | 2013-06-06 11:57:09 +0200 | [diff] [blame] | 3119 |   if (preverified || verifier_failure == verifier::MethodVerifier::kNoFailure) { | 
| Brian Carlstrom | 6d3f72c | 2013-08-21 18:06:34 -0700 | [diff] [blame] | 3120 |     // Class is verified so we don't need to do any access check on its methods. | 
| Sebastien Hertz | 233ea8e | 2013-06-06 11:57:09 +0200 | [diff] [blame] | 3121 |     // Let the interpreter know it by setting the kAccPreverified flag onto each | 
 | 3122 |     // method. | 
 | 3123 |     // Note: we're going here during compilation and at runtime. When we set the | 
 | 3124 |     // kAccPreverified flag when compiling image classes, the flag is recorded | 
 | 3125 |     // in the image and is set when loading the image. | 
| Andreas Gampe | 4849859 | 2014-09-10 19:48:05 -0700 | [diff] [blame] | 3126 |     EnsurePreverifiedMethods(klass); | 
 | 3127 |   } | 
 | 3128 | } | 
 | 3129 |  | 
| Andreas Gampe | 5a4b8a2 | 2014-09-11 08:30:08 -0700 | [diff] [blame] | 3130 | void ClassLinker::EnsurePreverifiedMethods(Handle<mirror::Class> klass) { | 
| Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 3131 |   if (!klass->IsPreverified()) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 3132 |     klass->SetPreverifiedFlagOnAllMethods(image_pointer_size_); | 
| Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 3133 |     klass->SetPreverified(); | 
| Sebastien Hertz | 233ea8e | 2013-06-06 11:57:09 +0200 | [diff] [blame] | 3134 |   } | 
| jeffhao | 98eacac | 2011-09-14 16:11:53 -0700 | [diff] [blame] | 3135 | } | 
 | 3136 |  | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 3137 | bool ClassLinker::VerifyClassUsingOatFile(const DexFile& dex_file, mirror::Class* klass, | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 3138 |                                           mirror::Class::Status& oat_file_class_status) { | 
| Anwar Ghuloum | 044d283 | 2013-07-17 15:22:31 -0700 | [diff] [blame] | 3139 |   // If we're compiling, we can only verify the class using the oat file if | 
 | 3140 |   // we are not compiling the image or if the class we're verifying is not part of | 
 | 3141 |   // the app.  In other words, we will only check for preverification of bootclasspath | 
 | 3142 |   // classes. | 
| Mathieu Chartier | e5f13e5 | 2015-02-24 09:37:21 -0800 | [diff] [blame] | 3143 |   if (Runtime::Current()->IsAotCompiler()) { | 
| Anwar Ghuloum | 044d283 | 2013-07-17 15:22:31 -0700 | [diff] [blame] | 3144 |     // Are we compiling the bootclasspath? | 
| Andreas Gampe | 81c6f8d | 2015-03-25 17:19:53 -0700 | [diff] [blame] | 3145 |     if (Runtime::Current()->GetCompilerCallbacks()->IsBootImage()) { | 
| Anwar Ghuloum | 044d283 | 2013-07-17 15:22:31 -0700 | [diff] [blame] | 3146 |       return false; | 
 | 3147 |     } | 
 | 3148 |     // We are compiling an app (not the image). | 
 | 3149 |  | 
 | 3150 |     // Is this an app class? (I.e. not a bootclasspath class) | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 3151 |     if (klass->GetClassLoader() != nullptr) { | 
| Anwar Ghuloum | 044d283 | 2013-07-17 15:22:31 -0700 | [diff] [blame] | 3152 |       return false; | 
 | 3153 |     } | 
| Brian Carlstrom | e7d856b | 2012-01-11 18:10:55 -0800 | [diff] [blame] | 3154 |   } | 
| Anwar Ghuloum | 044d283 | 2013-07-17 15:22:31 -0700 | [diff] [blame] | 3155 |  | 
| Richard Uhler | 07b3c23 | 2015-03-31 15:57:54 -0700 | [diff] [blame] | 3156 |   const OatFile::OatDexFile* oat_dex_file = dex_file.GetOatDexFile(); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 3157 |   // In case we run without an image there won't be a backing oat file. | 
 | 3158 |   if (oat_dex_file == nullptr) { | 
| Anwar Ghuloum | ad256bb | 2013-07-18 14:58:55 -0700 | [diff] [blame] | 3159 |     return false; | 
 | 3160 |   } | 
 | 3161 |  | 
| Andreas Gampe | 76bd880 | 2014-12-10 16:43:58 -0800 | [diff] [blame] | 3162 |   // We may be running with a preopted oat file but without image. In this case, | 
 | 3163 |   // we don't skip verification of preverified classes to ensure we initialize | 
 | 3164 |   // dex caches with all types resolved during verification. | 
 | 3165 |   // We need to trust image classes, as these might be coming out of a pre-opted, quickened boot | 
 | 3166 |   // image (that we just failed loading), and the verifier can't be run on quickened opcodes when | 
 | 3167 |   // the runtime isn't started. On the other hand, app classes can be re-verified even if they are | 
 | 3168 |   // already pre-opted, as then the runtime is started. | 
| Mathieu Chartier | e5f13e5 | 2015-02-24 09:37:21 -0800 | [diff] [blame] | 3169 |   if (!Runtime::Current()->IsAotCompiler() && | 
| Andreas Gampe | 76bd880 | 2014-12-10 16:43:58 -0800 | [diff] [blame] | 3170 |       !Runtime::Current()->GetHeap()->HasImageSpace() && | 
 | 3171 |       klass->GetClassLoader() != nullptr) { | 
 | 3172 |     return false; | 
 | 3173 |   } | 
 | 3174 |  | 
| Ian Rogers | 8b2c0b9 | 2013-09-19 02:56:49 -0700 | [diff] [blame] | 3175 |   uint16_t class_def_index = klass->GetDexClassDefIndex(); | 
| Vladimir Marko | d3c5beb | 2014-04-11 16:32:51 +0100 | [diff] [blame] | 3176 |   oat_file_class_status = oat_dex_file->GetOatClass(class_def_index).GetStatus(); | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 3177 |   if (oat_file_class_status == mirror::Class::kStatusVerified || | 
 | 3178 |       oat_file_class_status == mirror::Class::kStatusInitialized) { | 
| Anwar Ghuloum | 044d283 | 2013-07-17 15:22:31 -0700 | [diff] [blame] | 3179 |       return true; | 
| Brian Carlstrom | e7d856b | 2012-01-11 18:10:55 -0800 | [diff] [blame] | 3180 |   } | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 3181 |   if (oat_file_class_status == mirror::Class::kStatusRetryVerificationAtRuntime) { | 
| jeffhao | 1ac2944 | 2012-03-26 11:37:32 -0700 | [diff] [blame] | 3182 |     // Compile time verification failed with a soft error. Compile time verification can fail | 
 | 3183 |     // because we have incomplete type information. Consider the following: | 
| Ian Rogers | c476227 | 2012-02-01 15:55:55 -0800 | [diff] [blame] | 3184 |     // class ... { | 
 | 3185 |     //   Foo x; | 
 | 3186 |     //   .... () { | 
 | 3187 |     //     if (...) { | 
 | 3188 |     //       v1 gets assigned a type of resolved class Foo | 
 | 3189 |     //     } else { | 
 | 3190 |     //       v1 gets assigned a type of unresolved class Bar | 
 | 3191 |     //     } | 
 | 3192 |     //     iput x = v1 | 
 | 3193 |     // } } | 
 | 3194 |     // when we merge v1 following the if-the-else it results in Conflict | 
 | 3195 |     // (see verifier::RegType::Merge) as we can't know the type of Bar and we could possibly be | 
 | 3196 |     // allowing an unsafe assignment to the field x in the iput (javac may have compiled this as | 
 | 3197 |     // it knew Bar was a sub-class of Foo, but for us this may have been moved into a separate apk | 
 | 3198 |     // at compile time). | 
 | 3199 |     return false; | 
 | 3200 |   } | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 3201 |   if (oat_file_class_status == mirror::Class::kStatusError) { | 
| jeffhao | 1ac2944 | 2012-03-26 11:37:32 -0700 | [diff] [blame] | 3202 |     // Compile time verification failed with a hard error. This is caused by invalid instructions | 
 | 3203 |     // in the class. These errors are unrecoverable. | 
 | 3204 |     return false; | 
 | 3205 |   } | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 3206 |   if (oat_file_class_status == mirror::Class::kStatusNotReady) { | 
| Ian Rogers | c476227 | 2012-02-01 15:55:55 -0800 | [diff] [blame] | 3207 |     // Status is uninitialized if we couldn't determine the status at compile time, for example, | 
 | 3208 |     // not loading the class. | 
 | 3209 |     // TODO: when the verifier doesn't rely on Class-es failing to resolve/load the type hierarchy | 
 | 3210 |     // isn't a problem and this case shouldn't occur | 
| Brian Carlstrom | e7d856b | 2012-01-11 18:10:55 -0800 | [diff] [blame] | 3211 |     return false; | 
 | 3212 |   } | 
| Ian Rogers | 1ff3c98 | 2014-08-12 02:30:58 -0700 | [diff] [blame] | 3213 |   std::string temp; | 
| Elliott Hughes | 634eb2e | 2012-03-22 16:06:28 -0700 | [diff] [blame] | 3214 |   LOG(FATAL) << "Unexpected class status: " << oat_file_class_status | 
| Ian Rogers | fc0e94b | 2013-09-23 23:51:32 -0700 | [diff] [blame] | 3215 |              << " " << dex_file.GetLocation() << " " << PrettyClass(klass) << " " | 
| Ian Rogers | 1ff3c98 | 2014-08-12 02:30:58 -0700 | [diff] [blame] | 3216 |              << klass->GetDescriptor(&temp); | 
| Ian Rogers | e0a02da | 2014-12-02 14:10:53 -0800 | [diff] [blame] | 3217 |   UNREACHABLE(); | 
| Brian Carlstrom | e7d856b | 2012-01-11 18:10:55 -0800 | [diff] [blame] | 3218 | } | 
 | 3219 |  | 
| Mathieu Chartier | c528dba | 2013-11-26 12:00:11 -0800 | [diff] [blame] | 3220 | void ClassLinker::ResolveClassExceptionHandlerTypes(const DexFile& dex_file, | 
| Andreas Gampe | 5a4b8a2 | 2014-09-11 08:30:08 -0700 | [diff] [blame] | 3221 |                                                     Handle<mirror::Class> klass) { | 
| Brian Carlstrom | e7d856b | 2012-01-11 18:10:55 -0800 | [diff] [blame] | 3222 |   for (size_t i = 0; i < klass->NumDirectMethods(); i++) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 3223 |     ResolveMethodExceptionHandlerTypes(dex_file, klass->GetDirectMethod(i, image_pointer_size_)); | 
| Brian Carlstrom | e7d856b | 2012-01-11 18:10:55 -0800 | [diff] [blame] | 3224 |   } | 
 | 3225 |   for (size_t i = 0; i < klass->NumVirtualMethods(); i++) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 3226 |     ResolveMethodExceptionHandlerTypes(dex_file, klass->GetVirtualMethod(i, image_pointer_size_)); | 
| Brian Carlstrom | e7d856b | 2012-01-11 18:10:55 -0800 | [diff] [blame] | 3227 |   } | 
 | 3228 | } | 
 | 3229 |  | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 3230 | void ClassLinker::ResolveMethodExceptionHandlerTypes(const DexFile& dex_file, | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 3231 |                                                      ArtMethod* method) { | 
| Brian Carlstrom | e7d856b | 2012-01-11 18:10:55 -0800 | [diff] [blame] | 3232 |   // similar to DexVerifier::ScanTryCatchBlocks and dex2oat's ResolveExceptionsForMethod. | 
 | 3233 |   const DexFile::CodeItem* code_item = dex_file.GetCodeItem(method->GetCodeItemOffset()); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 3234 |   if (code_item == nullptr) { | 
| Brian Carlstrom | e7d856b | 2012-01-11 18:10:55 -0800 | [diff] [blame] | 3235 |     return;  // native or abstract method | 
 | 3236 |   } | 
 | 3237 |   if (code_item->tries_size_ == 0) { | 
 | 3238 |     return;  // nothing to process | 
 | 3239 |   } | 
| Ian Rogers | 1373595 | 2014-10-08 12:43:28 -0700 | [diff] [blame] | 3240 |   const uint8_t* handlers_ptr = DexFile::GetCatchHandlerData(*code_item, 0); | 
| Brian Carlstrom | e7d856b | 2012-01-11 18:10:55 -0800 | [diff] [blame] | 3241 |   uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr); | 
| Brian Carlstrom | e7d856b | 2012-01-11 18:10:55 -0800 | [diff] [blame] | 3242 |   for (uint32_t idx = 0; idx < handlers_size; idx++) { | 
 | 3243 |     CatchHandlerIterator iterator(handlers_ptr); | 
 | 3244 |     for (; iterator.HasNext(); iterator.Next()) { | 
 | 3245 |       // Ensure exception types are resolved so that they don't need resolution to be delivered, | 
 | 3246 |       // unresolved exception types will be ignored by exception delivery | 
 | 3247 |       if (iterator.GetHandlerTypeIndex() != DexFile::kDexNoIndex16) { | 
| Mathieu Chartier | 9044347 | 2015-07-16 20:32:27 -0700 | [diff] [blame] | 3248 |         mirror::Class* exception_type = ResolveType(iterator.GetHandlerTypeIndex(), method); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 3249 |         if (exception_type == nullptr) { | 
| Brian Carlstrom | e7d856b | 2012-01-11 18:10:55 -0800 | [diff] [blame] | 3250 |           DCHECK(Thread::Current()->IsExceptionPending()); | 
 | 3251 |           Thread::Current()->ClearException(); | 
 | 3252 |         } | 
 | 3253 |       } | 
 | 3254 |     } | 
 | 3255 |     handlers_ptr = iterator.EndDataPointer(); | 
 | 3256 |   } | 
 | 3257 | } | 
 | 3258 |  | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 3259 | mirror::Class* ClassLinker::CreateProxyClass(ScopedObjectAccessAlreadyRunnable& soa, jstring name, | 
 | 3260 |                                              jobjectArray interfaces, jobject loader, | 
 | 3261 |                                              jobjectArray methods, jobjectArray throws) { | 
| Mathieu Chartier | 590fee9 | 2013-09-13 13:46:47 -0700 | [diff] [blame] | 3262 |   Thread* self = soa.Self(); | 
| Hiroshi Yamauchi | 679b1cf | 2015-05-21 12:05:27 -0700 | [diff] [blame] | 3263 |   StackHandleScope<10> hs(self); | 
| Andreas Gampe | 5a4b8a2 | 2014-09-11 08:30:08 -0700 | [diff] [blame] | 3264 |   MutableHandle<mirror::Class> klass(hs.NewHandle( | 
| Mingyao Yang | 98d1cc8 | 2014-05-15 17:02:16 -0700 | [diff] [blame] | 3265 |       AllocClass(self, GetClassRoot(kJavaLangClass), sizeof(mirror::Class)))); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 3266 |   if (klass.Get() == nullptr) { | 
| Ian Rogers | a436fde | 2013-08-27 23:34:06 -0700 | [diff] [blame] | 3267 |     CHECK(self->IsExceptionPending());  // OOME. | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 3268 |     return nullptr; | 
| Ian Rogers | a436fde | 2013-08-27 23:34:06 -0700 | [diff] [blame] | 3269 |   } | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 3270 |   DCHECK(klass->GetClass() != nullptr); | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 3271 |   klass->SetObjectSize(sizeof(mirror::Proxy)); | 
| Andreas Gampe | 4849859 | 2014-09-10 19:48:05 -0700 | [diff] [blame] | 3272 |   // Set the class access flags incl. preverified, so we do not try to set the flag on the methods. | 
 | 3273 |   klass->SetAccessFlags(kAccClassIsProxy | kAccPublic | kAccFinal | kAccPreverified); | 
| Mathieu Chartier | 590fee9 | 2013-09-13 13:46:47 -0700 | [diff] [blame] | 3274 |   klass->SetClassLoader(soa.Decode<mirror::ClassLoader*>(loader)); | 
| Ian Rogers | c2b4447 | 2011-12-14 21:17:17 -0800 | [diff] [blame] | 3275 |   DCHECK_EQ(klass->GetPrimitiveType(), Primitive::kPrimNot); | 
| Mathieu Chartier | 590fee9 | 2013-09-13 13:46:47 -0700 | [diff] [blame] | 3276 |   klass->SetName(soa.Decode<mirror::String*>(name)); | 
| Hiroshi Yamauchi | 679b1cf | 2015-05-21 12:05:27 -0700 | [diff] [blame] | 3277 |   klass->SetDexCache(GetClassRoot(kJavaLangReflectProxy)->GetDexCache()); | 
| Hiroshi Yamauchi | 5b783e6 | 2015-03-18 17:20:11 -0700 | [diff] [blame] | 3278 |   mirror::Class::SetStatus(klass, mirror::Class::kStatusIdx, self); | 
| Hiroshi Yamauchi | 679b1cf | 2015-05-21 12:05:27 -0700 | [diff] [blame] | 3279 |   std::string descriptor(GetDescriptorForProxy(klass.Get())); | 
| Mathieu Chartier | cc5ebdf | 2015-07-27 11:19:43 -0700 | [diff] [blame] | 3280 |   const size_t hash = ComputeModifiedUtf8Hash(descriptor.c_str()); | 
| Hiroshi Yamauchi | 679b1cf | 2015-05-21 12:05:27 -0700 | [diff] [blame] | 3281 |  | 
 | 3282 |   // Insert the class before loading the fields as the field roots | 
 | 3283 |   // (ArtField::declaring_class_) are only visited from the class | 
 | 3284 |   // table. There can't be any suspend points between inserting the | 
 | 3285 |   // class and setting the field arrays below. | 
 | 3286 |   mirror::Class* existing = InsertClass(descriptor.c_str(), klass.Get(), hash); | 
 | 3287 |   CHECK(existing == nullptr); | 
| Ian Rogers | c2b4447 | 2011-12-14 21:17:17 -0800 | [diff] [blame] | 3288 |  | 
| Elliott Hughes | 2ed52c4 | 2012-03-21 16:56:56 -0700 | [diff] [blame] | 3289 |   // Instance fields are inherited, but we add a couple of static fields... | 
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 3290 |   const size_t num_fields = 2; | 
| Mathieu Chartier | 54d220e | 2015-07-30 16:20:06 -0700 | [diff] [blame] | 3291 |   LengthPrefixedArray<ArtField>* sfields = AllocArtFieldArray(self, num_fields); | 
 | 3292 |   klass->SetSFieldsPtr(sfields); | 
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 3293 |  | 
| Elliott Hughes | 2ed52c4 | 2012-03-21 16:56:56 -0700 | [diff] [blame] | 3294 |   // 1. Create a static field 'interfaces' that holds the _declared_ interfaces implemented by | 
 | 3295 |   // our proxy, so Class.getInterfaces doesn't return the flattened set. | 
| Mathieu Chartier | 54d220e | 2015-07-30 16:20:06 -0700 | [diff] [blame] | 3296 |   ArtField& interfaces_sfield = sfields->At(0); | 
 | 3297 |   interfaces_sfield.SetDexFieldIndex(0); | 
 | 3298 |   interfaces_sfield.SetDeclaringClass(klass.Get()); | 
 | 3299 |   interfaces_sfield.SetAccessFlags(kAccStatic | kAccPublic | kAccFinal); | 
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 3300 |  | 
| Elliott Hughes | 2ed52c4 | 2012-03-21 16:56:56 -0700 | [diff] [blame] | 3301 |   // 2. Create a static field 'throws' that holds exceptions thrown by our methods. | 
| Mathieu Chartier | 54d220e | 2015-07-30 16:20:06 -0700 | [diff] [blame] | 3302 |   ArtField& throws_sfield = sfields->At(1); | 
 | 3303 |   throws_sfield.SetDexFieldIndex(1); | 
 | 3304 |   throws_sfield.SetDeclaringClass(klass.Get()); | 
 | 3305 |   throws_sfield.SetAccessFlags(kAccStatic | kAccPublic | kAccFinal); | 
| Jesse Wilson | 95caa79 | 2011-10-12 18:14:17 -0400 | [diff] [blame] | 3306 |  | 
| Ian Rogers | 466bb25 | 2011-10-14 03:29:56 -0700 | [diff] [blame] | 3307 |   // Proxies have 1 direct method, the constructor | 
| Mathieu Chartier | 54d220e | 2015-07-30 16:20:06 -0700 | [diff] [blame] | 3308 |   LengthPrefixedArray<ArtMethod>* directs = AllocArtMethodArray(self, 1); | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 3309 |   // Currently AllocArtMethodArray cannot return null, but the OOM logic is left there in case we | 
 | 3310 |   // want to throw OOM in the future. | 
 | 3311 |   if (UNLIKELY(directs == nullptr)) { | 
 | 3312 |     self->AssertPendingOOMException(); | 
 | 3313 |     return nullptr; | 
| Ian Rogers | a436fde | 2013-08-27 23:34:06 -0700 | [diff] [blame] | 3314 |   } | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 3315 |   klass->SetDirectMethodsPtr(directs); | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 3316 |   CreateProxyConstructor(klass, klass->GetDirectMethodUnchecked(0, image_pointer_size_)); | 
| Jesse Wilson | 95caa79 | 2011-10-12 18:14:17 -0400 | [diff] [blame] | 3317 |  | 
| Mathieu Chartier | 590fee9 | 2013-09-13 13:46:47 -0700 | [diff] [blame] | 3318 |   // Create virtual method using specified prototypes. | 
| Mathieu Chartier | fc58af4 | 2015-04-16 18:00:39 -0700 | [diff] [blame] | 3319 |   auto h_methods = hs.NewHandle(soa.Decode<mirror::ObjectArray<mirror::Method>*>(methods)); | 
 | 3320 |   DCHECK_EQ(h_methods->GetClass(), mirror::Method::ArrayClass()) | 
| Mathieu Chartier | 54d220e | 2015-07-30 16:20:06 -0700 | [diff] [blame] | 3321 |       << PrettyClass(h_methods->GetClass()); | 
| Mathieu Chartier | fc58af4 | 2015-04-16 18:00:39 -0700 | [diff] [blame] | 3322 |   const size_t num_virtual_methods = h_methods->GetLength(); | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 3323 |   auto* virtuals = AllocArtMethodArray(self, num_virtual_methods); | 
 | 3324 |   // Currently AllocArtMethodArray cannot return null, but the OOM logic is left there in case we | 
 | 3325 |   // want to throw OOM in the future. | 
 | 3326 |   if (UNLIKELY(virtuals == nullptr)) { | 
 | 3327 |     self->AssertPendingOOMException(); | 
 | 3328 |     return nullptr; | 
| Ian Rogers | a436fde | 2013-08-27 23:34:06 -0700 | [diff] [blame] | 3329 |   } | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 3330 |   klass->SetVirtualMethodsPtr(virtuals); | 
| Jesse Wilson | 95caa79 | 2011-10-12 18:14:17 -0400 | [diff] [blame] | 3331 |   for (size_t i = 0; i < num_virtual_methods; ++i) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 3332 |     auto* virtual_method = klass->GetVirtualMethodUnchecked(i, image_pointer_size_); | 
 | 3333 |     auto* prototype = h_methods->Get(i)->GetArtMethod(); | 
 | 3334 |     CreateProxyMethod(klass, prototype, virtual_method); | 
 | 3335 |     DCHECK(virtual_method->GetDeclaringClass() != nullptr); | 
 | 3336 |     DCHECK(prototype->GetDeclaringClass() != nullptr); | 
| Jesse Wilson | 95caa79 | 2011-10-12 18:14:17 -0400 | [diff] [blame] | 3337 |   } | 
| Ian Rogers | c2b4447 | 2011-12-14 21:17:17 -0800 | [diff] [blame] | 3338 |  | 
| Hiroshi Yamauchi | 679b1cf | 2015-05-21 12:05:27 -0700 | [diff] [blame] | 3339 |   // The super class is java.lang.reflect.Proxy | 
 | 3340 |   klass->SetSuperClass(GetClassRoot(kJavaLangReflectProxy)); | 
 | 3341 |   // Now effectively in the loaded state. | 
 | 3342 |   mirror::Class::SetStatus(klass, mirror::Class::kStatusLoaded, self); | 
| Ian Rogers | 62d6c77 | 2013-02-27 08:32:07 -0800 | [diff] [blame] | 3343 |   self->AssertNoPendingException(); | 
| Ian Rogers | c2b4447 | 2011-12-14 21:17:17 -0800 | [diff] [blame] | 3344 |  | 
| Hiroshi Yamauchi | 679b1cf | 2015-05-21 12:05:27 -0700 | [diff] [blame] | 3345 |   MutableHandle<mirror::Class> new_class = hs.NewHandle<mirror::Class>(nullptr); | 
| Ian Rogers | c898258 | 2012-09-07 16:53:25 -0700 | [diff] [blame] | 3346 |   { | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 3347 |     // Must hold lock on object when resolved. | 
 | 3348 |     ObjectLock<mirror::Class> resolution_lock(self, klass); | 
| Hiroshi Yamauchi | 679b1cf | 2015-05-21 12:05:27 -0700 | [diff] [blame] | 3349 |     // Link the fields and virtual methods, creating vtable and iftables. | 
 | 3350 |     // The new class will replace the old one in the class table. | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 3351 |     Handle<mirror::ObjectArray<mirror::Class>> h_interfaces( | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 3352 |         hs.NewHandle(soa.Decode<mirror::ObjectArray<mirror::Class>*>(interfaces))); | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 3353 |     if (!LinkClass(self, descriptor.c_str(), klass, h_interfaces, &new_class)) { | 
| Hiroshi Yamauchi | 5b783e6 | 2015-03-18 17:20:11 -0700 | [diff] [blame] | 3354 |       mirror::Class::SetStatus(klass, mirror::Class::kStatusError, self); | 
| Mathieu Chartier | c528dba | 2013-11-26 12:00:11 -0800 | [diff] [blame] | 3355 |       return nullptr; | 
| Ian Rogers | 7dfb28c | 2013-08-22 08:18:36 -0700 | [diff] [blame] | 3356 |     } | 
| Mingyao Yang | 98d1cc8 | 2014-05-15 17:02:16 -0700 | [diff] [blame] | 3357 |   } | 
| Mingyao Yang | 98d1cc8 | 2014-05-15 17:02:16 -0700 | [diff] [blame] | 3358 |   CHECK(klass->IsRetired()); | 
| Hiroshi Yamauchi | 679b1cf | 2015-05-21 12:05:27 -0700 | [diff] [blame] | 3359 |   CHECK_NE(klass.Get(), new_class.Get()); | 
 | 3360 |   klass.Assign(new_class.Get()); | 
| Mingyao Yang | 98d1cc8 | 2014-05-15 17:02:16 -0700 | [diff] [blame] | 3361 |  | 
| Mathieu Chartier | 54d220e | 2015-07-30 16:20:06 -0700 | [diff] [blame] | 3362 |   CHECK_EQ(interfaces_sfield.GetDeclaringClass(), klass.Get()); | 
 | 3363 |   interfaces_sfield.SetObject<false>(klass.Get(), | 
 | 3364 |                                      soa.Decode<mirror::ObjectArray<mirror::Class>*>(interfaces)); | 
 | 3365 |   CHECK_EQ(throws_sfield.GetDeclaringClass(), klass.Get()); | 
 | 3366 |   throws_sfield.SetObject<false>( | 
 | 3367 |       klass.Get(), soa.Decode<mirror::ObjectArray<mirror::ObjectArray<mirror::Class> >*>(throws)); | 
| Mingyao Yang | 98d1cc8 | 2014-05-15 17:02:16 -0700 | [diff] [blame] | 3368 |  | 
 | 3369 |   { | 
 | 3370 |     // Lock on klass is released. Lock new class object. | 
 | 3371 |     ObjectLock<mirror::Class> initialization_lock(self, klass); | 
| Hiroshi Yamauchi | 5b783e6 | 2015-03-18 17:20:11 -0700 | [diff] [blame] | 3372 |     mirror::Class::SetStatus(klass, mirror::Class::kStatusInitialized, self); | 
| Ian Rogers | c898258 | 2012-09-07 16:53:25 -0700 | [diff] [blame] | 3373 |   } | 
| Ian Rogers | c2b4447 | 2011-12-14 21:17:17 -0800 | [diff] [blame] | 3374 |  | 
 | 3375 |   // sanity checks | 
| Elliott Hughes | 67d9200 | 2012-03-26 15:08:51 -0700 | [diff] [blame] | 3376 |   if (kIsDebugBuild) { | 
| Mathieu Chartier | 54d220e | 2015-07-30 16:20:06 -0700 | [diff] [blame] | 3377 |     CHECK(klass->GetIFieldsPtr() == nullptr); | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 3378 |     CheckProxyConstructor(klass->GetDirectMethod(0, image_pointer_size_)); | 
 | 3379 |  | 
| Ian Rogers | c2b4447 | 2011-12-14 21:17:17 -0800 | [diff] [blame] | 3380 |     for (size_t i = 0; i < num_virtual_methods; ++i) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 3381 |       auto* virtual_method = klass->GetVirtualMethodUnchecked(i, image_pointer_size_); | 
 | 3382 |       auto* prototype = h_methods->Get(i++)->GetArtMethod(); | 
| Mathieu Chartier | bfd9a43 | 2014-05-21 17:43:44 -0700 | [diff] [blame] | 3383 |       CheckProxyMethod(virtual_method, prototype); | 
| Ian Rogers | c2b4447 | 2011-12-14 21:17:17 -0800 | [diff] [blame] | 3384 |     } | 
| Elliott Hughes | 2ed52c4 | 2012-03-21 16:56:56 -0700 | [diff] [blame] | 3385 |  | 
| Hiroshi Yamauchi | 679b1cf | 2015-05-21 12:05:27 -0700 | [diff] [blame] | 3386 |     StackHandleScope<1> hs2(self); | 
 | 3387 |     Handle<mirror::String> decoded_name = hs2.NewHandle(soa.Decode<mirror::String*>(name)); | 
| Elliott Hughes | 2ed52c4 | 2012-03-21 16:56:56 -0700 | [diff] [blame] | 3388 |     std::string interfaces_field_name(StringPrintf("java.lang.Class[] %s.interfaces", | 
| Mathieu Chartier | 590fee9 | 2013-09-13 13:46:47 -0700 | [diff] [blame] | 3389 |                                                    decoded_name->ToModifiedUtf8().c_str())); | 
| Elliott Hughes | 2ed52c4 | 2012-03-21 16:56:56 -0700 | [diff] [blame] | 3390 |     CHECK_EQ(PrettyField(klass->GetStaticField(0)), interfaces_field_name); | 
 | 3391 |  | 
 | 3392 |     std::string throws_field_name(StringPrintf("java.lang.Class[][] %s.throws", | 
| Mathieu Chartier | 590fee9 | 2013-09-13 13:46:47 -0700 | [diff] [blame] | 3393 |                                                decoded_name->ToModifiedUtf8().c_str())); | 
| Elliott Hughes | 2ed52c4 | 2012-03-21 16:56:56 -0700 | [diff] [blame] | 3394 |     CHECK_EQ(PrettyField(klass->GetStaticField(1)), throws_field_name); | 
| Ian Rogers | c2b4447 | 2011-12-14 21:17:17 -0800 | [diff] [blame] | 3395 |  | 
| Mingyao Yang | 98d1cc8 | 2014-05-15 17:02:16 -0700 | [diff] [blame] | 3396 |     CHECK_EQ(klass.Get()->GetInterfaces(), | 
| Brian Carlstrom | f363283 | 2014-05-20 15:36:53 -0700 | [diff] [blame] | 3397 |              soa.Decode<mirror::ObjectArray<mirror::Class>*>(interfaces)); | 
| Mingyao Yang | 98d1cc8 | 2014-05-15 17:02:16 -0700 | [diff] [blame] | 3398 |     CHECK_EQ(klass.Get()->GetThrows(), | 
| Brian Carlstrom | f363283 | 2014-05-20 15:36:53 -0700 | [diff] [blame] | 3399 |              soa.Decode<mirror::ObjectArray<mirror::ObjectArray<mirror::Class>>*>(throws)); | 
| Ian Rogers | c2b4447 | 2011-12-14 21:17:17 -0800 | [diff] [blame] | 3400 |   } | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 3401 |   return klass.Get(); | 
| Jesse Wilson | 95caa79 | 2011-10-12 18:14:17 -0400 | [diff] [blame] | 3402 | } | 
 | 3403 |  | 
| Ian Rogers | ef7d42f | 2014-01-06 12:55:46 -0800 | [diff] [blame] | 3404 | std::string ClassLinker::GetDescriptorForProxy(mirror::Class* proxy_class) { | 
| Ian Rogers | 6d4d9fc | 2011-11-30 16:24:48 -0800 | [diff] [blame] | 3405 |   DCHECK(proxy_class->IsProxyClass()); | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 3406 |   mirror::String* name = proxy_class->GetName(); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 3407 |   DCHECK(name != nullptr); | 
| Ian Rogers | 6d4d9fc | 2011-11-30 16:24:48 -0800 | [diff] [blame] | 3408 |   return DotToDescriptor(name->ToModifiedUtf8().c_str()); | 
 | 3409 | } | 
 | 3410 |  | 
| Mathieu Chartier | 4e2cb09 | 2015-07-22 16:17:51 -0700 | [diff] [blame] | 3411 | ArtMethod* ClassLinker::FindMethodForProxy(mirror::Class* proxy_class, ArtMethod* proxy_method) { | 
| Ian Rogers | 16f9367 | 2012-02-14 12:29:06 -0800 | [diff] [blame] | 3412 |   DCHECK(proxy_class->IsProxyClass()); | 
 | 3413 |   DCHECK(proxy_method->IsProxyMethod()); | 
| Ian Rogers | 16f9367 | 2012-02-14 12:29:06 -0800 | [diff] [blame] | 3414 |   { | 
| Mathieu Chartier | 673ed3d | 2015-08-28 14:56:43 -0700 | [diff] [blame^] | 3415 |     Thread* const self = Thread::Current(); | 
 | 3416 |     ReaderMutexLock mu(self, dex_lock_); | 
| Mathieu Chartier | fc58af4 | 2015-04-16 18:00:39 -0700 | [diff] [blame] | 3417 |     // Locate the dex cache of the original interface/Object | 
| Mathieu Chartier | 673ed3d | 2015-08-28 14:56:43 -0700 | [diff] [blame^] | 3418 |     for (jobject weak_root : dex_caches_) { | 
 | 3419 |       mirror::DexCache* dex_cache = down_cast<mirror::DexCache*>(self->DecodeJObject(weak_root)); | 
 | 3420 |       if (dex_cache != nullptr && | 
 | 3421 |           proxy_method->HasSameDexCacheResolvedTypes(dex_cache->GetResolvedTypes())) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 3422 |         ArtMethod* resolved_method = dex_cache->GetResolvedMethod( | 
 | 3423 |             proxy_method->GetDexMethodIndex(), image_pointer_size_); | 
| Mathieu Chartier | fc58af4 | 2015-04-16 18:00:39 -0700 | [diff] [blame] | 3424 |         CHECK(resolved_method != nullptr); | 
 | 3425 |         return resolved_method; | 
| Ian Rogers | 16f9367 | 2012-02-14 12:29:06 -0800 | [diff] [blame] | 3426 |       } | 
 | 3427 |     } | 
 | 3428 |   } | 
| Mathieu Chartier | fc58af4 | 2015-04-16 18:00:39 -0700 | [diff] [blame] | 3429 |   LOG(FATAL) << "Didn't find dex cache for " << PrettyClass(proxy_class) << " " | 
 | 3430 |       << PrettyMethod(proxy_method); | 
 | 3431 |   UNREACHABLE(); | 
| Ian Rogers | 16f9367 | 2012-02-14 12:29:06 -0800 | [diff] [blame] | 3432 | } | 
 | 3433 |  | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 3434 | void ClassLinker::CreateProxyConstructor(Handle<mirror::Class> klass, ArtMethod* out) { | 
 | 3435 |   // Create constructor for Proxy that must initialize the method. | 
 | 3436 |   CHECK_EQ(GetClassRoot(kJavaLangReflectProxy)->NumDirectMethods(), 16u); | 
 | 3437 |   ArtMethod* proxy_constructor = GetClassRoot(kJavaLangReflectProxy)->GetDirectMethodUnchecked( | 
 | 3438 |       2, image_pointer_size_); | 
| Sebastien Hertz | ae94e35 | 2014-08-27 15:32:56 +0200 | [diff] [blame] | 3439 |   // Ensure constructor is in dex cache so that we can use the dex cache to look up the overridden | 
 | 3440 |   // constructor method. | 
| Hiroshi Yamauchi | 679b1cf | 2015-05-21 12:05:27 -0700 | [diff] [blame] | 3441 |   GetClassRoot(kJavaLangReflectProxy)->GetDexCache()->SetResolvedMethod( | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 3442 |       proxy_constructor->GetDexMethodIndex(), proxy_constructor, image_pointer_size_); | 
| Jeff Hao | db8a664 | 2014-08-14 17:18:52 -0700 | [diff] [blame] | 3443 |   // Clone the existing constructor of Proxy (our constructor would just invoke it so steal its | 
 | 3444 |   // code_ too) | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 3445 |   DCHECK(out != nullptr); | 
 | 3446 |   out->CopyFrom(proxy_constructor, image_pointer_size_); | 
| Ian Rogers | 466bb25 | 2011-10-14 03:29:56 -0700 | [diff] [blame] | 3447 |   // Make this constructor public and fix the class to be our Proxy version | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 3448 |   out->SetAccessFlags((out->GetAccessFlags() & ~kAccProtected) | kAccPublic); | 
 | 3449 |   out->SetDeclaringClass(klass.Get()); | 
| Ian Rogers | c2b4447 | 2011-12-14 21:17:17 -0800 | [diff] [blame] | 3450 | } | 
 | 3451 |  | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 3452 | void ClassLinker::CheckProxyConstructor(ArtMethod* constructor) const { | 
| Ian Rogers | 466bb25 | 2011-10-14 03:29:56 -0700 | [diff] [blame] | 3453 |   CHECK(constructor->IsConstructor()); | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 3454 |   auto* np = constructor->GetInterfaceMethodIfProxy(image_pointer_size_); | 
 | 3455 |   CHECK_STREQ(np->GetName(), "<init>"); | 
 | 3456 |   CHECK_STREQ(np->GetSignature().ToString().c_str(), "(Ljava/lang/reflect/InvocationHandler;)V"); | 
| Ian Rogers | 466bb25 | 2011-10-14 03:29:56 -0700 | [diff] [blame] | 3457 |   DCHECK(constructor->IsPublic()); | 
| Jesse Wilson | 95caa79 | 2011-10-12 18:14:17 -0400 | [diff] [blame] | 3458 | } | 
 | 3459 |  | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 3460 | void ClassLinker::CreateProxyMethod(Handle<mirror::Class> klass, ArtMethod* prototype, | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 3461 |                                     ArtMethod* out) { | 
| Ian Rogers | 6d4d9fc | 2011-11-30 16:24:48 -0800 | [diff] [blame] | 3462 |   // Ensure prototype is in dex cache so that we can use the dex cache to look up the overridden | 
 | 3463 |   // prototype method | 
| Mathieu Chartier | fc58af4 | 2015-04-16 18:00:39 -0700 | [diff] [blame] | 3464 |   auto* dex_cache = prototype->GetDeclaringClass()->GetDexCache(); | 
 | 3465 |   // Avoid dirtying the dex cache unless we need to. | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 3466 |   if (dex_cache->GetResolvedMethod(prototype->GetDexMethodIndex(), image_pointer_size_) != | 
 | 3467 |       prototype) { | 
 | 3468 |     dex_cache->SetResolvedMethod( | 
 | 3469 |         prototype->GetDexMethodIndex(), prototype, image_pointer_size_); | 
| Mathieu Chartier | fc58af4 | 2015-04-16 18:00:39 -0700 | [diff] [blame] | 3470 |   } | 
| Ian Rogers | 6d4d9fc | 2011-11-30 16:24:48 -0800 | [diff] [blame] | 3471 |   // We steal everything from the prototype (such as DexCache, invoke stub, etc.) then specialize | 
| Ian Rogers | 466bb25 | 2011-10-14 03:29:56 -0700 | [diff] [blame] | 3472 |   // as necessary | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 3473 |   DCHECK(out != nullptr); | 
 | 3474 |   out->CopyFrom(prototype, image_pointer_size_); | 
| Ian Rogers | 466bb25 | 2011-10-14 03:29:56 -0700 | [diff] [blame] | 3475 |  | 
 | 3476 |   // Set class to be the concrete proxy class and clear the abstract flag, modify exceptions to | 
 | 3477 |   // the intersection of throw exceptions as defined in Proxy | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 3478 |   out->SetDeclaringClass(klass.Get()); | 
 | 3479 |   out->SetAccessFlags((out->GetAccessFlags() & ~kAccAbstract) | kAccFinal); | 
| Jesse Wilson | 95caa79 | 2011-10-12 18:14:17 -0400 | [diff] [blame] | 3480 |  | 
| Ian Rogers | 466bb25 | 2011-10-14 03:29:56 -0700 | [diff] [blame] | 3481 |   // At runtime the method looks like a reference and argument saving method, clone the code | 
 | 3482 |   // related parameters from this method. | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 3483 |   out->SetEntryPointFromQuickCompiledCode(GetQuickProxyInvokeHandler()); | 
| Ian Rogers | c2b4447 | 2011-12-14 21:17:17 -0800 | [diff] [blame] | 3484 | } | 
| Jesse Wilson | 95caa79 | 2011-10-12 18:14:17 -0400 | [diff] [blame] | 3485 |  | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 3486 | void ClassLinker::CheckProxyMethod(ArtMethod* method, ArtMethod* prototype) const { | 
| Ian Rogers | 466bb25 | 2011-10-14 03:29:56 -0700 | [diff] [blame] | 3487 |   // Basic sanity | 
| Ian Rogers | 6d4d9fc | 2011-11-30 16:24:48 -0800 | [diff] [blame] | 3488 |   CHECK(!prototype->IsFinal()); | 
 | 3489 |   CHECK(method->IsFinal()); | 
 | 3490 |   CHECK(!method->IsAbstract()); | 
| Ian Rogers | 1984651 | 2012-02-24 11:42:47 -0800 | [diff] [blame] | 3491 |  | 
 | 3492 |   // The proxy method doesn't have its own dex cache or dex file and so it steals those of its | 
 | 3493 |   // interface prototype. The exception to this are Constructors and the Class of the Proxy itself. | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 3494 |   CHECK(prototype->HasSameDexCacheResolvedMethods(method)); | 
 | 3495 |   CHECK(prototype->HasSameDexCacheResolvedTypes(method)); | 
 | 3496 |   auto* np = method->GetInterfaceMethodIfProxy(image_pointer_size_); | 
 | 3497 |   CHECK_EQ(prototype->GetDeclaringClass()->GetDexCache(), np->GetDexCache()); | 
| Ian Rogers | 1984651 | 2012-02-24 11:42:47 -0800 | [diff] [blame] | 3498 |   CHECK_EQ(prototype->GetDexMethodIndex(), method->GetDexMethodIndex()); | 
 | 3499 |  | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 3500 |   CHECK_STREQ(np->GetName(), prototype->GetName()); | 
 | 3501 |   CHECK_STREQ(np->GetShorty(), prototype->GetShorty()); | 
| Ian Rogers | 466bb25 | 2011-10-14 03:29:56 -0700 | [diff] [blame] | 3502 |   // More complex sanity - via dex cache | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 3503 |   CHECK_EQ(np->GetReturnType(), prototype->GetReturnType()); | 
| Jesse Wilson | 95caa79 | 2011-10-12 18:14:17 -0400 | [diff] [blame] | 3504 | } | 
 | 3505 |  | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 3506 | bool ClassLinker::CanWeInitializeClass(mirror::Class* klass, bool can_init_statics, | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 3507 |                                        bool can_init_parents) { | 
| Brian Carlstrom | 610e49f | 2013-11-04 17:07:22 -0800 | [diff] [blame] | 3508 |   if (can_init_statics && can_init_parents) { | 
| Ian Rogers | 8f3c9ae | 2013-08-20 17:26:41 -0700 | [diff] [blame] | 3509 |     return true; | 
 | 3510 |   } | 
 | 3511 |   if (!can_init_statics) { | 
 | 3512 |     // Check if there's a class initializer. | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 3513 |     ArtMethod* clinit = klass->FindClassInitializer(image_pointer_size_); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 3514 |     if (clinit != nullptr) { | 
| Ian Rogers | 8f3c9ae | 2013-08-20 17:26:41 -0700 | [diff] [blame] | 3515 |       return false; | 
 | 3516 |     } | 
 | 3517 |     // Check if there are encoded static values needing initialization. | 
 | 3518 |     if (klass->NumStaticFields() != 0) { | 
| Mathieu Chartier | f832284 | 2014-05-16 10:59:25 -0700 | [diff] [blame] | 3519 |       const DexFile::ClassDef* dex_class_def = klass->GetClassDef(); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 3520 |       DCHECK(dex_class_def != nullptr); | 
| Ian Rogers | 8f3c9ae | 2013-08-20 17:26:41 -0700 | [diff] [blame] | 3521 |       if (dex_class_def->static_values_off_ != 0) { | 
 | 3522 |         return false; | 
 | 3523 |       } | 
 | 3524 |     } | 
 | 3525 |   } | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 3526 |   if (klass->IsInterface() || !klass->HasSuperClass()) { | 
 | 3527 |     return true; | 
| Ian Rogers | 8f3c9ae | 2013-08-20 17:26:41 -0700 | [diff] [blame] | 3528 |   } | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 3529 |   mirror::Class* super_class = klass->GetSuperClass(); | 
 | 3530 |   if (!can_init_parents && !super_class->IsInitialized()) { | 
 | 3531 |     return false; | 
 | 3532 |   } | 
 | 3533 |   return CanWeInitializeClass(super_class, can_init_statics, can_init_parents); | 
| Ian Rogers | 8f3c9ae | 2013-08-20 17:26:41 -0700 | [diff] [blame] | 3534 | } | 
 | 3535 |  | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 3536 | bool ClassLinker::InitializeClass(Thread* self, Handle<mirror::Class> klass, | 
 | 3537 |                                   bool can_init_statics, bool can_init_parents) { | 
| Ian Rogers | 8f3c9ae | 2013-08-20 17:26:41 -0700 | [diff] [blame] | 3538 |   // see JLS 3rd edition, 12.4.2 "Detailed Initialization Procedure" for the locking protocol | 
 | 3539 |  | 
 | 3540 |   // Are we already initialized and therefore done? | 
 | 3541 |   // Note: we differ from the JLS here as we don't do this under the lock, this is benign as | 
 | 3542 |   // an initialized class will never change its state. | 
 | 3543 |   if (klass->IsInitialized()) { | 
 | 3544 |     return true; | 
 | 3545 |   } | 
 | 3546 |  | 
 | 3547 |   // Fast fail if initialization requires a full runtime. Not part of the JLS. | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 3548 |   if (!CanWeInitializeClass(klass.Get(), can_init_statics, can_init_parents)) { | 
| Ian Rogers | 8f3c9ae | 2013-08-20 17:26:41 -0700 | [diff] [blame] | 3549 |     return false; | 
 | 3550 |   } | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 3551 |  | 
| Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 3552 |   self->AllowThreadSuspension(); | 
| Ian Rogers | 8f3c9ae | 2013-08-20 17:26:41 -0700 | [diff] [blame] | 3553 |   uint64_t t0; | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 3554 |   { | 
| Mathieu Chartier | db2633c | 2014-05-16 09:59:29 -0700 | [diff] [blame] | 3555 |     ObjectLock<mirror::Class> lock(self, klass); | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 3556 |  | 
| Ian Rogers | 8f3c9ae | 2013-08-20 17:26:41 -0700 | [diff] [blame] | 3557 |     // Re-check under the lock in case another thread initialized ahead of us. | 
 | 3558 |     if (klass->IsInitialized()) { | 
| Brian Carlstrom | d1422f8 | 2011-09-28 11:37:09 -0700 | [diff] [blame] | 3559 |       return true; | 
 | 3560 |     } | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 3561 |  | 
| Ian Rogers | 8f3c9ae | 2013-08-20 17:26:41 -0700 | [diff] [blame] | 3562 |     // Was the class already found to be erroneous? Done under the lock to match the JLS. | 
| Brian Carlstrom | d1422f8 | 2011-09-28 11:37:09 -0700 | [diff] [blame] | 3563 |     if (klass->IsErroneous()) { | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 3564 |       ThrowEarlierClassFailure(klass.Get()); | 
| Brian Carlstrom | b23eab1 | 2014-10-08 17:55:21 -0700 | [diff] [blame] | 3565 |       VlogClassInitializationFailure(klass); | 
| Brian Carlstrom | d1422f8 | 2011-09-28 11:37:09 -0700 | [diff] [blame] | 3566 |       return false; | 
 | 3567 |     } | 
 | 3568 |  | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 3569 |     CHECK(klass->IsResolved()) << PrettyClass(klass.Get()) << ": state=" << klass->GetStatus(); | 
| Ian Rogers | 8f3c9ae | 2013-08-20 17:26:41 -0700 | [diff] [blame] | 3570 |  | 
 | 3571 |     if (!klass->IsVerified()) { | 
| Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 3572 |       VerifyClass(self, klass); | 
| Ian Rogers | 8f3c9ae | 2013-08-20 17:26:41 -0700 | [diff] [blame] | 3573 |       if (!klass->IsVerified()) { | 
 | 3574 |         // We failed to verify, expect either the klass to be erroneous or verification failed at | 
 | 3575 |         // compile time. | 
 | 3576 |         if (klass->IsErroneous()) { | 
| jeffhao | a9b3bf4 | 2012-06-06 17:18:39 -0700 | [diff] [blame] | 3577 |           CHECK(self->IsExceptionPending()); | 
| Brian Carlstrom | b23eab1 | 2014-10-08 17:55:21 -0700 | [diff] [blame] | 3578 |           VlogClassInitializationFailure(klass); | 
| Ian Rogers | 8f3c9ae | 2013-08-20 17:26:41 -0700 | [diff] [blame] | 3579 |         } else { | 
| Mathieu Chartier | e5f13e5 | 2015-02-24 09:37:21 -0800 | [diff] [blame] | 3580 |           CHECK(Runtime::Current()->IsAotCompiler()); | 
| Ian Rogers | 8f3c9ae | 2013-08-20 17:26:41 -0700 | [diff] [blame] | 3581 |           CHECK_EQ(klass->GetStatus(), mirror::Class::kStatusRetryVerificationAtRuntime); | 
| jeffhao | a9b3bf4 | 2012-06-06 17:18:39 -0700 | [diff] [blame] | 3582 |         } | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 3583 |         return false; | 
| Mathieu Chartier | 524507a | 2014-08-27 15:28:28 -0700 | [diff] [blame] | 3584 |       } else { | 
 | 3585 |         self->AssertNoPendingException(); | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 3586 |       } | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 3587 |     } | 
 | 3588 |  | 
| Brian Carlstrom | d1422f8 | 2011-09-28 11:37:09 -0700 | [diff] [blame] | 3589 |     // If the class is kStatusInitializing, either this thread is | 
 | 3590 |     // initializing higher up the stack or another thread has beat us | 
 | 3591 |     // to initializing and we need to wait. Either way, this | 
 | 3592 |     // invocation of InitializeClass will not be responsible for | 
 | 3593 |     // running <clinit> and will return. | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 3594 |     if (klass->GetStatus() == mirror::Class::kStatusInitializing) { | 
| Mathieu Chartier | 524507a | 2014-08-27 15:28:28 -0700 | [diff] [blame] | 3595 |       // Could have got an exception during verification. | 
 | 3596 |       if (self->IsExceptionPending()) { | 
| Brian Carlstrom | b23eab1 | 2014-10-08 17:55:21 -0700 | [diff] [blame] | 3597 |         VlogClassInitializationFailure(klass); | 
| Mathieu Chartier | 524507a | 2014-08-27 15:28:28 -0700 | [diff] [blame] | 3598 |         return false; | 
 | 3599 |       } | 
| Elliott Hughes | 005ab2e | 2011-09-11 17:15:31 -0700 | [diff] [blame] | 3600 |       // We caught somebody else in the act; was it us? | 
| Elliott Hughes | dcc2474 | 2011-09-07 14:02:44 -0700 | [diff] [blame] | 3601 |       if (klass->GetClinitThreadId() == self->GetTid()) { | 
| Brian Carlstrom | d1422f8 | 2011-09-28 11:37:09 -0700 | [diff] [blame] | 3602 |         // Yes. That's fine. Return so we can continue initializing. | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 3603 |         return true; | 
 | 3604 |       } | 
| Brian Carlstrom | d1422f8 | 2011-09-28 11:37:09 -0700 | [diff] [blame] | 3605 |       // No. That's fine. Wait for another thread to finish initializing. | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 3606 |       return WaitForInitializeClass(klass, self, lock); | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 3607 |     } | 
 | 3608 |  | 
 | 3609 |     if (!ValidateSuperClassDescriptors(klass)) { | 
| Hiroshi Yamauchi | 5b783e6 | 2015-03-18 17:20:11 -0700 | [diff] [blame] | 3610 |       mirror::Class::SetStatus(klass, mirror::Class::kStatusError, self); | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 3611 |       return false; | 
 | 3612 |     } | 
| Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 3613 |     self->AllowThreadSuspension(); | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 3614 |  | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 3615 |     CHECK_EQ(klass->GetStatus(), mirror::Class::kStatusVerified) << PrettyClass(klass.Get()); | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 3616 |  | 
| Ian Rogers | 8f3c9ae | 2013-08-20 17:26:41 -0700 | [diff] [blame] | 3617 |     // From here out other threads may observe that we're initializing and so changes of state | 
 | 3618 |     // require the a notification. | 
| Elliott Hughes | dcc2474 | 2011-09-07 14:02:44 -0700 | [diff] [blame] | 3619 |     klass->SetClinitThreadId(self->GetTid()); | 
| Hiroshi Yamauchi | 5b783e6 | 2015-03-18 17:20:11 -0700 | [diff] [blame] | 3620 |     mirror::Class::SetStatus(klass, mirror::Class::kStatusInitializing, self); | 
| Ian Rogers | 8f3c9ae | 2013-08-20 17:26:41 -0700 | [diff] [blame] | 3621 |  | 
 | 3622 |     t0 = NanoTime(); | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 3623 |   } | 
 | 3624 |  | 
| Brian Carlstrom | 6d3f72c | 2013-08-21 18:06:34 -0700 | [diff] [blame] | 3625 |   // Initialize super classes, must be done while initializing for the JLS. | 
| Ian Rogers | 8f3c9ae | 2013-08-20 17:26:41 -0700 | [diff] [blame] | 3626 |   if (!klass->IsInterface() && klass->HasSuperClass()) { | 
 | 3627 |     mirror::Class* super_class = klass->GetSuperClass(); | 
 | 3628 |     if (!super_class->IsInitialized()) { | 
 | 3629 |       CHECK(!super_class->IsInterface()); | 
 | 3630 |       CHECK(can_init_parents); | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 3631 |       StackHandleScope<1> hs(self); | 
 | 3632 |       Handle<mirror::Class> handle_scope_super(hs.NewHandle(super_class)); | 
| Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 3633 |       bool super_initialized = InitializeClass(self, handle_scope_super, can_init_statics, true); | 
| Ian Rogers | 8f3c9ae | 2013-08-20 17:26:41 -0700 | [diff] [blame] | 3634 |       if (!super_initialized) { | 
 | 3635 |         // The super class was verified ahead of entering initializing, we should only be here if | 
 | 3636 |         // the super class became erroneous due to initialization. | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 3637 |         CHECK(handle_scope_super->IsErroneous() && self->IsExceptionPending()) | 
| Brian Carlstrom | f363283 | 2014-05-20 15:36:53 -0700 | [diff] [blame] | 3638 |             << "Super class initialization failed for " | 
 | 3639 |             << PrettyDescriptor(handle_scope_super.Get()) | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 3640 |             << " that has unexpected status " << handle_scope_super->GetStatus() | 
| Ian Rogers | 8f3c9ae | 2013-08-20 17:26:41 -0700 | [diff] [blame] | 3641 |             << "\nPending exception:\n" | 
| Nicolas Geoffray | 14691c5 | 2015-03-05 10:40:17 +0000 | [diff] [blame] | 3642 |             << (self->GetException() != nullptr ? self->GetException()->Dump() : ""); | 
| Mathieu Chartier | db2633c | 2014-05-16 09:59:29 -0700 | [diff] [blame] | 3643 |         ObjectLock<mirror::Class> lock(self, klass); | 
| Ian Rogers | 8f3c9ae | 2013-08-20 17:26:41 -0700 | [diff] [blame] | 3644 |         // Initialization failed because the super-class is erroneous. | 
| Hiroshi Yamauchi | 5b783e6 | 2015-03-18 17:20:11 -0700 | [diff] [blame] | 3645 |         mirror::Class::SetStatus(klass, mirror::Class::kStatusError, self); | 
| Ian Rogers | 8f3c9ae | 2013-08-20 17:26:41 -0700 | [diff] [blame] | 3646 |         return false; | 
 | 3647 |       } | 
| Ian Rogers | 1bddec3 | 2012-02-04 12:27:34 -0800 | [diff] [blame] | 3648 |     } | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 3649 |   } | 
 | 3650 |  | 
| Mathieu Chartier | 05d89ee | 2014-10-28 13:57:04 -0700 | [diff] [blame] | 3651 |   const size_t num_static_fields = klass->NumStaticFields(); | 
 | 3652 |   if (num_static_fields > 0) { | 
| Mathieu Chartier | f832284 | 2014-05-16 10:59:25 -0700 | [diff] [blame] | 3653 |     const DexFile::ClassDef* dex_class_def = klass->GetClassDef(); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 3654 |     CHECK(dex_class_def != nullptr); | 
| Mathieu Chartier | f832284 | 2014-05-16 10:59:25 -0700 | [diff] [blame] | 3655 |     const DexFile& dex_file = klass->GetDexFile(); | 
| Hiroshi Yamauchi | 67ef46a | 2014-08-21 15:59:43 -0700 | [diff] [blame] | 3656 |     StackHandleScope<3> hs(self); | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 3657 |     Handle<mirror::ClassLoader> class_loader(hs.NewHandle(klass->GetClassLoader())); | 
| Mathieu Chartier | f832284 | 2014-05-16 10:59:25 -0700 | [diff] [blame] | 3658 |     Handle<mirror::DexCache> dex_cache(hs.NewHandle(klass->GetDexCache())); | 
| Mathieu Chartier | 05d89ee | 2014-10-28 13:57:04 -0700 | [diff] [blame] | 3659 |  | 
 | 3660 |     // Eagerly fill in static fields so that the we don't have to do as many expensive | 
 | 3661 |     // Class::FindStaticField in ResolveField. | 
 | 3662 |     for (size_t i = 0; i < num_static_fields; ++i) { | 
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 3663 |       ArtField* field = klass->GetStaticField(i); | 
| Mathieu Chartier | 05d89ee | 2014-10-28 13:57:04 -0700 | [diff] [blame] | 3664 |       const uint32_t field_idx = field->GetDexFieldIndex(); | 
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 3665 |       ArtField* resolved_field = dex_cache->GetResolvedField(field_idx, image_pointer_size_); | 
| Mathieu Chartier | 05d89ee | 2014-10-28 13:57:04 -0700 | [diff] [blame] | 3666 |       if (resolved_field == nullptr) { | 
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 3667 |         dex_cache->SetResolvedField(field_idx, field, image_pointer_size_); | 
| Mathieu Chartier | 9f3629d | 2014-10-28 18:23:02 -0700 | [diff] [blame] | 3668 |       } else { | 
 | 3669 |         DCHECK_EQ(field, resolved_field); | 
| Mathieu Chartier | 05d89ee | 2014-10-28 13:57:04 -0700 | [diff] [blame] | 3670 |       } | 
 | 3671 |     } | 
 | 3672 |  | 
| Hiroshi Yamauchi | 8850011 | 2014-08-22 12:12:56 -0700 | [diff] [blame] | 3673 |     EncodedStaticFieldValueIterator value_it(dex_file, &dex_cache, &class_loader, | 
 | 3674 |                                              this, *dex_class_def); | 
| Ian Rogers | 1373595 | 2014-10-08 12:43:28 -0700 | [diff] [blame] | 3675 |     const uint8_t* class_data = dex_file.GetClassData(*dex_class_def); | 
| Hiroshi Yamauchi | 8850011 | 2014-08-22 12:12:56 -0700 | [diff] [blame] | 3676 |     ClassDataItemIterator field_it(dex_file, class_data); | 
 | 3677 |     if (value_it.HasNext()) { | 
 | 3678 |       DCHECK(field_it.HasNextStaticField()); | 
| Ian Rogers | 8f3c9ae | 2013-08-20 17:26:41 -0700 | [diff] [blame] | 3679 |       CHECK(can_init_statics); | 
| Hiroshi Yamauchi | 8850011 | 2014-08-22 12:12:56 -0700 | [diff] [blame] | 3680 |       for ( ; value_it.HasNext(); value_it.Next(), field_it.Next()) { | 
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 3681 |         ArtField* field = ResolveField( | 
 | 3682 |             dex_file, field_it.GetMemberIndex(), dex_cache, class_loader, true); | 
| Sebastien Hertz | d2fe10a | 2014-01-15 10:20:56 +0100 | [diff] [blame] | 3683 |         if (Runtime::Current()->IsActiveTransaction()) { | 
| Hiroshi Yamauchi | 8850011 | 2014-08-22 12:12:56 -0700 | [diff] [blame] | 3684 |           value_it.ReadValueToField<true>(field); | 
| Sebastien Hertz | d2fe10a | 2014-01-15 10:20:56 +0100 | [diff] [blame] | 3685 |         } else { | 
| Hiroshi Yamauchi | 8850011 | 2014-08-22 12:12:56 -0700 | [diff] [blame] | 3686 |           value_it.ReadValueToField<false>(field); | 
| Sebastien Hertz | d2fe10a | 2014-01-15 10:20:56 +0100 | [diff] [blame] | 3687 |         } | 
| Hiroshi Yamauchi | 8850011 | 2014-08-22 12:12:56 -0700 | [diff] [blame] | 3688 |         DCHECK(!value_it.HasNext() || field_it.HasNextStaticField()); | 
| Ian Rogers | 8f3c9ae | 2013-08-20 17:26:41 -0700 | [diff] [blame] | 3689 |       } | 
 | 3690 |     } | 
 | 3691 |   } | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 3692 |  | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 3693 |   ArtMethod* clinit = klass->FindClassInitializer(image_pointer_size_); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 3694 |   if (clinit != nullptr) { | 
| Ian Rogers | 8f3c9ae | 2013-08-20 17:26:41 -0700 | [diff] [blame] | 3695 |     CHECK(can_init_statics); | 
| Ian Rogers | 5d27faf | 2014-05-02 17:17:18 -0700 | [diff] [blame] | 3696 |     JValue result; | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 3697 |     clinit->Invoke(self, nullptr, 0, &result, "V"); | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 3698 |   } | 
 | 3699 |  | 
| Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 3700 |   self->AllowThreadSuspension(); | 
| Elliott Hughes | 83df2ac | 2011-10-11 16:37:54 -0700 | [diff] [blame] | 3701 |   uint64_t t1 = NanoTime(); | 
 | 3702 |  | 
| Ian Rogers | bdfb1a5 | 2012-01-12 14:05:22 -0800 | [diff] [blame] | 3703 |   bool success = true; | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 3704 |   { | 
| Mathieu Chartier | db2633c | 2014-05-16 09:59:29 -0700 | [diff] [blame] | 3705 |     ObjectLock<mirror::Class> lock(self, klass); | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 3706 |  | 
 | 3707 |     if (self->IsExceptionPending()) { | 
| Brian Carlstrom | b23eab1 | 2014-10-08 17:55:21 -0700 | [diff] [blame] | 3708 |       WrapExceptionInInitializer(klass); | 
| Hiroshi Yamauchi | 5b783e6 | 2015-03-18 17:20:11 -0700 | [diff] [blame] | 3709 |       mirror::Class::SetStatus(klass, mirror::Class::kStatusError, self); | 
| Ian Rogers | bdfb1a5 | 2012-01-12 14:05:22 -0800 | [diff] [blame] | 3710 |       success = false; | 
| Sebastien Hertz | 1c80bec | 2015-02-03 11:58:06 +0100 | [diff] [blame] | 3711 |     } else if (Runtime::Current()->IsTransactionAborted()) { | 
 | 3712 |       // The exception thrown when the transaction aborted has been caught and cleared | 
 | 3713 |       // so we need to throw it again now. | 
| Sebastien Hertz | bd9cf9f | 2015-03-03 12:16:13 +0100 | [diff] [blame] | 3714 |       VLOG(compiler) << "Return from class initializer of " << PrettyDescriptor(klass.Get()) | 
 | 3715 |                      << " without exception while transaction was aborted: re-throw it now."; | 
| Sebastien Hertz | 2fd7e69 | 2015-04-02 11:11:19 +0200 | [diff] [blame] | 3716 |       Runtime::Current()->ThrowTransactionAbortError(self); | 
| Hiroshi Yamauchi | 5b783e6 | 2015-03-18 17:20:11 -0700 | [diff] [blame] | 3717 |       mirror::Class::SetStatus(klass, mirror::Class::kStatusError, self); | 
| Sebastien Hertz | 1c80bec | 2015-02-03 11:58:06 +0100 | [diff] [blame] | 3718 |       success = false; | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 3719 |     } else { | 
| Elliott Hughes | 83df2ac | 2011-10-11 16:37:54 -0700 | [diff] [blame] | 3720 |       RuntimeStats* global_stats = Runtime::Current()->GetStats(); | 
 | 3721 |       RuntimeStats* thread_stats = self->GetStats(); | 
 | 3722 |       ++global_stats->class_init_count; | 
 | 3723 |       ++thread_stats->class_init_count; | 
 | 3724 |       global_stats->class_init_time_ns += (t1 - t0); | 
 | 3725 |       thread_stats->class_init_time_ns += (t1 - t0); | 
| Ian Rogers | e6bb3b2 | 2013-08-19 21:51:45 -0700 | [diff] [blame] | 3726 |       // Set the class as initialized except if failed to initialize static fields. | 
| Hiroshi Yamauchi | 5b783e6 | 2015-03-18 17:20:11 -0700 | [diff] [blame] | 3727 |       mirror::Class::SetStatus(klass, mirror::Class::kStatusInitialized, self); | 
| Ian Rogers | 8f3c9ae | 2013-08-20 17:26:41 -0700 | [diff] [blame] | 3728 |       if (VLOG_IS_ON(class_linker)) { | 
| Ian Rogers | 1ff3c98 | 2014-08-12 02:30:58 -0700 | [diff] [blame] | 3729 |         std::string temp; | 
 | 3730 |         LOG(INFO) << "Initialized class " << klass->GetDescriptor(&temp) << " from " << | 
| Mathieu Chartier | f832284 | 2014-05-16 10:59:25 -0700 | [diff] [blame] | 3731 |             klass->GetLocation(); | 
| Brian Carlstrom | ae82698 | 2011-11-09 01:33:42 -0800 | [diff] [blame] | 3732 |       } | 
| Brian Carlstrom | 073278c | 2014-02-19 15:21:21 -0800 | [diff] [blame] | 3733 |       // Opportunistically set static method trampolines to their destination. | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 3734 |       FixupStaticTrampolines(klass.Get()); | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 3735 |     } | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 3736 |   } | 
| Ian Rogers | bdfb1a5 | 2012-01-12 14:05:22 -0800 | [diff] [blame] | 3737 |   return success; | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 3738 | } | 
 | 3739 |  | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 3740 | bool ClassLinker::WaitForInitializeClass(Handle<mirror::Class> klass, Thread* self, | 
 | 3741 |                                          ObjectLock<mirror::Class>& lock) | 
| Mathieu Chartier | 9044347 | 2015-07-16 20:32:27 -0700 | [diff] [blame] | 3742 |     SHARED_REQUIRES(Locks::mutator_lock_) { | 
| Brian Carlstrom | d1422f8 | 2011-09-28 11:37:09 -0700 | [diff] [blame] | 3743 |   while (true) { | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 3744 |     self->AssertNoPendingException(); | 
| Ian Rogers | 8f3c9ae | 2013-08-20 17:26:41 -0700 | [diff] [blame] | 3745 |     CHECK(!klass->IsInitialized()); | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 3746 |     lock.WaitIgnoringInterrupts(); | 
| Brian Carlstrom | d1422f8 | 2011-09-28 11:37:09 -0700 | [diff] [blame] | 3747 |  | 
 | 3748 |     // When we wake up, repeat the test for init-in-progress.  If | 
 | 3749 |     // there's an exception pending (only possible if | 
| Brian Carlstrom | b23eab1 | 2014-10-08 17:55:21 -0700 | [diff] [blame] | 3750 |     // we were not using WaitIgnoringInterrupts), bail out. | 
| Brian Carlstrom | d1422f8 | 2011-09-28 11:37:09 -0700 | [diff] [blame] | 3751 |     if (self->IsExceptionPending()) { | 
| Brian Carlstrom | b23eab1 | 2014-10-08 17:55:21 -0700 | [diff] [blame] | 3752 |       WrapExceptionInInitializer(klass); | 
| Hiroshi Yamauchi | 5b783e6 | 2015-03-18 17:20:11 -0700 | [diff] [blame] | 3753 |       mirror::Class::SetStatus(klass, mirror::Class::kStatusError, self); | 
| Brian Carlstrom | d1422f8 | 2011-09-28 11:37:09 -0700 | [diff] [blame] | 3754 |       return false; | 
 | 3755 |     } | 
 | 3756 |     // Spurious wakeup? Go back to waiting. | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 3757 |     if (klass->GetStatus() == mirror::Class::kStatusInitializing) { | 
| Brian Carlstrom | d1422f8 | 2011-09-28 11:37:09 -0700 | [diff] [blame] | 3758 |       continue; | 
 | 3759 |     } | 
| Mathieu Chartier | e5f13e5 | 2015-02-24 09:37:21 -0800 | [diff] [blame] | 3760 |     if (klass->GetStatus() == mirror::Class::kStatusVerified && | 
 | 3761 |         Runtime::Current()->IsAotCompiler()) { | 
| Ian Rogers | 3d1548d | 2012-09-24 14:08:03 -0700 | [diff] [blame] | 3762 |       // Compile time initialization failed. | 
 | 3763 |       return false; | 
 | 3764 |     } | 
| Brian Carlstrom | d1422f8 | 2011-09-28 11:37:09 -0700 | [diff] [blame] | 3765 |     if (klass->IsErroneous()) { | 
 | 3766 |       // The caller wants an exception, but it was thrown in a | 
 | 3767 |       // different thread.  Synthesize one here. | 
| Brian Carlstrom | df14324 | 2011-10-10 18:05:34 -0700 | [diff] [blame] | 3768 |       ThrowNoClassDefFoundError("<clinit> failed for class %s; see exception in other thread", | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 3769 |                                 PrettyDescriptor(klass.Get()).c_str()); | 
| Brian Carlstrom | b23eab1 | 2014-10-08 17:55:21 -0700 | [diff] [blame] | 3770 |       VlogClassInitializationFailure(klass); | 
| Brian Carlstrom | d1422f8 | 2011-09-28 11:37:09 -0700 | [diff] [blame] | 3771 |       return false; | 
 | 3772 |     } | 
 | 3773 |     if (klass->IsInitialized()) { | 
 | 3774 |       return true; | 
 | 3775 |     } | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 3776 |     LOG(FATAL) << "Unexpected class status. " << PrettyClass(klass.Get()) << " is " | 
| Mathieu Chartier | c528dba | 2013-11-26 12:00:11 -0800 | [diff] [blame] | 3777 |         << klass->GetStatus(); | 
| Brian Carlstrom | d1422f8 | 2011-09-28 11:37:09 -0700 | [diff] [blame] | 3778 |   } | 
| Ian Rogers | 0714083 | 2014-09-30 15:43:59 -0700 | [diff] [blame] | 3779 |   UNREACHABLE(); | 
| Brian Carlstrom | d1422f8 | 2011-09-28 11:37:09 -0700 | [diff] [blame] | 3780 | } | 
 | 3781 |  | 
| Vladimir Marko | d5e5a0e | 2015-05-08 12:26:59 +0100 | [diff] [blame] | 3782 | static void ThrowSignatureCheckResolveReturnTypeException(Handle<mirror::Class> klass, | 
 | 3783 |                                                           Handle<mirror::Class> super_klass, | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 3784 |                                                           ArtMethod* method, | 
 | 3785 |                                                           ArtMethod* m) | 
| Mathieu Chartier | 9044347 | 2015-07-16 20:32:27 -0700 | [diff] [blame] | 3786 |     SHARED_REQUIRES(Locks::mutator_lock_) { | 
| Vladimir Marko | d5e5a0e | 2015-05-08 12:26:59 +0100 | [diff] [blame] | 3787 |   DCHECK(Thread::Current()->IsExceptionPending()); | 
 | 3788 |   DCHECK(!m->IsProxyMethod()); | 
 | 3789 |   const DexFile* dex_file = m->GetDexFile(); | 
 | 3790 |   const DexFile::MethodId& method_id = dex_file->GetMethodId(m->GetDexMethodIndex()); | 
 | 3791 |   const DexFile::ProtoId& proto_id = dex_file->GetMethodPrototype(method_id); | 
 | 3792 |   uint16_t return_type_idx = proto_id.return_type_idx_; | 
 | 3793 |   std::string return_type = PrettyType(return_type_idx, *dex_file); | 
 | 3794 |   std::string class_loader = PrettyTypeOf(m->GetDeclaringClass()->GetClassLoader()); | 
 | 3795 |   ThrowWrappedLinkageError(klass.Get(), | 
 | 3796 |                            "While checking class %s method %s signature against %s %s: " | 
 | 3797 |                            "Failed to resolve return type %s with %s", | 
 | 3798 |                            PrettyDescriptor(klass.Get()).c_str(), | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 3799 |                            PrettyMethod(method).c_str(), | 
| Vladimir Marko | d5e5a0e | 2015-05-08 12:26:59 +0100 | [diff] [blame] | 3800 |                            super_klass->IsInterface() ? "interface" : "superclass", | 
 | 3801 |                            PrettyDescriptor(super_klass.Get()).c_str(), | 
 | 3802 |                            return_type.c_str(), class_loader.c_str()); | 
 | 3803 | } | 
 | 3804 |  | 
 | 3805 | static void ThrowSignatureCheckResolveArgException(Handle<mirror::Class> klass, | 
 | 3806 |                                                    Handle<mirror::Class> super_klass, | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 3807 |                                                    ArtMethod* method, | 
 | 3808 |                                                    ArtMethod* m, | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 3809 |                                                    uint32_t index, uint32_t arg_type_idx) | 
| Mathieu Chartier | 9044347 | 2015-07-16 20:32:27 -0700 | [diff] [blame] | 3810 |     SHARED_REQUIRES(Locks::mutator_lock_) { | 
| Vladimir Marko | d5e5a0e | 2015-05-08 12:26:59 +0100 | [diff] [blame] | 3811 |   DCHECK(Thread::Current()->IsExceptionPending()); | 
 | 3812 |   DCHECK(!m->IsProxyMethod()); | 
 | 3813 |   const DexFile* dex_file = m->GetDexFile(); | 
 | 3814 |   std::string arg_type = PrettyType(arg_type_idx, *dex_file); | 
 | 3815 |   std::string class_loader = PrettyTypeOf(m->GetDeclaringClass()->GetClassLoader()); | 
 | 3816 |   ThrowWrappedLinkageError(klass.Get(), | 
 | 3817 |                            "While checking class %s method %s signature against %s %s: " | 
 | 3818 |                            "Failed to resolve arg %u type %s with %s", | 
 | 3819 |                            PrettyDescriptor(klass.Get()).c_str(), | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 3820 |                            PrettyMethod(method).c_str(), | 
| Vladimir Marko | d5e5a0e | 2015-05-08 12:26:59 +0100 | [diff] [blame] | 3821 |                            super_klass->IsInterface() ? "interface" : "superclass", | 
 | 3822 |                            PrettyDescriptor(super_klass.Get()).c_str(), | 
 | 3823 |                            index, arg_type.c_str(), class_loader.c_str()); | 
 | 3824 | } | 
 | 3825 |  | 
 | 3826 | static void ThrowSignatureMismatch(Handle<mirror::Class> klass, | 
 | 3827 |                                    Handle<mirror::Class> super_klass, | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 3828 |                                    ArtMethod* method, | 
| Vladimir Marko | d5e5a0e | 2015-05-08 12:26:59 +0100 | [diff] [blame] | 3829 |                                    const std::string& error_msg) | 
| Mathieu Chartier | 9044347 | 2015-07-16 20:32:27 -0700 | [diff] [blame] | 3830 |     SHARED_REQUIRES(Locks::mutator_lock_) { | 
| Vladimir Marko | d5e5a0e | 2015-05-08 12:26:59 +0100 | [diff] [blame] | 3831 |   ThrowLinkageError(klass.Get(), | 
 | 3832 |                     "Class %s method %s resolves differently in %s %s: %s", | 
 | 3833 |                     PrettyDescriptor(klass.Get()).c_str(), | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 3834 |                     PrettyMethod(method).c_str(), | 
| Vladimir Marko | d5e5a0e | 2015-05-08 12:26:59 +0100 | [diff] [blame] | 3835 |                     super_klass->IsInterface() ? "interface" : "superclass", | 
 | 3836 |                     PrettyDescriptor(super_klass.Get()).c_str(), | 
 | 3837 |                     error_msg.c_str()); | 
 | 3838 | } | 
 | 3839 |  | 
| Ian Rogers | b5fb207 | 2014-12-02 17:22:02 -0800 | [diff] [blame] | 3840 | static bool HasSameSignatureWithDifferentClassLoaders(Thread* self, | 
| Vladimir Marko | d5e5a0e | 2015-05-08 12:26:59 +0100 | [diff] [blame] | 3841 |                                                       Handle<mirror::Class> klass, | 
 | 3842 |                                                       Handle<mirror::Class> super_klass, | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 3843 |                                                       ArtMethod* method1, | 
 | 3844 |                                                       ArtMethod* method2) | 
| Mathieu Chartier | 9044347 | 2015-07-16 20:32:27 -0700 | [diff] [blame] | 3845 |     SHARED_REQUIRES(Locks::mutator_lock_) { | 
| Ian Rogers | b5fb207 | 2014-12-02 17:22:02 -0800 | [diff] [blame] | 3846 |   { | 
 | 3847 |     StackHandleScope<1> hs(self); | 
 | 3848 |     Handle<mirror::Class> return_type(hs.NewHandle(method1->GetReturnType())); | 
| Vladimir Marko | d5e5a0e | 2015-05-08 12:26:59 +0100 | [diff] [blame] | 3849 |     if (UNLIKELY(return_type.Get() == nullptr)) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 3850 |       ThrowSignatureCheckResolveReturnTypeException(klass, super_klass, method1, method1); | 
| Vladimir Marko | d5e5a0e | 2015-05-08 12:26:59 +0100 | [diff] [blame] | 3851 |       return false; | 
 | 3852 |     } | 
| Vladimir Marko | 862f43c | 2015-02-10 18:22:57 +0000 | [diff] [blame] | 3853 |     mirror::Class* other_return_type = method2->GetReturnType(); | 
| Vladimir Marko | d5e5a0e | 2015-05-08 12:26:59 +0100 | [diff] [blame] | 3854 |     if (UNLIKELY(other_return_type == nullptr)) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 3855 |       ThrowSignatureCheckResolveReturnTypeException(klass, super_klass, method1, method2); | 
| Vladimir Marko | d5e5a0e | 2015-05-08 12:26:59 +0100 | [diff] [blame] | 3856 |       return false; | 
 | 3857 |     } | 
| Vladimir Marko | 862f43c | 2015-02-10 18:22:57 +0000 | [diff] [blame] | 3858 |     if (UNLIKELY(other_return_type != return_type.Get())) { | 
| Vladimir Marko | d5e5a0e | 2015-05-08 12:26:59 +0100 | [diff] [blame] | 3859 |       ThrowSignatureMismatch(klass, super_klass, method1, | 
 | 3860 |                              StringPrintf("Return types mismatch: %s(%p) vs %s(%p)", | 
 | 3861 |                                           PrettyClassAndClassLoader(return_type.Get()).c_str(), | 
 | 3862 |                                           return_type.Get(), | 
 | 3863 |                                           PrettyClassAndClassLoader(other_return_type).c_str(), | 
 | 3864 |                                           other_return_type)); | 
| Ian Rogers | b5fb207 | 2014-12-02 17:22:02 -0800 | [diff] [blame] | 3865 |       return false; | 
 | 3866 |     } | 
 | 3867 |   } | 
 | 3868 |   const DexFile::TypeList* types1 = method1->GetParameterTypeList(); | 
 | 3869 |   const DexFile::TypeList* types2 = method2->GetParameterTypeList(); | 
 | 3870 |   if (types1 == nullptr) { | 
| Andreas Gampe | d8ca52e | 2015-02-13 15:23:18 -0800 | [diff] [blame] | 3871 |     if (types2 != nullptr && types2->Size() != 0) { | 
| Vladimir Marko | d5e5a0e | 2015-05-08 12:26:59 +0100 | [diff] [blame] | 3872 |       ThrowSignatureMismatch(klass, super_klass, method1, | 
 | 3873 |                              StringPrintf("Type list mismatch with %s", | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 3874 |                                           PrettyMethod(method2, true).c_str())); | 
| Andreas Gampe | d8ca52e | 2015-02-13 15:23:18 -0800 | [diff] [blame] | 3875 |       return false; | 
 | 3876 |     } | 
 | 3877 |     return true; | 
| Ian Rogers | b5fb207 | 2014-12-02 17:22:02 -0800 | [diff] [blame] | 3878 |   } else if (UNLIKELY(types2 == nullptr)) { | 
| Andreas Gampe | d8ca52e | 2015-02-13 15:23:18 -0800 | [diff] [blame] | 3879 |     if (types1->Size() != 0) { | 
| Vladimir Marko | d5e5a0e | 2015-05-08 12:26:59 +0100 | [diff] [blame] | 3880 |       ThrowSignatureMismatch(klass, super_klass, method1, | 
 | 3881 |                              StringPrintf("Type list mismatch with %s", | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 3882 |                                           PrettyMethod(method2, true).c_str())); | 
| Andreas Gampe | d8ca52e | 2015-02-13 15:23:18 -0800 | [diff] [blame] | 3883 |       return false; | 
 | 3884 |     } | 
 | 3885 |     return true; | 
| Ian Rogers | b5fb207 | 2014-12-02 17:22:02 -0800 | [diff] [blame] | 3886 |   } | 
 | 3887 |   uint32_t num_types = types1->Size(); | 
 | 3888 |   if (UNLIKELY(num_types != types2->Size())) { | 
| Vladimir Marko | d5e5a0e | 2015-05-08 12:26:59 +0100 | [diff] [blame] | 3889 |     ThrowSignatureMismatch(klass, super_klass, method1, | 
 | 3890 |                            StringPrintf("Type list mismatch with %s", | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 3891 |                                         PrettyMethod(method2, true).c_str())); | 
| Ian Rogers | b5fb207 | 2014-12-02 17:22:02 -0800 | [diff] [blame] | 3892 |     return false; | 
 | 3893 |   } | 
 | 3894 |   for (uint32_t i = 0; i < num_types; ++i) { | 
| Vladimir Marko | 862f43c | 2015-02-10 18:22:57 +0000 | [diff] [blame] | 3895 |     StackHandleScope<1> hs(self); | 
| Vladimir Marko | d5e5a0e | 2015-05-08 12:26:59 +0100 | [diff] [blame] | 3896 |     uint32_t param_type_idx = types1->GetTypeItem(i).type_idx_; | 
| Vladimir Marko | 862f43c | 2015-02-10 18:22:57 +0000 | [diff] [blame] | 3897 |     Handle<mirror::Class> param_type(hs.NewHandle( | 
| Vladimir Marko | d5e5a0e | 2015-05-08 12:26:59 +0100 | [diff] [blame] | 3898 |         method1->GetClassFromTypeIndex(param_type_idx, true))); | 
 | 3899 |     if (UNLIKELY(param_type.Get() == nullptr)) { | 
 | 3900 |       ThrowSignatureCheckResolveArgException(klass, super_klass, method1, | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 3901 |                                              method1, i, param_type_idx); | 
| Vladimir Marko | d5e5a0e | 2015-05-08 12:26:59 +0100 | [diff] [blame] | 3902 |       return false; | 
 | 3903 |     } | 
 | 3904 |     uint32_t other_param_type_idx = types2->GetTypeItem(i).type_idx_; | 
| Ian Rogers | b5fb207 | 2014-12-02 17:22:02 -0800 | [diff] [blame] | 3905 |     mirror::Class* other_param_type = | 
| Vladimir Marko | d5e5a0e | 2015-05-08 12:26:59 +0100 | [diff] [blame] | 3906 |         method2->GetClassFromTypeIndex(other_param_type_idx, true); | 
 | 3907 |     if (UNLIKELY(other_param_type == nullptr)) { | 
 | 3908 |       ThrowSignatureCheckResolveArgException(klass, super_klass, method1, | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 3909 |                                              method2, i, other_param_type_idx); | 
| Vladimir Marko | d5e5a0e | 2015-05-08 12:26:59 +0100 | [diff] [blame] | 3910 |       return false; | 
 | 3911 |     } | 
| Vladimir Marko | 862f43c | 2015-02-10 18:22:57 +0000 | [diff] [blame] | 3912 |     if (UNLIKELY(param_type.Get() != other_param_type)) { | 
| Vladimir Marko | d5e5a0e | 2015-05-08 12:26:59 +0100 | [diff] [blame] | 3913 |       ThrowSignatureMismatch(klass, super_klass, method1, | 
 | 3914 |                              StringPrintf("Parameter %u type mismatch: %s(%p) vs %s(%p)", | 
 | 3915 |                                           i, | 
 | 3916 |                                           PrettyClassAndClassLoader(param_type.Get()).c_str(), | 
 | 3917 |                                           param_type.Get(), | 
 | 3918 |                                           PrettyClassAndClassLoader(other_param_type).c_str(), | 
 | 3919 |                                           other_param_type)); | 
| Ian Rogers | b5fb207 | 2014-12-02 17:22:02 -0800 | [diff] [blame] | 3920 |       return false; | 
 | 3921 |     } | 
 | 3922 |   } | 
 | 3923 |   return true; | 
 | 3924 | } | 
 | 3925 |  | 
 | 3926 |  | 
| Andreas Gampe | 5a4b8a2 | 2014-09-11 08:30:08 -0700 | [diff] [blame] | 3927 | bool ClassLinker::ValidateSuperClassDescriptors(Handle<mirror::Class> klass) { | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 3928 |   if (klass->IsInterface()) { | 
 | 3929 |     return true; | 
 | 3930 |   } | 
| Ian Rogers | 151f221 | 2014-05-06 11:27:27 -0700 | [diff] [blame] | 3931 |   // Begin with the methods local to the superclass. | 
| Ian Rogers | ded66a0 | 2014-10-28 18:12:55 -0700 | [diff] [blame] | 3932 |   Thread* self = Thread::Current(); | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 3933 |   StackHandleScope<1> hs(self); | 
| Vladimir Marko | d5e5a0e | 2015-05-08 12:26:59 +0100 | [diff] [blame] | 3934 |   MutableHandle<mirror::Class> super_klass(hs.NewHandle<mirror::Class>(nullptr)); | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 3935 |   if (klass->HasSuperClass() && | 
 | 3936 |       klass->GetClassLoader() != klass->GetSuperClass()->GetClassLoader()) { | 
| Vladimir Marko | d5e5a0e | 2015-05-08 12:26:59 +0100 | [diff] [blame] | 3937 |     super_klass.Assign(klass->GetSuperClass()); | 
| Mingyao Yang | 2cdbad7 | 2014-07-16 10:44:41 -0700 | [diff] [blame] | 3938 |     for (int i = klass->GetSuperClass()->GetVTableLength() - 1; i >= 0; --i) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 3939 |       auto* m = klass->GetVTableEntry(i, image_pointer_size_); | 
 | 3940 |       auto* super_m = klass->GetSuperClass()->GetVTableEntry(i, image_pointer_size_); | 
 | 3941 |       if (m != super_m) { | 
| Vladimir Marko | d5e5a0e | 2015-05-08 12:26:59 +0100 | [diff] [blame] | 3942 |         if (UNLIKELY(!HasSameSignatureWithDifferentClassLoaders(self, klass, super_klass, | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 3943 |                                                                 m, super_m))) { | 
| Vladimir Marko | d5e5a0e | 2015-05-08 12:26:59 +0100 | [diff] [blame] | 3944 |           self->AssertPendingException(); | 
| Andreas Gampe | d8ca52e | 2015-02-13 15:23:18 -0800 | [diff] [blame] | 3945 |           return false; | 
 | 3946 |         } | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 3947 |       } | 
 | 3948 |     } | 
 | 3949 |   } | 
| Brian Carlstrom | 4b620ff | 2011-09-11 01:11:01 -0700 | [diff] [blame] | 3950 |   for (int32_t i = 0; i < klass->GetIfTableCount(); ++i) { | 
| Vladimir Marko | d5e5a0e | 2015-05-08 12:26:59 +0100 | [diff] [blame] | 3951 |     super_klass.Assign(klass->GetIfTable()->GetInterface(i)); | 
 | 3952 |     if (klass->GetClassLoader() != super_klass->GetClassLoader()) { | 
 | 3953 |       uint32_t num_methods = super_klass->NumVirtualMethods(); | 
| Ian Rogers | 151f221 | 2014-05-06 11:27:27 -0700 | [diff] [blame] | 3954 |       for (uint32_t j = 0; j < num_methods; ++j) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 3955 |         auto* m = klass->GetIfTable()->GetMethodArray(i)->GetElementPtrSize<ArtMethod*>( | 
 | 3956 |             j, image_pointer_size_); | 
 | 3957 |         auto* super_m = super_klass->GetVirtualMethod(j, image_pointer_size_); | 
 | 3958 |         if (m != super_m) { | 
| Vladimir Marko | d5e5a0e | 2015-05-08 12:26:59 +0100 | [diff] [blame] | 3959 |           if (UNLIKELY(!HasSameSignatureWithDifferentClassLoaders(self, klass, super_klass, | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 3960 |                                                                   m, super_m))) { | 
| Vladimir Marko | d5e5a0e | 2015-05-08 12:26:59 +0100 | [diff] [blame] | 3961 |             self->AssertPendingException(); | 
| Andreas Gampe | d8ca52e | 2015-02-13 15:23:18 -0800 | [diff] [blame] | 3962 |             return false; | 
 | 3963 |           } | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 3964 |         } | 
 | 3965 |       } | 
 | 3966 |     } | 
 | 3967 |   } | 
 | 3968 |   return true; | 
 | 3969 | } | 
 | 3970 |  | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 3971 | bool ClassLinker::EnsureInitialized(Thread* self, Handle<mirror::Class> c, bool can_init_fields, | 
| Andreas Gampe | 5a4b8a2 | 2014-09-11 08:30:08 -0700 | [diff] [blame] | 3972 |                                     bool can_init_parents) { | 
| Mathieu Chartier | 0cd8135 | 2014-05-22 16:48:55 -0700 | [diff] [blame] | 3973 |   DCHECK(c.Get() != nullptr); | 
| Mathieu Chartier | 524507a | 2014-08-27 15:28:28 -0700 | [diff] [blame] | 3974 |   if (c->IsInitialized()) { | 
| Andreas Gampe | 4849859 | 2014-09-10 19:48:05 -0700 | [diff] [blame] | 3975 |     EnsurePreverifiedMethods(c); | 
| Mathieu Chartier | 524507a | 2014-08-27 15:28:28 -0700 | [diff] [blame] | 3976 |     return true; | 
 | 3977 |   } | 
| Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 3978 |   const bool success = InitializeClass(self, c, can_init_fields, can_init_parents); | 
| Mathieu Chartier | 524507a | 2014-08-27 15:28:28 -0700 | [diff] [blame] | 3979 |   if (!success) { | 
 | 3980 |     if (can_init_fields && can_init_parents) { | 
 | 3981 |       CHECK(self->IsExceptionPending()) << PrettyClass(c.Get()); | 
 | 3982 |     } | 
 | 3983 |   } else { | 
 | 3984 |     self->AssertNoPendingException(); | 
| Ian Rogers | 595799e | 2012-01-11 17:32:51 -0800 | [diff] [blame] | 3985 |   } | 
 | 3986 |   return success; | 
| Elliott Hughes | f4c21c9 | 2011-08-19 17:31:31 -0700 | [diff] [blame] | 3987 | } | 
 | 3988 |  | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 3989 | void ClassLinker::FixupTemporaryDeclaringClass(mirror::Class* temp_class, | 
 | 3990 |                                                mirror::Class* new_class) { | 
| Mathieu Chartier | eb837eb | 2015-07-29 17:25:41 -0700 | [diff] [blame] | 3991 |   DCHECK_EQ(temp_class->NumInstanceFields(), 0u); | 
| Mathieu Chartier | 54d220e | 2015-07-30 16:20:06 -0700 | [diff] [blame] | 3992 |   for (ArtField& field : new_class->GetIFields()) { | 
 | 3993 |     if (field.GetDeclaringClass() == temp_class) { | 
 | 3994 |       field.SetDeclaringClass(new_class); | 
| Mingyao Yang | 98d1cc8 | 2014-05-15 17:02:16 -0700 | [diff] [blame] | 3995 |     } | 
 | 3996 |   } | 
 | 3997 |  | 
| Mathieu Chartier | eb837eb | 2015-07-29 17:25:41 -0700 | [diff] [blame] | 3998 |   DCHECK_EQ(temp_class->NumStaticFields(), 0u); | 
| Mathieu Chartier | 54d220e | 2015-07-30 16:20:06 -0700 | [diff] [blame] | 3999 |   for (ArtField& field : new_class->GetSFields()) { | 
 | 4000 |     if (field.GetDeclaringClass() == temp_class) { | 
 | 4001 |       field.SetDeclaringClass(new_class); | 
| Mingyao Yang | 98d1cc8 | 2014-05-15 17:02:16 -0700 | [diff] [blame] | 4002 |     } | 
 | 4003 |   } | 
 | 4004 |  | 
| Mathieu Chartier | eb837eb | 2015-07-29 17:25:41 -0700 | [diff] [blame] | 4005 |   DCHECK_EQ(temp_class->NumDirectMethods(), 0u); | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4006 |   for (auto& method : new_class->GetDirectMethods(image_pointer_size_)) { | 
 | 4007 |     if (method.GetDeclaringClass() == temp_class) { | 
 | 4008 |       method.SetDeclaringClass(new_class); | 
| Mingyao Yang | 98d1cc8 | 2014-05-15 17:02:16 -0700 | [diff] [blame] | 4009 |     } | 
 | 4010 |   } | 
 | 4011 |  | 
| Mathieu Chartier | eb837eb | 2015-07-29 17:25:41 -0700 | [diff] [blame] | 4012 |   DCHECK_EQ(temp_class->NumVirtualMethods(), 0u); | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4013 |   for (auto& method : new_class->GetVirtualMethods(image_pointer_size_)) { | 
 | 4014 |     if (method.GetDeclaringClass() == temp_class) { | 
 | 4015 |       method.SetDeclaringClass(new_class); | 
| Mingyao Yang | 98d1cc8 | 2014-05-15 17:02:16 -0700 | [diff] [blame] | 4016 |     } | 
 | 4017 |   } | 
| Mathieu Chartier | eb837eb | 2015-07-29 17:25:41 -0700 | [diff] [blame] | 4018 |  | 
 | 4019 |   // Make sure the remembered set and mod-union tables know that we updated some of the native | 
 | 4020 |   // roots. | 
 | 4021 |   Runtime::Current()->GetHeap()->WriteBarrierEveryFieldOf(new_class); | 
| Mingyao Yang | 98d1cc8 | 2014-05-15 17:02:16 -0700 | [diff] [blame] | 4022 | } | 
 | 4023 |  | 
| Mathieu Chartier | cc5ebdf | 2015-07-27 11:19:43 -0700 | [diff] [blame] | 4024 | ClassTable* ClassLinker::InsertClassTableForClassLoader(mirror::ClassLoader* class_loader) { | 
| Mathieu Chartier | 6b06953 | 2015-08-05 15:08:12 -0700 | [diff] [blame] | 4025 |   if (class_loader == nullptr) { | 
 | 4026 |     return &boot_class_table_; | 
| Mathieu Chartier | cc5ebdf | 2015-07-27 11:19:43 -0700 | [diff] [blame] | 4027 |   } | 
| Mathieu Chartier | 6b06953 | 2015-08-05 15:08:12 -0700 | [diff] [blame] | 4028 |   ClassTable* class_table = class_loader->GetClassTable(); | 
 | 4029 |   if (class_table == nullptr) { | 
 | 4030 |     class_table = new ClassTable; | 
 | 4031 |     class_loaders_.push_back(class_loader); | 
 | 4032 |     // Don't already have a class table, add it to the class loader. | 
 | 4033 |     class_loader->SetClassTable(class_table); | 
 | 4034 |   } | 
| Mathieu Chartier | cc5ebdf | 2015-07-27 11:19:43 -0700 | [diff] [blame] | 4035 |   return class_table; | 
 | 4036 | } | 
 | 4037 |  | 
 | 4038 | ClassTable* ClassLinker::ClassTableForClassLoader(mirror::ClassLoader* class_loader) { | 
| Mathieu Chartier | 6b06953 | 2015-08-05 15:08:12 -0700 | [diff] [blame] | 4039 |   return class_loader == nullptr ? &boot_class_table_ : class_loader->GetClassTable(); | 
| Mathieu Chartier | cc5ebdf | 2015-07-27 11:19:43 -0700 | [diff] [blame] | 4040 | } | 
 | 4041 |  | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 4042 | bool ClassLinker::LinkClass(Thread* self, const char* descriptor, Handle<mirror::Class> klass, | 
| Andreas Gampe | 5a4b8a2 | 2014-09-11 08:30:08 -0700 | [diff] [blame] | 4043 |                             Handle<mirror::ObjectArray<mirror::Class>> interfaces, | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 4044 |                             MutableHandle<mirror::Class>* h_new_class_out) { | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 4045 |   CHECK_EQ(mirror::Class::kStatusLoaded, klass->GetStatus()); | 
| Mingyao Yang | 98d1cc8 | 2014-05-15 17:02:16 -0700 | [diff] [blame] | 4046 |  | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 4047 |   if (!LinkSuperClass(klass)) { | 
 | 4048 |     return false; | 
 | 4049 |   } | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4050 |   ArtMethod* imt[mirror::Class::kImtSize]; | 
 | 4051 |   std::fill_n(imt, arraysize(imt), Runtime::Current()->GetImtUnimplementedMethod()); | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 4052 |   if (!LinkMethods(self, klass, interfaces, imt)) { | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 4053 |     return false; | 
 | 4054 |   } | 
| Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 4055 |   if (!LinkInstanceFields(self, klass)) { | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 4056 |     return false; | 
 | 4057 |   } | 
| Mingyao Yang | 98d1cc8 | 2014-05-15 17:02:16 -0700 | [diff] [blame] | 4058 |   size_t class_size; | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 4059 |   if (!LinkStaticFields(self, klass, &class_size)) { | 
| Brian Carlstrom | 4873d46 | 2011-08-21 15:23:39 -0700 | [diff] [blame] | 4060 |     return false; | 
 | 4061 |   } | 
 | 4062 |   CreateReferenceInstanceOffsets(klass); | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 4063 |   CHECK_EQ(mirror::Class::kStatusLoaded, klass->GetStatus()); | 
| Mingyao Yang | 98d1cc8 | 2014-05-15 17:02:16 -0700 | [diff] [blame] | 4064 |  | 
 | 4065 |   if (!klass->IsTemp() || (!init_done_ && klass->GetClassSize() == class_size)) { | 
 | 4066 |     // We don't need to retire this class as it has no embedded tables or it was created the | 
 | 4067 |     // correct size during class linker initialization. | 
 | 4068 |     CHECK_EQ(klass->GetClassSize(), class_size) << PrettyDescriptor(klass.Get()); | 
 | 4069 |  | 
 | 4070 |     if (klass->ShouldHaveEmbeddedImtAndVTable()) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4071 |       klass->PopulateEmbeddedImtAndVTable(imt, image_pointer_size_); | 
| Mingyao Yang | 98d1cc8 | 2014-05-15 17:02:16 -0700 | [diff] [blame] | 4072 |     } | 
 | 4073 |  | 
 | 4074 |     // This will notify waiters on klass that saw the not yet resolved | 
 | 4075 |     // class in the class_table_ during EnsureResolved. | 
| Hiroshi Yamauchi | 5b783e6 | 2015-03-18 17:20:11 -0700 | [diff] [blame] | 4076 |     mirror::Class::SetStatus(klass, mirror::Class::kStatusResolved, self); | 
| Hiroshi Yamauchi | 679b1cf | 2015-05-21 12:05:27 -0700 | [diff] [blame] | 4077 |     h_new_class_out->Assign(klass.Get()); | 
| Mingyao Yang | 98d1cc8 | 2014-05-15 17:02:16 -0700 | [diff] [blame] | 4078 |   } else { | 
 | 4079 |     CHECK(!klass->IsResolved()); | 
 | 4080 |     // Retire the temporary class and create the correctly sized resolved class. | 
| Hiroshi Yamauchi | 679b1cf | 2015-05-21 12:05:27 -0700 | [diff] [blame] | 4081 |     StackHandleScope<1> hs(self); | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4082 |     auto h_new_class = hs.NewHandle(klass->CopyOf(self, class_size, imt, image_pointer_size_)); | 
| Mathieu Chartier | 3ee25bb | 2015-08-10 10:13:02 -0700 | [diff] [blame] | 4083 |     // Set arrays to null since we don't want to have multiple classes with the same ArtField or | 
 | 4084 |     // ArtMethod array pointers. If this occurs, it causes bugs in remembered sets since the GC | 
 | 4085 |     // may not see any references to the target space and clean the card for a class if another | 
 | 4086 |     // class had the same array pointer. | 
| Mathieu Chartier | 54d220e | 2015-07-30 16:20:06 -0700 | [diff] [blame] | 4087 |     klass->SetDirectMethodsPtrUnchecked(nullptr); | 
 | 4088 |     klass->SetVirtualMethodsPtr(nullptr); | 
 | 4089 |     klass->SetSFieldsPtrUnchecked(nullptr); | 
 | 4090 |     klass->SetIFieldsPtrUnchecked(nullptr); | 
| Hiroshi Yamauchi | 679b1cf | 2015-05-21 12:05:27 -0700 | [diff] [blame] | 4091 |     if (UNLIKELY(h_new_class.Get() == nullptr)) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4092 |       self->AssertPendingOOMException(); | 
| Hiroshi Yamauchi | 5b783e6 | 2015-03-18 17:20:11 -0700 | [diff] [blame] | 4093 |       mirror::Class::SetStatus(klass, mirror::Class::kStatusError, self); | 
| Mingyao Yang | 98d1cc8 | 2014-05-15 17:02:16 -0700 | [diff] [blame] | 4094 |       return false; | 
 | 4095 |     } | 
 | 4096 |  | 
| Hiroshi Yamauchi | 679b1cf | 2015-05-21 12:05:27 -0700 | [diff] [blame] | 4097 |     CHECK_EQ(h_new_class->GetClassSize(), class_size); | 
 | 4098 |     ObjectLock<mirror::Class> lock(self, h_new_class); | 
 | 4099 |     FixupTemporaryDeclaringClass(klass.Get(), h_new_class.Get()); | 
| Mathieu Chartier | cc5ebdf | 2015-07-27 11:19:43 -0700 | [diff] [blame] | 4100 |  | 
 | 4101 |     { | 
| Mathieu Chartier | eb837eb | 2015-07-29 17:25:41 -0700 | [diff] [blame] | 4102 |       WriterMutexLock mu(self, *Locks::classlinker_classes_lock_); | 
| Mathieu Chartier | cc5ebdf | 2015-07-27 11:19:43 -0700 | [diff] [blame] | 4103 |       mirror::ClassLoader* const class_loader = h_new_class.Get()->GetClassLoader(); | 
 | 4104 |       ClassTable* const table = InsertClassTableForClassLoader(class_loader); | 
 | 4105 |       mirror::Class* existing = table->UpdateClass(descriptor, h_new_class.Get(), | 
 | 4106 |                                                    ComputeModifiedUtf8Hash(descriptor)); | 
 | 4107 |       CHECK_EQ(existing, klass.Get()); | 
 | 4108 |       if (kIsDebugBuild && class_loader == nullptr && dex_cache_image_class_lookup_required_) { | 
 | 4109 |         // Check a class loaded with the system class loader matches one in the image if the class | 
 | 4110 |         // is in the image. | 
 | 4111 |         mirror::Class* const image_class = LookupClassFromImage(descriptor); | 
 | 4112 |         if (image_class != nullptr) { | 
 | 4113 |           CHECK_EQ(klass.Get(), existing) << descriptor; | 
 | 4114 |         } | 
 | 4115 |       } | 
 | 4116 |       if (log_new_class_table_roots_) { | 
 | 4117 |         new_class_roots_.push_back(GcRoot<mirror::Class>(h_new_class.Get())); | 
 | 4118 |       } | 
 | 4119 |     } | 
| Mingyao Yang | 98d1cc8 | 2014-05-15 17:02:16 -0700 | [diff] [blame] | 4120 |  | 
 | 4121 |     // This will notify waiters on temp class that saw the not yet resolved class in the | 
 | 4122 |     // class_table_ during EnsureResolved. | 
| Hiroshi Yamauchi | 5b783e6 | 2015-03-18 17:20:11 -0700 | [diff] [blame] | 4123 |     mirror::Class::SetStatus(klass, mirror::Class::kStatusRetired, self); | 
| Mingyao Yang | 98d1cc8 | 2014-05-15 17:02:16 -0700 | [diff] [blame] | 4124 |  | 
| Hiroshi Yamauchi | 679b1cf | 2015-05-21 12:05:27 -0700 | [diff] [blame] | 4125 |     CHECK_EQ(h_new_class->GetStatus(), mirror::Class::kStatusResolving); | 
| Mingyao Yang | 98d1cc8 | 2014-05-15 17:02:16 -0700 | [diff] [blame] | 4126 |     // This will notify waiters on new_class that saw the not yet resolved | 
 | 4127 |     // class in the class_table_ during EnsureResolved. | 
| Hiroshi Yamauchi | 679b1cf | 2015-05-21 12:05:27 -0700 | [diff] [blame] | 4128 |     mirror::Class::SetStatus(h_new_class, mirror::Class::kStatusResolved, self); | 
 | 4129 |     // Return the new class. | 
 | 4130 |     h_new_class_out->Assign(h_new_class.Get()); | 
| Mingyao Yang | 98d1cc8 | 2014-05-15 17:02:16 -0700 | [diff] [blame] | 4131 |   } | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 4132 |   return true; | 
 | 4133 | } | 
 | 4134 |  | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 4135 | static void CountMethodsAndFields(ClassDataItemIterator& dex_data, | 
 | 4136 |                                   size_t* virtual_methods, | 
 | 4137 |                                   size_t* direct_methods, | 
 | 4138 |                                   size_t* static_fields, | 
 | 4139 |                                   size_t* instance_fields) { | 
| Andreas Gampe | fd9eb39 | 2014-11-06 16:52:58 -0800 | [diff] [blame] | 4140 |   *virtual_methods = *direct_methods = *static_fields = *instance_fields = 0; | 
 | 4141 |  | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 4142 |   while (dex_data.HasNextStaticField()) { | 
 | 4143 |     dex_data.Next(); | 
| Andreas Gampe | fd9eb39 | 2014-11-06 16:52:58 -0800 | [diff] [blame] | 4144 |     (*static_fields)++; | 
 | 4145 |   } | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 4146 |   while (dex_data.HasNextInstanceField()) { | 
 | 4147 |     dex_data.Next(); | 
| Andreas Gampe | fd9eb39 | 2014-11-06 16:52:58 -0800 | [diff] [blame] | 4148 |     (*instance_fields)++; | 
 | 4149 |   } | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 4150 |   while (dex_data.HasNextDirectMethod()) { | 
| Andreas Gampe | fd9eb39 | 2014-11-06 16:52:58 -0800 | [diff] [blame] | 4151 |     (*direct_methods)++; | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 4152 |     dex_data.Next(); | 
| Andreas Gampe | fd9eb39 | 2014-11-06 16:52:58 -0800 | [diff] [blame] | 4153 |   } | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 4154 |   while (dex_data.HasNextVirtualMethod()) { | 
| Andreas Gampe | fd9eb39 | 2014-11-06 16:52:58 -0800 | [diff] [blame] | 4155 |     (*virtual_methods)++; | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 4156 |     dex_data.Next(); | 
| Andreas Gampe | fd9eb39 | 2014-11-06 16:52:58 -0800 | [diff] [blame] | 4157 |   } | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 4158 |   DCHECK(!dex_data.HasNext()); | 
| Andreas Gampe | fd9eb39 | 2014-11-06 16:52:58 -0800 | [diff] [blame] | 4159 | } | 
 | 4160 |  | 
 | 4161 | static void DumpClass(std::ostream& os, | 
 | 4162 |                       const DexFile& dex_file, const DexFile::ClassDef& dex_class_def, | 
 | 4163 |                       const char* suffix) { | 
 | 4164 |   ClassDataItemIterator dex_data(dex_file, dex_file.GetClassData(dex_class_def)); | 
 | 4165 |   os << dex_file.GetClassDescriptor(dex_class_def) << suffix << ":\n"; | 
 | 4166 |   os << " Static fields:\n"; | 
 | 4167 |   while (dex_data.HasNextStaticField()) { | 
 | 4168 |     const DexFile::FieldId& id = dex_file.GetFieldId(dex_data.GetMemberIndex()); | 
 | 4169 |     os << "  " << dex_file.GetFieldTypeDescriptor(id) << " " << dex_file.GetFieldName(id) << "\n"; | 
 | 4170 |     dex_data.Next(); | 
 | 4171 |   } | 
 | 4172 |   os << " Instance fields:\n"; | 
 | 4173 |   while (dex_data.HasNextInstanceField()) { | 
 | 4174 |     const DexFile::FieldId& id = dex_file.GetFieldId(dex_data.GetMemberIndex()); | 
 | 4175 |     os << "  " << dex_file.GetFieldTypeDescriptor(id) << " " << dex_file.GetFieldName(id) << "\n"; | 
 | 4176 |     dex_data.Next(); | 
 | 4177 |   } | 
 | 4178 |   os << " Direct methods:\n"; | 
 | 4179 |   while (dex_data.HasNextDirectMethod()) { | 
 | 4180 |     const DexFile::MethodId& id = dex_file.GetMethodId(dex_data.GetMemberIndex()); | 
 | 4181 |     os << "  " << dex_file.GetMethodName(id) << dex_file.GetMethodSignature(id).ToString() << "\n"; | 
 | 4182 |     dex_data.Next(); | 
 | 4183 |   } | 
 | 4184 |   os << " Virtual methods:\n"; | 
 | 4185 |   while (dex_data.HasNextVirtualMethod()) { | 
 | 4186 |     const DexFile::MethodId& id = dex_file.GetMethodId(dex_data.GetMemberIndex()); | 
 | 4187 |     os << "  " << dex_file.GetMethodName(id) << dex_file.GetMethodSignature(id).ToString() << "\n"; | 
 | 4188 |     dex_data.Next(); | 
 | 4189 |   } | 
 | 4190 | } | 
 | 4191 |  | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 4192 | static std::string DumpClasses(const DexFile& dex_file1, const DexFile::ClassDef& dex_class_def1, | 
 | 4193 |                                const DexFile& dex_file2, const DexFile::ClassDef& dex_class_def2) { | 
| Andreas Gampe | fd9eb39 | 2014-11-06 16:52:58 -0800 | [diff] [blame] | 4194 |   std::ostringstream os; | 
 | 4195 |   DumpClass(os, dex_file1, dex_class_def1, " (Compile time)"); | 
 | 4196 |   DumpClass(os, dex_file2, dex_class_def2, " (Runtime)"); | 
 | 4197 |   return os.str(); | 
 | 4198 | } | 
 | 4199 |  | 
 | 4200 |  | 
 | 4201 | // Very simple structural check on whether the classes match. Only compares the number of | 
 | 4202 | // methods and fields. | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 4203 | static bool SimpleStructuralCheck(const DexFile& dex_file1, const DexFile::ClassDef& dex_class_def1, | 
 | 4204 |                                   const DexFile& dex_file2, const DexFile::ClassDef& dex_class_def2, | 
| Andreas Gampe | fd9eb39 | 2014-11-06 16:52:58 -0800 | [diff] [blame] | 4205 |                                   std::string* error_msg) { | 
 | 4206 |   ClassDataItemIterator dex_data1(dex_file1, dex_file1.GetClassData(dex_class_def1)); | 
 | 4207 |   ClassDataItemIterator dex_data2(dex_file2, dex_file2.GetClassData(dex_class_def2)); | 
 | 4208 |  | 
 | 4209 |   // Counters for current dex file. | 
 | 4210 |   size_t dex_virtual_methods1, dex_direct_methods1, dex_static_fields1, dex_instance_fields1; | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 4211 |   CountMethodsAndFields(dex_data1, &dex_virtual_methods1, &dex_direct_methods1, &dex_static_fields1, | 
 | 4212 |                         &dex_instance_fields1); | 
| Andreas Gampe | fd9eb39 | 2014-11-06 16:52:58 -0800 | [diff] [blame] | 4213 |   // Counters for compile-time dex file. | 
 | 4214 |   size_t dex_virtual_methods2, dex_direct_methods2, dex_static_fields2, dex_instance_fields2; | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 4215 |   CountMethodsAndFields(dex_data2, &dex_virtual_methods2, &dex_direct_methods2, &dex_static_fields2, | 
 | 4216 |                         &dex_instance_fields2); | 
| Andreas Gampe | fd9eb39 | 2014-11-06 16:52:58 -0800 | [diff] [blame] | 4217 |  | 
 | 4218 |   if (dex_virtual_methods1 != dex_virtual_methods2) { | 
 | 4219 |     std::string class_dump = DumpClasses(dex_file1, dex_class_def1, dex_file2, dex_class_def2); | 
 | 4220 |     *error_msg = StringPrintf("Virtual method count off: %zu vs %zu\n%s", dex_virtual_methods1, | 
 | 4221 |                               dex_virtual_methods2, class_dump.c_str()); | 
 | 4222 |     return false; | 
 | 4223 |   } | 
 | 4224 |   if (dex_direct_methods1 != dex_direct_methods2) { | 
 | 4225 |     std::string class_dump = DumpClasses(dex_file1, dex_class_def1, dex_file2, dex_class_def2); | 
 | 4226 |     *error_msg = StringPrintf("Direct method count off: %zu vs %zu\n%s", dex_direct_methods1, | 
 | 4227 |                               dex_direct_methods2, class_dump.c_str()); | 
 | 4228 |     return false; | 
 | 4229 |   } | 
 | 4230 |   if (dex_static_fields1 != dex_static_fields2) { | 
 | 4231 |     std::string class_dump = DumpClasses(dex_file1, dex_class_def1, dex_file2, dex_class_def2); | 
 | 4232 |     *error_msg = StringPrintf("Static field count off: %zu vs %zu\n%s", dex_static_fields1, | 
 | 4233 |                               dex_static_fields2, class_dump.c_str()); | 
 | 4234 |     return false; | 
 | 4235 |   } | 
 | 4236 |   if (dex_instance_fields1 != dex_instance_fields2) { | 
 | 4237 |     std::string class_dump = DumpClasses(dex_file1, dex_class_def1, dex_file2, dex_class_def2); | 
 | 4238 |     *error_msg = StringPrintf("Instance field count off: %zu vs %zu\n%s", dex_instance_fields1, | 
 | 4239 |                               dex_instance_fields2, class_dump.c_str()); | 
 | 4240 |     return false; | 
 | 4241 |   } | 
 | 4242 |  | 
 | 4243 |   return true; | 
 | 4244 | } | 
 | 4245 |  | 
 | 4246 | // Checks whether a the super-class changed from what we had at compile-time. This would | 
 | 4247 | // invalidate quickening. | 
 | 4248 | static bool CheckSuperClassChange(Handle<mirror::Class> klass, | 
 | 4249 |                                   const DexFile& dex_file, | 
 | 4250 |                                   const DexFile::ClassDef& class_def, | 
 | 4251 |                                   mirror::Class* super_class) | 
| Mathieu Chartier | 9044347 | 2015-07-16 20:32:27 -0700 | [diff] [blame] | 4252 |     SHARED_REQUIRES(Locks::mutator_lock_) { | 
| Andreas Gampe | fd9eb39 | 2014-11-06 16:52:58 -0800 | [diff] [blame] | 4253 |   // Check for unexpected changes in the superclass. | 
 | 4254 |   // Quick check 1) is the super_class class-loader the boot class loader? This always has | 
 | 4255 |   // precedence. | 
 | 4256 |   if (super_class->GetClassLoader() != nullptr && | 
 | 4257 |       // Quick check 2) different dex cache? Breaks can only occur for different dex files, | 
 | 4258 |       // which is implied by different dex cache. | 
 | 4259 |       klass->GetDexCache() != super_class->GetDexCache()) { | 
 | 4260 |     // Now comes the expensive part: things can be broken if (a) the klass' dex file has a | 
 | 4261 |     // definition for the super-class, and (b) the files are in separate oat files. The oat files | 
 | 4262 |     // are referenced from the dex file, so do (b) first. Only relevant if we have oat files. | 
| Richard Uhler | 07b3c23 | 2015-03-31 15:57:54 -0700 | [diff] [blame] | 4263 |     const OatDexFile* class_oat_dex_file = dex_file.GetOatDexFile(); | 
 | 4264 |     const OatFile* class_oat_file = nullptr; | 
 | 4265 |     if (class_oat_dex_file != nullptr) { | 
 | 4266 |       class_oat_file = class_oat_dex_file->GetOatFile(); | 
 | 4267 |     } | 
 | 4268 |  | 
| Andreas Gampe | fd9eb39 | 2014-11-06 16:52:58 -0800 | [diff] [blame] | 4269 |     if (class_oat_file != nullptr) { | 
| Richard Uhler | 07b3c23 | 2015-03-31 15:57:54 -0700 | [diff] [blame] | 4270 |       const OatDexFile* loaded_super_oat_dex_file = super_class->GetDexFile().GetOatDexFile(); | 
 | 4271 |       const OatFile* loaded_super_oat_file = nullptr; | 
 | 4272 |       if (loaded_super_oat_dex_file != nullptr) { | 
 | 4273 |         loaded_super_oat_file = loaded_super_oat_dex_file->GetOatFile(); | 
 | 4274 |       } | 
 | 4275 |  | 
| Andreas Gampe | fd9eb39 | 2014-11-06 16:52:58 -0800 | [diff] [blame] | 4276 |       if (loaded_super_oat_file != nullptr && class_oat_file != loaded_super_oat_file) { | 
 | 4277 |         // Now check (a). | 
 | 4278 |         const DexFile::ClassDef* super_class_def = dex_file.FindClassDef(class_def.superclass_idx_); | 
 | 4279 |         if (super_class_def != nullptr) { | 
 | 4280 |           // Uh-oh, we found something. Do our check. | 
 | 4281 |           std::string error_msg; | 
 | 4282 |           if (!SimpleStructuralCheck(dex_file, *super_class_def, | 
 | 4283 |                                      super_class->GetDexFile(), *super_class->GetClassDef(), | 
 | 4284 |                                      &error_msg)) { | 
 | 4285 |             // Print a warning to the log. This exception might be caught, e.g., as common in test | 
 | 4286 |             // drivers. When the class is later tried to be used, we re-throw a new instance, as we | 
 | 4287 |             // only save the type of the exception. | 
 | 4288 |             LOG(WARNING) << "Incompatible structural change detected: " << | 
 | 4289 |                 StringPrintf( | 
 | 4290 |                     "Structural change of %s is hazardous (%s at compile time, %s at runtime): %s", | 
 | 4291 |                     PrettyType(super_class_def->class_idx_, dex_file).c_str(), | 
 | 4292 |                     class_oat_file->GetLocation().c_str(), | 
 | 4293 |                     loaded_super_oat_file->GetLocation().c_str(), | 
 | 4294 |                     error_msg.c_str()); | 
 | 4295 |             ThrowIncompatibleClassChangeError(klass.Get(), | 
 | 4296 |                 "Structural change of %s is hazardous (%s at compile time, %s at runtime): %s", | 
 | 4297 |                 PrettyType(super_class_def->class_idx_, dex_file).c_str(), | 
 | 4298 |                 class_oat_file->GetLocation().c_str(), | 
 | 4299 |                 loaded_super_oat_file->GetLocation().c_str(), | 
 | 4300 |                 error_msg.c_str()); | 
 | 4301 |             return false; | 
 | 4302 |           } | 
 | 4303 |         } | 
 | 4304 |       } | 
 | 4305 |     } | 
 | 4306 |   } | 
 | 4307 |   return true; | 
 | 4308 | } | 
 | 4309 |  | 
| Andreas Gampe | 5a4b8a2 | 2014-09-11 08:30:08 -0700 | [diff] [blame] | 4310 | bool ClassLinker::LoadSuperAndInterfaces(Handle<mirror::Class> klass, const DexFile& dex_file) { | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 4311 |   CHECK_EQ(mirror::Class::kStatusIdx, klass->GetStatus()); | 
| Ian Rogers | 8b2c0b9 | 2013-09-19 02:56:49 -0700 | [diff] [blame] | 4312 |   const DexFile::ClassDef& class_def = dex_file.GetClassDef(klass->GetDexClassDefIndex()); | 
 | 4313 |   uint16_t super_class_idx = class_def.superclass_idx_; | 
| Ian Rogers | 6d4d9fc | 2011-11-30 16:24:48 -0800 | [diff] [blame] | 4314 |   if (super_class_idx != DexFile::kDexNoIndex16) { | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 4315 |     mirror::Class* super_class = ResolveType(dex_file, super_class_idx, klass.Get()); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 4316 |     if (super_class == nullptr) { | 
| Brian Carlstrom | 65ca077 | 2011-09-24 16:03:08 -0700 | [diff] [blame] | 4317 |       DCHECK(Thread::Current()->IsExceptionPending()); | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 4318 |       return false; | 
 | 4319 |     } | 
| Ian Rogers | be125a9 | 2012-01-11 15:19:49 -0800 | [diff] [blame] | 4320 |     // Verify | 
 | 4321 |     if (!klass->CanAccess(super_class)) { | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 4322 |       ThrowIllegalAccessError(klass.Get(), "Class %s extended by class %s is inaccessible", | 
| Ian Rogers | 62d6c77 | 2013-02-27 08:32:07 -0800 | [diff] [blame] | 4323 |                               PrettyDescriptor(super_class).c_str(), | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 4324 |                               PrettyDescriptor(klass.Get()).c_str()); | 
| Ian Rogers | be125a9 | 2012-01-11 15:19:49 -0800 | [diff] [blame] | 4325 |       return false; | 
 | 4326 |     } | 
| Mingyao Yang | 98d1cc8 | 2014-05-15 17:02:16 -0700 | [diff] [blame] | 4327 |     CHECK(super_class->IsResolved()); | 
| Ian Rogers | 0cfe1fb | 2011-08-26 03:29:44 -0700 | [diff] [blame] | 4328 |     klass->SetSuperClass(super_class); | 
| Andreas Gampe | fd9eb39 | 2014-11-06 16:52:58 -0800 | [diff] [blame] | 4329 |  | 
 | 4330 |     if (!CheckSuperClassChange(klass, dex_file, class_def, super_class)) { | 
 | 4331 |       DCHECK(Thread::Current()->IsExceptionPending()); | 
 | 4332 |       return false; | 
 | 4333 |     } | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 4334 |   } | 
| Ian Rogers | 8b2c0b9 | 2013-09-19 02:56:49 -0700 | [diff] [blame] | 4335 |   const DexFile::TypeList* interfaces = dex_file.GetInterfacesList(class_def); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 4336 |   if (interfaces != nullptr) { | 
| Ian Rogers | 6d4d9fc | 2011-11-30 16:24:48 -0800 | [diff] [blame] | 4337 |     for (size_t i = 0; i < interfaces->Size(); i++) { | 
 | 4338 |       uint16_t idx = interfaces->GetTypeItem(i).type_idx_; | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 4339 |       mirror::Class* interface = ResolveType(dex_file, idx, klass.Get()); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 4340 |       if (interface == nullptr) { | 
| Ian Rogers | 6d4d9fc | 2011-11-30 16:24:48 -0800 | [diff] [blame] | 4341 |         DCHECK(Thread::Current()->IsExceptionPending()); | 
 | 4342 |         return false; | 
 | 4343 |       } | 
 | 4344 |       // Verify | 
 | 4345 |       if (!klass->CanAccess(interface)) { | 
 | 4346 |         // TODO: the RI seemed to ignore this in my testing. | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 4347 |         ThrowIllegalAccessError(klass.Get(), "Interface %s implemented by class %s is inaccessible", | 
| Ian Rogers | 62d6c77 | 2013-02-27 08:32:07 -0800 | [diff] [blame] | 4348 |                                 PrettyDescriptor(interface).c_str(), | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 4349 |                                 PrettyDescriptor(klass.Get()).c_str()); | 
| Ian Rogers | 6d4d9fc | 2011-11-30 16:24:48 -0800 | [diff] [blame] | 4350 |         return false; | 
 | 4351 |       } | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 4352 |     } | 
 | 4353 |   } | 
| Brian Carlstrom | 74eb46a | 2011-08-02 20:10:14 -0700 | [diff] [blame] | 4354 |   // Mark the class as loaded. | 
| Hiroshi Yamauchi | 5b783e6 | 2015-03-18 17:20:11 -0700 | [diff] [blame] | 4355 |   mirror::Class::SetStatus(klass, mirror::Class::kStatusLoaded, nullptr); | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 4356 |   return true; | 
 | 4357 | } | 
 | 4358 |  | 
| Andreas Gampe | 5a4b8a2 | 2014-09-11 08:30:08 -0700 | [diff] [blame] | 4359 | bool ClassLinker::LinkSuperClass(Handle<mirror::Class> klass) { | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 4360 |   CHECK(!klass->IsPrimitive()); | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 4361 |   mirror::Class* super = klass->GetSuperClass(); | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 4362 |   if (klass.Get() == GetClassRoot(kJavaLangObject)) { | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 4363 |     if (super != nullptr) { | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 4364 |       ThrowClassFormatError(klass.Get(), "java.lang.Object must not have a superclass"); | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 4365 |       return false; | 
 | 4366 |     } | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 4367 |     return true; | 
 | 4368 |   } | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 4369 |   if (super == nullptr) { | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 4370 |     ThrowLinkageError(klass.Get(), "No superclass defined for class %s", | 
 | 4371 |                       PrettyDescriptor(klass.Get()).c_str()); | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 4372 |     return false; | 
 | 4373 |   } | 
 | 4374 |   // Verify | 
| Elliott Hughes | 4a2b417 | 2011-09-20 17:08:25 -0700 | [diff] [blame] | 4375 |   if (super->IsFinal() || super->IsInterface()) { | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 4376 |     ThrowIncompatibleClassChangeError(klass.Get(), "Superclass %s of %s is %s", | 
| Ian Rogers | 62d6c77 | 2013-02-27 08:32:07 -0800 | [diff] [blame] | 4377 |                                       PrettyDescriptor(super).c_str(), | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 4378 |                                       PrettyDescriptor(klass.Get()).c_str(), | 
| Ian Rogers | 62d6c77 | 2013-02-27 08:32:07 -0800 | [diff] [blame] | 4379 |                                       super->IsFinal() ? "declared final" : "an interface"); | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 4380 |     return false; | 
 | 4381 |   } | 
 | 4382 |   if (!klass->CanAccess(super)) { | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 4383 |     ThrowIllegalAccessError(klass.Get(), "Superclass %s is inaccessible to class %s", | 
| Ian Rogers | 62d6c77 | 2013-02-27 08:32:07 -0800 | [diff] [blame] | 4384 |                             PrettyDescriptor(super).c_str(), | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 4385 |                             PrettyDescriptor(klass.Get()).c_str()); | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 4386 |     return false; | 
 | 4387 |   } | 
| Elliott Hughes | 20cde90 | 2011-10-04 17:37:27 -0700 | [diff] [blame] | 4388 |  | 
| Brian Carlstrom | f363283 | 2014-05-20 15:36:53 -0700 | [diff] [blame] | 4389 |   // Inherit kAccClassIsFinalizable from the superclass in case this | 
 | 4390 |   // class doesn't override finalize. | 
| Elliott Hughes | 20cde90 | 2011-10-04 17:37:27 -0700 | [diff] [blame] | 4391 |   if (super->IsFinalizable()) { | 
 | 4392 |     klass->SetFinalizable(); | 
 | 4393 |   } | 
 | 4394 |  | 
| Mathieu Chartier | e4275c0 | 2015-08-06 15:34:15 -0700 | [diff] [blame] | 4395 |   // Inherit class loader flag form super class. | 
 | 4396 |   if (super->IsClassLoaderClass()) { | 
 | 4397 |     klass->SetClassLoaderClass(); | 
 | 4398 |   } | 
 | 4399 |  | 
| Elliott Hughes | 2da5036 | 2011-10-10 16:57:08 -0700 | [diff] [blame] | 4400 |   // Inherit reference flags (if any) from the superclass. | 
| Mathieu Chartier | 66c2d2d | 2015-08-25 14:32:32 -0700 | [diff] [blame] | 4401 |   uint32_t reference_flags = (super->GetClassFlags() & mirror::kClassFlagReference); | 
| Elliott Hughes | 2da5036 | 2011-10-10 16:57:08 -0700 | [diff] [blame] | 4402 |   if (reference_flags != 0) { | 
| Mathieu Chartier | 66c2d2d | 2015-08-25 14:32:32 -0700 | [diff] [blame] | 4403 |     CHECK_EQ(klass->GetClassFlags(), 0u); | 
| Mathieu Chartier | 52a7f5c | 2015-08-18 18:35:52 -0700 | [diff] [blame] | 4404 |     klass->SetClassFlags(klass->GetClassFlags() | reference_flags); | 
| Elliott Hughes | 2da5036 | 2011-10-10 16:57:08 -0700 | [diff] [blame] | 4405 |   } | 
| Elliott Hughes | 72ee0ae | 2011-10-10 17:31:28 -0700 | [diff] [blame] | 4406 |   // Disallow custom direct subclasses of java.lang.ref.Reference. | 
| Elliott Hughes | bf61ba3 | 2011-10-11 10:53:09 -0700 | [diff] [blame] | 4407 |   if (init_done_ && super == GetClassRoot(kJavaLangRefReference)) { | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 4408 |     ThrowLinkageError(klass.Get(), | 
| Ian Rogers | 62d6c77 | 2013-02-27 08:32:07 -0800 | [diff] [blame] | 4409 |                       "Class %s attempts to subclass java.lang.ref.Reference, which is not allowed", | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 4410 |                       PrettyDescriptor(klass.Get()).c_str()); | 
| Elliott Hughes | 72ee0ae | 2011-10-10 17:31:28 -0700 | [diff] [blame] | 4411 |     return false; | 
 | 4412 |   } | 
| Elliott Hughes | 2da5036 | 2011-10-10 16:57:08 -0700 | [diff] [blame] | 4413 |  | 
| Ian Rogers | 7dfb28c | 2013-08-22 08:18:36 -0700 | [diff] [blame] | 4414 |   if (kIsDebugBuild) { | 
 | 4415 |     // Ensure super classes are fully resolved prior to resolving fields.. | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 4416 |     while (super != nullptr) { | 
| Ian Rogers | 7dfb28c | 2013-08-22 08:18:36 -0700 | [diff] [blame] | 4417 |       CHECK(super->IsResolved()); | 
 | 4418 |       super = super->GetSuperClass(); | 
 | 4419 |     } | 
| Ian Rogers | 0cfe1fb | 2011-08-26 03:29:44 -0700 | [diff] [blame] | 4420 |   } | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 4421 |   return true; | 
 | 4422 | } | 
 | 4423 |  | 
| Ian Rogers | 0cfe1fb | 2011-08-26 03:29:44 -0700 | [diff] [blame] | 4424 | // Populate the class vtable and itable. Compute return type indices. | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 4425 | bool ClassLinker::LinkMethods(Thread* self, Handle<mirror::Class> klass, | 
| Mathieu Chartier | 2d2621a | 2014-10-23 16:48:06 -0700 | [diff] [blame] | 4426 |                               Handle<mirror::ObjectArray<mirror::Class>> interfaces, | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 4427 |                               ArtMethod** out_imt) { | 
| Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 4428 |   self->AllowThreadSuspension(); | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 4429 |   if (klass->IsInterface()) { | 
 | 4430 |     // No vtable. | 
 | 4431 |     size_t count = klass->NumVirtualMethods(); | 
| Andreas Gampe | ab1eb0d | 2015-02-13 19:23:55 -0800 | [diff] [blame] | 4432 |     if (!IsUint<16>(count)) { | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 4433 |       ThrowClassFormatError(klass.Get(), "Too many methods on interface: %zd", count); | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 4434 |       return false; | 
 | 4435 |     } | 
| Carl Shapiro | 565f507 | 2011-07-10 13:39:43 -0700 | [diff] [blame] | 4436 |     for (size_t i = 0; i < count; ++i) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4437 |       klass->GetVirtualMethodDuringLinking(i, image_pointer_size_)->SetMethodIndex(i); | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 4438 |     } | 
| Mathieu Chartier | 2d2621a | 2014-10-23 16:48:06 -0700 | [diff] [blame] | 4439 |   } else if (!LinkVirtualMethods(self, klass)) {  // Link virtual methods first. | 
 | 4440 |     return false; | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 4441 |   } | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 4442 |   return LinkInterfaceMethods(self, klass, interfaces, out_imt);  // Link interface method last. | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 4443 | } | 
 | 4444 |  | 
| Ian Rogers | 03b6eaf | 2014-10-28 09:34:57 -0700 | [diff] [blame] | 4445 | // Comparator for name and signature of a method, used in finding overriding methods. Implementation | 
 | 4446 | // avoids the use of handles, if it didn't then rather than compare dex files we could compare dex | 
 | 4447 | // caches in the implementation below. | 
 | 4448 | class MethodNameAndSignatureComparator FINAL : public ValueObject { | 
 | 4449 |  public: | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4450 |   explicit MethodNameAndSignatureComparator(ArtMethod* method) | 
| Mathieu Chartier | 9044347 | 2015-07-16 20:32:27 -0700 | [diff] [blame] | 4451 |       SHARED_REQUIRES(Locks::mutator_lock_) : | 
| Ian Rogers | 03b6eaf | 2014-10-28 09:34:57 -0700 | [diff] [blame] | 4452 |       dex_file_(method->GetDexFile()), mid_(&dex_file_->GetMethodId(method->GetDexMethodIndex())), | 
 | 4453 |       name_(nullptr), name_len_(0) { | 
| Mathieu Chartier | 9f3629d | 2014-10-28 18:23:02 -0700 | [diff] [blame] | 4454 |     DCHECK(!method->IsProxyMethod()) << PrettyMethod(method); | 
 | 4455 |   } | 
 | 4456 |  | 
 | 4457 |   const char* GetName() { | 
 | 4458 |     if (name_ == nullptr) { | 
 | 4459 |       name_ = dex_file_->StringDataAndUtf16LengthByIdx(mid_->name_idx_, &name_len_); | 
 | 4460 |     } | 
 | 4461 |     return name_; | 
| Ian Rogers | 03b6eaf | 2014-10-28 09:34:57 -0700 | [diff] [blame] | 4462 |   } | 
 | 4463 |  | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4464 |   bool HasSameNameAndSignature(ArtMethod* other) | 
| Mathieu Chartier | 9044347 | 2015-07-16 20:32:27 -0700 | [diff] [blame] | 4465 |       SHARED_REQUIRES(Locks::mutator_lock_) { | 
| Ian Rogers | 03b6eaf | 2014-10-28 09:34:57 -0700 | [diff] [blame] | 4466 |     DCHECK(!other->IsProxyMethod()) << PrettyMethod(other); | 
 | 4467 |     const DexFile* other_dex_file = other->GetDexFile(); | 
 | 4468 |     const DexFile::MethodId& other_mid = other_dex_file->GetMethodId(other->GetDexMethodIndex()); | 
 | 4469 |     if (dex_file_ == other_dex_file) { | 
 | 4470 |       return mid_->name_idx_ == other_mid.name_idx_ && mid_->proto_idx_ == other_mid.proto_idx_; | 
 | 4471 |     } | 
| Mathieu Chartier | 9f3629d | 2014-10-28 18:23:02 -0700 | [diff] [blame] | 4472 |     GetName();  // Only used to make sure its calculated. | 
| Ian Rogers | 03b6eaf | 2014-10-28 09:34:57 -0700 | [diff] [blame] | 4473 |     uint32_t other_name_len; | 
 | 4474 |     const char* other_name = other_dex_file->StringDataAndUtf16LengthByIdx(other_mid.name_idx_, | 
 | 4475 |                                                                            &other_name_len); | 
 | 4476 |     if (name_len_ != other_name_len || strcmp(name_, other_name) != 0) { | 
 | 4477 |       return false; | 
 | 4478 |     } | 
 | 4479 |     return dex_file_->GetMethodSignature(*mid_) == other_dex_file->GetMethodSignature(other_mid); | 
 | 4480 |   } | 
 | 4481 |  | 
 | 4482 |  private: | 
 | 4483 |   // Dex file for the method to compare against. | 
 | 4484 |   const DexFile* const dex_file_; | 
 | 4485 |   // MethodId for the method to compare against. | 
 | 4486 |   const DexFile::MethodId* const mid_; | 
 | 4487 |   // Lazily computed name from the dex file's strings. | 
 | 4488 |   const char* name_; | 
 | 4489 |   // Lazily computed name length. | 
 | 4490 |   uint32_t name_len_; | 
 | 4491 | }; | 
 | 4492 |  | 
| Mathieu Chartier | 9f3629d | 2014-10-28 18:23:02 -0700 | [diff] [blame] | 4493 | class LinkVirtualHashTable { | 
 | 4494 |  public: | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 4495 |   LinkVirtualHashTable(Handle<mirror::Class> klass, size_t hash_size, uint32_t* hash_table, | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4496 |                        size_t image_pointer_size) | 
 | 4497 |      : klass_(klass), hash_size_(hash_size), hash_table_(hash_table), | 
 | 4498 |        image_pointer_size_(image_pointer_size) { | 
| Mathieu Chartier | 9f3629d | 2014-10-28 18:23:02 -0700 | [diff] [blame] | 4499 |     std::fill(hash_table_, hash_table_ + hash_size_, invalid_index_); | 
 | 4500 |   } | 
| Mathieu Chartier | 9044347 | 2015-07-16 20:32:27 -0700 | [diff] [blame] | 4501 |   void Add(uint32_t virtual_method_index) SHARED_REQUIRES(Locks::mutator_lock_) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4502 |     ArtMethod* local_method = klass_->GetVirtualMethodDuringLinking( | 
 | 4503 |         virtual_method_index, image_pointer_size_); | 
 | 4504 |     const char* name = local_method->GetInterfaceMethodIfProxy(image_pointer_size_)->GetName(); | 
| Mathieu Chartier | e7c9a8c | 2014-11-06 16:35:45 -0800 | [diff] [blame] | 4505 |     uint32_t hash = ComputeModifiedUtf8Hash(name); | 
| Mathieu Chartier | 9f3629d | 2014-10-28 18:23:02 -0700 | [diff] [blame] | 4506 |     uint32_t index = hash % hash_size_; | 
 | 4507 |     // Linear probe until we have an empty slot. | 
 | 4508 |     while (hash_table_[index] != invalid_index_) { | 
 | 4509 |       if (++index == hash_size_) { | 
 | 4510 |         index = 0; | 
 | 4511 |       } | 
 | 4512 |     } | 
 | 4513 |     hash_table_[index] = virtual_method_index; | 
 | 4514 |   } | 
 | 4515 |   uint32_t FindAndRemove(MethodNameAndSignatureComparator* comparator) | 
| Mathieu Chartier | 9044347 | 2015-07-16 20:32:27 -0700 | [diff] [blame] | 4516 |       SHARED_REQUIRES(Locks::mutator_lock_) { | 
| Mathieu Chartier | 9f3629d | 2014-10-28 18:23:02 -0700 | [diff] [blame] | 4517 |     const char* name = comparator->GetName(); | 
| Mathieu Chartier | e7c9a8c | 2014-11-06 16:35:45 -0800 | [diff] [blame] | 4518 |     uint32_t hash = ComputeModifiedUtf8Hash(name); | 
| Mathieu Chartier | 9f3629d | 2014-10-28 18:23:02 -0700 | [diff] [blame] | 4519 |     size_t index = hash % hash_size_; | 
 | 4520 |     while (true) { | 
 | 4521 |       const uint32_t value = hash_table_[index]; | 
 | 4522 |       // Since linear probe makes continuous blocks, hitting an invalid index means we are done | 
 | 4523 |       // the block and can safely assume not found. | 
 | 4524 |       if (value == invalid_index_) { | 
 | 4525 |         break; | 
 | 4526 |       } | 
 | 4527 |       if (value != removed_index_) {  // This signifies not already overriden. | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4528 |         ArtMethod* virtual_method = | 
 | 4529 |             klass_->GetVirtualMethodDuringLinking(value, image_pointer_size_); | 
 | 4530 |         if (comparator->HasSameNameAndSignature( | 
 | 4531 |             virtual_method->GetInterfaceMethodIfProxy(image_pointer_size_))) { | 
| Mathieu Chartier | 9f3629d | 2014-10-28 18:23:02 -0700 | [diff] [blame] | 4532 |           hash_table_[index] = removed_index_; | 
 | 4533 |           return value; | 
 | 4534 |         } | 
 | 4535 |       } | 
 | 4536 |       if (++index == hash_size_) { | 
 | 4537 |         index = 0; | 
 | 4538 |       } | 
 | 4539 |     } | 
 | 4540 |     return GetNotFoundIndex(); | 
 | 4541 |   } | 
 | 4542 |   static uint32_t GetNotFoundIndex() { | 
 | 4543 |     return invalid_index_; | 
 | 4544 |   } | 
 | 4545 |  | 
 | 4546 |  private: | 
 | 4547 |   static const uint32_t invalid_index_; | 
 | 4548 |   static const uint32_t removed_index_; | 
 | 4549 |  | 
 | 4550 |   Handle<mirror::Class> klass_; | 
 | 4551 |   const size_t hash_size_; | 
 | 4552 |   uint32_t* const hash_table_; | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4553 |   const size_t image_pointer_size_; | 
| Mathieu Chartier | 9f3629d | 2014-10-28 18:23:02 -0700 | [diff] [blame] | 4554 | }; | 
 | 4555 |  | 
 | 4556 | const uint32_t LinkVirtualHashTable::invalid_index_ = std::numeric_limits<uint32_t>::max(); | 
 | 4557 | const uint32_t LinkVirtualHashTable::removed_index_ = std::numeric_limits<uint32_t>::max() - 1; | 
 | 4558 |  | 
| Andreas Gampe | 5a4b8a2 | 2014-09-11 08:30:08 -0700 | [diff] [blame] | 4559 | bool ClassLinker::LinkVirtualMethods(Thread* self, Handle<mirror::Class> klass) { | 
| Mathieu Chartier | 2d2621a | 2014-10-23 16:48:06 -0700 | [diff] [blame] | 4560 |   const size_t num_virtual_methods = klass->NumVirtualMethods(); | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 4561 |   if (klass->HasSuperClass()) { | 
| Mathieu Chartier | 2d2621a | 2014-10-23 16:48:06 -0700 | [diff] [blame] | 4562 |     const size_t super_vtable_length = klass->GetSuperClass()->GetVTableLength(); | 
 | 4563 |     const size_t max_count = num_virtual_methods + super_vtable_length; | 
| Mathieu Chartier | 2d2621a | 2014-10-23 16:48:06 -0700 | [diff] [blame] | 4564 |     StackHandleScope<2> hs(self); | 
| Mingyao Yang | 38eecb0 | 2014-08-13 14:51:03 -0700 | [diff] [blame] | 4565 |     Handle<mirror::Class> super_class(hs.NewHandle(klass->GetSuperClass())); | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4566 |     MutableHandle<mirror::PointerArray> vtable; | 
| Mingyao Yang | 2cdbad7 | 2014-07-16 10:44:41 -0700 | [diff] [blame] | 4567 |     if (super_class->ShouldHaveEmbeddedImtAndVTable()) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4568 |       vtable = hs.NewHandle(AllocPointerArray(self, max_count)); | 
| Mingyao Yang | 2cdbad7 | 2014-07-16 10:44:41 -0700 | [diff] [blame] | 4569 |       if (UNLIKELY(vtable.Get() == nullptr)) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4570 |         self->AssertPendingOOMException(); | 
| Mingyao Yang | 2cdbad7 | 2014-07-16 10:44:41 -0700 | [diff] [blame] | 4571 |         return false; | 
 | 4572 |       } | 
| Mathieu Chartier | 2d2621a | 2014-10-23 16:48:06 -0700 | [diff] [blame] | 4573 |       for (size_t i = 0; i < super_vtable_length; i++) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4574 |         vtable->SetElementPtrSize( | 
 | 4575 |             i, super_class->GetEmbeddedVTableEntry(i, image_pointer_size_), image_pointer_size_); | 
| Mingyao Yang | 2cdbad7 | 2014-07-16 10:44:41 -0700 | [diff] [blame] | 4576 |       } | 
| Mathieu Chartier | 9f3629d | 2014-10-28 18:23:02 -0700 | [diff] [blame] | 4577 |       if (num_virtual_methods == 0) { | 
 | 4578 |         klass->SetVTable(vtable.Get()); | 
 | 4579 |         return true; | 
 | 4580 |       } | 
| Mingyao Yang | 2cdbad7 | 2014-07-16 10:44:41 -0700 | [diff] [blame] | 4581 |     } else { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4582 |       auto* super_vtable = super_class->GetVTable(); | 
| Mathieu Chartier | 9f3629d | 2014-10-28 18:23:02 -0700 | [diff] [blame] | 4583 |       CHECK(super_vtable != nullptr) << PrettyClass(super_class.Get()); | 
 | 4584 |       if (num_virtual_methods == 0) { | 
 | 4585 |         klass->SetVTable(super_vtable); | 
 | 4586 |         return true; | 
 | 4587 |       } | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4588 |       vtable = hs.NewHandle(down_cast<mirror::PointerArray*>( | 
 | 4589 |           super_vtable->CopyOf(self, max_count))); | 
| Mingyao Yang | 2cdbad7 | 2014-07-16 10:44:41 -0700 | [diff] [blame] | 4590 |       if (UNLIKELY(vtable.Get() == nullptr)) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4591 |         self->AssertPendingOOMException(); | 
| Mingyao Yang | 2cdbad7 | 2014-07-16 10:44:41 -0700 | [diff] [blame] | 4592 |         return false; | 
 | 4593 |       } | 
| Ian Rogers | a436fde | 2013-08-27 23:34:06 -0700 | [diff] [blame] | 4594 |     } | 
| Mathieu Chartier | 9f3629d | 2014-10-28 18:23:02 -0700 | [diff] [blame] | 4595 |     // How the algorithm works: | 
 | 4596 |     // 1. Populate hash table by adding num_virtual_methods from klass. The values in the hash | 
 | 4597 |     // table are: invalid_index for unused slots, index super_vtable_length + i for a virtual | 
 | 4598 |     // method which has not been matched to a vtable method, and j if the virtual method at the | 
 | 4599 |     // index overrode the super virtual method at index j. | 
 | 4600 |     // 2. Loop through super virtual methods, if they overwrite, update hash table to j | 
 | 4601 |     // (j < super_vtable_length) to avoid redundant checks. (TODO maybe use this info for reducing | 
 | 4602 |     // the need for the initial vtable which we later shrink back down). | 
 | 4603 |     // 3. Add non overridden methods to the end of the vtable. | 
 | 4604 |     static constexpr size_t kMaxStackHash = 250; | 
 | 4605 |     const size_t hash_table_size = num_virtual_methods * 3; | 
 | 4606 |     uint32_t* hash_table_ptr; | 
 | 4607 |     std::unique_ptr<uint32_t[]> hash_heap_storage; | 
 | 4608 |     if (hash_table_size <= kMaxStackHash) { | 
 | 4609 |       hash_table_ptr = reinterpret_cast<uint32_t*>( | 
 | 4610 |           alloca(hash_table_size * sizeof(*hash_table_ptr))); | 
 | 4611 |     } else { | 
 | 4612 |       hash_heap_storage.reset(new uint32_t[hash_table_size]); | 
 | 4613 |       hash_table_ptr = hash_heap_storage.get(); | 
 | 4614 |     } | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4615 |     LinkVirtualHashTable hash_table(klass, hash_table_size, hash_table_ptr, image_pointer_size_); | 
| Mathieu Chartier | 9f3629d | 2014-10-28 18:23:02 -0700 | [diff] [blame] | 4616 |     // Add virtual methods to the hash table. | 
| Mathieu Chartier | 2d2621a | 2014-10-23 16:48:06 -0700 | [diff] [blame] | 4617 |     for (size_t i = 0; i < num_virtual_methods; ++i) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4618 |       DCHECK(klass->GetVirtualMethodDuringLinking( | 
 | 4619 |           i, image_pointer_size_)->GetDeclaringClass() != nullptr); | 
| Mathieu Chartier | 9f3629d | 2014-10-28 18:23:02 -0700 | [diff] [blame] | 4620 |       hash_table.Add(i); | 
 | 4621 |     } | 
 | 4622 |     // Loop through each super vtable method and see if they are overriden by a method we added to | 
 | 4623 |     // the hash table. | 
 | 4624 |     for (size_t j = 0; j < super_vtable_length; ++j) { | 
 | 4625 |       // Search the hash table to see if we are overidden by any method. | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4626 |       ArtMethod* super_method = vtable->GetElementPtrSize<ArtMethod*>(j, image_pointer_size_); | 
| Mathieu Chartier | 9f3629d | 2014-10-28 18:23:02 -0700 | [diff] [blame] | 4627 |       MethodNameAndSignatureComparator super_method_name_comparator( | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4628 |           super_method->GetInterfaceMethodIfProxy(image_pointer_size_)); | 
| Mathieu Chartier | 9f3629d | 2014-10-28 18:23:02 -0700 | [diff] [blame] | 4629 |       uint32_t hash_index = hash_table.FindAndRemove(&super_method_name_comparator); | 
 | 4630 |       if (hash_index != hash_table.GetNotFoundIndex()) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4631 |         ArtMethod* virtual_method = klass->GetVirtualMethodDuringLinking( | 
 | 4632 |             hash_index, image_pointer_size_); | 
| Mathieu Chartier | 9f3629d | 2014-10-28 18:23:02 -0700 | [diff] [blame] | 4633 |         if (klass->CanAccessMember(super_method->GetDeclaringClass(), | 
 | 4634 |                                    super_method->GetAccessFlags())) { | 
 | 4635 |           if (super_method->IsFinal()) { | 
 | 4636 |             ThrowLinkageError(klass.Get(), "Method %s overrides final method in class %s", | 
 | 4637 |                               PrettyMethod(virtual_method).c_str(), | 
 | 4638 |                               super_method->GetDeclaringClassDescriptor()); | 
 | 4639 |             return false; | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 4640 |           } | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4641 |           vtable->SetElementPtrSize(j, virtual_method, image_pointer_size_); | 
| Mathieu Chartier | 9f3629d | 2014-10-28 18:23:02 -0700 | [diff] [blame] | 4642 |           virtual_method->SetMethodIndex(j); | 
 | 4643 |         } else { | 
 | 4644 |           LOG(WARNING) << "Before Android 4.1, method " << PrettyMethod(virtual_method) | 
| Mathieu Chartier | 2d2621a | 2014-10-23 16:48:06 -0700 | [diff] [blame] | 4645 |                        << " would have incorrectly overridden the package-private method in " | 
 | 4646 |                        << PrettyDescriptor(super_method->GetDeclaringClassDescriptor()); | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 4647 |         } | 
 | 4648 |       } | 
| Mathieu Chartier | 9f3629d | 2014-10-28 18:23:02 -0700 | [diff] [blame] | 4649 |     } | 
 | 4650 |     // Add the non overridden methods at the end. | 
 | 4651 |     size_t actual_count = super_vtable_length; | 
 | 4652 |     for (size_t i = 0; i < num_virtual_methods; ++i) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4653 |       ArtMethod* local_method = klass->GetVirtualMethodDuringLinking(i, image_pointer_size_); | 
| Mathieu Chartier | 9f3629d | 2014-10-28 18:23:02 -0700 | [diff] [blame] | 4654 |       size_t method_idx = local_method->GetMethodIndexDuringLinking(); | 
 | 4655 |       if (method_idx < super_vtable_length && | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4656 |           local_method == vtable->GetElementPtrSize<ArtMethod*>(method_idx, image_pointer_size_)) { | 
| Mathieu Chartier | 9f3629d | 2014-10-28 18:23:02 -0700 | [diff] [blame] | 4657 |         continue; | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 4658 |       } | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4659 |       vtable->SetElementPtrSize(actual_count, local_method, image_pointer_size_); | 
| Mathieu Chartier | 9f3629d | 2014-10-28 18:23:02 -0700 | [diff] [blame] | 4660 |       local_method->SetMethodIndex(actual_count); | 
 | 4661 |       ++actual_count; | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 4662 |     } | 
| Andreas Gampe | ab1eb0d | 2015-02-13 19:23:55 -0800 | [diff] [blame] | 4663 |     if (!IsUint<16>(actual_count)) { | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 4664 |       ThrowClassFormatError(klass.Get(), "Too many methods defined on class: %zd", actual_count); | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 4665 |       return false; | 
 | 4666 |     } | 
| Ian Rogers | 0cfe1fb | 2011-08-26 03:29:44 -0700 | [diff] [blame] | 4667 |     // Shrink vtable if possible | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 4668 |     CHECK_LE(actual_count, max_count); | 
 | 4669 |     if (actual_count < max_count) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4670 |       vtable.Assign(down_cast<mirror::PointerArray*>(vtable->CopyOf(self, actual_count))); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 4671 |       if (UNLIKELY(vtable.Get() == nullptr)) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4672 |         self->AssertPendingOOMException(); | 
| Ian Rogers | a436fde | 2013-08-27 23:34:06 -0700 | [diff] [blame] | 4673 |         return false; | 
 | 4674 |       } | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 4675 |     } | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 4676 |     klass->SetVTable(vtable.Get()); | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 4677 |   } else { | 
| Mathieu Chartier | bfd9a43 | 2014-05-21 17:43:44 -0700 | [diff] [blame] | 4678 |     CHECK_EQ(klass.Get(), GetClassRoot(kJavaLangObject)); | 
| Andreas Gampe | ab1eb0d | 2015-02-13 19:23:55 -0800 | [diff] [blame] | 4679 |     if (!IsUint<16>(num_virtual_methods)) { | 
| Mathieu Chartier | 2d2621a | 2014-10-23 16:48:06 -0700 | [diff] [blame] | 4680 |       ThrowClassFormatError(klass.Get(), "Too many methods: %d", | 
 | 4681 |                             static_cast<int>(num_virtual_methods)); | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 4682 |       return false; | 
 | 4683 |     } | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4684 |     auto* vtable = AllocPointerArray(self, num_virtual_methods); | 
| Mathieu Chartier | 2d2621a | 2014-10-23 16:48:06 -0700 | [diff] [blame] | 4685 |     if (UNLIKELY(vtable == nullptr)) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4686 |       self->AssertPendingOOMException(); | 
| Ian Rogers | a436fde | 2013-08-27 23:34:06 -0700 | [diff] [blame] | 4687 |       return false; | 
 | 4688 |     } | 
| Brian Carlstrom | a40f9bc | 2011-07-26 21:26:07 -0700 | [diff] [blame] | 4689 |     for (size_t i = 0; i < num_virtual_methods; ++i) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4690 |       ArtMethod* virtual_method = klass->GetVirtualMethodDuringLinking(i, image_pointer_size_); | 
 | 4691 |       vtable->SetElementPtrSize(i, virtual_method, image_pointer_size_); | 
| Ian Rogers | 0cfe1fb | 2011-08-26 03:29:44 -0700 | [diff] [blame] | 4692 |       virtual_method->SetMethodIndex(i & 0xFFFF); | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 4693 |     } | 
| Mathieu Chartier | 2d2621a | 2014-10-23 16:48:06 -0700 | [diff] [blame] | 4694 |     klass->SetVTable(vtable); | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 4695 |   } | 
 | 4696 |   return true; | 
 | 4697 | } | 
 | 4698 |  | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 4699 | bool ClassLinker::LinkInterfaceMethods(Thread* self, Handle<mirror::Class> klass, | 
| Mathieu Chartier | 2d2621a | 2014-10-23 16:48:06 -0700 | [diff] [blame] | 4700 |                                        Handle<mirror::ObjectArray<mirror::Class>> interfaces, | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 4701 |                                        ArtMethod** out_imt) { | 
| Mathieu Chartier | d035c2d | 2014-10-27 17:30:20 -0700 | [diff] [blame] | 4702 |   StackHandleScope<3> hs(self); | 
| Mathieu Chartier | bfd9a43 | 2014-05-21 17:43:44 -0700 | [diff] [blame] | 4703 |   Runtime* const runtime = Runtime::Current(); | 
| Mathieu Chartier | 2d2621a | 2014-10-23 16:48:06 -0700 | [diff] [blame] | 4704 |   const bool has_superclass = klass->HasSuperClass(); | 
 | 4705 |   const size_t super_ifcount = has_superclass ? klass->GetSuperClass()->GetIfTableCount() : 0U; | 
 | 4706 |   const bool have_interfaces = interfaces.Get() != nullptr; | 
 | 4707 |   const size_t num_interfaces = | 
 | 4708 |       have_interfaces ? interfaces->GetLength() : klass->NumDirectInterfaces(); | 
| Vladimir Marko | 1463285 | 2015-08-17 12:07:23 +0100 | [diff] [blame] | 4709 |   const size_t method_alignment = ArtMethod::Alignment(image_pointer_size_); | 
 | 4710 |   const size_t method_size = ArtMethod::Size(image_pointer_size_); | 
| Mathieu Chartier | 2d2621a | 2014-10-23 16:48:06 -0700 | [diff] [blame] | 4711 |   if (num_interfaces == 0) { | 
 | 4712 |     if (super_ifcount == 0) { | 
 | 4713 |       // Class implements no interfaces. | 
 | 4714 |       DCHECK_EQ(klass->GetIfTableCount(), 0); | 
 | 4715 |       DCHECK(klass->GetIfTable() == nullptr); | 
 | 4716 |       return true; | 
 | 4717 |     } | 
| Ian Rogers | 9bc8191 | 2012-10-11 21:43:36 -0700 | [diff] [blame] | 4718 |     // Class implements same interfaces as parent, are any of these not marker interfaces? | 
 | 4719 |     bool has_non_marker_interface = false; | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 4720 |     mirror::IfTable* super_iftable = klass->GetSuperClass()->GetIfTable(); | 
| Mathieu Chartier | 2d2621a | 2014-10-23 16:48:06 -0700 | [diff] [blame] | 4721 |     for (size_t i = 0; i < super_ifcount; ++i) { | 
| Ian Rogers | 9bc8191 | 2012-10-11 21:43:36 -0700 | [diff] [blame] | 4722 |       if (super_iftable->GetMethodArrayCount(i) > 0) { | 
 | 4723 |         has_non_marker_interface = true; | 
 | 4724 |         break; | 
 | 4725 |       } | 
 | 4726 |     } | 
| Mathieu Chartier | 2d2621a | 2014-10-23 16:48:06 -0700 | [diff] [blame] | 4727 |     // Class just inherits marker interfaces from parent so recycle parent's iftable. | 
| Ian Rogers | 9bc8191 | 2012-10-11 21:43:36 -0700 | [diff] [blame] | 4728 |     if (!has_non_marker_interface) { | 
| Ian Rogers | 9bc8191 | 2012-10-11 21:43:36 -0700 | [diff] [blame] | 4729 |       klass->SetIfTable(super_iftable); | 
 | 4730 |       return true; | 
 | 4731 |     } | 
 | 4732 |   } | 
| Mathieu Chartier | 2d2621a | 2014-10-23 16:48:06 -0700 | [diff] [blame] | 4733 |   size_t ifcount = super_ifcount + num_interfaces; | 
 | 4734 |   for (size_t i = 0; i < num_interfaces; i++) { | 
 | 4735 |     mirror::Class* interface = have_interfaces ? | 
 | 4736 |         interfaces->GetWithoutChecks(i) : mirror::Class::GetDirectInterface(self, klass, i); | 
 | 4737 |     DCHECK(interface != nullptr); | 
| Mathieu Chartier | 2d2621a | 2014-10-23 16:48:06 -0700 | [diff] [blame] | 4738 |     if (UNLIKELY(!interface->IsInterface())) { | 
 | 4739 |       std::string temp; | 
 | 4740 |       ThrowIncompatibleClassChangeError(klass.Get(), "Class %s implements non-interface class %s", | 
 | 4741 |                                         PrettyDescriptor(klass.Get()).c_str(), | 
 | 4742 |                                         PrettyDescriptor(interface->GetDescriptor(&temp)).c_str()); | 
 | 4743 |       return false; | 
 | 4744 |     } | 
 | 4745 |     ifcount += interface->GetIfTableCount(); | 
 | 4746 |   } | 
| Andreas Gampe | 5a4b8a2 | 2014-09-11 08:30:08 -0700 | [diff] [blame] | 4747 |   MutableHandle<mirror::IfTable> iftable(hs.NewHandle(AllocIfTable(self, ifcount))); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 4748 |   if (UNLIKELY(iftable.Get() == nullptr)) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4749 |     self->AssertPendingOOMException(); | 
| Ian Rogers | a436fde | 2013-08-27 23:34:06 -0700 | [diff] [blame] | 4750 |     return false; | 
 | 4751 |   } | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 4752 |   if (super_ifcount != 0) { | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 4753 |     mirror::IfTable* super_iftable = klass->GetSuperClass()->GetIfTable(); | 
| Brian Carlstrom | 4b620ff | 2011-09-11 01:11:01 -0700 | [diff] [blame] | 4754 |     for (size_t i = 0; i < super_ifcount; i++) { | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 4755 |       mirror::Class* super_interface = super_iftable->GetInterface(i); | 
| Ian Rogers | 9bc8191 | 2012-10-11 21:43:36 -0700 | [diff] [blame] | 4756 |       iftable->SetInterface(i, super_interface); | 
| Brian Carlstrom | 4b620ff | 2011-09-11 01:11:01 -0700 | [diff] [blame] | 4757 |     } | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 4758 |   } | 
| Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 4759 |   self->AllowThreadSuspension(); | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 4760 |   // Flatten the interface inheritance hierarchy. | 
 | 4761 |   size_t idx = super_ifcount; | 
| Ian Rogers | 6d4d9fc | 2011-11-30 16:24:48 -0800 | [diff] [blame] | 4762 |   for (size_t i = 0; i < num_interfaces; i++) { | 
| Mathieu Chartier | d035c2d | 2014-10-27 17:30:20 -0700 | [diff] [blame] | 4763 |     mirror::Class* interface = have_interfaces ? interfaces->Get(i) : | 
 | 4764 |         mirror::Class::GetDirectInterface(self, klass, i); | 
| Ian Rogers | b52b01a | 2012-01-12 17:01:38 -0800 | [diff] [blame] | 4765 |     // Check if interface is already in iftable | 
 | 4766 |     bool duplicate = false; | 
 | 4767 |     for (size_t j = 0; j < idx; j++) { | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 4768 |       mirror::Class* existing_interface = iftable->GetInterface(j); | 
| Ian Rogers | b52b01a | 2012-01-12 17:01:38 -0800 | [diff] [blame] | 4769 |       if (existing_interface == interface) { | 
 | 4770 |         duplicate = true; | 
 | 4771 |         break; | 
 | 4772 |       } | 
 | 4773 |     } | 
 | 4774 |     if (!duplicate) { | 
 | 4775 |       // Add this non-duplicate interface. | 
| Ian Rogers | 9bc8191 | 2012-10-11 21:43:36 -0700 | [diff] [blame] | 4776 |       iftable->SetInterface(idx++, interface); | 
| Ian Rogers | b52b01a | 2012-01-12 17:01:38 -0800 | [diff] [blame] | 4777 |       // Add this interface's non-duplicate super-interfaces. | 
 | 4778 |       for (int32_t j = 0; j < interface->GetIfTableCount(); j++) { | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 4779 |         mirror::Class* super_interface = interface->GetIfTable()->GetInterface(j); | 
| Ian Rogers | b52b01a | 2012-01-12 17:01:38 -0800 | [diff] [blame] | 4780 |         bool super_duplicate = false; | 
 | 4781 |         for (size_t k = 0; k < idx; k++) { | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 4782 |           mirror::Class* existing_interface = iftable->GetInterface(k); | 
| Ian Rogers | b52b01a | 2012-01-12 17:01:38 -0800 | [diff] [blame] | 4783 |           if (existing_interface == super_interface) { | 
 | 4784 |             super_duplicate = true; | 
 | 4785 |             break; | 
 | 4786 |           } | 
 | 4787 |         } | 
 | 4788 |         if (!super_duplicate) { | 
| Ian Rogers | 9bc8191 | 2012-10-11 21:43:36 -0700 | [diff] [blame] | 4789 |           iftable->SetInterface(idx++, super_interface); | 
| Ian Rogers | b52b01a | 2012-01-12 17:01:38 -0800 | [diff] [blame] | 4790 |         } | 
 | 4791 |       } | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 4792 |     } | 
 | 4793 |   } | 
| Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 4794 |   self->AllowThreadSuspension(); | 
| Ian Rogers | b52b01a | 2012-01-12 17:01:38 -0800 | [diff] [blame] | 4795 |   // Shrink iftable in case duplicates were found | 
 | 4796 |   if (idx < ifcount) { | 
| Mathieu Chartier | 2d2621a | 2014-10-23 16:48:06 -0700 | [diff] [blame] | 4797 |     DCHECK_NE(num_interfaces, 0U); | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4798 |     iftable.Assign(down_cast<mirror::IfTable*>( | 
 | 4799 |         iftable->CopyOf(self, idx * mirror::IfTable::kMax))); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 4800 |     if (UNLIKELY(iftable.Get() == nullptr)) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4801 |       self->AssertPendingOOMException(); | 
| Ian Rogers | a436fde | 2013-08-27 23:34:06 -0700 | [diff] [blame] | 4802 |       return false; | 
 | 4803 |     } | 
| Ian Rogers | b52b01a | 2012-01-12 17:01:38 -0800 | [diff] [blame] | 4804 |     ifcount = idx; | 
 | 4805 |   } else { | 
| Mathieu Chartier | 2d2621a | 2014-10-23 16:48:06 -0700 | [diff] [blame] | 4806 |     DCHECK_EQ(idx, ifcount); | 
| Ian Rogers | b52b01a | 2012-01-12 17:01:38 -0800 | [diff] [blame] | 4807 |   } | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 4808 |   klass->SetIfTable(iftable.Get()); | 
| Elliott Hughes | 4681c80 | 2011-09-25 18:04:37 -0700 | [diff] [blame] | 4809 |   // If we're an interface, we don't need the vtable pointers, so we're done. | 
| Ian Rogers | 9bc8191 | 2012-10-11 21:43:36 -0700 | [diff] [blame] | 4810 |   if (klass->IsInterface()) { | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 4811 |     return true; | 
 | 4812 |   } | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4813 |   // These are allocated on the heap to begin, we then transfer to linear alloc when we re-create | 
 | 4814 |   // the virtual methods array. | 
 | 4815 |   // Need to use low 4GB arenas for compiler or else the pointers wont fit in 32 bit method array | 
 | 4816 |   // during cross compilation. | 
 | 4817 |   // Use the linear alloc pool since this one is in the low 4gb for the compiler. | 
 | 4818 |   ArenaStack stack(runtime->GetLinearAlloc()->GetArenaPool()); | 
 | 4819 |   ScopedArenaAllocator allocator(&stack); | 
 | 4820 |   ScopedArenaVector<ArtMethod*> miranda_methods(allocator.Adapter()); | 
 | 4821 |  | 
 | 4822 |   MutableHandle<mirror::PointerArray> vtable(hs.NewHandle(klass->GetVTableDuringLinking())); | 
 | 4823 |   ArtMethod* const unimplemented_method = runtime->GetImtUnimplementedMethod(); | 
 | 4824 |   ArtMethod* const conflict_method = runtime->GetImtConflictMethod(); | 
| Mathieu Chartier | 2d2621a | 2014-10-23 16:48:06 -0700 | [diff] [blame] | 4825 |   // Copy the IMT from the super class if possible. | 
 | 4826 |   bool extend_super_iftable = false; | 
 | 4827 |   if (has_superclass) { | 
 | 4828 |     mirror::Class* super_class = klass->GetSuperClass(); | 
 | 4829 |     extend_super_iftable = true; | 
 | 4830 |     if (super_class->ShouldHaveEmbeddedImtAndVTable()) { | 
 | 4831 |       for (size_t i = 0; i < mirror::Class::kImtSize; ++i) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4832 |         out_imt[i] = super_class->GetEmbeddedImTableEntry(i, image_pointer_size_); | 
| Mathieu Chartier | 2d2621a | 2014-10-23 16:48:06 -0700 | [diff] [blame] | 4833 |       } | 
 | 4834 |     } else { | 
 | 4835 |       // No imt in the super class, need to reconstruct from the iftable. | 
 | 4836 |       mirror::IfTable* if_table = super_class->GetIfTable(); | 
| Mathieu Chartier | 2d2621a | 2014-10-23 16:48:06 -0700 | [diff] [blame] | 4837 |       const size_t length = super_class->GetIfTableCount(); | 
 | 4838 |       for (size_t i = 0; i < length; ++i) { | 
 | 4839 |         mirror::Class* interface = iftable->GetInterface(i); | 
 | 4840 |         const size_t num_virtuals = interface->NumVirtualMethods(); | 
 | 4841 |         const size_t method_array_count = if_table->GetMethodArrayCount(i); | 
 | 4842 |         DCHECK_EQ(num_virtuals, method_array_count); | 
 | 4843 |         if (method_array_count == 0) { | 
 | 4844 |           continue; | 
 | 4845 |         } | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4846 |         auto* method_array = if_table->GetMethodArray(i); | 
| Mathieu Chartier | 2d2621a | 2014-10-23 16:48:06 -0700 | [diff] [blame] | 4847 |         for (size_t j = 0; j < num_virtuals; ++j) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4848 |           auto method = method_array->GetElementPtrSize<ArtMethod*>(j, image_pointer_size_); | 
 | 4849 |           DCHECK(method != nullptr) << PrettyClass(super_class); | 
| Mathieu Chartier | 2d2621a | 2014-10-23 16:48:06 -0700 | [diff] [blame] | 4850 |           if (method->IsMiranda()) { | 
 | 4851 |             continue; | 
 | 4852 |           } | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4853 |           ArtMethod* interface_method = interface->GetVirtualMethod(j, image_pointer_size_); | 
| Mathieu Chartier | 2d2621a | 2014-10-23 16:48:06 -0700 | [diff] [blame] | 4854 |           uint32_t imt_index = interface_method->GetDexMethodIndex() % mirror::Class::kImtSize; | 
| Mathieu Chartier | cf3b1a3 | 2015-06-01 14:30:06 -0700 | [diff] [blame] | 4855 |           auto** imt_ref = &out_imt[imt_index]; | 
 | 4856 |           if (*imt_ref == unimplemented_method) { | 
 | 4857 |             *imt_ref = method; | 
 | 4858 |           } else if (*imt_ref != conflict_method) { | 
 | 4859 |             *imt_ref = conflict_method; | 
| Mathieu Chartier | 2d2621a | 2014-10-23 16:48:06 -0700 | [diff] [blame] | 4860 |           } | 
 | 4861 |         } | 
 | 4862 |       } | 
 | 4863 |     } | 
 | 4864 |   } | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4865 |   // Allocate method arrays before since we don't want miss visiting miranda method roots due to | 
 | 4866 |   // thread suspension. | 
| Brian Carlstrom | 4b620ff | 2011-09-11 01:11:01 -0700 | [diff] [blame] | 4867 |   for (size_t i = 0; i < ifcount; ++i) { | 
| Mathieu Chartier | c528dba | 2013-11-26 12:00:11 -0800 | [diff] [blame] | 4868 |     size_t num_methods = iftable->GetInterface(i)->NumVirtualMethods(); | 
| Ian Rogers | 9bc8191 | 2012-10-11 21:43:36 -0700 | [diff] [blame] | 4869 |     if (num_methods > 0) { | 
| Mathieu Chartier | 2d2621a | 2014-10-23 16:48:06 -0700 | [diff] [blame] | 4870 |       const bool is_super = i < super_ifcount; | 
 | 4871 |       const bool super_interface = is_super && extend_super_iftable; | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4872 |       mirror::PointerArray* method_array; | 
| Mathieu Chartier | 2d2621a | 2014-10-23 16:48:06 -0700 | [diff] [blame] | 4873 |       if (super_interface) { | 
 | 4874 |         mirror::IfTable* if_table = klass->GetSuperClass()->GetIfTable(); | 
 | 4875 |         DCHECK(if_table != nullptr); | 
 | 4876 |         DCHECK(if_table->GetMethodArray(i) != nullptr); | 
 | 4877 |         // If we are working on a super interface, try extending the existing method array. | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4878 |         method_array = down_cast<mirror::PointerArray*>(if_table->GetMethodArray(i)->Clone(self)); | 
| Mathieu Chartier | 2d2621a | 2014-10-23 16:48:06 -0700 | [diff] [blame] | 4879 |       } else { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4880 |         method_array = AllocPointerArray(self, num_methods); | 
| Mathieu Chartier | 2d2621a | 2014-10-23 16:48:06 -0700 | [diff] [blame] | 4881 |       } | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4882 |       if (UNLIKELY(method_array == nullptr)) { | 
 | 4883 |         self->AssertPendingOOMException(); | 
| Ian Rogers | a436fde | 2013-08-27 23:34:06 -0700 | [diff] [blame] | 4884 |         return false; | 
 | 4885 |       } | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4886 |       iftable->SetMethodArray(i, method_array); | 
 | 4887 |     } | 
 | 4888 |   } | 
 | 4889 |  | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 4890 |   auto* old_cause = self->StartAssertNoThreadSuspension( | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4891 |       "Copying ArtMethods for LinkInterfaceMethods"); | 
 | 4892 |   for (size_t i = 0; i < ifcount; ++i) { | 
 | 4893 |     size_t num_methods = iftable->GetInterface(i)->NumVirtualMethods(); | 
 | 4894 |     if (num_methods > 0) { | 
 | 4895 |       StackHandleScope<2> hs2(self); | 
 | 4896 |       const bool is_super = i < super_ifcount; | 
 | 4897 |       const bool super_interface = is_super && extend_super_iftable; | 
 | 4898 |       auto method_array(hs2.NewHandle(iftable->GetMethodArray(i))); | 
 | 4899 |  | 
| Mathieu Chartier | 54d220e | 2015-07-30 16:20:06 -0700 | [diff] [blame] | 4900 |       LengthPrefixedArray<ArtMethod>* input_virtual_methods = nullptr; | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4901 |       Handle<mirror::PointerArray> input_vtable_array = NullHandle<mirror::PointerArray>(); | 
 | 4902 |       int32_t input_array_length = 0; | 
 | 4903 |       if (super_interface) { | 
 | 4904 |         // We are overwriting a super class interface, try to only virtual methods instead of the | 
 | 4905 |         // whole vtable. | 
 | 4906 |         input_virtual_methods = klass->GetVirtualMethodsPtr(); | 
 | 4907 |         input_array_length = klass->NumVirtualMethods(); | 
 | 4908 |       } else { | 
 | 4909 |         // A new interface, we need the whole vtable in case a new interface method is implemented | 
 | 4910 |         // in the whole superclass. | 
 | 4911 |         input_vtable_array = vtable; | 
 | 4912 |         input_array_length = input_vtable_array->GetLength(); | 
 | 4913 |       } | 
 | 4914 |       if (input_array_length == 0) { | 
| Mathieu Chartier | 2d2621a | 2014-10-23 16:48:06 -0700 | [diff] [blame] | 4915 |         // If the added virtual methods is empty, do nothing. | 
 | 4916 |         DCHECK(super_interface); | 
 | 4917 |         continue; | 
 | 4918 |       } | 
| Ian Rogers | 62d6c77 | 2013-02-27 08:32:07 -0800 | [diff] [blame] | 4919 |       for (size_t j = 0; j < num_methods; ++j) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4920 |         auto* interface_method = iftable->GetInterface(i)->GetVirtualMethod( | 
 | 4921 |             j, image_pointer_size_); | 
| Mathieu Chartier | 9f3629d | 2014-10-28 18:23:02 -0700 | [diff] [blame] | 4922 |         MethodNameAndSignatureComparator interface_name_comparator( | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4923 |             interface_method->GetInterfaceMethodIfProxy(image_pointer_size_)); | 
| Ian Rogers | 9bc8191 | 2012-10-11 21:43:36 -0700 | [diff] [blame] | 4924 |         int32_t k; | 
 | 4925 |         // For each method listed in the interface's method list, find the | 
 | 4926 |         // matching method in our class's method list.  We want to favor the | 
 | 4927 |         // subclass over the superclass, which just requires walking | 
 | 4928 |         // back from the end of the vtable.  (This only matters if the | 
 | 4929 |         // superclass defines a private method and this class redefines | 
 | 4930 |         // it -- otherwise it would use the same vtable slot.  In .dex files | 
 | 4931 |         // those don't end up in the virtual method table, so it shouldn't | 
 | 4932 |         // matter which direction we go.  We walk it backward anyway.) | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4933 |         for (k = input_array_length - 1; k >= 0; --k) { | 
 | 4934 |           ArtMethod* vtable_method = input_virtual_methods != nullptr ? | 
| Vladimir Marko | cf36d49 | 2015-08-12 19:27:26 +0100 | [diff] [blame] | 4935 |               &input_virtual_methods->At(k, method_size, method_alignment) : | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4936 |               input_vtable_array->GetElementPtrSize<ArtMethod*>(k, image_pointer_size_); | 
 | 4937 |           ArtMethod* vtable_method_for_name_comparison = | 
 | 4938 |               vtable_method->GetInterfaceMethodIfProxy(image_pointer_size_); | 
| Ian Rogers | 03b6eaf | 2014-10-28 09:34:57 -0700 | [diff] [blame] | 4939 |           if (interface_name_comparator.HasSameNameAndSignature( | 
| Mathieu Chartier | 9f3629d | 2014-10-28 18:23:02 -0700 | [diff] [blame] | 4940 |               vtable_method_for_name_comparison)) { | 
| Mathieu Chartier | 2d2621a | 2014-10-23 16:48:06 -0700 | [diff] [blame] | 4941 |             if (!vtable_method->IsAbstract() && !vtable_method->IsPublic()) { | 
| Mathieu Chartier | 4d122c1 | 2015-06-17 14:14:36 -0700 | [diff] [blame] | 4942 |               // Must do EndAssertNoThreadSuspension before throw since the throw can cause | 
 | 4943 |               // allocations. | 
 | 4944 |               self->EndAssertNoThreadSuspension(old_cause); | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4945 |               ThrowIllegalAccessError(klass.Get(), | 
| Brian Carlstrom | f363283 | 2014-05-20 15:36:53 -0700 | [diff] [blame] | 4946 |                   "Method '%s' implementing interface method '%s' is not public", | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4947 |                   PrettyMethod(vtable_method).c_str(), PrettyMethod(interface_method).c_str()); | 
| Ian Rogers | 9bc8191 | 2012-10-11 21:43:36 -0700 | [diff] [blame] | 4948 |               return false; | 
 | 4949 |             } | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4950 |             method_array->SetElementPtrSize(j, vtable_method, image_pointer_size_); | 
| Jeff Hao | 88474b4 | 2013-10-23 16:24:40 -0700 | [diff] [blame] | 4951 |             // Place method in imt if entry is empty, place conflict otherwise. | 
| Mathieu Chartier | 2d2621a | 2014-10-23 16:48:06 -0700 | [diff] [blame] | 4952 |             uint32_t imt_index = interface_method->GetDexMethodIndex() % mirror::Class::kImtSize; | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4953 |             auto** imt_ref = &out_imt[imt_index]; | 
 | 4954 |             if (*imt_ref == unimplemented_method) { | 
 | 4955 |               *imt_ref = vtable_method; | 
 | 4956 |             } else if (*imt_ref != conflict_method) { | 
| Mathieu Chartier | 2d2621a | 2014-10-23 16:48:06 -0700 | [diff] [blame] | 4957 |               // If we are not a conflict and we have the same signature and name as the imt entry, | 
 | 4958 |               // it must be that we overwrote a superclass vtable entry. | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4959 |               MethodNameAndSignatureComparator imt_comparator( | 
 | 4960 |                   (*imt_ref)->GetInterfaceMethodIfProxy(image_pointer_size_)); | 
 | 4961 |               *imt_ref = imt_comparator.HasSameNameAndSignature(vtable_method_for_name_comparison) ? | 
 | 4962 |                   vtable_method : conflict_method; | 
| Jeff Hao | 88474b4 | 2013-10-23 16:24:40 -0700 | [diff] [blame] | 4963 |             } | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 4964 |             break; | 
 | 4965 |           } | 
 | 4966 |         } | 
| Mathieu Chartier | 2d2621a | 2014-10-23 16:48:06 -0700 | [diff] [blame] | 4967 |         if (k < 0 && !super_interface) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4968 |           ArtMethod* miranda_method = nullptr; | 
 | 4969 |           for (auto& mir_method : miranda_methods) { | 
| Ian Rogers | 03b6eaf | 2014-10-28 09:34:57 -0700 | [diff] [blame] | 4970 |             if (interface_name_comparator.HasSameNameAndSignature(mir_method)) { | 
| Mathieu Chartier | 2d2621a | 2014-10-23 16:48:06 -0700 | [diff] [blame] | 4971 |               miranda_method = mir_method; | 
| Ian Rogers | 9bc8191 | 2012-10-11 21:43:36 -0700 | [diff] [blame] | 4972 |               break; | 
 | 4973 |             } | 
 | 4974 |           } | 
| Mathieu Chartier | 2d2621a | 2014-10-23 16:48:06 -0700 | [diff] [blame] | 4975 |           if (miranda_method == nullptr) { | 
| Mathieu Chartier | d4d83b8 | 2015-06-19 20:24:45 -0700 | [diff] [blame] | 4976 |             miranda_method = reinterpret_cast<ArtMethod*>(allocator.Alloc(method_size)); | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4977 |             CHECK(miranda_method != nullptr); | 
| Ian Rogers | a436fde | 2013-08-27 23:34:06 -0700 | [diff] [blame] | 4978 |             // Point the interface table at a phantom slot. | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4979 |             new(miranda_method) ArtMethod(*interface_method, image_pointer_size_); | 
 | 4980 |             miranda_methods.push_back(miranda_method); | 
| Ian Rogers | 9bc8191 | 2012-10-11 21:43:36 -0700 | [diff] [blame] | 4981 |           } | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4982 |           method_array->SetElementPtrSize(j, miranda_method, image_pointer_size_); | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 4983 |         } | 
 | 4984 |       } | 
 | 4985 |     } | 
 | 4986 |   } | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4987 |   if (!miranda_methods.empty()) { | 
 | 4988 |     const size_t old_method_count = klass->NumVirtualMethods(); | 
 | 4989 |     const size_t new_method_count = old_method_count + miranda_methods.size(); | 
 | 4990 |     // Attempt to realloc to save RAM if possible. | 
| Mathieu Chartier | 54d220e | 2015-07-30 16:20:06 -0700 | [diff] [blame] | 4991 |     LengthPrefixedArray<ArtMethod>* old_virtuals = klass->GetVirtualMethodsPtr(); | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 4992 |     // The Realloced virtual methods aren't visiblef from the class roots, so there is no issue | 
 | 4993 |     // where GCs could attempt to mark stale pointers due to memcpy. And since we overwrite the | 
 | 4994 |     // realloced memory with out->CopyFrom, we are guaranteed to have objects in the to space since | 
 | 4995 |     // CopyFrom has internal read barriers. | 
| Vladimir Marko | cf36d49 | 2015-08-12 19:27:26 +0100 | [diff] [blame] | 4996 |     const size_t old_size = old_virtuals != nullptr | 
 | 4997 |         ? LengthPrefixedArray<ArtMethod>::ComputeSize(old_method_count, | 
 | 4998 |                                                       method_size, | 
 | 4999 |                                                       method_alignment) | 
 | 5000 |         : 0u; | 
| Mathieu Chartier | 54d220e | 2015-07-30 16:20:06 -0700 | [diff] [blame] | 5001 |     const size_t new_size = LengthPrefixedArray<ArtMethod>::ComputeSize(new_method_count, | 
| Vladimir Marko | cf36d49 | 2015-08-12 19:27:26 +0100 | [diff] [blame] | 5002 |                                                                         method_size, | 
 | 5003 |                                                                         method_alignment); | 
| Mathieu Chartier | c0fe56a | 2015-08-11 13:01:23 -0700 | [diff] [blame] | 5004 |     auto* virtuals = reinterpret_cast<LengthPrefixedArray<ArtMethod>*>( | 
 | 5005 |         runtime->GetLinearAlloc()->Realloc(self, old_virtuals, old_size, new_size)); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 5006 |     if (UNLIKELY(virtuals == nullptr)) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 5007 |       self->AssertPendingOOMException(); | 
| Mathieu Chartier | 4e2cb09 | 2015-07-22 16:17:51 -0700 | [diff] [blame] | 5008 |       self->EndAssertNoThreadSuspension(old_cause); | 
| Ian Rogers | a436fde | 2013-08-27 23:34:06 -0700 | [diff] [blame] | 5009 |       return false; | 
 | 5010 |     } | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 5011 |     ScopedArenaUnorderedMap<ArtMethod*, ArtMethod*> move_table(allocator.Adapter()); | 
 | 5012 |     if (virtuals != old_virtuals) { | 
 | 5013 |       // Maps from heap allocated miranda method to linear alloc miranda method. | 
| Vladimir Marko | cf36d49 | 2015-08-12 19:27:26 +0100 | [diff] [blame] | 5014 |       StrideIterator<ArtMethod> out = virtuals->Begin(method_size, method_alignment); | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 5015 |       // Copy over the old methods + miranda methods. | 
 | 5016 |       for (auto& m : klass->GetVirtualMethods(image_pointer_size_)) { | 
 | 5017 |         move_table.emplace(&m, &*out); | 
 | 5018 |         // The CopyFrom is only necessary to not miss read barriers since Realloc won't do read | 
 | 5019 |         // barriers when it copies. | 
 | 5020 |         out->CopyFrom(&m, image_pointer_size_); | 
 | 5021 |         ++out; | 
 | 5022 |       } | 
 | 5023 |     } | 
| Vladimir Marko | cf36d49 | 2015-08-12 19:27:26 +0100 | [diff] [blame] | 5024 |     StrideIterator<ArtMethod> out(virtuals->Begin(method_size, method_alignment) + old_method_count); | 
| Mathieu Chartier | d4d83b8 | 2015-06-19 20:24:45 -0700 | [diff] [blame] | 5025 |     // Copy over miranda methods before copying vtable since CopyOf may cause thread suspension and | 
 | 5026 |     // we want the roots of the miranda methods to get visited. | 
 | 5027 |     for (ArtMethod* mir_method : miranda_methods) { | 
 | 5028 |       out->CopyFrom(mir_method, image_pointer_size_); | 
 | 5029 |       out->SetAccessFlags(out->GetAccessFlags() | kAccMiranda); | 
 | 5030 |       move_table.emplace(mir_method, &*out); | 
| Mathieu Chartier | cf3b1a3 | 2015-06-01 14:30:06 -0700 | [diff] [blame] | 5031 |       ++out; | 
| Mathieu Chartier | cf3b1a3 | 2015-06-01 14:30:06 -0700 | [diff] [blame] | 5032 |     } | 
| Mathieu Chartier | c0fe56a | 2015-08-11 13:01:23 -0700 | [diff] [blame] | 5033 |     virtuals->SetLength(new_method_count); | 
| Mathieu Chartier | 54d220e | 2015-07-30 16:20:06 -0700 | [diff] [blame] | 5034 |     UpdateClassVirtualMethods(klass.Get(), virtuals); | 
| Mathieu Chartier | d4d83b8 | 2015-06-19 20:24:45 -0700 | [diff] [blame] | 5035 |     // Done copying methods, they are all roots in the class now, so we can end the no thread | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 5036 |     // suspension assert. | 
 | 5037 |     self->EndAssertNoThreadSuspension(old_cause); | 
| Mathieu Chartier | d4d83b8 | 2015-06-19 20:24:45 -0700 | [diff] [blame] | 5038 |  | 
 | 5039 |     const size_t old_vtable_count = vtable->GetLength(); | 
 | 5040 |     const size_t new_vtable_count = old_vtable_count + miranda_methods.size(); | 
 | 5041 |     miranda_methods.clear(); | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 5042 |     vtable.Assign(down_cast<mirror::PointerArray*>(vtable->CopyOf(self, new_vtable_count))); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 5043 |     if (UNLIKELY(vtable.Get() == nullptr)) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 5044 |       self->AssertPendingOOMException(); | 
| Ian Rogers | a436fde | 2013-08-27 23:34:06 -0700 | [diff] [blame] | 5045 |       return false; | 
 | 5046 |     } | 
| Vladimir Marko | cf36d49 | 2015-08-12 19:27:26 +0100 | [diff] [blame] | 5047 |     out = virtuals->Begin(method_size, method_alignment) + old_method_count; | 
| Mathieu Chartier | d4d83b8 | 2015-06-19 20:24:45 -0700 | [diff] [blame] | 5048 |     size_t vtable_pos = old_vtable_count; | 
 | 5049 |     for (size_t i = old_method_count; i < new_method_count; ++i) { | 
 | 5050 |       // Leave the declaring class alone as type indices are relative to it | 
 | 5051 |       out->SetMethodIndex(0xFFFF & vtable_pos); | 
 | 5052 |       vtable->SetElementPtrSize(vtable_pos, &*out, image_pointer_size_); | 
 | 5053 |       ++out; | 
 | 5054 |       ++vtable_pos; | 
 | 5055 |     } | 
 | 5056 |     CHECK_EQ(vtable_pos, new_vtable_count); | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 5057 |     // Update old vtable methods. | 
| Mathieu Chartier | d4d83b8 | 2015-06-19 20:24:45 -0700 | [diff] [blame] | 5058 |     for (size_t i = 0; i < old_vtable_count; ++i) { | 
 | 5059 |       auto* m = vtable->GetElementPtrSize<ArtMethod*>(i, image_pointer_size_); | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 5060 |       DCHECK(m != nullptr) << PrettyClass(klass.Get()); | 
 | 5061 |       auto it = move_table.find(m); | 
 | 5062 |       if (it != move_table.end()) { | 
 | 5063 |         auto* new_m = it->second; | 
 | 5064 |         DCHECK(new_m != nullptr) << PrettyClass(klass.Get()); | 
| Mathieu Chartier | d4d83b8 | 2015-06-19 20:24:45 -0700 | [diff] [blame] | 5065 |         vtable->SetElementPtrSize(i, new_m, image_pointer_size_); | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 5066 |       } | 
 | 5067 |     } | 
| Mathieu Chartier | cf3b1a3 | 2015-06-01 14:30:06 -0700 | [diff] [blame] | 5068 |  | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 5069 |     klass->SetVTable(vtable.Get()); | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 5070 |     // Go fix up all the stale miranda pointers. | 
 | 5071 |     for (size_t i = 0; i < ifcount; ++i) { | 
 | 5072 |       for (size_t j = 0, count = iftable->GetMethodArrayCount(i); j < count; ++j) { | 
 | 5073 |         auto* method_array = iftable->GetMethodArray(i); | 
 | 5074 |         auto* m = method_array->GetElementPtrSize<ArtMethod*>(j, image_pointer_size_); | 
 | 5075 |         DCHECK(m != nullptr) << PrettyClass(klass.Get()); | 
 | 5076 |         auto it = move_table.find(m); | 
 | 5077 |         if (it != move_table.end()) { | 
 | 5078 |           auto* new_m = it->second; | 
 | 5079 |           DCHECK(new_m != nullptr) << PrettyClass(klass.Get()); | 
 | 5080 |           method_array->SetElementPtrSize(j, new_m, image_pointer_size_); | 
 | 5081 |         } | 
 | 5082 |       } | 
 | 5083 |     } | 
| Mathieu Chartier | a40c74a | 2015-06-02 09:56:04 -0700 | [diff] [blame] | 5084 |     // Fix up IMT in case it has any miranda methods in it. | 
 | 5085 |     for (size_t i = 0; i < mirror::Class::kImtSize; ++i) { | 
 | 5086 |       auto it = move_table.find(out_imt[i]); | 
 | 5087 |       if (it != move_table.end()) { | 
 | 5088 |         out_imt[i] = it->second; | 
 | 5089 |       } | 
 | 5090 |     } | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 5091 |     // Check that there are no stale methods are in the dex cache array. | 
 | 5092 |     if (kIsDebugBuild) { | 
 | 5093 |       auto* resolved_methods = klass->GetDexCache()->GetResolvedMethods(); | 
 | 5094 |       for (size_t i = 0, count = resolved_methods->GetLength(); i < count; ++i) { | 
 | 5095 |         auto* m = resolved_methods->GetElementPtrSize<ArtMethod*>(i, image_pointer_size_); | 
 | 5096 |         CHECK(move_table.find(m) == move_table.end()) << PrettyMethod(m); | 
 | 5097 |       } | 
 | 5098 |     } | 
 | 5099 |     // Put some random garbage in old virtuals to help find stale pointers. | 
 | 5100 |     if (virtuals != old_virtuals) { | 
| Mathieu Chartier | 54d220e | 2015-07-30 16:20:06 -0700 | [diff] [blame] | 5101 |       memset(old_virtuals, 0xFEu, old_size); | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 5102 |     } | 
 | 5103 |   } else { | 
 | 5104 |     self->EndAssertNoThreadSuspension(old_cause); | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 5105 |   } | 
| Mathieu Chartier | 2d2621a | 2014-10-23 16:48:06 -0700 | [diff] [blame] | 5106 |   if (kIsDebugBuild) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 5107 |     auto* check_vtable = klass->GetVTableDuringLinking(); | 
| Andreas Gampe | 277ccbd | 2014-11-03 21:36:10 -0800 | [diff] [blame] | 5108 |     for (int i = 0; i < check_vtable->GetLength(); ++i) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 5109 |       CHECK(check_vtable->GetElementPtrSize<ArtMethod*>(i, image_pointer_size_) != nullptr); | 
| Mathieu Chartier | 2d2621a | 2014-10-23 16:48:06 -0700 | [diff] [blame] | 5110 |     } | 
| Elliott Hughes | 4681c80 | 2011-09-25 18:04:37 -0700 | [diff] [blame] | 5111 |   } | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 5112 |   return true; | 
 | 5113 | } | 
 | 5114 |  | 
| Andreas Gampe | 5a4b8a2 | 2014-09-11 08:30:08 -0700 | [diff] [blame] | 5115 | bool ClassLinker::LinkInstanceFields(Thread* self, Handle<mirror::Class> klass) { | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 5116 |   CHECK(klass.Get() != nullptr); | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 5117 |   return LinkFields(self, klass, false, nullptr); | 
| Brian Carlstrom | 4873d46 | 2011-08-21 15:23:39 -0700 | [diff] [blame] | 5118 | } | 
 | 5119 |  | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 5120 | bool ClassLinker::LinkStaticFields(Thread* self, Handle<mirror::Class> klass, size_t* class_size) { | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 5121 |   CHECK(klass.Get() != nullptr); | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 5122 |   return LinkFields(self, klass, true, class_size); | 
| Brian Carlstrom | 4873d46 | 2011-08-21 15:23:39 -0700 | [diff] [blame] | 5123 | } | 
 | 5124 |  | 
| Brian Carlstrom | dbc0525 | 2011-09-09 01:59:59 -0700 | [diff] [blame] | 5125 | struct LinkFieldsComparator { | 
| Mathieu Chartier | 9044347 | 2015-07-16 20:32:27 -0700 | [diff] [blame] | 5126 |   explicit LinkFieldsComparator() SHARED_REQUIRES(Locks::mutator_lock_) { | 
| Mathieu Chartier | 590fee9 | 2013-09-13 13:46:47 -0700 | [diff] [blame] | 5127 |   } | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 5128 |   // No thread safety analysis as will be called from STL. Checked lock held in constructor. | 
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 5129 |   bool operator()(ArtField* field1, ArtField* field2) | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 5130 |       NO_THREAD_SAFETY_ANALYSIS { | 
| Fred Shih | 37f05ef | 2014-07-16 18:38:08 -0700 | [diff] [blame] | 5131 |     // First come reference fields, then 64-bit, then 32-bit, and then 16-bit, then finally 8-bit. | 
| Mathieu Chartier | 61c5ebc | 2014-06-05 17:42:53 -0700 | [diff] [blame] | 5132 |     Primitive::Type type1 = field1->GetTypeAsPrimitiveType(); | 
 | 5133 |     Primitive::Type type2 = field2->GetTypeAsPrimitiveType(); | 
| Ian Rogers | ef7d42f | 2014-01-06 12:55:46 -0800 | [diff] [blame] | 5134 |     if (type1 != type2) { | 
| Vladimir Marko | d577748 | 2014-11-12 17:02:02 +0000 | [diff] [blame] | 5135 |       if (type1 == Primitive::kPrimNot) { | 
 | 5136 |         // Reference always goes first. | 
 | 5137 |         return true; | 
| Ian Rogers | ef7d42f | 2014-01-06 12:55:46 -0800 | [diff] [blame] | 5138 |       } | 
| Vladimir Marko | d577748 | 2014-11-12 17:02:02 +0000 | [diff] [blame] | 5139 |       if (type2 == Primitive::kPrimNot) { | 
 | 5140 |         // Reference always goes first. | 
 | 5141 |         return false; | 
 | 5142 |       } | 
 | 5143 |       size_t size1 = Primitive::ComponentSize(type1); | 
 | 5144 |       size_t size2 = Primitive::ComponentSize(type2); | 
 | 5145 |       if (size1 != size2) { | 
 | 5146 |         // Larger primitive types go first. | 
 | 5147 |         return size1 > size2; | 
 | 5148 |       } | 
 | 5149 |       // Primitive types differ but sizes match. Arbitrarily order by primitive type. | 
 | 5150 |       return type1 < type2; | 
| Brian Carlstrom | dbc0525 | 2011-09-09 01:59:59 -0700 | [diff] [blame] | 5151 |     } | 
| Vladimir Marko | 7a7c1db | 2014-11-17 15:13:34 +0000 | [diff] [blame] | 5152 |     // Same basic group? Then sort by dex field index. This is guaranteed to be sorted | 
 | 5153 |     // by name and for equal names by type id index. | 
 | 5154 |     // NOTE: This works also for proxies. Their static fields are assigned appropriate indexes. | 
 | 5155 |     return field1->GetDexFieldIndex() < field2->GetDexFieldIndex(); | 
| Brian Carlstrom | dbc0525 | 2011-09-09 01:59:59 -0700 | [diff] [blame] | 5156 |   } | 
 | 5157 | }; | 
 | 5158 |  | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 5159 | bool ClassLinker::LinkFields(Thread* self, Handle<mirror::Class> klass, bool is_static, | 
 | 5160 |                              size_t* class_size) { | 
| Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 5161 |   self->AllowThreadSuspension(); | 
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 5162 |   const size_t num_fields = is_static ? klass->NumStaticFields() : klass->NumInstanceFields(); | 
| Mathieu Chartier | 54d220e | 2015-07-30 16:20:06 -0700 | [diff] [blame] | 5163 |   LengthPrefixedArray<ArtField>* const fields = is_static ? klass->GetSFieldsPtr() : | 
 | 5164 |       klass->GetIFieldsPtr(); | 
| Ian Rogers | 0cfe1fb | 2011-08-26 03:29:44 -0700 | [diff] [blame] | 5165 |  | 
| Mingyao Yang | 98d1cc8 | 2014-05-15 17:02:16 -0700 | [diff] [blame] | 5166 |   // Initialize field_offset | 
| Brian Carlstrom | 693267a | 2011-09-06 09:25:34 -0700 | [diff] [blame] | 5167 |   MemberOffset field_offset(0); | 
| Brian Carlstrom | 3320cf4 | 2011-10-04 14:58:28 -0700 | [diff] [blame] | 5168 |   if (is_static) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 5169 |     field_offset = klass->GetFirstReferenceStaticFieldOffsetDuringLinking(image_pointer_size_); | 
| Brian Carlstrom | 3320cf4 | 2011-10-04 14:58:28 -0700 | [diff] [blame] | 5170 |   } else { | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 5171 |     mirror::Class* super_class = klass->GetSuperClass(); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 5172 |     if (super_class != nullptr) { | 
| Brian Carlstrom | f363283 | 2014-05-20 15:36:53 -0700 | [diff] [blame] | 5173 |       CHECK(super_class->IsResolved()) | 
 | 5174 |           << PrettyClass(klass.Get()) << " " << PrettyClass(super_class); | 
| Ian Rogers | 0cfe1fb | 2011-08-26 03:29:44 -0700 | [diff] [blame] | 5175 |       field_offset = MemberOffset(super_class->GetObjectSize()); | 
| Ian Rogers | 0cfe1fb | 2011-08-26 03:29:44 -0700 | [diff] [blame] | 5176 |     } | 
| Ian Rogers | 0cfe1fb | 2011-08-26 03:29:44 -0700 | [diff] [blame] | 5177 |   } | 
| Ian Rogers | 0cfe1fb | 2011-08-26 03:29:44 -0700 | [diff] [blame] | 5178 |  | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 5179 |   CHECK_EQ(num_fields == 0, fields == nullptr) << PrettyClass(klass.Get()); | 
| Ian Rogers | 0cfe1fb | 2011-08-26 03:29:44 -0700 | [diff] [blame] | 5180 |  | 
| Brian Carlstrom | dbc0525 | 2011-09-09 01:59:59 -0700 | [diff] [blame] | 5181 |   // we want a relatively stable order so that adding new fields | 
| Elliott Hughes | adb460d | 2011-10-05 17:02:34 -0700 | [diff] [blame] | 5182 |   // minimizes disruption of C++ version such as Class and Method. | 
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 5183 |   std::deque<ArtField*> grouped_and_sorted_fields; | 
| Mathieu Chartier | 2d5f39e | 2014-09-19 17:52:37 -0700 | [diff] [blame] | 5184 |   const char* old_no_suspend_cause = self->StartAssertNoThreadSuspension( | 
| Fred Shih | 37f05ef | 2014-07-16 18:38:08 -0700 | [diff] [blame] | 5185 |       "Naked ArtField references in deque"); | 
| Brian Carlstrom | dbc0525 | 2011-09-09 01:59:59 -0700 | [diff] [blame] | 5186 |   for (size_t i = 0; i < num_fields; i++) { | 
| Mathieu Chartier | 54d220e | 2015-07-30 16:20:06 -0700 | [diff] [blame] | 5187 |     grouped_and_sorted_fields.push_back(&fields->At(i)); | 
| Brian Carlstrom | dbc0525 | 2011-09-09 01:59:59 -0700 | [diff] [blame] | 5188 |   } | 
| Mathieu Chartier | 590fee9 | 2013-09-13 13:46:47 -0700 | [diff] [blame] | 5189 |   std::sort(grouped_and_sorted_fields.begin(), grouped_and_sorted_fields.end(), | 
 | 5190 |             LinkFieldsComparator()); | 
| Brian Carlstrom | dbc0525 | 2011-09-09 01:59:59 -0700 | [diff] [blame] | 5191 |  | 
| Fred Shih | 381e4ca | 2014-08-25 17:24:27 -0700 | [diff] [blame] | 5192 |   // References should be at the front. | 
| Brian Carlstrom | dbc0525 | 2011-09-09 01:59:59 -0700 | [diff] [blame] | 5193 |   size_t current_field = 0; | 
 | 5194 |   size_t num_reference_fields = 0; | 
| Fred Shih | 381e4ca | 2014-08-25 17:24:27 -0700 | [diff] [blame] | 5195 |   FieldGaps gaps; | 
 | 5196 |  | 
| Brian Carlstrom | dbc0525 | 2011-09-09 01:59:59 -0700 | [diff] [blame] | 5197 |   for (; current_field < num_fields; current_field++) { | 
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 5198 |     ArtField* field = grouped_and_sorted_fields.front(); | 
| Mathieu Chartier | 61c5ebc | 2014-06-05 17:42:53 -0700 | [diff] [blame] | 5199 |     Primitive::Type type = field->GetTypeAsPrimitiveType(); | 
| Brian Carlstrom | 6b4ef02 | 2011-10-23 14:59:04 -0700 | [diff] [blame] | 5200 |     bool isPrimitive = type != Primitive::kPrimNot; | 
| Brian Carlstrom | dbc0525 | 2011-09-09 01:59:59 -0700 | [diff] [blame] | 5201 |     if (isPrimitive) { | 
| Brian Carlstrom | 7934ac2 | 2013-07-26 10:54:15 -0700 | [diff] [blame] | 5202 |       break;  // past last reference, move on to the next phase | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 5203 |     } | 
| Vladimir Marko | 76649e8 | 2014-11-10 18:32:59 +0000 | [diff] [blame] | 5204 |     if (UNLIKELY(!IsAligned<sizeof(mirror::HeapReference<mirror::Object>)>( | 
 | 5205 |         field_offset.Uint32Value()))) { | 
| Fred Shih | 381e4ca | 2014-08-25 17:24:27 -0700 | [diff] [blame] | 5206 |       MemberOffset old_offset = field_offset; | 
 | 5207 |       field_offset = MemberOffset(RoundUp(field_offset.Uint32Value(), 4)); | 
 | 5208 |       AddFieldGap(old_offset.Uint32Value(), field_offset.Uint32Value(), &gaps); | 
 | 5209 |     } | 
| Roland Levillain | 14d9057 | 2015-07-16 10:52:26 +0100 | [diff] [blame] | 5210 |     DCHECK_ALIGNED(field_offset.Uint32Value(), sizeof(mirror::HeapReference<mirror::Object>)); | 
| Brian Carlstrom | dbc0525 | 2011-09-09 01:59:59 -0700 | [diff] [blame] | 5211 |     grouped_and_sorted_fields.pop_front(); | 
 | 5212 |     num_reference_fields++; | 
| Ian Rogers | 0cfe1fb | 2011-08-26 03:29:44 -0700 | [diff] [blame] | 5213 |     field->SetOffset(field_offset); | 
| Vladimir Marko | 76649e8 | 2014-11-10 18:32:59 +0000 | [diff] [blame] | 5214 |     field_offset = MemberOffset(field_offset.Uint32Value() + | 
 | 5215 |                                 sizeof(mirror::HeapReference<mirror::Object>)); | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 5216 |   } | 
| Fred Shih | 381e4ca | 2014-08-25 17:24:27 -0700 | [diff] [blame] | 5217 |   // Gaps are stored as a max heap which means that we must shuffle from largest to smallest | 
 | 5218 |   // otherwise we could end up with suboptimal gap fills. | 
| Vladimir Marko | 76649e8 | 2014-11-10 18:32:59 +0000 | [diff] [blame] | 5219 |   ShuffleForward<8>(¤t_field, &field_offset, &grouped_and_sorted_fields, &gaps); | 
 | 5220 |   ShuffleForward<4>(¤t_field, &field_offset, &grouped_and_sorted_fields, &gaps); | 
 | 5221 |   ShuffleForward<2>(¤t_field, &field_offset, &grouped_and_sorted_fields, &gaps); | 
 | 5222 |   ShuffleForward<1>(¤t_field, &field_offset, &grouped_and_sorted_fields, &gaps); | 
| Fred Shih | 37f05ef | 2014-07-16 18:38:08 -0700 | [diff] [blame] | 5223 |   CHECK(grouped_and_sorted_fields.empty()) << "Missed " << grouped_and_sorted_fields.size() << | 
 | 5224 |       " fields."; | 
| Ian Rogers | 7b078e8 | 2014-09-10 14:44:24 -0700 | [diff] [blame] | 5225 |   self->EndAssertNoThreadSuspension(old_no_suspend_cause); | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 5226 |  | 
| Elliott Hughes | adb460d | 2011-10-05 17:02:34 -0700 | [diff] [blame] | 5227 |   // We lie to the GC about the java.lang.ref.Reference.referent field, so it doesn't scan it. | 
| Mathieu Chartier | 0cd8135 | 2014-05-22 16:48:55 -0700 | [diff] [blame] | 5228 |   if (!is_static && klass->DescriptorEquals("Ljava/lang/ref/Reference;")) { | 
| Elliott Hughes | adb460d | 2011-10-05 17:02:34 -0700 | [diff] [blame] | 5229 |     // We know there are no non-reference fields in the Reference classes, and we know | 
 | 5230 |     // that 'referent' is alphabetically last, so this is easy... | 
| Brian Carlstrom | f363283 | 2014-05-20 15:36:53 -0700 | [diff] [blame] | 5231 |     CHECK_EQ(num_reference_fields, num_fields) << PrettyClass(klass.Get()); | 
| Mathieu Chartier | 54d220e | 2015-07-30 16:20:06 -0700 | [diff] [blame] | 5232 |     CHECK_STREQ(fields->At(num_fields - 1).GetName(), "referent") | 
 | 5233 |         << PrettyClass(klass.Get()); | 
| Elliott Hughes | adb460d | 2011-10-05 17:02:34 -0700 | [diff] [blame] | 5234 |     --num_reference_fields; | 
 | 5235 |   } | 
 | 5236 |  | 
| Mingyao Yang | 98d1cc8 | 2014-05-15 17:02:16 -0700 | [diff] [blame] | 5237 |   size_t size = field_offset.Uint32Value(); | 
| Ian Rogers | 0cfe1fb | 2011-08-26 03:29:44 -0700 | [diff] [blame] | 5238 |   // Update klass | 
| Brian Carlstrom | 3320cf4 | 2011-10-04 14:58:28 -0700 | [diff] [blame] | 5239 |   if (is_static) { | 
 | 5240 |     klass->SetNumReferenceStaticFields(num_reference_fields); | 
| Mingyao Yang | 98d1cc8 | 2014-05-15 17:02:16 -0700 | [diff] [blame] | 5241 |     *class_size = size; | 
| Brian Carlstrom | 3320cf4 | 2011-10-04 14:58:28 -0700 | [diff] [blame] | 5242 |   } else { | 
| Ian Rogers | 0cfe1fb | 2011-08-26 03:29:44 -0700 | [diff] [blame] | 5243 |     klass->SetNumReferenceInstanceFields(num_reference_fields); | 
| Mathieu Chartier | 52a7f5c | 2015-08-18 18:35:52 -0700 | [diff] [blame] | 5244 |     mirror::Class* super_class = klass->GetSuperClass(); | 
 | 5245 |     if (num_reference_fields == 0 || super_class == nullptr) { | 
 | 5246 |       // object has one reference field, klass, but we ignore it since we always visit the class. | 
| Mathieu Chartier | 66c2d2d | 2015-08-25 14:32:32 -0700 | [diff] [blame] | 5247 |       // super_class is null iff the class is java.lang.Object. | 
| Mathieu Chartier | 52a7f5c | 2015-08-18 18:35:52 -0700 | [diff] [blame] | 5248 |       if (super_class == nullptr || | 
 | 5249 |           (super_class->GetClassFlags() & mirror::kClassFlagNoReferenceFields) != 0) { | 
 | 5250 |         klass->SetClassFlags(klass->GetClassFlags() | mirror::kClassFlagNoReferenceFields); | 
| Mathieu Chartier | 66c2d2d | 2015-08-25 14:32:32 -0700 | [diff] [blame] | 5251 |       } | 
 | 5252 |     } | 
 | 5253 |     if (kIsDebugBuild) { | 
 | 5254 |       DCHECK_EQ(super_class == nullptr, klass->DescriptorEquals("Ljava/lang/Object;")); | 
 | 5255 |       size_t total_reference_instance_fields = 0; | 
 | 5256 |       mirror::Class* cur_super = klass.Get(); | 
 | 5257 |       while (cur_super != nullptr) { | 
 | 5258 |         total_reference_instance_fields += cur_super->NumReferenceInstanceFieldsDuringLinking(); | 
 | 5259 |         cur_super = cur_super->GetSuperClass(); | 
 | 5260 |       } | 
 | 5261 |       if (super_class == nullptr) { | 
 | 5262 |         CHECK_EQ(total_reference_instance_fields, 1u) << PrettyDescriptor(klass.Get()); | 
 | 5263 |       } else { | 
 | 5264 |         // Check that there is at least num_reference_fields other than Object.class. | 
 | 5265 |         CHECK_GE(total_reference_instance_fields, 1u + num_reference_fields) | 
 | 5266 |             << PrettyClass(klass.Get()); | 
| Mathieu Chartier | 52a7f5c | 2015-08-18 18:35:52 -0700 | [diff] [blame] | 5267 |       } | 
 | 5268 |     } | 
| Brian Carlstrom | dbc0525 | 2011-09-09 01:59:59 -0700 | [diff] [blame] | 5269 |     if (!klass->IsVariableSize()) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 5270 |       std::string temp; | 
 | 5271 |       DCHECK_GE(size, sizeof(mirror::Object)) << klass->GetDescriptor(&temp); | 
 | 5272 |       size_t previous_size = klass->GetObjectSize(); | 
 | 5273 |       if (previous_size != 0) { | 
 | 5274 |         // Make sure that we didn't originally have an incorrect size. | 
 | 5275 |         CHECK_EQ(previous_size, size) << klass->GetDescriptor(&temp); | 
| Mathieu Chartier | 79b4f38 | 2013-10-23 15:21:37 -0700 | [diff] [blame] | 5276 |       } | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 5277 |       klass->SetObjectSize(size); | 
| Ian Rogers | 0cfe1fb | 2011-08-26 03:29:44 -0700 | [diff] [blame] | 5278 |     } | 
| Ian Rogers | 0cfe1fb | 2011-08-26 03:29:44 -0700 | [diff] [blame] | 5279 |   } | 
| Vladimir Marko | 76649e8 | 2014-11-10 18:32:59 +0000 | [diff] [blame] | 5280 |  | 
 | 5281 |   if (kIsDebugBuild) { | 
 | 5282 |     // Make sure that the fields array is ordered by name but all reference | 
 | 5283 |     // offsets are at the beginning as far as alignment allows. | 
 | 5284 |     MemberOffset start_ref_offset = is_static | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 5285 |         ? klass->GetFirstReferenceStaticFieldOffsetDuringLinking(image_pointer_size_) | 
| Vladimir Marko | 76649e8 | 2014-11-10 18:32:59 +0000 | [diff] [blame] | 5286 |         : klass->GetFirstReferenceInstanceFieldOffset(); | 
 | 5287 |     MemberOffset end_ref_offset(start_ref_offset.Uint32Value() + | 
 | 5288 |                                 num_reference_fields * | 
 | 5289 |                                     sizeof(mirror::HeapReference<mirror::Object>)); | 
 | 5290 |     MemberOffset current_ref_offset = start_ref_offset; | 
 | 5291 |     for (size_t i = 0; i < num_fields; i++) { | 
| Mathieu Chartier | 54d220e | 2015-07-30 16:20:06 -0700 | [diff] [blame] | 5292 |       ArtField* field = &fields->At(i); | 
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 5293 |       VLOG(class_linker) << "LinkFields: " << (is_static ? "static" : "instance") | 
 | 5294 |           << " class=" << PrettyClass(klass.Get()) << " field=" << PrettyField(field) << " offset=" | 
| Nicolas Geoffray | 555b3d0 | 2015-06-23 12:11:24 +0100 | [diff] [blame] | 5295 |           << field->GetOffsetDuringLinking(); | 
| Vladimir Marko | 76649e8 | 2014-11-10 18:32:59 +0000 | [diff] [blame] | 5296 |       if (i != 0) { | 
| Mathieu Chartier | 54d220e | 2015-07-30 16:20:06 -0700 | [diff] [blame] | 5297 |         ArtField* const prev_field = &fields->At(i - 1); | 
| Vladimir Marko | 7a7c1db | 2014-11-17 15:13:34 +0000 | [diff] [blame] | 5298 |         // NOTE: The field names can be the same. This is not possible in the Java language | 
 | 5299 |         // but it's valid Java/dex bytecode and for example proguard can generate such bytecode. | 
| Mathieu Chartier | 54d220e | 2015-07-30 16:20:06 -0700 | [diff] [blame] | 5300 |         DCHECK_LE(strcmp(prev_field->GetName(), field->GetName()), 0); | 
| Vladimir Marko | 76649e8 | 2014-11-10 18:32:59 +0000 | [diff] [blame] | 5301 |       } | 
 | 5302 |       Primitive::Type type = field->GetTypeAsPrimitiveType(); | 
 | 5303 |       bool is_primitive = type != Primitive::kPrimNot; | 
 | 5304 |       if (klass->DescriptorEquals("Ljava/lang/ref/Reference;") && | 
 | 5305 |           strcmp("referent", field->GetName()) == 0) { | 
 | 5306 |         is_primitive = true;  // We lied above, so we have to expect a lie here. | 
 | 5307 |       } | 
 | 5308 |       MemberOffset offset = field->GetOffsetDuringLinking(); | 
 | 5309 |       if (is_primitive) { | 
 | 5310 |         if (offset.Uint32Value() < end_ref_offset.Uint32Value()) { | 
 | 5311 |           // Shuffled before references. | 
 | 5312 |           size_t type_size = Primitive::ComponentSize(type); | 
 | 5313 |           CHECK_LT(type_size, sizeof(mirror::HeapReference<mirror::Object>)); | 
 | 5314 |           CHECK_LT(offset.Uint32Value(), start_ref_offset.Uint32Value()); | 
 | 5315 |           CHECK_LE(offset.Uint32Value() + type_size, start_ref_offset.Uint32Value()); | 
 | 5316 |           CHECK(!IsAligned<sizeof(mirror::HeapReference<mirror::Object>)>(offset.Uint32Value())); | 
 | 5317 |         } | 
 | 5318 |       } else { | 
 | 5319 |         CHECK_EQ(current_ref_offset.Uint32Value(), offset.Uint32Value()); | 
 | 5320 |         current_ref_offset = MemberOffset(current_ref_offset.Uint32Value() + | 
 | 5321 |                                           sizeof(mirror::HeapReference<mirror::Object>)); | 
 | 5322 |       } | 
 | 5323 |     } | 
 | 5324 |     CHECK_EQ(current_ref_offset.Uint32Value(), end_ref_offset.Uint32Value()); | 
 | 5325 |   } | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 5326 |   return true; | 
 | 5327 | } | 
 | 5328 |  | 
| Vladimir Marko | 76649e8 | 2014-11-10 18:32:59 +0000 | [diff] [blame] | 5329 | //  Set the bitmap of reference instance field offsets. | 
| Andreas Gampe | 5a4b8a2 | 2014-09-11 08:30:08 -0700 | [diff] [blame] | 5330 | void ClassLinker::CreateReferenceInstanceOffsets(Handle<mirror::Class> klass) { | 
| Ian Rogers | 0cfe1fb | 2011-08-26 03:29:44 -0700 | [diff] [blame] | 5331 |   uint32_t reference_offsets = 0; | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 5332 |   mirror::Class* super_class = klass->GetSuperClass(); | 
| Ian Rogers | cdc1aaf | 2014-10-09 13:21:38 -0700 | [diff] [blame] | 5333 |   // Leave the reference offsets as 0 for mirror::Object (the class field is handled specially). | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 5334 |   if (super_class != nullptr) { | 
| Ian Rogers | 0cfe1fb | 2011-08-26 03:29:44 -0700 | [diff] [blame] | 5335 |     reference_offsets = super_class->GetReferenceInstanceOffsets(); | 
| Ian Rogers | cdc1aaf | 2014-10-09 13:21:38 -0700 | [diff] [blame] | 5336 |     // Compute reference offsets unless our superclass overflowed. | 
 | 5337 |     if (reference_offsets != mirror::Class::kClassWalkSuper) { | 
 | 5338 |       size_t num_reference_fields = klass->NumReferenceInstanceFieldsDuringLinking(); | 
| Vladimir Marko | 76649e8 | 2014-11-10 18:32:59 +0000 | [diff] [blame] | 5339 |       if (num_reference_fields != 0u) { | 
 | 5340 |         // All of the fields that contain object references are guaranteed be grouped in memory | 
 | 5341 |         // starting at an appropriately aligned address after super class object data. | 
 | 5342 |         uint32_t start_offset = RoundUp(super_class->GetObjectSize(), | 
 | 5343 |                                         sizeof(mirror::HeapReference<mirror::Object>)); | 
 | 5344 |         uint32_t start_bit = (start_offset - mirror::kObjectHeaderSize) / | 
| Ian Rogers | cdc1aaf | 2014-10-09 13:21:38 -0700 | [diff] [blame] | 5345 |             sizeof(mirror::HeapReference<mirror::Object>); | 
| Vladimir Marko | 76649e8 | 2014-11-10 18:32:59 +0000 | [diff] [blame] | 5346 |         if (start_bit + num_reference_fields > 32) { | 
| Ian Rogers | cdc1aaf | 2014-10-09 13:21:38 -0700 | [diff] [blame] | 5347 |           reference_offsets = mirror::Class::kClassWalkSuper; | 
| Ian Rogers | cdc1aaf | 2014-10-09 13:21:38 -0700 | [diff] [blame] | 5348 |         } else { | 
| Vladimir Marko | 76649e8 | 2014-11-10 18:32:59 +0000 | [diff] [blame] | 5349 |           reference_offsets |= (0xffffffffu << start_bit) & | 
 | 5350 |                                (0xffffffffu >> (32 - (start_bit + num_reference_fields))); | 
| Ian Rogers | cdc1aaf | 2014-10-09 13:21:38 -0700 | [diff] [blame] | 5351 |         } | 
 | 5352 |       } | 
| Brian Carlstrom | 4873d46 | 2011-08-21 15:23:39 -0700 | [diff] [blame] | 5353 |     } | 
 | 5354 |   } | 
| Mingyao Yang | faff0f0 | 2014-09-10 12:03:22 -0700 | [diff] [blame] | 5355 |   klass->SetReferenceInstanceOffsets(reference_offsets); | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 5356 | } | 
 | 5357 |  | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 5358 | mirror::String* ClassLinker::ResolveString(const DexFile& dex_file, uint32_t string_idx, | 
| Andreas Gampe | 5a4b8a2 | 2014-09-11 08:30:08 -0700 | [diff] [blame] | 5359 |                                            Handle<mirror::DexCache> dex_cache) { | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 5360 |   DCHECK(dex_cache.Get() != nullptr); | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 5361 |   mirror::String* resolved = dex_cache->GetResolvedString(string_idx); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 5362 |   if (resolved != nullptr) { | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 5363 |     return resolved; | 
 | 5364 |   } | 
| Ian Rogers | dfb325e | 2013-10-30 01:00:44 -0700 | [diff] [blame] | 5365 |   uint32_t utf16_length; | 
 | 5366 |   const char* utf8_data = dex_file.StringDataAndUtf16LengthByIdx(string_idx, &utf16_length); | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 5367 |   mirror::String* string = intern_table_->InternStrong(utf16_length, utf8_data); | 
| Brian Carlstrom | 9ea1cb1 | 2011-08-24 23:18:18 -0700 | [diff] [blame] | 5368 |   dex_cache->SetResolvedString(string_idx, string); | 
 | 5369 |   return string; | 
 | 5370 | } | 
 | 5371 |  | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 5372 | mirror::Class* ClassLinker::ResolveType(const DexFile& dex_file, uint16_t type_idx, | 
| Ian Rogers | ef7d42f | 2014-01-06 12:55:46 -0800 | [diff] [blame] | 5373 |                                         mirror::Class* referrer) { | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 5374 |   StackHandleScope<2> hs(Thread::Current()); | 
 | 5375 |   Handle<mirror::DexCache> dex_cache(hs.NewHandle(referrer->GetDexCache())); | 
 | 5376 |   Handle<mirror::ClassLoader> class_loader(hs.NewHandle(referrer->GetClassLoader())); | 
| Mathieu Chartier | 590fee9 | 2013-09-13 13:46:47 -0700 | [diff] [blame] | 5377 |   return ResolveType(dex_file, type_idx, dex_cache, class_loader); | 
 | 5378 | } | 
 | 5379 |  | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 5380 | mirror::Class* ClassLinker::ResolveType(const DexFile& dex_file, uint16_t type_idx, | 
| Andreas Gampe | 5a4b8a2 | 2014-09-11 08:30:08 -0700 | [diff] [blame] | 5381 |                                         Handle<mirror::DexCache> dex_cache, | 
 | 5382 |                                         Handle<mirror::ClassLoader> class_loader) { | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 5383 |   DCHECK(dex_cache.Get() != nullptr); | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 5384 |   mirror::Class* resolved = dex_cache->GetResolvedType(type_idx); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 5385 |   if (resolved == nullptr) { | 
| Ian Rogers | 9837939 | 2014-02-24 16:53:16 -0800 | [diff] [blame] | 5386 |     Thread* self = Thread::Current(); | 
| Ian Rogers | 0571d35 | 2011-11-03 19:51:38 -0700 | [diff] [blame] | 5387 |     const char* descriptor = dex_file.StringByTypeIdx(type_idx); | 
| Ian Rogers | 9837939 | 2014-02-24 16:53:16 -0800 | [diff] [blame] | 5388 |     resolved = FindClass(self, descriptor, class_loader); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 5389 |     if (resolved != nullptr) { | 
| Jesse Wilson | 254db0f | 2011-11-16 16:44:11 -0500 | [diff] [blame] | 5390 |       // TODO: we used to throw here if resolved's class loader was not the | 
 | 5391 |       //       boot class loader. This was to permit different classes with the | 
 | 5392 |       //       same name to be loaded simultaneously by different loaders | 
| Ian Rogers | 0cfe1fb | 2011-08-26 03:29:44 -0700 | [diff] [blame] | 5393 |       dex_cache->SetResolvedType(type_idx, resolved); | 
 | 5394 |     } else { | 
| Ian Rogers | 62d6c77 | 2013-02-27 08:32:07 -0800 | [diff] [blame] | 5395 |       CHECK(self->IsExceptionPending()) | 
| Ian Rogers | cab0101 | 2012-01-10 17:35:46 -0800 | [diff] [blame] | 5396 |           << "Expected pending exception for failed resolution of: " << descriptor; | 
| Ian Rogers | 62d6c77 | 2013-02-27 08:32:07 -0800 | [diff] [blame] | 5397 |       // Convert a ClassNotFoundException to a NoClassDefFoundError. | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 5398 |       StackHandleScope<1> hs(self); | 
| Nicolas Geoffray | 14691c5 | 2015-03-05 10:40:17 +0000 | [diff] [blame] | 5399 |       Handle<mirror::Throwable> cause(hs.NewHandle(self->GetException())); | 
| Ian Rogers | 62d6c77 | 2013-02-27 08:32:07 -0800 | [diff] [blame] | 5400 |       if (cause->InstanceOf(GetClassRoot(kJavaLangClassNotFoundException))) { | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 5401 |         DCHECK(resolved == nullptr);  // No Handle needed to preserve resolved. | 
| Ian Rogers | 9837939 | 2014-02-24 16:53:16 -0800 | [diff] [blame] | 5402 |         self->ClearException(); | 
| jeffhao | 8cd6dda | 2012-02-22 10:15:34 -0800 | [diff] [blame] | 5403 |         ThrowNoClassDefFoundError("Failed resolution of: %s", descriptor); | 
| Nicolas Geoffray | 14691c5 | 2015-03-05 10:40:17 +0000 | [diff] [blame] | 5404 |         self->GetException()->SetCause(cause.Get()); | 
| jeffhao | 8cd6dda | 2012-02-22 10:15:34 -0800 | [diff] [blame] | 5405 |       } | 
| Ian Rogers | 0cfe1fb | 2011-08-26 03:29:44 -0700 | [diff] [blame] | 5406 |     } | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 5407 |   } | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 5408 |   DCHECK((resolved == nullptr) || resolved->IsResolved() || resolved->IsErroneous()) | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 5409 |       << PrettyDescriptor(resolved) << " " << resolved->GetStatus(); | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 5410 |   return resolved; | 
 | 5411 | } | 
 | 5412 |  | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 5413 | ArtMethod* ClassLinker::ResolveMethod(const DexFile& dex_file, uint32_t method_idx, | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 5414 |                                       Handle<mirror::DexCache> dex_cache, | 
 | 5415 |                                       Handle<mirror::ClassLoader> class_loader, | 
 | 5416 |                                       ArtMethod* referrer, InvokeType type) { | 
| Andreas Gampe | eff0f5d | 2014-08-13 21:49:37 -0700 | [diff] [blame] | 5417 |   DCHECK(dex_cache.Get() != nullptr); | 
| Ian Rogers | 08f753d | 2012-08-24 14:35:25 -0700 | [diff] [blame] | 5418 |   // Check for hit in the dex cache. | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 5419 |   ArtMethod* resolved = dex_cache->GetResolvedMethod(method_idx, image_pointer_size_); | 
| Mathieu Chartier | 0cd8135 | 2014-05-22 16:48:55 -0700 | [diff] [blame] | 5420 |   if (resolved != nullptr && !resolved->IsRuntimeMethod()) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 5421 |     DCHECK(resolved->GetDeclaringClassUnchecked() != nullptr) << resolved->GetDexMethodIndex(); | 
| Brian Carlstrom | 9ea1cb1 | 2011-08-24 23:18:18 -0700 | [diff] [blame] | 5422 |     return resolved; | 
 | 5423 |   } | 
| Ian Rogers | 08f753d | 2012-08-24 14:35:25 -0700 | [diff] [blame] | 5424 |   // Fail, get the declaring class. | 
| Brian Carlstrom | 9ea1cb1 | 2011-08-24 23:18:18 -0700 | [diff] [blame] | 5425 |   const DexFile::MethodId& method_id = dex_file.GetMethodId(method_idx); | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 5426 |   mirror::Class* klass = ResolveType(dex_file, method_id.class_idx_, dex_cache, class_loader); | 
| Andreas Gampe | eff0f5d | 2014-08-13 21:49:37 -0700 | [diff] [blame] | 5427 |   if (klass == nullptr) { | 
| Elliott Hughes | cc5f9a9 | 2011-09-28 19:17:29 -0700 | [diff] [blame] | 5428 |     DCHECK(Thread::Current()->IsExceptionPending()); | 
| Andreas Gampe | eff0f5d | 2014-08-13 21:49:37 -0700 | [diff] [blame] | 5429 |     return nullptr; | 
| Brian Carlstrom | 9ea1cb1 | 2011-08-24 23:18:18 -0700 | [diff] [blame] | 5430 |   } | 
| Ian Rogers | 08f753d | 2012-08-24 14:35:25 -0700 | [diff] [blame] | 5431 |   // Scan using method_idx, this saves string compares but will only hit for matching dex | 
 | 5432 |   // caches/files. | 
 | 5433 |   switch (type) { | 
 | 5434 |     case kDirect:  // Fall-through. | 
 | 5435 |     case kStatic: | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 5436 |       resolved = klass->FindDirectMethod(dex_cache.Get(), method_idx, image_pointer_size_); | 
 | 5437 |       DCHECK(resolved == nullptr || resolved->GetDeclaringClassUnchecked() != nullptr); | 
| Ian Rogers | 08f753d | 2012-08-24 14:35:25 -0700 | [diff] [blame] | 5438 |       break; | 
 | 5439 |     case kInterface: | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 5440 |       resolved = klass->FindInterfaceMethod(dex_cache.Get(), method_idx, image_pointer_size_); | 
| Andreas Gampe | eff0f5d | 2014-08-13 21:49:37 -0700 | [diff] [blame] | 5441 |       DCHECK(resolved == nullptr || resolved->GetDeclaringClass()->IsInterface()); | 
| Ian Rogers | 08f753d | 2012-08-24 14:35:25 -0700 | [diff] [blame] | 5442 |       break; | 
 | 5443 |     case kSuper:  // Fall-through. | 
 | 5444 |     case kVirtual: | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 5445 |       resolved = klass->FindVirtualMethod(dex_cache.Get(), method_idx, image_pointer_size_); | 
| Ian Rogers | 08f753d | 2012-08-24 14:35:25 -0700 | [diff] [blame] | 5446 |       break; | 
 | 5447 |     default: | 
 | 5448 |       LOG(FATAL) << "Unreachable - invocation type: " << type; | 
| Ian Rogers | 2c4257b | 2014-10-24 14:20:06 -0700 | [diff] [blame] | 5449 |       UNREACHABLE(); | 
| Brian Carlstrom | 20cfffa | 2011-08-26 02:31:27 -0700 | [diff] [blame] | 5450 |   } | 
| Andreas Gampe | eff0f5d | 2014-08-13 21:49:37 -0700 | [diff] [blame] | 5451 |   if (resolved == nullptr) { | 
| Ian Rogers | 08f753d | 2012-08-24 14:35:25 -0700 | [diff] [blame] | 5452 |     // Search by name, which works across dex files. | 
| Ian Rogers | 7b0c5b4 | 2012-02-16 15:29:07 -0800 | [diff] [blame] | 5453 |     const char* name = dex_file.StringDataByIdx(method_id.name_idx_); | 
| Ian Rogers | d91d6d6 | 2013-09-25 20:26:14 -0700 | [diff] [blame] | 5454 |     const Signature signature = dex_file.GetMethodSignature(method_id); | 
| Ian Rogers | 08f753d | 2012-08-24 14:35:25 -0700 | [diff] [blame] | 5455 |     switch (type) { | 
 | 5456 |       case kDirect:  // Fall-through. | 
 | 5457 |       case kStatic: | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 5458 |         resolved = klass->FindDirectMethod(name, signature, image_pointer_size_); | 
 | 5459 |         DCHECK(resolved == nullptr || resolved->GetDeclaringClassUnchecked() != nullptr); | 
| Ian Rogers | 08f753d | 2012-08-24 14:35:25 -0700 | [diff] [blame] | 5460 |         break; | 
 | 5461 |       case kInterface: | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 5462 |         resolved = klass->FindInterfaceMethod(name, signature, image_pointer_size_); | 
| Andreas Gampe | eff0f5d | 2014-08-13 21:49:37 -0700 | [diff] [blame] | 5463 |         DCHECK(resolved == nullptr || resolved->GetDeclaringClass()->IsInterface()); | 
| Ian Rogers | 08f753d | 2012-08-24 14:35:25 -0700 | [diff] [blame] | 5464 |         break; | 
 | 5465 |       case kSuper:  // Fall-through. | 
 | 5466 |       case kVirtual: | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 5467 |         resolved = klass->FindVirtualMethod(name, signature, image_pointer_size_); | 
| Ian Rogers | 08f753d | 2012-08-24 14:35:25 -0700 | [diff] [blame] | 5468 |         break; | 
| Ian Rogers | 7b0c5b4 | 2012-02-16 15:29:07 -0800 | [diff] [blame] | 5469 |     } | 
| Brian Carlstrom | 9ea1cb1 | 2011-08-24 23:18:18 -0700 | [diff] [blame] | 5470 |   } | 
| Andreas Gampe | eff0f5d | 2014-08-13 21:49:37 -0700 | [diff] [blame] | 5471 |   // If we found a method, check for incompatible class changes. | 
 | 5472 |   if (LIKELY(resolved != nullptr && !resolved->CheckIncompatibleClassChange(type))) { | 
| Ian Rogers | 08f753d | 2012-08-24 14:35:25 -0700 | [diff] [blame] | 5473 |     // Be a good citizen and update the dex cache to speed subsequent calls. | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 5474 |     dex_cache->SetResolvedMethod(method_idx, resolved, image_pointer_size_); | 
| Ian Rogers | 08f753d | 2012-08-24 14:35:25 -0700 | [diff] [blame] | 5475 |     return resolved; | 
 | 5476 |   } else { | 
| Andreas Gampe | eff0f5d | 2014-08-13 21:49:37 -0700 | [diff] [blame] | 5477 |     // If we had a method, it's an incompatible-class-change error. | 
 | 5478 |     if (resolved != nullptr) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 5479 |       ThrowIncompatibleClassChangeError(type, resolved->GetInvokeType(), resolved, referrer); | 
| Andreas Gampe | eff0f5d | 2014-08-13 21:49:37 -0700 | [diff] [blame] | 5480 |     } else { | 
 | 5481 |       // We failed to find the method which means either an access error, an incompatible class | 
 | 5482 |       // change, or no such method. First try to find the method among direct and virtual methods. | 
 | 5483 |       const char* name = dex_file.StringDataByIdx(method_id.name_idx_); | 
 | 5484 |       const Signature signature = dex_file.GetMethodSignature(method_id); | 
 | 5485 |       switch (type) { | 
 | 5486 |         case kDirect: | 
 | 5487 |         case kStatic: | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 5488 |           resolved = klass->FindVirtualMethod(name, signature, image_pointer_size_); | 
| Andreas Gampe | eff0f5d | 2014-08-13 21:49:37 -0700 | [diff] [blame] | 5489 |           // Note: kDirect and kStatic are also mutually exclusive, but in that case we would | 
 | 5490 |           //       have had a resolved method before, which triggers the "true" branch above. | 
 | 5491 |           break; | 
 | 5492 |         case kInterface: | 
 | 5493 |         case kVirtual: | 
 | 5494 |         case kSuper: | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 5495 |           resolved = klass->FindDirectMethod(name, signature, image_pointer_size_); | 
| Andreas Gampe | eff0f5d | 2014-08-13 21:49:37 -0700 | [diff] [blame] | 5496 |           break; | 
 | 5497 |       } | 
 | 5498 |  | 
 | 5499 |       // If we found something, check that it can be accessed by the referrer. | 
| Ian Rogers | e0a02da | 2014-12-02 14:10:53 -0800 | [diff] [blame] | 5500 |       bool exception_generated = false; | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 5501 |       if (resolved != nullptr && referrer != nullptr) { | 
| Andreas Gampe | eff0f5d | 2014-08-13 21:49:37 -0700 | [diff] [blame] | 5502 |         mirror::Class* methods_class = resolved->GetDeclaringClass(); | 
 | 5503 |         mirror::Class* referring_class = referrer->GetDeclaringClass(); | 
 | 5504 |         if (!referring_class->CanAccess(methods_class)) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 5505 |           ThrowIllegalAccessErrorClassForMethodDispatch(referring_class, methods_class, resolved, | 
 | 5506 |                                                         type); | 
| Ian Rogers | e0a02da | 2014-12-02 14:10:53 -0800 | [diff] [blame] | 5507 |           exception_generated = true; | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 5508 |         } else if (!referring_class->CanAccessMember(methods_class, resolved->GetAccessFlags())) { | 
| Andreas Gampe | eff0f5d | 2014-08-13 21:49:37 -0700 | [diff] [blame] | 5509 |           ThrowIllegalAccessErrorMethod(referring_class, resolved); | 
| Ian Rogers | e0a02da | 2014-12-02 14:10:53 -0800 | [diff] [blame] | 5510 |           exception_generated = true; | 
| Andreas Gampe | eff0f5d | 2014-08-13 21:49:37 -0700 | [diff] [blame] | 5511 |         } | 
 | 5512 |       } | 
| Ian Rogers | e0a02da | 2014-12-02 14:10:53 -0800 | [diff] [blame] | 5513 |       if (!exception_generated) { | 
 | 5514 |         // Otherwise, throw an IncompatibleClassChangeError if we found something, and check | 
 | 5515 |         // interface methods and throw if we find the method there. If we find nothing, throw a | 
 | 5516 |         // NoSuchMethodError. | 
 | 5517 |         switch (type) { | 
 | 5518 |           case kDirect: | 
 | 5519 |           case kStatic: | 
| Andreas Gampe | eff0f5d | 2014-08-13 21:49:37 -0700 | [diff] [blame] | 5520 |             if (resolved != nullptr) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 5521 |               ThrowIncompatibleClassChangeError(type, kVirtual, resolved, referrer); | 
| Andreas Gampe | eff0f5d | 2014-08-13 21:49:37 -0700 | [diff] [blame] | 5522 |             } else { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 5523 |               resolved = klass->FindInterfaceMethod(name, signature, image_pointer_size_); | 
| Ian Rogers | e0a02da | 2014-12-02 14:10:53 -0800 | [diff] [blame] | 5524 |               if (resolved != nullptr) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 5525 |                 ThrowIncompatibleClassChangeError(type, kInterface, resolved, referrer); | 
| Ian Rogers | e0a02da | 2014-12-02 14:10:53 -0800 | [diff] [blame] | 5526 |               } else { | 
 | 5527 |                 ThrowNoSuchMethodError(type, klass, name, signature); | 
 | 5528 |               } | 
| Andreas Gampe | eff0f5d | 2014-08-13 21:49:37 -0700 | [diff] [blame] | 5529 |             } | 
| Ian Rogers | e0a02da | 2014-12-02 14:10:53 -0800 | [diff] [blame] | 5530 |             break; | 
 | 5531 |           case kInterface: | 
| Andreas Gampe | eff0f5d | 2014-08-13 21:49:37 -0700 | [diff] [blame] | 5532 |             if (resolved != nullptr) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 5533 |               ThrowIncompatibleClassChangeError(type, kDirect, resolved, referrer); | 
| Ian Rogers | e0a02da | 2014-12-02 14:10:53 -0800 | [diff] [blame] | 5534 |             } else { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 5535 |               resolved = klass->FindVirtualMethod(name, signature, image_pointer_size_); | 
| Ian Rogers | e0a02da | 2014-12-02 14:10:53 -0800 | [diff] [blame] | 5536 |               if (resolved != nullptr) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 5537 |                 ThrowIncompatibleClassChangeError(type, kVirtual, resolved, referrer); | 
| Ian Rogers | e0a02da | 2014-12-02 14:10:53 -0800 | [diff] [blame] | 5538 |               } else { | 
 | 5539 |                 ThrowNoSuchMethodError(type, klass, name, signature); | 
 | 5540 |               } | 
 | 5541 |             } | 
 | 5542 |             break; | 
 | 5543 |           case kSuper: | 
 | 5544 |             if (resolved != nullptr) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 5545 |               ThrowIncompatibleClassChangeError(type, kDirect, resolved, referrer); | 
| Andreas Gampe | eff0f5d | 2014-08-13 21:49:37 -0700 | [diff] [blame] | 5546 |             } else { | 
 | 5547 |               ThrowNoSuchMethodError(type, klass, name, signature); | 
 | 5548 |             } | 
| Ian Rogers | e0a02da | 2014-12-02 14:10:53 -0800 | [diff] [blame] | 5549 |             break; | 
 | 5550 |           case kVirtual: | 
 | 5551 |             if (resolved != nullptr) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 5552 |               ThrowIncompatibleClassChangeError(type, kDirect, resolved, referrer); | 
| Ian Rogers | e0a02da | 2014-12-02 14:10:53 -0800 | [diff] [blame] | 5553 |             } else { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 5554 |               resolved = klass->FindInterfaceMethod(name, signature, image_pointer_size_); | 
| Ian Rogers | e0a02da | 2014-12-02 14:10:53 -0800 | [diff] [blame] | 5555 |               if (resolved != nullptr) { | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 5556 |                 ThrowIncompatibleClassChangeError(type, kInterface, resolved, referrer); | 
| Ian Rogers | e0a02da | 2014-12-02 14:10:53 -0800 | [diff] [blame] | 5557 |               } else { | 
 | 5558 |                 ThrowNoSuchMethodError(type, klass, name, signature); | 
 | 5559 |               } | 
 | 5560 |             } | 
 | 5561 |             break; | 
 | 5562 |         } | 
| Andreas Gampe | eff0f5d | 2014-08-13 21:49:37 -0700 | [diff] [blame] | 5563 |       } | 
| Ian Rogers | 08f753d | 2012-08-24 14:35:25 -0700 | [diff] [blame] | 5564 |     } | 
| Ian Rogers | e0a02da | 2014-12-02 14:10:53 -0800 | [diff] [blame] | 5565 |     Thread::Current()->AssertPendingException(); | 
| Andreas Gampe | eff0f5d | 2014-08-13 21:49:37 -0700 | [diff] [blame] | 5566 |     return nullptr; | 
| Ian Rogers | 08f753d | 2012-08-24 14:35:25 -0700 | [diff] [blame] | 5567 |   } | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 5568 | } | 
 | 5569 |  | 
| Jeff Hao | 13e748b | 2015-08-25 20:44:19 +0000 | [diff] [blame] | 5570 | ArtMethod* ClassLinker::ResolveMethodWithoutInvokeType(const DexFile& dex_file, | 
 | 5571 |                                                        uint32_t method_idx, | 
 | 5572 |                                                        Handle<mirror::DexCache> dex_cache, | 
 | 5573 |                                                        Handle<mirror::ClassLoader> class_loader) { | 
 | 5574 |   ArtMethod* resolved = dex_cache->GetResolvedMethod(method_idx, image_pointer_size_); | 
 | 5575 |   if (resolved != nullptr && !resolved->IsRuntimeMethod()) { | 
 | 5576 |     DCHECK(resolved->GetDeclaringClassUnchecked() != nullptr) << resolved->GetDexMethodIndex(); | 
 | 5577 |     return resolved; | 
 | 5578 |   } | 
 | 5579 |   // Fail, get the declaring class. | 
 | 5580 |   const DexFile::MethodId& method_id = dex_file.GetMethodId(method_idx); | 
 | 5581 |   mirror::Class* klass = ResolveType(dex_file, method_id.class_idx_, dex_cache, class_loader); | 
 | 5582 |   if (klass == nullptr) { | 
 | 5583 |     Thread::Current()->AssertPendingException(); | 
 | 5584 |     return nullptr; | 
 | 5585 |   } | 
 | 5586 |   if (klass->IsInterface()) { | 
 | 5587 |     LOG(FATAL) << "ResolveAmbiguousMethod: unexpected method in interface: " << PrettyClass(klass); | 
 | 5588 |     return nullptr; | 
 | 5589 |   } | 
 | 5590 |  | 
 | 5591 |   // Search both direct and virtual methods | 
 | 5592 |   resolved = klass->FindDirectMethod(dex_cache.Get(), method_idx, image_pointer_size_); | 
 | 5593 |   if (resolved == nullptr) { | 
 | 5594 |     resolved = klass->FindVirtualMethod(dex_cache.Get(), method_idx, image_pointer_size_); | 
 | 5595 |   } | 
 | 5596 |  | 
 | 5597 |   return resolved; | 
 | 5598 | } | 
 | 5599 |  | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 5600 | ArtField* ClassLinker::ResolveField(const DexFile& dex_file, uint32_t field_idx, | 
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 5601 |                                     Handle<mirror::DexCache> dex_cache, | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 5602 |                                     Handle<mirror::ClassLoader> class_loader, bool is_static) { | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 5603 |   DCHECK(dex_cache.Get() != nullptr); | 
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 5604 |   ArtField* resolved = dex_cache->GetResolvedField(field_idx, image_pointer_size_); | 
| Andreas Gampe | 58a5af8 | 2014-07-31 16:23:49 -0700 | [diff] [blame] | 5605 |   if (resolved != nullptr) { | 
| Brian Carlstrom | 9ea1cb1 | 2011-08-24 23:18:18 -0700 | [diff] [blame] | 5606 |     return resolved; | 
 | 5607 |   } | 
 | 5608 |   const DexFile::FieldId& field_id = dex_file.GetFieldId(field_idx); | 
| Mathieu Chartier | f832284 | 2014-05-16 10:59:25 -0700 | [diff] [blame] | 5609 |   Thread* const self = Thread::Current(); | 
 | 5610 |   StackHandleScope<1> hs(self); | 
 | 5611 |   Handle<mirror::Class> klass( | 
 | 5612 |       hs.NewHandle(ResolveType(dex_file, field_id.class_idx_, dex_cache, class_loader))); | 
| Andreas Gampe | 58a5af8 | 2014-07-31 16:23:49 -0700 | [diff] [blame] | 5613 |   if (klass.Get() == nullptr) { | 
| Ian Rogers | 9f1ab12 | 2011-12-12 08:52:43 -0800 | [diff] [blame] | 5614 |     DCHECK(Thread::Current()->IsExceptionPending()); | 
| Andreas Gampe | 58a5af8 | 2014-07-31 16:23:49 -0700 | [diff] [blame] | 5615 |     return nullptr; | 
| Brian Carlstrom | 9ea1cb1 | 2011-08-24 23:18:18 -0700 | [diff] [blame] | 5616 |   } | 
 | 5617 |  | 
| Brian Carlstrom | 20cfffa | 2011-08-26 02:31:27 -0700 | [diff] [blame] | 5618 |   if (is_static) { | 
| Mathieu Chartier | f832284 | 2014-05-16 10:59:25 -0700 | [diff] [blame] | 5619 |     resolved = mirror::Class::FindStaticField(self, klass, dex_cache.Get(), field_idx); | 
| Brian Carlstrom | 20cfffa | 2011-08-26 02:31:27 -0700 | [diff] [blame] | 5620 |   } else { | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 5621 |     resolved = klass->FindInstanceField(dex_cache.Get(), field_idx); | 
| Brian Carlstrom | 20cfffa | 2011-08-26 02:31:27 -0700 | [diff] [blame] | 5622 |   } | 
| Ian Rogers | 7b0c5b4 | 2012-02-16 15:29:07 -0800 | [diff] [blame] | 5623 |  | 
| Andreas Gampe | 58a5af8 | 2014-07-31 16:23:49 -0700 | [diff] [blame] | 5624 |   if (resolved == nullptr) { | 
| Ian Rogers | 7b0c5b4 | 2012-02-16 15:29:07 -0800 | [diff] [blame] | 5625 |     const char* name = dex_file.GetFieldName(field_id); | 
 | 5626 |     const char* type = dex_file.GetFieldTypeDescriptor(field_id); | 
 | 5627 |     if (is_static) { | 
| Mathieu Chartier | f832284 | 2014-05-16 10:59:25 -0700 | [diff] [blame] | 5628 |       resolved = mirror::Class::FindStaticField(self, klass, name, type); | 
| Ian Rogers | 7b0c5b4 | 2012-02-16 15:29:07 -0800 | [diff] [blame] | 5629 |     } else { | 
 | 5630 |       resolved = klass->FindInstanceField(name, type); | 
 | 5631 |     } | 
| Andreas Gampe | 58a5af8 | 2014-07-31 16:23:49 -0700 | [diff] [blame] | 5632 |     if (resolved == nullptr) { | 
| Mathieu Chartier | f832284 | 2014-05-16 10:59:25 -0700 | [diff] [blame] | 5633 |       ThrowNoSuchFieldError(is_static ? "static " : "instance ", klass.Get(), type, name); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 5634 |       return nullptr; | 
| Ian Rogers | 7b0c5b4 | 2012-02-16 15:29:07 -0800 | [diff] [blame] | 5635 |     } | 
| Ian Rogers | b067ac2 | 2011-12-13 18:05:09 -0800 | [diff] [blame] | 5636 |   } | 
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 5637 |   dex_cache->SetResolvedField(field_idx, resolved, image_pointer_size_); | 
| Ian Rogers | b067ac2 | 2011-12-13 18:05:09 -0800 | [diff] [blame] | 5638 |   return resolved; | 
 | 5639 | } | 
 | 5640 |  | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 5641 | ArtField* ClassLinker::ResolveFieldJLS(const DexFile& dex_file, uint32_t field_idx, | 
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 5642 |                                        Handle<mirror::DexCache> dex_cache, | 
 | 5643 |                                        Handle<mirror::ClassLoader> class_loader) { | 
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 5644 |   DCHECK(dex_cache.Get() != nullptr); | 
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 5645 |   ArtField* resolved = dex_cache->GetResolvedField(field_idx, image_pointer_size_); | 
| Andreas Gampe | 58a5af8 | 2014-07-31 16:23:49 -0700 | [diff] [blame] | 5646 |   if (resolved != nullptr) { | 
| Ian Rogers | b067ac2 | 2011-12-13 18:05:09 -0800 | [diff] [blame] | 5647 |     return resolved; | 
 | 5648 |   } | 
 | 5649 |   const DexFile::FieldId& field_id = dex_file.GetFieldId(field_idx); | 
| Mathieu Chartier | f832284 | 2014-05-16 10:59:25 -0700 | [diff] [blame] | 5650 |   Thread* self = Thread::Current(); | 
 | 5651 |   StackHandleScope<1> hs(self); | 
 | 5652 |   Handle<mirror::Class> klass( | 
 | 5653 |       hs.NewHandle(ResolveType(dex_file, field_id.class_idx_, dex_cache, class_loader))); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 5654 |   if (klass.Get() == nullptr) { | 
| Ian Rogers | b067ac2 | 2011-12-13 18:05:09 -0800 | [diff] [blame] | 5655 |     DCHECK(Thread::Current()->IsExceptionPending()); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 5656 |     return nullptr; | 
| Ian Rogers | b067ac2 | 2011-12-13 18:05:09 -0800 | [diff] [blame] | 5657 |   } | 
 | 5658 |  | 
| Ian Rogers | dfb325e | 2013-10-30 01:00:44 -0700 | [diff] [blame] | 5659 |   StringPiece name(dex_file.StringDataByIdx(field_id.name_idx_)); | 
 | 5660 |   StringPiece type(dex_file.StringDataByIdx( | 
| Ian Rogers | fc0e94b | 2013-09-23 23:51:32 -0700 | [diff] [blame] | 5661 |       dex_file.GetTypeId(field_id.type_idx_).descriptor_idx_)); | 
| Mathieu Chartier | f832284 | 2014-05-16 10:59:25 -0700 | [diff] [blame] | 5662 |   resolved = mirror::Class::FindField(self, klass, name, type); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 5663 |   if (resolved != nullptr) { | 
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 5664 |     dex_cache->SetResolvedField(field_idx, resolved, image_pointer_size_); | 
| Ian Rogers | b067ac2 | 2011-12-13 18:05:09 -0800 | [diff] [blame] | 5665 |   } else { | 
| Mathieu Chartier | f832284 | 2014-05-16 10:59:25 -0700 | [diff] [blame] | 5666 |     ThrowNoSuchFieldError("", klass.Get(), type, name); | 
| Brian Carlstrom | 9ea1cb1 | 2011-08-24 23:18:18 -0700 | [diff] [blame] | 5667 |   } | 
 | 5668 |   return resolved; | 
| Carl Shapiro | 5fafe2b | 2011-07-09 15:34:41 -0700 | [diff] [blame] | 5669 | } | 
 | 5670 |  | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 5671 | const char* ClassLinker::MethodShorty(uint32_t method_idx, ArtMethod* referrer, | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 5672 |                                       uint32_t* length) { | 
 | 5673 |   mirror::Class* declaring_class = referrer->GetDeclaringClass(); | 
 | 5674 |   mirror::DexCache* dex_cache = declaring_class->GetDexCache(); | 
| Ian Rogers | 4445a7e | 2012-10-05 17:19:13 -0700 | [diff] [blame] | 5675 |   const DexFile& dex_file = *dex_cache->GetDexFile(); | 
| Ian Rogers | ad25ac5 | 2011-10-04 19:13:33 -0700 | [diff] [blame] | 5676 |   const DexFile::MethodId& method_id = dex_file.GetMethodId(method_idx); | 
| Ian Rogers | 1984651 | 2012-02-24 11:42:47 -0800 | [diff] [blame] | 5677 |   return dex_file.GetMethodShorty(method_id, length); | 
| Ian Rogers | ad25ac5 | 2011-10-04 19:13:33 -0700 | [diff] [blame] | 5678 | } | 
 | 5679 |  | 
| Mathieu Chartier | e0671ce | 2015-07-28 17:23:28 -0700 | [diff] [blame] | 5680 | class DumpClassVisitor : public ClassVisitor { | 
 | 5681 |  public: | 
 | 5682 |   explicit DumpClassVisitor(int flags) : flags_(flags) {} | 
 | 5683 |  | 
 | 5684 |   bool Visit(mirror::Class* klass) OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) { | 
 | 5685 |     klass->DumpClass(LOG(ERROR), flags_); | 
 | 5686 |     return true; | 
 | 5687 |   } | 
 | 5688 |  | 
 | 5689 |  private: | 
 | 5690 |   const int flags_; | 
 | 5691 | }; | 
| Elliott Hughes | 9d5ccec | 2011-09-19 13:19:50 -0700 | [diff] [blame] | 5692 |  | 
| Mathieu Chartier | cc5ebdf | 2015-07-27 11:19:43 -0700 | [diff] [blame] | 5693 | void ClassLinker::DumpAllClasses(int flags) { | 
| Mathieu Chartier | e0671ce | 2015-07-28 17:23:28 -0700 | [diff] [blame] | 5694 |   DumpClassVisitor visitor(flags); | 
 | 5695 |   VisitClasses(&visitor); | 
| Elliott Hughes | 9d5ccec | 2011-09-19 13:19:50 -0700 | [diff] [blame] | 5696 | } | 
 | 5697 |  | 
| Elliott Hughes | 956af0f | 2014-12-11 14:34:28 -0800 | [diff] [blame] | 5698 | static OatFile::OatMethod CreateOatMethod(const void* code) { | 
| Ian Rogers | 6f3dbba | 2014-10-14 17:41:57 -0700 | [diff] [blame] | 5699 |   CHECK(code != nullptr); | 
| Mathieu Chartier | 957ca1c | 2014-11-21 16:51:29 -0800 | [diff] [blame] | 5700 |   const uint8_t* base = reinterpret_cast<const uint8_t*>(code);  // Base of data points at code. | 
 | 5701 |   base -= sizeof(void*);  // Move backward so that code_offset != 0. | 
 | 5702 |   const uint32_t code_offset = sizeof(void*); | 
 | 5703 |   return OatFile::OatMethod(base, code_offset); | 
| Ian Rogers | 6f3dbba | 2014-10-14 17:41:57 -0700 | [diff] [blame] | 5704 | } | 
 | 5705 |  | 
| Ian Rogers | 6f3dbba | 2014-10-14 17:41:57 -0700 | [diff] [blame] | 5706 | bool ClassLinker::IsQuickResolutionStub(const void* entry_point) const { | 
 | 5707 |   return (entry_point == GetQuickResolutionStub()) || | 
 | 5708 |       (quick_resolution_trampoline_ == entry_point); | 
 | 5709 | } | 
 | 5710 |  | 
| Ian Rogers | 6f3dbba | 2014-10-14 17:41:57 -0700 | [diff] [blame] | 5711 | bool ClassLinker::IsQuickToInterpreterBridge(const void* entry_point) const { | 
 | 5712 |   return (entry_point == GetQuickToInterpreterBridge()) || | 
 | 5713 |       (quick_to_interpreter_bridge_trampoline_ == entry_point); | 
 | 5714 | } | 
 | 5715 |  | 
 | 5716 | bool ClassLinker::IsQuickGenericJniStub(const void* entry_point) const { | 
 | 5717 |   return (entry_point == GetQuickGenericJniStub()) || | 
 | 5718 |       (quick_generic_jni_trampoline_ == entry_point); | 
 | 5719 | } | 
 | 5720 |  | 
 | 5721 | const void* ClassLinker::GetRuntimeQuickGenericJniStub() const { | 
 | 5722 |   return GetQuickGenericJniStub(); | 
 | 5723 | } | 
 | 5724 |  | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 5725 | void ClassLinker::SetEntryPointsToCompiledCode(ArtMethod* method, | 
| Elliott Hughes | 956af0f | 2014-12-11 14:34:28 -0800 | [diff] [blame] | 5726 |                                                const void* method_code) const { | 
 | 5727 |   OatFile::OatMethod oat_method = CreateOatMethod(method_code); | 
| Ian Rogers | 6f3dbba | 2014-10-14 17:41:57 -0700 | [diff] [blame] | 5728 |   oat_method.LinkMethod(method); | 
| Ian Rogers | 6f3dbba | 2014-10-14 17:41:57 -0700 | [diff] [blame] | 5729 | } | 
 | 5730 |  | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 5731 | void ClassLinker::SetEntryPointsToInterpreter(ArtMethod* method) const { | 
| Ian Rogers | 6f3dbba | 2014-10-14 17:41:57 -0700 | [diff] [blame] | 5732 |   if (!method->IsNative()) { | 
| Ian Rogers | 6f3dbba | 2014-10-14 17:41:57 -0700 | [diff] [blame] | 5733 |     method->SetEntryPointFromQuickCompiledCode(GetQuickToInterpreterBridge()); | 
 | 5734 |   } else { | 
 | 5735 |     const void* quick_method_code = GetQuickGenericJniStub(); | 
| Elliott Hughes | 956af0f | 2014-12-11 14:34:28 -0800 | [diff] [blame] | 5736 |     OatFile::OatMethod oat_method = CreateOatMethod(quick_method_code); | 
| Ian Rogers | 6f3dbba | 2014-10-14 17:41:57 -0700 | [diff] [blame] | 5737 |     oat_method.LinkMethod(method); | 
| Ian Rogers | 6f3dbba | 2014-10-14 17:41:57 -0700 | [diff] [blame] | 5738 |   } | 
 | 5739 | } | 
 | 5740 |  | 
| Ian Rogers | 7dfb28c | 2013-08-22 08:18:36 -0700 | [diff] [blame] | 5741 | void ClassLinker::DumpForSigQuit(std::ostream& os) { | 
| Mathieu Chartier | 6b06953 | 2015-08-05 15:08:12 -0700 | [diff] [blame] | 5742 |   ScopedObjectAccess soa(Thread::Current()); | 
| Ian Rogers | 7dfb28c | 2013-08-22 08:18:36 -0700 | [diff] [blame] | 5743 |   if (dex_cache_image_class_lookup_required_) { | 
 | 5744 |     MoveImageClassesToClassTable(); | 
 | 5745 |   } | 
| Mathieu Chartier | 6b06953 | 2015-08-05 15:08:12 -0700 | [diff] [blame] | 5746 |   ReaderMutexLock mu(soa.Self(), *Locks::classlinker_classes_lock_); | 
| Mathieu Chartier | cc5ebdf | 2015-07-27 11:19:43 -0700 | [diff] [blame] | 5747 |   os << "Zygote loaded classes=" << NumZygoteClasses() << " post zygote classes=" | 
 | 5748 |      << NumNonZygoteClasses() << "\n"; | 
 | 5749 | } | 
 | 5750 |  | 
 | 5751 | size_t ClassLinker::NumZygoteClasses() const { | 
| Mathieu Chartier | 6b06953 | 2015-08-05 15:08:12 -0700 | [diff] [blame] | 5752 |   size_t sum = boot_class_table_.NumZygoteClasses(); | 
 | 5753 |   for (const GcRoot<mirror::ClassLoader>& root : class_loaders_) { | 
 | 5754 |     ClassTable* const class_table = root.Read()->GetClassTable(); | 
 | 5755 |     if (class_table != nullptr) { | 
 | 5756 |       sum += class_table->NumZygoteClasses(); | 
 | 5757 |     } | 
| Mathieu Chartier | cc5ebdf | 2015-07-27 11:19:43 -0700 | [diff] [blame] | 5758 |   } | 
 | 5759 |   return sum; | 
 | 5760 | } | 
 | 5761 |  | 
 | 5762 | size_t ClassLinker::NumNonZygoteClasses() const { | 
| Mathieu Chartier | 6b06953 | 2015-08-05 15:08:12 -0700 | [diff] [blame] | 5763 |   size_t sum = boot_class_table_.NumNonZygoteClasses(); | 
 | 5764 |   for (const GcRoot<mirror::ClassLoader>& root : class_loaders_) { | 
 | 5765 |     ClassTable* const class_table = root.Read()->GetClassTable(); | 
 | 5766 |     if (class_table != nullptr) { | 
 | 5767 |       sum += class_table->NumNonZygoteClasses(); | 
 | 5768 |     } | 
| Mathieu Chartier | cc5ebdf | 2015-07-27 11:19:43 -0700 | [diff] [blame] | 5769 |   } | 
 | 5770 |   return sum; | 
| Elliott Hughes | cac6cc7 | 2011-11-03 20:31:21 -0700 | [diff] [blame] | 5771 | } | 
 | 5772 |  | 
| Ian Rogers | 7dfb28c | 2013-08-22 08:18:36 -0700 | [diff] [blame] | 5773 | size_t ClassLinker::NumLoadedClasses() { | 
 | 5774 |   if (dex_cache_image_class_lookup_required_) { | 
 | 5775 |     MoveImageClassesToClassTable(); | 
 | 5776 |   } | 
| Ian Rogers | 1bf8d4d | 2013-05-30 00:18:49 -0700 | [diff] [blame] | 5777 |   ReaderMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_); | 
| Mathieu Chartier | c2e2062 | 2014-11-03 11:41:47 -0800 | [diff] [blame] | 5778 |   // Only return non zygote classes since these are the ones which apps which care about. | 
| Mathieu Chartier | cc5ebdf | 2015-07-27 11:19:43 -0700 | [diff] [blame] | 5779 |   return NumNonZygoteClasses(); | 
| Elliott Hughes | e27955c | 2011-08-26 15:21:24 -0700 | [diff] [blame] | 5780 | } | 
 | 5781 |  | 
| Brian Carlstrom | 47d237a | 2011-10-18 15:08:33 -0700 | [diff] [blame] | 5782 | pid_t ClassLinker::GetClassesLockOwner() { | 
| Ian Rogers | b726dcb | 2012-09-05 08:57:23 -0700 | [diff] [blame] | 5783 |   return Locks::classlinker_classes_lock_->GetExclusiveOwnerTid(); | 
| Brian Carlstrom | 47d237a | 2011-10-18 15:08:33 -0700 | [diff] [blame] | 5784 | } | 
 | 5785 |  | 
 | 5786 | pid_t ClassLinker::GetDexLockOwner() { | 
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 5787 |   return dex_lock_.GetExclusiveOwnerTid(); | 
| Brian Carlstrom | 24a3c2e | 2011-10-17 18:07:52 -0700 | [diff] [blame] | 5788 | } | 
 | 5789 |  | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 5790 | void ClassLinker::SetClassRoot(ClassRoot class_root, mirror::Class* klass) { | 
| Ian Rogers | 6d4d9fc | 2011-11-30 16:24:48 -0800 | [diff] [blame] | 5791 |   DCHECK(!init_done_); | 
 | 5792 |  | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 5793 |   DCHECK(klass != nullptr); | 
 | 5794 |   DCHECK(klass->GetClassLoader() == nullptr); | 
| Ian Rogers | 6d4d9fc | 2011-11-30 16:24:48 -0800 | [diff] [blame] | 5795 |  | 
| Hiroshi Yamauchi | 94f7b49 | 2014-07-22 18:08:23 -0700 | [diff] [blame] | 5796 |   mirror::ObjectArray<mirror::Class>* class_roots = class_roots_.Read(); | 
| Andreas Gampe | 2ed8def | 2014-08-28 14:41:02 -0700 | [diff] [blame] | 5797 |   DCHECK(class_roots != nullptr); | 
 | 5798 |   DCHECK(class_roots->Get(class_root) == nullptr); | 
| Hiroshi Yamauchi | e9e3e69 | 2014-06-24 14:31:37 -0700 | [diff] [blame] | 5799 |   class_roots->Set<false>(class_root, klass); | 
| Ian Rogers | 6d4d9fc | 2011-11-30 16:24:48 -0800 | [diff] [blame] | 5800 | } | 
 | 5801 |  | 
| Ian Rogers | 6f3dbba | 2014-10-14 17:41:57 -0700 | [diff] [blame] | 5802 | const char* ClassLinker::GetClassRootDescriptor(ClassRoot class_root) { | 
 | 5803 |   static const char* class_roots_descriptors[] = { | 
 | 5804 |     "Ljava/lang/Class;", | 
 | 5805 |     "Ljava/lang/Object;", | 
 | 5806 |     "[Ljava/lang/Class;", | 
 | 5807 |     "[Ljava/lang/Object;", | 
 | 5808 |     "Ljava/lang/String;", | 
 | 5809 |     "Ljava/lang/DexCache;", | 
 | 5810 |     "Ljava/lang/ref/Reference;", | 
| Mathieu Chartier | fc58af4 | 2015-04-16 18:00:39 -0700 | [diff] [blame] | 5811 |     "Ljava/lang/reflect/Constructor;", | 
| Mathieu Chartier | daaf326 | 2015-03-24 13:30:28 -0700 | [diff] [blame] | 5812 |     "Ljava/lang/reflect/Field;", | 
| Mathieu Chartier | fc58af4 | 2015-04-16 18:00:39 -0700 | [diff] [blame] | 5813 |     "Ljava/lang/reflect/Method;", | 
| Ian Rogers | 6f3dbba | 2014-10-14 17:41:57 -0700 | [diff] [blame] | 5814 |     "Ljava/lang/reflect/Proxy;", | 
 | 5815 |     "[Ljava/lang/String;", | 
| Mathieu Chartier | fc58af4 | 2015-04-16 18:00:39 -0700 | [diff] [blame] | 5816 |     "[Ljava/lang/reflect/Constructor;", | 
| Mathieu Chartier | daaf326 | 2015-03-24 13:30:28 -0700 | [diff] [blame] | 5817 |     "[Ljava/lang/reflect/Field;", | 
| Mathieu Chartier | fc58af4 | 2015-04-16 18:00:39 -0700 | [diff] [blame] | 5818 |     "[Ljava/lang/reflect/Method;", | 
| Ian Rogers | 6f3dbba | 2014-10-14 17:41:57 -0700 | [diff] [blame] | 5819 |     "Ljava/lang/ClassLoader;", | 
 | 5820 |     "Ljava/lang/Throwable;", | 
 | 5821 |     "Ljava/lang/ClassNotFoundException;", | 
 | 5822 |     "Ljava/lang/StackTraceElement;", | 
 | 5823 |     "Z", | 
 | 5824 |     "B", | 
 | 5825 |     "C", | 
 | 5826 |     "D", | 
 | 5827 |     "F", | 
 | 5828 |     "I", | 
 | 5829 |     "J", | 
 | 5830 |     "S", | 
 | 5831 |     "V", | 
 | 5832 |     "[Z", | 
 | 5833 |     "[B", | 
 | 5834 |     "[C", | 
 | 5835 |     "[D", | 
 | 5836 |     "[F", | 
 | 5837 |     "[I", | 
 | 5838 |     "[J", | 
 | 5839 |     "[S", | 
 | 5840 |     "[Ljava/lang/StackTraceElement;", | 
 | 5841 |   }; | 
| Andreas Gampe | 575e78c | 2014-11-03 23:41:03 -0800 | [diff] [blame] | 5842 |   static_assert(arraysize(class_roots_descriptors) == size_t(kClassRootsMax), | 
 | 5843 |                 "Mismatch between class descriptors and class-root enum"); | 
| Ian Rogers | 6f3dbba | 2014-10-14 17:41:57 -0700 | [diff] [blame] | 5844 |  | 
 | 5845 |   const char* descriptor = class_roots_descriptors[class_root]; | 
 | 5846 |   CHECK(descriptor != nullptr); | 
 | 5847 |   return descriptor; | 
 | 5848 | } | 
 | 5849 |  | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 5850 | bool ClassLinker::MayBeCalledWithDirectCodePointer(ArtMethod* m) { | 
| Mathieu Chartier | d856545 | 2015-03-26 09:41:50 -0700 | [diff] [blame] | 5851 |   if (Runtime::Current()->UseJit()) { | 
 | 5852 |     // JIT can have direct code pointers from any method to any other method. | 
 | 5853 |     return true; | 
 | 5854 |   } | 
| Sebastien Hertz | 6963e44 | 2014-11-26 22:11:27 +0100 | [diff] [blame] | 5855 |   // Non-image methods don't use direct code pointer. | 
 | 5856 |   if (!m->GetDeclaringClass()->IsBootStrapClassLoaded()) { | 
 | 5857 |     return false; | 
 | 5858 |   } | 
 | 5859 |   if (m->IsPrivate()) { | 
 | 5860 |     // The method can only be called inside its own oat file. Therefore it won't be called using | 
 | 5861 |     // its direct code if the oat file has been compiled in PIC mode. | 
| Sebastien Hertz | 6963e44 | 2014-11-26 22:11:27 +0100 | [diff] [blame] | 5862 |     const DexFile& dex_file = m->GetDeclaringClass()->GetDexFile(); | 
| Richard Uhler | 07b3c23 | 2015-03-31 15:57:54 -0700 | [diff] [blame] | 5863 |     const OatFile::OatDexFile* oat_dex_file = dex_file.GetOatDexFile(); | 
| Sebastien Hertz | 6963e44 | 2014-11-26 22:11:27 +0100 | [diff] [blame] | 5864 |     if (oat_dex_file == nullptr) { | 
 | 5865 |       // No oat file: the method has not been compiled. | 
 | 5866 |       return false; | 
 | 5867 |     } | 
 | 5868 |     const OatFile* oat_file = oat_dex_file->GetOatFile(); | 
 | 5869 |     return oat_file != nullptr && !oat_file->IsPic(); | 
 | 5870 |   } else { | 
 | 5871 |     // The method can be called outside its own oat file. Therefore it won't be called using its | 
 | 5872 |     // direct code pointer only if all loaded oat files have been compiled in PIC mode. | 
 | 5873 |     ReaderMutexLock mu(Thread::Current(), dex_lock_); | 
 | 5874 |     for (const OatFile* oat_file : oat_files_) { | 
 | 5875 |       if (!oat_file->IsPic()) { | 
 | 5876 |         return true; | 
 | 5877 |       } | 
 | 5878 |     } | 
 | 5879 |     return false; | 
 | 5880 |   } | 
 | 5881 | } | 
 | 5882 |  | 
| Igor Murashkin | b1d8c31 | 2015-08-04 11:18:43 -0700 | [diff] [blame] | 5883 | jobject ClassLinker::CreatePathClassLoader(Thread* self, std::vector<const DexFile*>& dex_files) { | 
| Andreas Gampe | 81c6f8d | 2015-03-25 17:19:53 -0700 | [diff] [blame] | 5884 |   // SOAAlreadyRunnable is protected, and we need something to add a global reference. | 
 | 5885 |   // We could move the jobject to the callers, but all call-sites do this... | 
 | 5886 |   ScopedObjectAccessUnchecked soa(self); | 
 | 5887 |  | 
| Andreas Gampe | 81c6f8d | 2015-03-25 17:19:53 -0700 | [diff] [blame] | 5888 |   // For now, create a libcore-level DexFile for each ART DexFile. This "explodes" multidex. | 
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 5889 |   StackHandleScope<10> hs(self); | 
| Andreas Gampe | 81c6f8d | 2015-03-25 17:19:53 -0700 | [diff] [blame] | 5890 |  | 
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 5891 |   ArtField* dex_elements_field = | 
 | 5892 |       soa.DecodeField(WellKnownClasses::dalvik_system_DexPathList_dexElements); | 
| Andreas Gampe | 81c6f8d | 2015-03-25 17:19:53 -0700 | [diff] [blame] | 5893 |  | 
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 5894 |   mirror::Class* dex_elements_class = dex_elements_field->GetType<true>(); | 
| Andreas Gampe | 81c6f8d | 2015-03-25 17:19:53 -0700 | [diff] [blame] | 5895 |   DCHECK(dex_elements_class != nullptr); | 
 | 5896 |   DCHECK(dex_elements_class->IsArrayClass()); | 
| Mathieu Chartier | daaf326 | 2015-03-24 13:30:28 -0700 | [diff] [blame] | 5897 |   Handle<mirror::ObjectArray<mirror::Object>> h_dex_elements(hs.NewHandle( | 
 | 5898 |       mirror::ObjectArray<mirror::Object>::Alloc(self, dex_elements_class, dex_files.size()))); | 
| Andreas Gampe | 81c6f8d | 2015-03-25 17:19:53 -0700 | [diff] [blame] | 5899 |   Handle<mirror::Class> h_dex_element_class = | 
 | 5900 |       hs.NewHandle(dex_elements_class->GetComponentType()); | 
 | 5901 |  | 
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 5902 |   ArtField* element_file_field = | 
 | 5903 |       soa.DecodeField(WellKnownClasses::dalvik_system_DexPathList__Element_dexFile); | 
 | 5904 |   DCHECK_EQ(h_dex_element_class.Get(), element_file_field->GetDeclaringClass()); | 
| Andreas Gampe | 81c6f8d | 2015-03-25 17:19:53 -0700 | [diff] [blame] | 5905 |  | 
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 5906 |   ArtField* cookie_field = soa.DecodeField(WellKnownClasses::dalvik_system_DexFile_cookie); | 
 | 5907 |   DCHECK_EQ(cookie_field->GetDeclaringClass(), element_file_field->GetType<false>()); | 
| Andreas Gampe | 81c6f8d | 2015-03-25 17:19:53 -0700 | [diff] [blame] | 5908 |  | 
 | 5909 |   // Fill the elements array. | 
 | 5910 |   int32_t index = 0; | 
 | 5911 |   for (const DexFile* dex_file : dex_files) { | 
 | 5912 |     StackHandleScope<3> hs2(self); | 
 | 5913 |  | 
 | 5914 |     Handle<mirror::LongArray> h_long_array = hs2.NewHandle(mirror::LongArray::Alloc(self, 1)); | 
 | 5915 |     DCHECK(h_long_array.Get() != nullptr); | 
 | 5916 |     h_long_array->Set(0, reinterpret_cast<intptr_t>(dex_file)); | 
 | 5917 |  | 
 | 5918 |     Handle<mirror::Object> h_dex_file = hs2.NewHandle( | 
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 5919 |         cookie_field->GetDeclaringClass()->AllocObject(self)); | 
| Andreas Gampe | 81c6f8d | 2015-03-25 17:19:53 -0700 | [diff] [blame] | 5920 |     DCHECK(h_dex_file.Get() != nullptr); | 
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 5921 |     cookie_field->SetObject<false>(h_dex_file.Get(), h_long_array.Get()); | 
| Andreas Gampe | 81c6f8d | 2015-03-25 17:19:53 -0700 | [diff] [blame] | 5922 |  | 
 | 5923 |     Handle<mirror::Object> h_element = hs2.NewHandle(h_dex_element_class->AllocObject(self)); | 
 | 5924 |     DCHECK(h_element.Get() != nullptr); | 
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 5925 |     element_file_field->SetObject<false>(h_element.Get(), h_dex_file.Get()); | 
| Andreas Gampe | 81c6f8d | 2015-03-25 17:19:53 -0700 | [diff] [blame] | 5926 |  | 
 | 5927 |     h_dex_elements->Set(index, h_element.Get()); | 
 | 5928 |     index++; | 
 | 5929 |   } | 
 | 5930 |   DCHECK_EQ(index, h_dex_elements->GetLength()); | 
 | 5931 |  | 
 | 5932 |   // Create DexPathList. | 
 | 5933 |   Handle<mirror::Object> h_dex_path_list = hs.NewHandle( | 
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 5934 |       dex_elements_field->GetDeclaringClass()->AllocObject(self)); | 
| Andreas Gampe | 81c6f8d | 2015-03-25 17:19:53 -0700 | [diff] [blame] | 5935 |   DCHECK(h_dex_path_list.Get() != nullptr); | 
 | 5936 |   // Set elements. | 
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 5937 |   dex_elements_field->SetObject<false>(h_dex_path_list.Get(), h_dex_elements.Get()); | 
| Andreas Gampe | 81c6f8d | 2015-03-25 17:19:53 -0700 | [diff] [blame] | 5938 |  | 
 | 5939 |   // Create PathClassLoader. | 
 | 5940 |   Handle<mirror::Class> h_path_class_class = hs.NewHandle( | 
 | 5941 |       soa.Decode<mirror::Class*>(WellKnownClasses::dalvik_system_PathClassLoader)); | 
 | 5942 |   Handle<mirror::Object> h_path_class_loader = hs.NewHandle( | 
 | 5943 |       h_path_class_class->AllocObject(self)); | 
 | 5944 |   DCHECK(h_path_class_loader.Get() != nullptr); | 
 | 5945 |   // Set DexPathList. | 
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 5946 |   ArtField* path_list_field = | 
 | 5947 |       soa.DecodeField(WellKnownClasses::dalvik_system_PathClassLoader_pathList); | 
 | 5948 |   DCHECK(path_list_field != nullptr); | 
 | 5949 |   path_list_field->SetObject<false>(h_path_class_loader.Get(), h_dex_path_list.Get()); | 
| Andreas Gampe | 81c6f8d | 2015-03-25 17:19:53 -0700 | [diff] [blame] | 5950 |  | 
 | 5951 |   // Make a pretend boot-classpath. | 
 | 5952 |   // TODO: Should we scan the image? | 
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 5953 |   ArtField* const parent_field = | 
| Andreas Gampe | 81c6f8d | 2015-03-25 17:19:53 -0700 | [diff] [blame] | 5954 |       mirror::Class::FindField(self, hs.NewHandle(h_path_class_loader->GetClass()), "parent", | 
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 5955 |                                "Ljava/lang/ClassLoader;"); | 
| Roland Levillain | f39c9eb | 2015-05-26 15:02:07 +0100 | [diff] [blame] | 5956 |   DCHECK(parent_field != nullptr); | 
| Andreas Gampe | 81c6f8d | 2015-03-25 17:19:53 -0700 | [diff] [blame] | 5957 |   mirror::Object* boot_cl = | 
 | 5958 |       soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_BootClassLoader)->AllocObject(self); | 
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 5959 |   parent_field->SetObject<false>(h_path_class_loader.Get(), boot_cl); | 
| Andreas Gampe | 81c6f8d | 2015-03-25 17:19:53 -0700 | [diff] [blame] | 5960 |  | 
 | 5961 |   // Make it a global ref and return. | 
 | 5962 |   ScopedLocalRef<jobject> local_ref( | 
 | 5963 |       soa.Env(), soa.Env()->AddLocalReference<jobject>(h_path_class_loader.Get())); | 
 | 5964 |   return soa.Env()->NewGlobalRef(local_ref.get()); | 
 | 5965 | } | 
 | 5966 |  | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 5967 | ArtMethod* ClassLinker::CreateRuntimeMethod() { | 
| Vladimir Marko | 1463285 | 2015-08-17 12:07:23 +0100 | [diff] [blame] | 5968 |   const size_t method_alignment = ArtMethod::Alignment(image_pointer_size_); | 
 | 5969 |   const size_t method_size = ArtMethod::Size(image_pointer_size_); | 
| Vladimir Marko | cf36d49 | 2015-08-12 19:27:26 +0100 | [diff] [blame] | 5970 |   LengthPrefixedArray<ArtMethod>* method_array = AllocArtMethodArray(Thread::Current(), 1); | 
 | 5971 |   ArtMethod* method = &method_array->At(0, method_size, method_alignment); | 
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 5972 |   CHECK(method != nullptr); | 
 | 5973 |   method->SetDexMethodIndex(DexFile::kDexNoIndex); | 
 | 5974 |   CHECK(method->IsRuntimeMethod()); | 
 | 5975 |   return method; | 
 | 5976 | } | 
 | 5977 |  | 
| Andreas Gampe | 8ac7595 | 2015-06-02 21:01:45 -0700 | [diff] [blame] | 5978 | void ClassLinker::DropFindArrayClassCache() { | 
 | 5979 |   std::fill_n(find_array_class_cache_, kFindArrayCacheSize, GcRoot<mirror::Class>(nullptr)); | 
 | 5980 |   find_array_class_cache_next_victim_ = 0; | 
 | 5981 | } | 
 | 5982 |  | 
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 5983 | }  // namespace art |