Home | History | Annotate | Download | only in dex
      1 /*
      2  * Copyright (C) 2014 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  */
     16 
     17 # include "mir_method_info.h"
     18 
     19 #include "driver/compiler_driver.h"
     20 #include "driver/dex_compilation_unit.h"
     21 #include "driver/compiler_driver-inl.h"
     22 #include "mirror/class_loader.h"  // Only to allow casts in Handle<ClassLoader>.
     23 #include "mirror/dex_cache.h"     // Only to allow casts in Handle<DexCache>.
     24 #include "scoped_thread_state_change.h"
     25 #include "handle_scope-inl.h"
     26 
     27 namespace art {
     28 
     29 void MirMethodLoweringInfo::Resolve(CompilerDriver* compiler_driver,
     30                                     const DexCompilationUnit* mUnit,
     31                                     MirMethodLoweringInfo* method_infos, size_t count) {
     32   if (kIsDebugBuild) {
     33     DCHECK(method_infos != nullptr);
     34     DCHECK_NE(count, 0u);
     35     for (auto it = method_infos, end = method_infos + count; it != end; ++it) {
     36       MirMethodLoweringInfo unresolved(it->MethodIndex(), it->GetInvokeType());
     37       if (it->target_dex_file_ != nullptr) {
     38         unresolved.target_dex_file_ = it->target_dex_file_;
     39         unresolved.target_method_idx_ = it->target_method_idx_;
     40       }
     41       DCHECK_EQ(memcmp(&unresolved, &*it, sizeof(*it)), 0);
     42     }
     43   }
     44 
     45   // We're going to resolve methods and check access in a tight loop. It's better to hold
     46   // the lock and needed references once than re-acquiring them again and again.
     47   ScopedObjectAccess soa(Thread::Current());
     48   StackHandleScope<3> hs(soa.Self());
     49   Handle<mirror::DexCache> dex_cache(hs.NewHandle(compiler_driver->GetDexCache(mUnit)));
     50   Handle<mirror::ClassLoader> class_loader(
     51       hs.NewHandle(compiler_driver->GetClassLoader(soa, mUnit)));
     52   Handle<mirror::Class> referrer_class(hs.NewHandle(
     53       compiler_driver->ResolveCompilingMethodsClass(soa, dex_cache, class_loader, mUnit)));
     54   // Even if the referrer class is unresolved (i.e. we're compiling a method without class
     55   // definition) we still want to resolve methods and record all available info.
     56 
     57   for (auto it = method_infos, end = method_infos + count; it != end; ++it) {
     58     // Remember devirtualized invoke target and set the called method to the default.
     59     MethodReference devirt_ref(it->target_dex_file_, it->target_method_idx_);
     60     MethodReference* devirt_target = (it->target_dex_file_ != nullptr) ? &devirt_ref : nullptr;
     61     it->target_dex_file_ = mUnit->GetDexFile();
     62     it->target_method_idx_ = it->MethodIndex();
     63 
     64     InvokeType invoke_type = it->GetInvokeType();
     65     mirror::ArtMethod* resolved_method =
     66         compiler_driver->ResolveMethod(soa, dex_cache, class_loader, mUnit, it->MethodIndex(),
     67                                        invoke_type);
     68     if (UNLIKELY(resolved_method == nullptr)) {
     69       continue;
     70     }
     71     compiler_driver->GetResolvedMethodDexFileLocation(resolved_method,
     72         &it->declaring_dex_file_, &it->declaring_class_idx_, &it->declaring_method_idx_);
     73     it->vtable_idx_ = compiler_driver->GetResolvedMethodVTableIndex(resolved_method, invoke_type);
     74 
     75     MethodReference target_method(mUnit->GetDexFile(), it->MethodIndex());
     76     int fast_path_flags = compiler_driver->IsFastInvoke(
     77         soa, dex_cache, class_loader, mUnit, referrer_class.Get(), resolved_method, &invoke_type,
     78         &target_method, devirt_target, &it->direct_code_, &it->direct_method_);
     79     bool needs_clinit =
     80         compiler_driver->NeedsClassInitialization(referrer_class.Get(), resolved_method);
     81     uint16_t other_flags = it->flags_ &
     82         ~(kFlagFastPath | kFlagNeedsClassInitialization | (kInvokeTypeMask << kBitSharpTypeBegin));
     83     it->flags_ = other_flags |
     84         (fast_path_flags != 0 ? kFlagFastPath : 0u) |
     85         (static_cast<uint16_t>(invoke_type) << kBitSharpTypeBegin) |
     86         (needs_clinit ? kFlagNeedsClassInitialization : 0u);
     87     it->target_dex_file_ = target_method.dex_file;
     88     it->target_method_idx_ = target_method.dex_method_index;
     89     it->stats_flags_ = fast_path_flags;
     90   }
     91 }
     92 
     93 }  // namespace art
     94