Merge "Fix the memory protection issue in RosAllocSpace::CreateFromMemMap()"
diff --git a/compiler/dex/frontend.cc b/compiler/dex/frontend.cc
index 591d92a..6800f7b 100644
--- a/compiler/dex/frontend.cc
+++ b/compiler/dex/frontend.cc
@@ -211,7 +211,7 @@
class_loader, dex_file);
cu.NewTimingSplit("MIROpt:CheckFilters");
- if (cu.mir_graph->SkipCompilation(Runtime::Current()->GetCompilerFilter())) {
+ if (cu.mir_graph->SkipCompilation()) {
return NULL;
}
diff --git a/compiler/dex/mir_analysis.cc b/compiler/dex/mir_analysis.cc
index ab55333..7ce8f69 100644
--- a/compiler/dex/mir_analysis.cc
+++ b/compiler/dex/mir_analysis.cc
@@ -18,6 +18,7 @@
#include "dataflow_iterator-inl.h"
#include "dex/quick/dex_file_method_inliner.h"
#include "dex/quick/dex_file_to_method_inliner_map.h"
+#include "driver/compiler_options.h"
namespace art {
@@ -958,7 +959,7 @@
}
// Complex, logic-intensive?
- if ((GetNumDalvikInsns() > Runtime::Current()->GetSmallMethodThreshold()) &&
+ if (cu_->compiler_driver->GetCompilerOptions().IsSmallMethod(GetNumDalvikInsns()) &&
stats->branch_ratio > 0.3) {
return false;
}
@@ -984,7 +985,7 @@
}
// If significant in size and high proportion of expensive operations, skip.
- if ((GetNumDalvikInsns() > Runtime::Current()->GetSmallMethodThreshold()) &&
+ if (cu_->compiler_driver->GetCompilerOptions().IsSmallMethod(GetNumDalvikInsns()) &&
(stats->heavyweight_ratio > 0.3)) {
return true;
}
@@ -996,12 +997,14 @@
* Will eventually want this to be a bit more sophisticated and happen at verification time.
* Ultimate goal is to drive with profile data.
*/
-bool MIRGraph::SkipCompilation(Runtime::CompilerFilter compiler_filter) {
- if (compiler_filter == Runtime::kEverything) {
+bool MIRGraph::SkipCompilation() {
+ const CompilerOptions& compiler_options = cu_->compiler_driver->GetCompilerOptions();
+ CompilerOptions::CompilerFilter compiler_filter = compiler_options.GetCompilerFilter();
+ if (compiler_filter == CompilerOptions::kEverything) {
return false;
}
- if (compiler_filter == Runtime::kInterpretOnly) {
+ if (compiler_filter == CompilerOptions::kInterpretOnly) {
LOG(WARNING) << "InterpretOnly should ideally be filtered out prior to parsing.";
return true;
}
@@ -1010,17 +1013,17 @@
size_t small_cutoff = 0;
size_t default_cutoff = 0;
switch (compiler_filter) {
- case Runtime::kBalanced:
- small_cutoff = Runtime::Current()->GetSmallMethodThreshold();
- default_cutoff = Runtime::Current()->GetLargeMethodThreshold();
+ case CompilerOptions::kBalanced:
+ small_cutoff = compiler_options.GetSmallMethodThreshold();
+ default_cutoff = compiler_options.GetLargeMethodThreshold();
break;
- case Runtime::kSpace:
- small_cutoff = Runtime::Current()->GetTinyMethodThreshold();
- default_cutoff = Runtime::Current()->GetSmallMethodThreshold();
+ case CompilerOptions::kSpace:
+ small_cutoff = compiler_options.GetTinyMethodThreshold();
+ default_cutoff = compiler_options.GetSmallMethodThreshold();
break;
- case Runtime::kSpeed:
- small_cutoff = Runtime::Current()->GetHugeMethodThreshold();
- default_cutoff = Runtime::Current()->GetHugeMethodThreshold();
+ case CompilerOptions::kSpeed:
+ small_cutoff = compiler_options.GetHugeMethodThreshold();
+ default_cutoff = compiler_options.GetHugeMethodThreshold();
break;
default:
LOG(FATAL) << "Unexpected compiler_filter_: " << compiler_filter;
@@ -1033,17 +1036,17 @@
* Filter 1: Huge methods are likely to be machine generated, but some aren't.
* If huge, assume we won't compile, but allow futher analysis to turn it back on.
*/
- if (GetNumDalvikInsns() > Runtime::Current()->GetHugeMethodThreshold()) {
+ if (compiler_options.IsHugeMethod(GetNumDalvikInsns())) {
skip_compilation = true;
// If we're got a huge number of basic blocks, don't bother with further analysis.
- if (static_cast<size_t>(num_blocks_) > (Runtime::Current()->GetHugeMethodThreshold() / 2)) {
+ if (static_cast<size_t>(num_blocks_) > (compiler_options.GetHugeMethodThreshold() / 2)) {
return true;
}
- } else if (GetNumDalvikInsns() > Runtime::Current()->GetLargeMethodThreshold() &&
+ } else if (compiler_options.IsLargeMethod(GetNumDalvikInsns()) &&
/* If it's large and contains no branches, it's likely to be machine generated initialization */
(GetBranchCount() == 0)) {
return true;
- } else if (compiler_filter == Runtime::kSpeed) {
+ } else if (compiler_filter == CompilerOptions::kSpeed) {
// If not huge, compile.
return false;
}
diff --git a/compiler/dex/mir_graph.h b/compiler/dex/mir_graph.h
index d844aac..2174f67 100644
--- a/compiler/dex/mir_graph.h
+++ b/compiler/dex/mir_graph.h
@@ -372,7 +372,7 @@
* Examine the graph to determine whether it's worthwile to spend the time compiling
* this method.
*/
- bool SkipCompilation(Runtime::CompilerFilter compiler_filter);
+ bool SkipCompilation();
/*
* Parse dex method and add MIR at current insert point. Returns id (which is
diff --git a/compiler/dex/mir_optimization.cc b/compiler/dex/mir_optimization.cc
index b91ef28..67d4769 100644
--- a/compiler/dex/mir_optimization.cc
+++ b/compiler/dex/mir_optimization.cc
@@ -406,7 +406,7 @@
// Is this the select pattern?
// TODO: flesh out support for Mips. NOTE: llvm's select op doesn't quite work here.
// TUNING: expand to support IF_xx compare & branches
- if (cu_->compiler_backend->IsPortable() &&
+ if (!cu_->compiler_backend->IsPortable() &&
(cu_->instruction_set == kThumb2 || cu_->instruction_set == kX86) &&
((mir->dalvikInsn.opcode == Instruction::IF_EQZ) ||
(mir->dalvikInsn.opcode == Instruction::IF_NEZ))) {
diff --git a/compiler/dex/quick/codegen_util.cc b/compiler/dex/quick/codegen_util.cc
index c5dccda..3185449 100644
--- a/compiler/dex/quick/codegen_util.cc
+++ b/compiler/dex/quick/codegen_util.cc
@@ -25,6 +25,7 @@
#include "dex/verified_method.h"
#include "verifier/dex_gc_map.h"
#include "verifier/method_verifier.h"
+#include "vmap_table.h"
namespace art {
@@ -1042,30 +1043,32 @@
}
CompiledMethod* Mir2Lir::GetCompiledMethod() {
- // Combine vmap tables - core regs, then fp regs - into vmap_table
- std::vector<uint16_t> raw_vmap_table;
- // Core regs may have been inserted out of order - sort first
- std::sort(core_vmap_table_.begin(), core_vmap_table_.end());
- for (size_t i = 0 ; i < core_vmap_table_.size(); ++i) {
- // Copy, stripping out the phys register sort key
- raw_vmap_table.push_back(~(-1 << VREG_NUM_WIDTH) & core_vmap_table_[i]);
- }
- // If we have a frame, push a marker to take place of lr
+ // Combine vmap tables - core regs, then fp regs - into vmap_table.
+ Leb128EncodingVector vmap_encoder;
if (frame_size_ > 0) {
- raw_vmap_table.push_back(INVALID_VREG);
+ // Prefix the encoded data with its size.
+ size_t size = core_vmap_table_.size() + 1 /* marker */ + fp_vmap_table_.size();
+ vmap_encoder.Reserve(size + 1u); // All values are likely to be one byte in ULEB128 (<128).
+ vmap_encoder.PushBackUnsigned(size);
+ // Core regs may have been inserted out of order - sort first.
+ std::sort(core_vmap_table_.begin(), core_vmap_table_.end());
+ for (size_t i = 0 ; i < core_vmap_table_.size(); ++i) {
+ // Copy, stripping out the phys register sort key.
+ vmap_encoder.PushBackUnsigned(
+ ~(-1 << VREG_NUM_WIDTH) & (core_vmap_table_[i] + VmapTable::kEntryAdjustment));
+ }
+ // Push a marker to take place of lr.
+ vmap_encoder.PushBackUnsigned(VmapTable::kAdjustedFpMarker);
+ // fp regs already sorted.
+ for (uint32_t i = 0; i < fp_vmap_table_.size(); i++) {
+ vmap_encoder.PushBackUnsigned(fp_vmap_table_[i] + VmapTable::kEntryAdjustment);
+ }
} else {
DCHECK_EQ(__builtin_popcount(core_spill_mask_), 0);
DCHECK_EQ(__builtin_popcount(fp_spill_mask_), 0);
- }
- // Combine vmap tables - core regs, then fp regs. fp regs already sorted
- for (uint32_t i = 0; i < fp_vmap_table_.size(); i++) {
- raw_vmap_table.push_back(fp_vmap_table_[i]);
- }
- Leb128EncodingVector vmap_encoder;
- // Prefix the encoded data with its size.
- vmap_encoder.PushBackUnsigned(raw_vmap_table.size());
- for (uint16_t cur : raw_vmap_table) {
- vmap_encoder.PushBackUnsigned(cur);
+ DCHECK_EQ(core_vmap_table_.size(), 0u);
+ DCHECK_EQ(fp_vmap_table_.size(), 0u);
+ vmap_encoder.PushBackUnsigned(0u); // Size is 0.
}
CompiledMethod* result =
new CompiledMethod(*cu_->compiler_driver, cu_->instruction_set, code_buffer_, frame_size_,
diff --git a/compiler/dex/quick/x86/target_x86.cc b/compiler/dex/quick/x86/target_x86.cc
index ad5b154..eea7191 100644
--- a/compiler/dex/quick/x86/target_x86.cc
+++ b/compiler/dex/quick/x86/target_x86.cc
@@ -20,6 +20,8 @@
#include "codegen_x86.h"
#include "dex/compiler_internals.h"
#include "dex/quick/mir_to_lir-inl.h"
+#include "mirror/array.h"
+#include "mirror/string.h"
#include "x86_lir.h"
namespace art {
@@ -944,12 +946,6 @@
Mir2Lir::InstallLiteralPools();
}
-// Offsets within java.lang.String.
-#define STRING_VALUE_OFFSET 8
-#define STRING_COUNT_OFFSET 12
-#define STRING_OFFSET_OFFSET 20
-#define STRING_DATA_OFFSET 12
-
/*
* Fast string.index_of(I) & (II). Inline check for simple case of char <= 0xffff,
* otherwise bails to standard library code.
@@ -1001,6 +997,14 @@
}
// From here down, we know that we are looking for a char that fits in 16 bits.
+ // Location of reference to data array within the String object.
+ int value_offset = mirror::String::ValueOffset().Int32Value();
+ // Location of count within the String object.
+ int count_offset = mirror::String::CountOffset().Int32Value();
+ // Starting offset within data array.
+ int offset_offset = mirror::String::OffsetOffset().Int32Value();
+ // Start of char data with array_.
+ int data_offset = mirror::Array::DataOffset(sizeof(uint16_t)).Int32Value();
// Character is in EAX.
// Object pointer is in EDX.
@@ -1010,7 +1014,7 @@
NewLIR1(kX86Push32R, rDI);
// Compute the number of words to search in to rCX.
- LoadWordDisp(rDX, STRING_COUNT_OFFSET, rCX);
+ LoadWordDisp(rDX, count_offset, rCX);
LIR *length_compare = nullptr;
int start_value = 0;
if (zero_based) {
@@ -1048,10 +1052,10 @@
// ECX now contains the count in words to be searched.
// Load the address of the string into EBX.
- // The string starts at VALUE(String) + 2 * OFFSET(String) + STRING_DATA_OFFSET.
- LoadWordDisp(rDX, STRING_VALUE_OFFSET, rDI);
- LoadWordDisp(rDX, STRING_OFFSET_OFFSET, rBX);
- OpLea(rBX, rDI, rBX, 1, STRING_DATA_OFFSET);
+ // The string starts at VALUE(String) + 2 * OFFSET(String) + DATA_OFFSET.
+ LoadWordDisp(rDX, value_offset, rDI);
+ LoadWordDisp(rDX, offset_offset, rBX);
+ OpLea(rBX, rDI, rBX, 1, data_offset);
// Now compute into EDI where the search will start.
if (zero_based || rl_start.is_const) {
diff --git a/compiler/dex/verification_results.cc b/compiler/dex/verification_results.cc
index edccec5..947c22d 100644
--- a/compiler/dex/verification_results.cc
+++ b/compiler/dex/verification_results.cc
@@ -19,6 +19,8 @@
#include "base/stl_util.h"
#include "base/mutex.h"
#include "base/mutex-inl.h"
+#include "driver/compiler_driver.h"
+#include "driver/compiler_options.h"
#include "thread.h"
#include "thread-inl.h"
#include "verified_method.h"
@@ -27,8 +29,9 @@
namespace art {
-VerificationResults::VerificationResults()
- : verified_methods_lock_("compiler verified methods lock"),
+VerificationResults::VerificationResults(const CompilerOptions* compiler_options)
+ : compiler_options_(compiler_options),
+ verified_methods_lock_("compiler verified methods lock"),
verified_methods_(),
rejected_classes_lock_("compiler rejected classes lock"),
rejected_classes_() {
@@ -43,6 +46,7 @@
}
bool VerificationResults::ProcessVerifiedMethod(verifier::MethodVerifier* method_verifier) {
+ DCHECK(method_verifier != NULL);
MethodReference ref = method_verifier->GetMethodReference();
bool compile = IsCandidateForCompilation(ref, method_verifier->GetAccessFlags());
// TODO: Check also for virtual/interface invokes when DEX-to-DEX supports devirtualization.
@@ -95,16 +99,18 @@
bool VerificationResults::IsCandidateForCompilation(MethodReference& method_ref,
const uint32_t access_flags) {
#ifdef ART_SEA_IR_MODE
- bool use_sea = Runtime::Current()->IsSeaIRMode();
- use_sea = use_sea && (std::string::npos != PrettyMethod(
- method_ref.dex_method_index, *(method_ref.dex_file)).find("fibonacci"));
- if (use_sea) return true;
+ bool use_sea = compiler_options_->GetSeaIrMode();
+ use_sea = use_sea && (std::string::npos != PrettyMethod(
+ method_ref.dex_method_index, *(method_ref.dex_file)).find("fibonacci"));
+ if (use_sea) {
+ return true;
+ }
#endif
// Don't compile class initializers, ever.
if (((access_flags & kAccConstructor) != 0) && ((access_flags & kAccStatic) != 0)) {
return false;
}
- return (Runtime::Current()->GetCompilerFilter() != Runtime::kInterpretOnly);
+ return (compiler_options_->GetCompilerFilter() != CompilerOptions::kInterpretOnly);
}
} // namespace art
diff --git a/compiler/dex/verification_results.h b/compiler/dex/verification_results.h
index 2eb0713..278182f 100644
--- a/compiler/dex/verification_results.h
+++ b/compiler/dex/verification_results.h
@@ -33,11 +33,13 @@
class MethodVerifier;
} // namespace verifier
+class CompilerOptions;
class VerifiedMethod;
+// Used by CompilerCallbacks to track verification information from the Runtime.
class VerificationResults {
public:
- VerificationResults();
+ explicit VerificationResults(const CompilerOptions* compiler_options);
~VerificationResults();
bool ProcessVerifiedMethod(verifier::MethodVerifier* method_verifier)
@@ -50,15 +52,17 @@
void AddRejectedClass(ClassReference ref) LOCKS_EXCLUDED(rejected_classes_lock_);
bool IsClassRejected(ClassReference ref) LOCKS_EXCLUDED(rejected_classes_lock_);
- static bool IsCandidateForCompilation(MethodReference& method_ref,
- const uint32_t access_flags);
+ bool IsCandidateForCompilation(MethodReference& method_ref,
+ const uint32_t access_flags);
private:
+ const CompilerOptions* compiler_options_;
+
// Verified methods.
typedef SafeMap<MethodReference, const VerifiedMethod*,
MethodReferenceComparator> VerifiedMethodMap;
ReaderWriterMutex verified_methods_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
- VerifiedMethodMap verified_methods_;
+ VerifiedMethodMap verified_methods_ GUARDED_BY(verified_methods_lock_);
// Rejected classes.
ReaderWriterMutex rejected_classes_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
diff --git a/compiler/driver/compiler_callbacks_impl.h b/compiler/driver/compiler_callbacks_impl.h
new file mode 100644
index 0000000..fd2cd4a
--- /dev/null
+++ b/compiler/driver/compiler_callbacks_impl.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_COMPILER_DRIVER_COMPILER_CALLBACKS_IMPL_H_
+#define ART_COMPILER_DRIVER_COMPILER_CALLBACKS_IMPL_H_
+
+#include "compiler_callbacks.h"
+#include "dex/quick/dex_file_to_method_inliner_map.h"
+#include "verifier/method_verifier-inl.h"
+
+namespace art {
+
+class CompilerCallbacksImpl : public CompilerCallbacks {
+ public:
+ CompilerCallbacksImpl(VerificationResults* verification_results,
+ DexFileToMethodInlinerMap* method_inliner_map)
+ : verification_results_(verification_results),
+ method_inliner_map_(method_inliner_map) {
+ CHECK(verification_results != nullptr);
+ CHECK(method_inliner_map != nullptr);
+ }
+
+ virtual ~CompilerCallbacksImpl() { }
+
+ virtual bool MethodVerified(verifier::MethodVerifier* verifier)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ bool result = verification_results_->ProcessVerifiedMethod(verifier);
+ if (result) {
+ MethodReference ref = verifier->GetMethodReference();
+ method_inliner_map_->GetMethodInliner(ref.dex_file)
+ ->AnalyseMethodCode(verifier);
+ }
+ return result;
+ }
+ virtual void ClassRejected(ClassReference ref) {
+ verification_results_->AddRejectedClass(ref);
+ }
+
+ private:
+ VerificationResults* const verification_results_;
+ DexFileToMethodInlinerMap* const method_inliner_map_;
+};
+
+} // namespace art
+
+#endif // ART_COMPILER_DRIVER_COMPILER_CALLBACKS_IMPL_H_
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index 5adb792..1b284de 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -293,14 +293,16 @@
jobject class_loader,
const art::DexFile& dex_file);
-CompilerDriver::CompilerDriver(VerificationResults* verification_results,
+CompilerDriver::CompilerDriver(const CompilerOptions* compiler_options,
+ VerificationResults* verification_results,
DexFileToMethodInlinerMap* method_inliner_map,
CompilerBackend::Kind compiler_backend_kind,
InstructionSet instruction_set,
InstructionSetFeatures instruction_set_features,
bool image, DescriptorSet* image_classes, size_t thread_count,
bool dump_stats, bool dump_passes, CumulativeLogger* timer)
- : verification_results_(verification_results),
+ : compiler_options_(compiler_options),
+ verification_results_(verification_results),
method_inliner_map_(method_inliner_map),
compiler_backend_(CompilerBackend::Create(compiler_backend_kind)),
instruction_set_(instruction_set),
@@ -325,6 +327,9 @@
dedupe_mapping_table_("dedupe mapping table"),
dedupe_vmap_table_("dedupe vmap table"),
dedupe_gc_map_("dedupe gc map") {
+ DCHECK(compiler_options_ != nullptr);
+ DCHECK(verification_results_ != nullptr);
+ DCHECK(method_inliner_map_ != nullptr);
CHECK_PTHREAD_CALL(pthread_key_create, (&tls_key_, NULL), "compiler tls key");
@@ -447,13 +452,12 @@
}
static DexToDexCompilationLevel GetDexToDexCompilationlevel(
- SirtRef<mirror::ClassLoader>& class_loader, const DexFile& dex_file,
+ Thread* self, SirtRef<mirror::ClassLoader>& class_loader, const DexFile& dex_file,
const DexFile::ClassDef& class_def) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
const char* descriptor = dex_file.GetClassDescriptor(class_def);
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- mirror::Class* klass = class_linker->FindClass(descriptor, class_loader);
+ mirror::Class* klass = class_linker->FindClass(self, descriptor, class_loader);
if (klass == NULL) {
- Thread* self = Thread::Current();
CHECK(self->IsExceptionPending());
self->ClearException();
return kDontDexToDexCompile;
@@ -515,7 +519,8 @@
const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_idx);
SirtRef<mirror::ClassLoader> class_loader(soa.Self(),
soa.Decode<mirror::ClassLoader*>(jclass_loader));
- dex_to_dex_compilation_level = GetDexToDexCompilationlevel(class_loader, *dex_file, class_def);
+ dex_to_dex_compilation_level = GetDexToDexCompilationlevel(self, class_loader, *dex_file,
+ class_def);
}
CompileMethod(code_item, access_flags, invoke_type, class_def_idx, method_idx, jclass_loader,
*dex_file, dex_to_dex_compilation_level);
@@ -633,7 +638,7 @@
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
for (auto it = image_classes_->begin(), end = image_classes_->end(); it != end;) {
const std::string& descriptor(*it);
- SirtRef<mirror::Class> klass(self, class_linker->FindSystemClass(descriptor.c_str()));
+ SirtRef<mirror::Class> klass(self, class_linker->FindSystemClass(self, descriptor.c_str()));
if (klass.get() == NULL) {
VLOG(compiler) << "Failed to find class " << descriptor;
image_classes_->erase(it++);
@@ -648,7 +653,7 @@
// Do this here so that exception classes appear to have been specified image classes.
std::set<std::pair<uint16_t, const DexFile*> > unresolved_exception_types;
SirtRef<mirror::Class> java_lang_Throwable(self,
- class_linker->FindSystemClass("Ljava/lang/Throwable;"));
+ class_linker->FindSystemClass(self, "Ljava/lang/Throwable;"));
do {
unresolved_exception_types.clear();
class_linker->VisitClasses(ResolveCatchBlockExceptionsClassVisitor,
@@ -1661,7 +1666,8 @@
jobject jclass_loader = manager->GetClassLoader();
SirtRef<mirror::ClassLoader> class_loader(
soa.Self(), soa.Decode<mirror::ClassLoader*>(jclass_loader));
- SirtRef<mirror::Class> klass(soa.Self(), class_linker->FindClass(descriptor, class_loader));
+ SirtRef<mirror::Class> klass(soa.Self(), class_linker->FindClass(soa.Self(), descriptor,
+ class_loader));
if (klass.get() == nullptr) {
CHECK(soa.Self()->IsExceptionPending());
soa.Self()->ClearException();
@@ -1716,7 +1722,8 @@
SirtRef<mirror::ClassLoader> class_loader(soa.Self(),
soa.Decode<mirror::ClassLoader*>(jclass_loader));
SirtRef<mirror::Class> klass(soa.Self(),
- manager->GetClassLinker()->FindClass(descriptor, class_loader));
+ manager->GetClassLinker()->FindClass(soa.Self(), descriptor,
+ class_loader));
if (klass.get() != nullptr && !SkipClass(jclass_loader, dex_file, klass.get())) {
// Only try to initialize classes that were successfully verified.
@@ -1861,7 +1868,8 @@
ScopedObjectAccess soa(Thread::Current());
SirtRef<mirror::ClassLoader> class_loader(soa.Self(),
soa.Decode<mirror::ClassLoader*>(jclass_loader));
- dex_to_dex_compilation_level = GetDexToDexCompilationlevel(class_loader, dex_file, class_def);
+ dex_to_dex_compilation_level = GetDexToDexCompilationlevel(soa.Self(), class_loader, dex_file,
+ class_def);
}
ClassDataItemIterator it(dex_file, class_data);
// Skip fields
@@ -1929,7 +1937,7 @@
} else if ((access_flags & kAccAbstract) != 0) {
} else {
MethodReference method_ref(&dex_file, method_idx);
- bool compile = VerificationResults::IsCandidateForCompilation(method_ref, access_flags);
+ bool compile = verification_results_->IsCandidateForCompilation(method_ref, access_flags);
if (compile) {
// NOTE: if compiler declines to compile this method, it will return NULL.
diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h
index 092fe52..377eb6f 100644
--- a/compiler/driver/compiler_driver.h
+++ b/compiler/driver/compiler_driver.h
@@ -45,6 +45,7 @@
} // namespace verifier
class AOTCompilationStats;
+class CompilerOptions;
class DexCompilationUnit;
class DexFileToMethodInlinerMap;
class InlineIGetIPutData;
@@ -94,7 +95,8 @@
// enabled. "image_classes" lets the compiler know what classes it
// can assume will be in the image, with NULL implying all available
// classes.
- explicit CompilerDriver(VerificationResults* verification_results,
+ explicit CompilerDriver(const CompilerOptions* compiler_options,
+ VerificationResults* verification_results,
DexFileToMethodInlinerMap* method_inliner_map,
CompilerBackend::Kind compiler_backend_kind,
InstructionSet instruction_set,
@@ -129,6 +131,11 @@
return instruction_set_features_;
}
+ const CompilerOptions& GetCompilerOptions() const {
+ DCHECK(compiler_options_ != nullptr);
+ return *compiler_options_;
+ }
+
CompilerBackend* GetCompilerBackend() const {
return compiler_backend_.get();
}
@@ -551,8 +558,9 @@
std::vector<const CallPatchInformation*> methods_to_patch_;
std::vector<const TypePatchInformation*> classes_to_patch_;
- VerificationResults* verification_results_;
- DexFileToMethodInlinerMap* method_inliner_map_;
+ const CompilerOptions* const compiler_options_;
+ VerificationResults* const verification_results_;
+ DexFileToMethodInlinerMap* const method_inliner_map_;
UniquePtr<CompilerBackend> compiler_backend_;
diff --git a/compiler/driver/compiler_driver_test.cc b/compiler/driver/compiler_driver_test.cc
index 0d0c204..ec0a8bd 100644
--- a/compiler/driver/compiler_driver_test.cc
+++ b/compiler/driver/compiler_driver_test.cc
@@ -79,9 +79,8 @@
const DexFile::ClassDef& class_def = dex_file.GetClassDef(i);
const char* descriptor = dex_file.GetClassDescriptor(class_def);
ScopedObjectAccess soa(Thread::Current());
- Thread* self = Thread::Current();
- SirtRef<mirror::ClassLoader> loader(self, soa.Decode<mirror::ClassLoader*>(class_loader));
- mirror::Class* c = class_linker->FindClass(descriptor, loader);
+ SirtRef<mirror::ClassLoader> loader(soa.Self(), soa.Decode<mirror::ClassLoader*>(class_loader));
+ mirror::Class* c = class_linker->FindClass(soa.Self(), descriptor, loader);
CHECK(c != NULL);
for (size_t i = 0; i < c->NumDirectMethods(); i++) {
MakeExecutable(c->GetDirectMethod(i));
diff --git a/compiler/driver/compiler_options.h b/compiler/driver/compiler_options.h
new file mode 100644
index 0000000..9f6745b
--- /dev/null
+++ b/compiler/driver/compiler_options.h
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_COMPILER_DRIVER_COMPILER_OPTIONS_H_
+#define ART_COMPILER_DRIVER_COMPILER_OPTIONS_H_
+
+namespace art {
+
+class CompilerOptions {
+ public:
+ enum CompilerFilter {
+ kInterpretOnly, // Compile nothing.
+ kSpace, // Maximize space savings.
+ kBalanced, // Try to get the best performance return on compilation investment.
+ kSpeed, // Maximize runtime performance.
+ kEverything // Force compilation (Note: excludes compilaton of class initializers).
+ };
+
+ // Guide heuristics to determine whether to compile method if profile data not available.
+ static const CompilerFilter kDefaultCompilerFilter = kSpeed;
+ static const size_t kDefaultHugeMethodThreshold = 10000;
+ static const size_t kDefaultLargeMethodThreshold = 600;
+ static const size_t kDefaultSmallMethodThreshold = 60;
+ static const size_t kDefaultTinyMethodThreshold = 20;
+ static const size_t kDefaultNumDexMethodsThreshold = 900;
+
+ CompilerOptions() :
+ compiler_filter_(kDefaultCompilerFilter),
+ huge_method_threshold_(kDefaultHugeMethodThreshold),
+ large_method_threshold_(kDefaultLargeMethodThreshold),
+ small_method_threshold_(kDefaultSmallMethodThreshold),
+ tiny_method_threshold_(kDefaultTinyMethodThreshold),
+ num_dex_methods_threshold_(kDefaultNumDexMethodsThreshold)
+#ifdef ART_SEA_IR_MODE
+ , sea_ir_mode_(false)
+#endif
+ {}
+
+ CompilerOptions(CompilerFilter compiler_filter,
+ size_t huge_method_threshold,
+ size_t large_method_threshold,
+ size_t small_method_threshold,
+ size_t tiny_method_threshold,
+ size_t num_dex_methods_threshold
+#ifdef ART_SEA_IR_MODE
+ , bool sea_ir_mode
+#endif
+ ) : // NOLINT(whitespace/parens)
+ compiler_filter_(compiler_filter),
+ huge_method_threshold_(huge_method_threshold),
+ large_method_threshold_(large_method_threshold),
+ small_method_threshold_(small_method_threshold),
+ tiny_method_threshold_(tiny_method_threshold),
+ num_dex_methods_threshold_(num_dex_methods_threshold)
+#ifdef ART_SEA_IR_MODE
+ , sea_ir_mode_(sea_ir_mode)
+#endif
+ {}
+
+ CompilerFilter GetCompilerFilter() const {
+ return compiler_filter_;
+ }
+
+ void SetCompilerFilter(CompilerFilter compiler_filter) {
+ compiler_filter_ = compiler_filter;
+ }
+
+ size_t GetHugeMethodThreshold() const {
+ return huge_method_threshold_;
+ }
+
+ size_t GetLargeMethodThreshold() const {
+ return large_method_threshold_;
+ }
+
+ size_t GetSmallMethodThreshold() const {
+ return small_method_threshold_;
+ }
+
+ size_t GetTinyMethodThreshold() const {
+ return tiny_method_threshold_;
+ }
+
+ bool IsHugeMethod(size_t num_dalvik_instructions) const {
+ return num_dalvik_instructions > huge_method_threshold_;
+ }
+
+ bool IsLargeMethod(size_t num_dalvik_instructions) const {
+ return num_dalvik_instructions > large_method_threshold_;
+ }
+
+ bool IsSmallMethod(size_t num_dalvik_instructions) const {
+ return num_dalvik_instructions > small_method_threshold_;
+ }
+
+ bool IsTinyMethod(size_t num_dalvik_instructions) const {
+ return num_dalvik_instructions > tiny_method_threshold_;
+ }
+
+ size_t GetNumDexMethodsThreshold() const {
+ return num_dex_methods_threshold_;
+ }
+
+#ifdef ART_SEA_IR_MODE
+ bool GetSeaIrMode();
+#endif
+
+ private:
+ CompilerFilter compiler_filter_;
+ size_t huge_method_threshold_;
+ size_t large_method_threshold_;
+ size_t small_method_threshold_;
+ size_t tiny_method_threshold_;
+ size_t num_dex_methods_threshold_;
+
+#ifdef ART_SEA_IR_MODE
+ bool sea_ir_mode_;
+#endif
+};
+
+} // namespace art
+
+#endif // ART_COMPILER_DRIVER_COMPILER_OPTIONS_H_
diff --git a/compiler/image_test.cc b/compiler/image_test.cc
index 3406fe6..49cabdc 100644
--- a/compiler/image_test.cc
+++ b/compiler/image_test.cc
@@ -151,7 +151,7 @@
for (size_t i = 0; i < dex->NumClassDefs(); ++i) {
const DexFile::ClassDef& class_def = dex->GetClassDef(i);
const char* descriptor = dex->GetClassDescriptor(class_def);
- mirror::Class* klass = class_linker_->FindSystemClass(descriptor);
+ mirror::Class* klass = class_linker_->FindSystemClass(soa.Self(), descriptor);
EXPECT_TRUE(klass != nullptr) << descriptor;
if (image_classes.find(descriptor) != image_classes.end()) {
// Image classes should be located inside the image.
diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc
index 58f66b9..c8447be 100644
--- a/compiler/image_writer.cc
+++ b/compiler/image_writer.cc
@@ -401,7 +401,8 @@
Runtime* runtime = Runtime::Current();
ClassLinker* class_linker = runtime->GetClassLinker();
Thread* self = Thread::Current();
- SirtRef<Class> object_array_class(self, class_linker->FindSystemClass("[Ljava/lang/Object;"));
+ SirtRef<Class> object_array_class(self, class_linker->FindSystemClass(self,
+ "[Ljava/lang/Object;"));
// build an Object[] of all the DexCaches used in the source_space_
ObjectArray<Object>* dex_caches = ObjectArray<Object>::Alloc(self, object_array_class.get(),
diff --git a/compiler/jni/jni_compiler_test.cc b/compiler/jni/jni_compiler_test.cc
index c77d319..1bdff37 100644
--- a/compiler/jni/jni_compiler_test.cc
+++ b/compiler/jni/jni_compiler_test.cc
@@ -50,7 +50,7 @@
ScopedObjectAccess soa(Thread::Current());
SirtRef<mirror::ClassLoader> loader(soa.Self(), soa.Decode<mirror::ClassLoader*>(class_loader));
// Compile the native method before starting the runtime
- mirror::Class* c = class_linker_->FindClass("LMyClassNatives;", loader);
+ mirror::Class* c = class_linker_->FindClass(soa.Self(), "LMyClassNatives;", loader);
mirror::ArtMethod* method;
if (direct) {
method = c->FindDirectMethod(method_name, method_sig);
diff --git a/compiler/oat_test.cc b/compiler/oat_test.cc
index 10d2c5c..e91ffcb 100644
--- a/compiler/oat_test.cc
+++ b/compiler/oat_test.cc
@@ -91,11 +91,14 @@
InstructionSet insn_set = kIsTargetBuild ? kThumb2 : kX86;
InstructionSetFeatures insn_features;
- verification_results_.reset(new VerificationResults);
+ compiler_options_.reset(new CompilerOptions);
+ verification_results_.reset(new VerificationResults(compiler_options_.get()));
method_inliner_map_.reset(new DexFileToMethodInlinerMap);
- callbacks_.Reset(verification_results_.get(), method_inliner_map_.get());
+ callbacks_.reset(new CompilerCallbacksImpl(verification_results_.get(),
+ method_inliner_map_.get()));
timer_.reset(new CumulativeLogger("Compilation times"));
- compiler_driver_.reset(new CompilerDriver(verification_results_.get(),
+ compiler_driver_.reset(new CompilerDriver(compiler_options_.get(),
+ verification_results_.get(),
method_inliner_map_.get(),
compiler_backend, insn_set,
insn_features, false, NULL, 2, true, true,
@@ -150,8 +153,8 @@
num_virtual_methods = it.NumVirtualMethods();
}
const char* descriptor = dex_file->GetClassDescriptor(class_def);
- SirtRef<mirror::ClassLoader> loader(Thread::Current(), nullptr);
- mirror::Class* klass = class_linker->FindClass(descriptor, loader);
+ SirtRef<mirror::ClassLoader> loader(soa.Self(), nullptr);
+ mirror::Class* klass = class_linker->FindClass(soa.Self(), descriptor, loader);
UniquePtr<const OatFile::OatClass> oat_class(oat_dex_file->GetOatClass(i));
CHECK_EQ(mirror::Class::Status::kStatusNotReady, oat_class->GetStatus()) << descriptor;
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index bfda17d..a082e36 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -34,7 +34,9 @@
#include "compiler_callbacks.h"
#include "dex_file-inl.h"
#include "dex/verification_results.h"
+#include "driver/compiler_callbacks_impl.h"
#include "driver/compiler_driver.h"
+#include "driver/compiler_options.h"
#include "elf_fixup.h"
#include "elf_stripper.h"
#include "gc/space/image_space.h"
@@ -54,15 +56,22 @@
#include "scoped_thread_state_change.h"
#include "sirt_ref.h"
#include "vector_output_stream.h"
-#include "verifier/method_verifier.h"
-#include "verifier/method_verifier-inl.h"
#include "well_known_classes.h"
#include "zip_archive.h"
-#include "dex/quick/dex_file_to_method_inliner_map.h"
-
namespace art {
+static int original_argc;
+static char** original_argv;
+
+static std::string CommandLine() {
+ std::vector<std::string> command;
+ for (int i = 0; i < original_argc; ++i) {
+ command.push_back(original_argv[i]);
+ }
+ return Join(command, ' ');
+}
+
static void UsageErrorV(const char* fmt, va_list ap) {
std::string error;
StringAppendV(&error, fmt, ap);
@@ -82,6 +91,8 @@
UsageErrorV(fmt, ap);
va_end(ap);
+ UsageError("Command: %s", CommandLine().c_str());
+
UsageError("Usage: dex2oat [options]...");
UsageError("");
UsageError(" --dex-file=<dex-file>: specifies a .dex file to compile.");
@@ -147,6 +158,46 @@
UsageError(" Example: --compiler-backend=Portable");
UsageError(" Default: Quick");
UsageError("");
+ UsageError(" --compiler-filter=(interpret-only|space|balanced|speed|everything): select");
+ UsageError(" compiler filter.");
+ UsageError(" Example: --compiler-filter=everything");
+#if ART_SMALL_MODE
+ UsageError(" Default: interpret-only");
+#else
+ UsageError(" Default: speed");
+#endif
+ UsageError("");
+ UsageError(" --huge-method-max=<method-instruction-count>: the threshold size for a huge");
+ UsageError(" method for compiler filter tuning.");
+ UsageError(" Example: --huge-method-max=%d", CompilerOptions::kDefaultHugeMethodThreshold);
+ UsageError(" Default: %d", CompilerOptions::kDefaultHugeMethodThreshold);
+ UsageError("");
+ UsageError(" --huge-method-max=<method-instruction-count>: threshold size for a huge");
+ UsageError(" method for compiler filter tuning.");
+ UsageError(" Example: --huge-method-max=%d", CompilerOptions::kDefaultHugeMethodThreshold);
+ UsageError(" Default: %d", CompilerOptions::kDefaultHugeMethodThreshold);
+ UsageError("");
+ UsageError(" --large-method-max=<method-instruction-count>: threshold size for a large");
+ UsageError(" method for compiler filter tuning.");
+ UsageError(" Example: --large-method-max=%d", CompilerOptions::kDefaultLargeMethodThreshold);
+ UsageError(" Default: %d", CompilerOptions::kDefaultLargeMethodThreshold);
+ UsageError("");
+ UsageError(" --small-method-max=<method-instruction-count>: threshold size for a small");
+ UsageError(" method for compiler filter tuning.");
+ UsageError(" Example: --small-method-max=%d", CompilerOptions::kDefaultSmallMethodThreshold);
+ UsageError(" Default: %d", CompilerOptions::kDefaultSmallMethodThreshold);
+ UsageError("");
+ UsageError(" --tiny-method-max=<method-instruction-count>: threshold size for a tiny");
+ UsageError(" method for compiler filter tuning.");
+ UsageError(" Example: --tiny-method-max=%d", CompilerOptions::kDefaultTinyMethodThreshold);
+ UsageError(" Default: %d", CompilerOptions::kDefaultTinyMethodThreshold);
+ UsageError("");
+ UsageError(" --num-dex-methods=<method-count>: threshold size for a small dex file for");
+ UsageError(" compiler filter tuning. If the input has fewer than this many methods");
+ UsageError(" and the filter is not interpret-only, overrides the filter to use speed");
+ UsageError(" Example: --num-dex-method=%d", CompilerOptions::kDefaultNumDexMethodsThreshold);
+ UsageError(" Default: %d", CompilerOptions::kDefaultNumDexMethodsThreshold);
+ UsageError("");
UsageError(" --host: used with Portable backend to link against host runtime libraries");
UsageError("");
UsageError(" --dump-timing: display a breakdown of where time was spent");
@@ -163,15 +214,25 @@
class Dex2Oat {
public:
static bool Create(Dex2Oat** p_dex2oat,
- Runtime::Options& options,
+ const Runtime::Options& runtime_options,
+ const CompilerOptions& compiler_options,
CompilerBackend::Kind compiler_backend,
InstructionSet instruction_set,
InstructionSetFeatures instruction_set_features,
+ VerificationResults* verification_results,
+ DexFileToMethodInlinerMap* method_inliner_map,
size_t thread_count)
SHARED_TRYLOCK_FUNCTION(true, Locks::mutator_lock_) {
- UniquePtr<Dex2Oat> dex2oat(new Dex2Oat(compiler_backend, instruction_set,
- instruction_set_features, thread_count));
- if (!dex2oat->CreateRuntime(options, instruction_set)) {
+ CHECK(verification_results != nullptr);
+ CHECK(method_inliner_map != nullptr);
+ UniquePtr<Dex2Oat> dex2oat(new Dex2Oat(&compiler_options,
+ compiler_backend,
+ instruction_set,
+ instruction_set_features,
+ verification_results,
+ method_inliner_map,
+ thread_count));
+ if (!dex2oat->CreateRuntime(runtime_options, instruction_set)) {
*p_dex2oat = NULL;
return false;
}
@@ -275,8 +336,9 @@
Runtime::Current()->SetCompileTimeClassPath(class_loader, class_path_files);
}
- UniquePtr<CompilerDriver> driver(new CompilerDriver(verification_results_.get(),
- method_inliner_map_.get(),
+ UniquePtr<CompilerDriver> driver(new CompilerDriver(compiler_options_,
+ verification_results_,
+ method_inliner_map_,
compiler_backend_,
instruction_set_,
instruction_set_features_,
@@ -353,53 +415,30 @@
}
private:
- class Dex2OatCompilerCallbacks : public CompilerCallbacks {
- public:
- Dex2OatCompilerCallbacks(VerificationResults* verification_results,
- DexFileToMethodInlinerMap* method_inliner_map)
- : verification_results_(verification_results),
- method_inliner_map_(method_inliner_map) { }
- virtual ~Dex2OatCompilerCallbacks() { }
-
- virtual bool MethodVerified(verifier::MethodVerifier* verifier)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- bool result = verification_results_->ProcessVerifiedMethod(verifier);
- if (result) {
- MethodReference ref = verifier->GetMethodReference();
- method_inliner_map_->GetMethodInliner(ref.dex_file)
- ->AnalyseMethodCode(verifier);
- }
- return result;
- }
- virtual void ClassRejected(ClassReference ref) {
- verification_results_->AddRejectedClass(ref);
- }
-
- private:
- VerificationResults* verification_results_;
- DexFileToMethodInlinerMap* method_inliner_map_;
- };
-
- explicit Dex2Oat(CompilerBackend::Kind compiler_backend,
+ explicit Dex2Oat(const CompilerOptions* compiler_options,
+ CompilerBackend::Kind compiler_backend,
InstructionSet instruction_set,
InstructionSetFeatures instruction_set_features,
+ VerificationResults* verification_results,
+ DexFileToMethodInlinerMap* method_inliner_map,
size_t thread_count)
- : compiler_backend_(compiler_backend),
+ : compiler_options_(compiler_options),
+ compiler_backend_(compiler_backend),
instruction_set_(instruction_set),
instruction_set_features_(instruction_set_features),
- verification_results_(new VerificationResults),
- method_inliner_map_(new DexFileToMethodInlinerMap),
- callbacks_(verification_results_.get(), method_inliner_map_.get()),
+ verification_results_(verification_results),
+ method_inliner_map_(method_inliner_map),
runtime_(nullptr),
thread_count_(thread_count),
start_ns_(NanoTime()) {
+ CHECK(compiler_options != nullptr);
+ CHECK(verification_results != nullptr);
+ CHECK(method_inliner_map != nullptr);
}
- bool CreateRuntime(Runtime::Options& options, InstructionSet instruction_set)
+ bool CreateRuntime(const Runtime::Options& runtime_options, InstructionSet instruction_set)
SHARED_TRYLOCK_FUNCTION(true, Locks::mutator_lock_) {
- options.push_back(
- std::make_pair("compilercallbacks", static_cast<CompilerCallbacks*>(&callbacks_)));
- if (!Runtime::Create(options, false)) {
+ if (!Runtime::Create(runtime_options, false)) {
LOG(ERROR) << "Failed to create runtime";
return false;
}
@@ -448,14 +487,14 @@
return false;
}
+ const CompilerOptions* const compiler_options_;
const CompilerBackend::Kind compiler_backend_;
const InstructionSet instruction_set_;
const InstructionSetFeatures instruction_set_features_;
- UniquePtr<VerificationResults> verification_results_;
- UniquePtr<DexFileToMethodInlinerMap> method_inliner_map_;
- Dex2OatCompilerCallbacks callbacks_;
+ VerificationResults* const verification_results_;
+ DexFileToMethodInlinerMap* const method_inliner_map_;
Runtime* runtime_;
size_t thread_count_;
uint64_t start_ns_;
@@ -656,6 +695,9 @@
}
static int dex2oat(int argc, char** argv) {
+ original_argc = argc;
+ original_argv = argv;
+
TimingLogger timings("compiler", false, false);
CumulativeLogger compiler_phases_timings("compilation times");
@@ -690,6 +732,12 @@
CompilerBackend::Kind compiler_backend = kUsePortableCompiler
? CompilerBackend::kPortable
: CompilerBackend::kQuick;
+ const char* compiler_filter_string = NULL;
+ int huge_method_threshold = CompilerOptions::kDefaultHugeMethodThreshold;
+ int large_method_threshold = CompilerOptions::kDefaultLargeMethodThreshold;
+ int small_method_threshold = CompilerOptions::kDefaultSmallMethodThreshold;
+ int tiny_method_threshold = CompilerOptions::kDefaultTinyMethodThreshold;
+ int num_dex_methods_threshold = CompilerOptions::kDefaultNumDexMethodsThreshold;
// Take the default set of instruction features from the build.
InstructionSetFeatures instruction_set_features =
@@ -713,7 +761,6 @@
bool dump_slow_timing = kIsDebugBuild;
bool watch_dog_enabled = !kIsTargetBuild;
-
for (int i = 0; i < argc; i++) {
const StringPiece option(argv[i]);
bool log_options = false;
@@ -729,6 +776,9 @@
if (!ParseInt(zip_fd_str, &zip_fd)) {
Usage("Failed to parse --zip-fd argument '%s' as an integer", zip_fd_str);
}
+ if (zip_fd < 0) {
+ Usage("--zip-fd passed a negative value %d", zip_fd);
+ }
} else if (option.starts_with("--zip-location=")) {
zip_location = option.substr(strlen("--zip-location=")).data();
} else if (option.starts_with("--oat-file=")) {
@@ -740,6 +790,9 @@
if (!ParseInt(oat_fd_str, &oat_fd)) {
Usage("Failed to parse --oat-fd argument '%s' as an integer", oat_fd_str);
}
+ if (oat_fd < 0) {
+ Usage("--oat-fd passed a negative value %d", oat_fd);
+ }
} else if (option == "--watch-dog") {
watch_dog_enabled = true;
} else if (option == "--no-watch-dog") {
@@ -793,6 +846,48 @@
} else if (backend_str == "Portable") {
compiler_backend = CompilerBackend::kPortable;
}
+ } else if (option.starts_with("--compiler-filter=")) {
+ compiler_filter_string = option.substr(strlen("--compiler-filter=")).data();
+ } else if (option.starts_with("--huge-method-max=")) {
+ const char* threshold = option.substr(strlen("--huge-method-max=")).data();
+ if (!ParseInt(threshold, &huge_method_threshold)) {
+ Usage("Failed to parse --huge-method-max '%s' as an integer", threshold);
+ }
+ if (huge_method_threshold < 0) {
+ Usage("--huge-method-max passed a negative value %s", huge_method_threshold);
+ }
+ } else if (option.starts_with("--large-method-max=")) {
+ const char* threshold = option.substr(strlen("--large-method-max=")).data();
+ if (!ParseInt(threshold, &large_method_threshold)) {
+ Usage("Failed to parse --large-method-max '%s' as an integer", threshold);
+ }
+ if (large_method_threshold < 0) {
+ Usage("--large-method-max passed a negative value %s", large_method_threshold);
+ }
+ } else if (option.starts_with("--small-method-max=")) {
+ const char* threshold = option.substr(strlen("--small-method-max=")).data();
+ if (!ParseInt(threshold, &small_method_threshold)) {
+ Usage("Failed to parse --small-method-max '%s' as an integer", threshold);
+ }
+ if (small_method_threshold < 0) {
+ Usage("--small-method-max passed a negative value %s", small_method_threshold);
+ }
+ } else if (option.starts_with("--tiny-method-max=")) {
+ const char* threshold = option.substr(strlen("--tiny-method-max=")).data();
+ if (!ParseInt(threshold, &tiny_method_threshold)) {
+ Usage("Failed to parse --tiny-method-max '%s' as an integer", threshold);
+ }
+ if (tiny_method_threshold < 0) {
+ Usage("--tiny-method-max passed a negative value %s", tiny_method_threshold);
+ }
+ } else if (option.starts_with("--num-dex-methods=")) {
+ const char* threshold = option.substr(strlen("--num-dex-methods=")).data();
+ if (!ParseInt(threshold, &num_dex_methods_threshold)) {
+ Usage("Failed to parse --num-dex-methods '%s' as an integer", threshold);
+ }
+ if (num_dex_methods_threshold < 0) {
+ Usage("--num-dex-methods passed a negative value %s", num_dex_methods_threshold);
+ }
} else if (option == "--host") {
is_host = true;
} else if (option == "--runtime-arg") {
@@ -915,6 +1010,44 @@
oat_unstripped += oat_filename;
}
+ if (compiler_filter_string == NULL) {
+ if (image) {
+ compiler_filter_string = "everything";
+ } else {
+#if ART_SMALL_MODE
+ compiler_filter_string = "interpret-only";
+#else
+ compiler_filter_string = "speed";
+#endif
+ }
+ }
+ CHECK(compiler_filter_string != nullptr);
+ CompilerOptions::CompilerFilter compiler_filter = CompilerOptions::kDefaultCompilerFilter;
+ if (strcmp(compiler_filter_string, "interpret-only") == 0) {
+ compiler_filter = CompilerOptions::kInterpretOnly;
+ } else if (strcmp(compiler_filter_string, "space") == 0) {
+ compiler_filter = CompilerOptions::kSpace;
+ } else if (strcmp(compiler_filter_string, "balanced") == 0) {
+ compiler_filter = CompilerOptions::kBalanced;
+ } else if (strcmp(compiler_filter_string, "speed") == 0) {
+ compiler_filter = CompilerOptions::kSpeed;
+ } else if (strcmp(compiler_filter_string, "everything") == 0) {
+ compiler_filter = CompilerOptions::kEverything;
+ } else {
+ Usage("Unknown --compiler-filter value %s", compiler_filter_string);
+ }
+
+ CompilerOptions compiler_options(compiler_filter,
+ huge_method_threshold,
+ large_method_threshold,
+ small_method_threshold,
+ tiny_method_threshold,
+ num_dex_methods_threshold
+#ifdef ART_SEA_IR_MODE
+ , compiler_options.sea_ir_ = true;
+#endif
+ ); // NOLINT(whitespace/parens)
+
// Done with usage checks, enable watchdog if requested
WatchDog watch_dog(watch_dog_enabled);
@@ -940,22 +1073,9 @@
}
timings.StartSplit("dex2oat Setup");
- LOG(INFO) << "dex2oat: " << oat_location;
+ LOG(INFO) << "dex2oat: " << CommandLine();
- if (image) {
- bool has_compiler_filter = false;
- for (const char* r : runtime_args) {
- if (strncmp(r, "-compiler-filter:", 17) == 0) {
- has_compiler_filter = true;
- break;
- }
- }
- if (!has_compiler_filter) {
- runtime_args.push_back("-compiler-filter:everything");
- }
- }
-
- Runtime::Options options;
+ Runtime::Options runtime_options;
std::vector<const DexFile*> boot_class_path;
if (boot_image_option.empty()) {
size_t failure_count = OpenDexFiles(dex_filenames, dex_locations, boot_class_path);
@@ -963,24 +1083,33 @@
LOG(ERROR) << "Failed to open some dex files: " << failure_count;
return EXIT_FAILURE;
}
- options.push_back(std::make_pair("bootclasspath", &boot_class_path));
+ runtime_options.push_back(std::make_pair("bootclasspath", &boot_class_path));
} else {
- options.push_back(std::make_pair(boot_image_option.c_str(), reinterpret_cast<void*>(NULL)));
+ runtime_options.push_back(std::make_pair(boot_image_option.c_str(),
+ reinterpret_cast<void*>(NULL)));
}
if (host_prefix.get() != NULL) {
- options.push_back(std::make_pair("host-prefix", host_prefix->c_str()));
+ runtime_options.push_back(std::make_pair("host-prefix", host_prefix->c_str()));
}
for (size_t i = 0; i < runtime_args.size(); i++) {
- options.push_back(std::make_pair(runtime_args[i], reinterpret_cast<void*>(NULL)));
+ runtime_options.push_back(std::make_pair(runtime_args[i], reinterpret_cast<void*>(NULL)));
}
-#ifdef ART_SEA_IR_MODE
- options.push_back(std::make_pair("-sea_ir", reinterpret_cast<void*>(NULL)));
-#endif
+ VerificationResults verification_results(&compiler_options);
+ DexFileToMethodInlinerMap method_inliner_map;
+ CompilerCallbacksImpl callbacks(&verification_results, &method_inliner_map);
+ runtime_options.push_back(std::make_pair("compilercallbacks", &callbacks));
Dex2Oat* p_dex2oat;
- if (!Dex2Oat::Create(&p_dex2oat, options, compiler_backend, instruction_set,
- instruction_set_features, thread_count)) {
+ if (!Dex2Oat::Create(&p_dex2oat,
+ runtime_options,
+ compiler_options,
+ compiler_backend,
+ instruction_set,
+ instruction_set_features,
+ &verification_results,
+ &method_inliner_map,
+ thread_count)) {
LOG(ERROR) << "Failed to create dex2oat";
return EXIT_FAILURE;
}
@@ -1050,7 +1179,8 @@
std::string tmp_file_name(StringPrintf("/data/local/tmp/dex2oat.%d.%zd.dex", getpid(), i));
UniquePtr<File> tmp_file(OS::CreateEmptyFile(tmp_file_name.c_str()));
if (tmp_file.get() == nullptr) {
- PLOG(ERROR) << "Failed to open file " << tmp_file_name << ". Try: adb shell chmod 777 /data/local/tmp";
+ PLOG(ERROR) << "Failed to open file " << tmp_file_name
+ << ". Try: adb shell chmod 777 /data/local/tmp";
continue;
}
tmp_file->WriteFully(dex_file->Begin(), dex_file->Size());
@@ -1070,15 +1200,15 @@
* If we're not in interpret-only mode, go ahead and compile small applications. Don't
* bother to check if we're doing the image.
*/
- if (!image && (Runtime::Current()->GetCompilerFilter() != Runtime::kInterpretOnly)) {
+ if (!image && (compiler_options.GetCompilerFilter() != CompilerOptions::kInterpretOnly)) {
size_t num_methods = 0;
for (size_t i = 0; i != dex_files.size(); ++i) {
const DexFile* dex_file = dex_files[i];
CHECK(dex_file != NULL);
num_methods += dex_file->NumMethodIds();
}
- if (num_methods <= Runtime::Current()->GetNumDexMethodsThreshold()) {
- Runtime::Current()->SetCompilerFilter(Runtime::kSpeed);
+ if (num_methods <= compiler_options.GetNumDexMethodsThreshold()) {
+ compiler_options.SetCompilerFilter(CompilerOptions::kSpeed);
VLOG(compiler) << "Below method threshold, compiling anyways";
}
}
@@ -1222,13 +1352,13 @@
// Everything was successfully written, do an explicit exit here to avoid running Runtime
// destructors that take time (bug 10645725) unless we're a debug build or running on valgrind.
- if (!kIsDebugBuild || (RUNNING_ON_VALGRIND == 0)) {
+ if (!kIsDebugBuild && (RUNNING_ON_VALGRIND == 0)) {
dex2oat->LogCompletionTime();
exit(EXIT_SUCCESS);
}
return EXIT_SUCCESS;
-}
+} // NOLINT(readability/fn_size)
} // namespace art
int main(int argc, char** argv) {
diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc
index 2a0d826..330a307 100644
--- a/oatdump/oatdump.cc
+++ b/oatdump/oatdump.cc
@@ -49,6 +49,7 @@
#include "runtime.h"
#include "safe_map.h"
#include "scoped_thread_state_change.h"
+#include "thread_list.h"
#include "verifier/dex_gc_map.h"
#include "verifier/method_verifier.h"
#include "vmap_table.h"
@@ -83,6 +84,11 @@
" --output=<file> may be used to send the output to a file.\n"
" Example: --output=/tmp/oatdump.txt\n"
"\n");
+ fprintf(stderr,
+ " --dump:[raw_mapping_table|raw_gc_map]\n"
+ " Example: --dump:raw_gc_map\n"
+ " Default: neither\n"
+ "\n");
exit(EXIT_FAILURE);
}
@@ -100,10 +106,12 @@
class OatDumper {
public:
- explicit OatDumper(const std::string& host_prefix, const OatFile& oat_file)
+ explicit OatDumper(const std::string& host_prefix, const OatFile& oat_file, bool dump_raw_mapping_table, bool dump_raw_gc_map)
: host_prefix_(host_prefix),
oat_file_(oat_file),
oat_dex_files_(oat_file.GetOatDexFiles()),
+ dump_raw_mapping_table_(dump_raw_mapping_table),
+ dump_raw_gc_map_(dump_raw_gc_map),
disassembler_(Disassembler::Create(oat_file_.GetOatHeader().GetInstructionSet())) {
AddAllOffsets();
}
@@ -358,16 +366,14 @@
DumpVmap(indent2_os, oat_method);
indent2_os << StringPrintf("mapping_table: %p (offset=0x%08x)\n",
oat_method.GetMappingTable(), oat_method.GetMappingTableOffset());
- const bool kDumpRawMappingTable = false;
- if (kDumpRawMappingTable) {
+ if (dump_raw_mapping_table_) {
Indenter indent3_filter(indent2_os.rdbuf(), kIndentChar, kIndentBy1Count);
std::ostream indent3_os(&indent3_filter);
DumpMappingTable(indent3_os, oat_method);
}
indent2_os << StringPrintf("gc_map: %p (offset=0x%08x)\n",
oat_method.GetNativeGcMap(), oat_method.GetNativeGcMapOffset());
- const bool kDumpRawGcMap = false;
- if (kDumpRawGcMap) {
+ if (dump_raw_gc_map_) {
Indenter indent3_filter(indent2_os.rdbuf(), kIndentChar, kIndentBy1Count);
std::ostream indent3_os(&indent3_filter);
DumpGcMap(indent3_os, oat_method, code_item);
@@ -699,6 +705,8 @@
const std::string host_prefix_;
const OatFile& oat_file_;
std::vector<const OatFile::OatDexFile*> oat_dex_files_;
+ bool dump_raw_mapping_table_;
+ bool dump_raw_gc_map_;
std::set<uintptr_t> offsets_;
UniquePtr<Disassembler> disassembler_;
};
@@ -707,9 +715,12 @@
public:
explicit ImageDumper(std::ostream* os, const std::string& image_filename,
const std::string& host_prefix, gc::space::ImageSpace& image_space,
- const ImageHeader& image_header)
+ const ImageHeader& image_header, bool dump_raw_mapping_table,
+ bool dump_raw_gc_map)
: os_(os), image_filename_(image_filename), host_prefix_(host_prefix),
- image_space_(image_space), image_header_(image_header) {}
+ image_space_(image_space), image_header_(image_header),
+ dump_raw_mapping_table_(dump_raw_mapping_table),
+ dump_raw_gc_map_(dump_raw_gc_map) {}
void Dump() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
std::ostream& os = *os_;
@@ -791,7 +802,8 @@
stats_.oat_file_bytes = oat_file->Size();
- oat_dumper_.reset(new OatDumper(host_prefix_, *oat_file));
+ oat_dumper_.reset(new OatDumper(host_prefix_, *oat_file, dump_raw_mapping_table_,
+ dump_raw_gc_map_));
for (const OatFile::OatDexFile* oat_dex_file : oat_file->GetOatDexFiles()) {
CHECK(oat_dex_file != NULL);
@@ -806,12 +818,21 @@
const std::vector<gc::space::ContinuousSpace*>& spaces = heap->GetContinuousSpaces();
Thread* self = Thread::Current();
{
- WriterMutexLock mu(self, *Locks::heap_bitmap_lock_);
- heap->FlushAllocStack();
+ {
+ WriterMutexLock mu(self, *Locks::heap_bitmap_lock_);
+ heap->FlushAllocStack();
+ }
// Since FlushAllocStack() above resets the (active) allocation
// stack. Need to revoke the thread-local allocation stacks that
// point into it.
- heap->RevokeAllThreadLocalAllocationStacks(self);
+ {
+ self->TransitionFromRunnableToSuspended(kNative);
+ ThreadList* thread_list = Runtime::Current()->GetThreadList();
+ thread_list->SuspendAll();
+ heap->RevokeAllThreadLocalAllocationStacks(self);
+ thread_list->ResumeAll();
+ self->TransitionFromSuspendedToRunnable();
+ }
}
{
std::ostream* saved_os = os_;
@@ -1406,6 +1427,8 @@
const std::string host_prefix_;
gc::space::ImageSpace& image_space_;
const ImageHeader& image_header_;
+ bool dump_raw_mapping_table_;
+ bool dump_raw_gc_map_;
DISALLOW_COPY_AND_ASSIGN(ImageDumper);
};
@@ -1429,6 +1452,8 @@
UniquePtr<std::string> host_prefix;
std::ostream* os = &std::cout;
UniquePtr<std::ofstream> out;
+ bool dump_raw_mapping_table = false;
+ bool dump_raw_gc_map = false;
for (int i = 0; i < argc; i++) {
const StringPiece option(argv[i]);
@@ -1440,6 +1465,15 @@
boot_image_filename = option.substr(strlen("--boot-image=")).data();
} else if (option.starts_with("--host-prefix=")) {
host_prefix.reset(new std::string(option.substr(strlen("--host-prefix=")).data()));
+ } else if (option.starts_with("--dump:")) {
+ if (option == "--dump:raw_mapping_table") {
+ dump_raw_mapping_table = true;
+ } else if (option == "--dump:raw_gc_map") {
+ dump_raw_gc_map = true;
+ } else {
+ fprintf(stderr, "Unknown argument %s\n", option.data());
+ usage();
+ }
} else if (option.starts_with("--output=")) {
const char* filename = option.substr(strlen("--output=")).data();
out.reset(new std::ofstream(filename));
@@ -1481,7 +1515,7 @@
fprintf(stderr, "Failed to open oat file from '%s': %s\n", oat_filename, error_msg.c_str());
return EXIT_FAILURE;
}
- OatDumper oat_dumper(*host_prefix.get(), *oat_file);
+ OatDumper oat_dumper(*host_prefix.get(), *oat_file, dump_raw_mapping_table, dump_raw_gc_map);
oat_dumper.Dump(*os);
return EXIT_SUCCESS;
}
@@ -1524,7 +1558,6 @@
// give it away now and then switch to a more managable ScopedObjectAccess.
Thread::Current()->TransitionFromRunnableToSuspended(kNative);
ScopedObjectAccess soa(Thread::Current());
-
gc::Heap* heap = Runtime::Current()->GetHeap();
gc::space::ImageSpace* image_space = heap->GetImageSpace();
CHECK(image_space != NULL);
@@ -1533,7 +1566,8 @@
fprintf(stderr, "Invalid image header %s\n", image_filename);
return EXIT_FAILURE;
}
- ImageDumper image_dumper(os, image_filename, *host_prefix.get(), *image_space, image_header);
+ ImageDumper image_dumper(os, image_filename, *host_prefix.get(), *image_space, image_header,
+ dump_raw_mapping_table, dump_raw_gc_map);
image_dumper.Dump();
return EXIT_SUCCESS;
}
diff --git a/runtime/class_linker-inl.h b/runtime/class_linker-inl.h
index 66c24b5..6ef0082 100644
--- a/runtime/class_linker-inl.h
+++ b/runtime/class_linker-inl.h
@@ -23,10 +23,40 @@
#include "mirror/dex_cache.h"
#include "mirror/iftable.h"
#include "mirror/object_array.h"
+#include "object_utils.h"
#include "sirt_ref.h"
namespace art {
+inline bool ClassLinker::IsInBootClassPath(const char* descriptor) {
+ DexFile::ClassPathEntry pair = DexFile::FindInClassPath(descriptor, boot_class_path_);
+ return pair.second != nullptr;
+}
+
+inline mirror::Class* ClassLinker::FindSystemClass(Thread* self, const char* descriptor) {
+ SirtRef<mirror::ClassLoader> class_loader(self, nullptr);
+ return FindClass(self, descriptor, class_loader);
+}
+
+inline mirror::Class* ClassLinker::FindArrayClass(Thread* self, mirror::Class* element_class) {
+ for (size_t i = 0; i < kFindArrayCacheSize; ++i) {
+ // Read the cached the array class once to avoid races with other threads setting it.
+ mirror::Class* array_class = find_array_class_cache_[i];
+ if (array_class != nullptr && array_class->GetComponentType() == element_class) {
+ return array_class;
+ }
+ }
+ std::string descriptor("[");
+ descriptor += ClassHelper(element_class).GetDescriptor();
+ SirtRef<mirror::ClassLoader> class_loader(self, element_class->GetClassLoader());
+ mirror::Class* array_class = FindClass(self, descriptor.c_str(), class_loader);
+ // Benign races in storing array class and incrementing index.
+ size_t victim_index = find_array_class_cache_next_victim_;
+ find_array_class_cache_[victim_index] = array_class;
+ find_array_class_cache_next_victim_ = (victim_index + 1) % kFindArrayCacheSize;
+ return array_class;
+}
+
inline mirror::String* ClassLinker::ResolveString(uint32_t string_idx,
mirror::ArtMethod* referrer) {
mirror::String* resolved_string = referrer->GetDexCacheStrings()->Get(string_idx);
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 48ec5ab..69d957f 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -19,8 +19,6 @@
#include <fcntl.h>
#include <sys/file.h>
#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/wait.h>
#include <deque>
#include <string>
@@ -176,17 +174,19 @@
: dex_lock_("ClassLinker dex lock", kDefaultMutexLevel),
dex_cache_image_class_lookup_required_(false),
failed_dex_cache_class_lookups_(0),
- class_roots_(NULL),
- array_iftable_(NULL),
+ class_roots_(nullptr),
+ array_iftable_(nullptr),
+ find_array_class_cache_next_victim_(0),
init_done_(false),
dex_caches_dirty_(false),
class_table_dirty_(false),
intern_table_(intern_table),
- portable_resolution_trampoline_(NULL),
- quick_resolution_trampoline_(NULL),
- portable_imt_conflict_trampoline_(NULL),
- quick_imt_conflict_trampoline_(NULL) {
+ portable_resolution_trampoline_(nullptr),
+ quick_resolution_trampoline_(nullptr),
+ portable_imt_conflict_trampoline_(nullptr),
+ quick_imt_conflict_trampoline_(nullptr) {
CHECK_EQ(arraysize(class_roots_descriptors_), size_t(kClassRootsMax));
+ memset(find_array_class_cache_, 0, kFindArrayCacheSize * sizeof(mirror::Class*));
}
void ClassLinker::InitFromCompiler(const std::vector<const DexFile*>& boot_class_path) {
@@ -335,54 +335,54 @@
// Object, String and DexCache need to be rerun through FindSystemClass to finish init
java_lang_Object->SetStatus(mirror::Class::kStatusNotReady, self);
- mirror::Class* Object_class = FindSystemClass("Ljava/lang/Object;");
+ mirror::Class* Object_class = FindSystemClass(self, "Ljava/lang/Object;");
CHECK_EQ(java_lang_Object.get(), Object_class);
CHECK_EQ(java_lang_Object->GetObjectSize(), sizeof(mirror::Object));
java_lang_String->SetStatus(mirror::Class::kStatusNotReady, self);
- mirror::Class* String_class = FindSystemClass("Ljava/lang/String;");
+ mirror::Class* String_class = FindSystemClass(self, "Ljava/lang/String;");
CHECK_EQ(java_lang_String.get(), String_class);
CHECK_EQ(java_lang_String->GetObjectSize(), sizeof(mirror::String));
java_lang_DexCache->SetStatus(mirror::Class::kStatusNotReady, self);
- mirror::Class* DexCache_class = FindSystemClass("Ljava/lang/DexCache;");
+ mirror::Class* DexCache_class = FindSystemClass(self, "Ljava/lang/DexCache;");
CHECK_EQ(java_lang_String.get(), String_class);
CHECK_EQ(java_lang_DexCache.get(), DexCache_class);
CHECK_EQ(java_lang_DexCache->GetObjectSize(), sizeof(mirror::DexCache));
// Setup the primitive array type classes - can't be done until Object has a vtable.
- SetClassRoot(kBooleanArrayClass, FindSystemClass("[Z"));
+ SetClassRoot(kBooleanArrayClass, FindSystemClass(self, "[Z"));
mirror::BooleanArray::SetArrayClass(GetClassRoot(kBooleanArrayClass));
- SetClassRoot(kByteArrayClass, FindSystemClass("[B"));
+ SetClassRoot(kByteArrayClass, FindSystemClass(self, "[B"));
mirror::ByteArray::SetArrayClass(GetClassRoot(kByteArrayClass));
- mirror::Class* found_char_array_class = FindSystemClass("[C");
+ mirror::Class* found_char_array_class = FindSystemClass(self, "[C");
CHECK_EQ(char_array_class.get(), found_char_array_class);
- SetClassRoot(kShortArrayClass, FindSystemClass("[S"));
+ SetClassRoot(kShortArrayClass, FindSystemClass(self, "[S"));
mirror::ShortArray::SetArrayClass(GetClassRoot(kShortArrayClass));
- mirror::Class* found_int_array_class = FindSystemClass("[I");
+ mirror::Class* found_int_array_class = FindSystemClass(self, "[I");
CHECK_EQ(int_array_class.get(), found_int_array_class);
- SetClassRoot(kLongArrayClass, FindSystemClass("[J"));
+ SetClassRoot(kLongArrayClass, FindSystemClass(self, "[J"));
mirror::LongArray::SetArrayClass(GetClassRoot(kLongArrayClass));
- SetClassRoot(kFloatArrayClass, FindSystemClass("[F"));
+ SetClassRoot(kFloatArrayClass, FindSystemClass(self, "[F"));
mirror::FloatArray::SetArrayClass(GetClassRoot(kFloatArrayClass));
- SetClassRoot(kDoubleArrayClass, FindSystemClass("[D"));
+ SetClassRoot(kDoubleArrayClass, FindSystemClass(self, "[D"));
mirror::DoubleArray::SetArrayClass(GetClassRoot(kDoubleArrayClass));
- mirror::Class* found_class_array_class = FindSystemClass("[Ljava/lang/Class;");
+ mirror::Class* found_class_array_class = FindSystemClass(self, "[Ljava/lang/Class;");
CHECK_EQ(class_array_class.get(), found_class_array_class);
- mirror::Class* found_object_array_class = FindSystemClass("[Ljava/lang/Object;");
+ mirror::Class* found_object_array_class = FindSystemClass(self, "[Ljava/lang/Object;");
CHECK_EQ(object_array_class.get(), found_object_array_class);
// Setup the single, global copy of "iftable".
- mirror::Class* java_lang_Cloneable = FindSystemClass("Ljava/lang/Cloneable;");
+ mirror::Class* java_lang_Cloneable = FindSystemClass(self, "Ljava/lang/Cloneable;");
CHECK(java_lang_Cloneable != NULL);
- mirror::Class* java_io_Serializable = FindSystemClass("Ljava/io/Serializable;");
+ mirror::Class* java_io_Serializable = FindSystemClass(self, "Ljava/io/Serializable;");
CHECK(java_io_Serializable != NULL);
// We assume that Cloneable/Serializable don't have superinterfaces -- normally we'd have to
// crawl up and explicitly list all of the supers as well.
@@ -398,73 +398,73 @@
CHECK_EQ(java_io_Serializable, kh.GetDirectInterface(1));
// Run Class, ArtField, and ArtMethod through FindSystemClass. This initializes their
// dex_cache_ fields and register them in class_table_.
- mirror::Class* Class_class = FindSystemClass("Ljava/lang/Class;");
+ mirror::Class* Class_class = FindSystemClass(self, "Ljava/lang/Class;");
CHECK_EQ(java_lang_Class.get(), Class_class);
java_lang_reflect_ArtMethod->SetStatus(mirror::Class::kStatusNotReady, self);
- mirror::Class* Art_method_class = FindSystemClass("Ljava/lang/reflect/ArtMethod;");
+ mirror::Class* Art_method_class = FindSystemClass(self, "Ljava/lang/reflect/ArtMethod;");
CHECK_EQ(java_lang_reflect_ArtMethod.get(), Art_method_class);
java_lang_reflect_ArtField->SetStatus(mirror::Class::kStatusNotReady, self);
- mirror::Class* Art_field_class = FindSystemClass("Ljava/lang/reflect/ArtField;");
+ mirror::Class* Art_field_class = FindSystemClass(self, "Ljava/lang/reflect/ArtField;");
CHECK_EQ(java_lang_reflect_ArtField.get(), Art_field_class);
- mirror::Class* String_array_class = FindSystemClass(class_roots_descriptors_[kJavaLangStringArrayClass]);
+ mirror::Class* String_array_class = FindSystemClass(self, class_roots_descriptors_[kJavaLangStringArrayClass]);
CHECK_EQ(object_array_string.get(), String_array_class);
mirror::Class* Art_method_array_class =
- FindSystemClass(class_roots_descriptors_[kJavaLangReflectArtMethodArrayClass]);
+ FindSystemClass(self, class_roots_descriptors_[kJavaLangReflectArtMethodArrayClass]);
CHECK_EQ(object_array_art_method.get(), Art_method_array_class);
mirror::Class* Art_field_array_class =
- FindSystemClass(class_roots_descriptors_[kJavaLangReflectArtFieldArrayClass]);
+ FindSystemClass(self, class_roots_descriptors_[kJavaLangReflectArtFieldArrayClass]);
CHECK_EQ(object_array_art_field.get(), Art_field_array_class);
// End of special init trickery, subsequent classes may be loaded via FindSystemClass.
// Create java.lang.reflect.Proxy root.
- mirror::Class* java_lang_reflect_Proxy = FindSystemClass("Ljava/lang/reflect/Proxy;");
+ mirror::Class* java_lang_reflect_Proxy = FindSystemClass(self, "Ljava/lang/reflect/Proxy;");
SetClassRoot(kJavaLangReflectProxy, java_lang_reflect_Proxy);
// java.lang.ref classes need to be specially flagged, but otherwise are normal classes
- mirror::Class* java_lang_ref_Reference = FindSystemClass("Ljava/lang/ref/Reference;");
+ mirror::Class* java_lang_ref_Reference = FindSystemClass(self, "Ljava/lang/ref/Reference;");
SetClassRoot(kJavaLangRefReference, java_lang_ref_Reference);
- mirror::Class* java_lang_ref_FinalizerReference = FindSystemClass("Ljava/lang/ref/FinalizerReference;");
+ mirror::Class* java_lang_ref_FinalizerReference = FindSystemClass(self, "Ljava/lang/ref/FinalizerReference;");
java_lang_ref_FinalizerReference->SetAccessFlags(
java_lang_ref_FinalizerReference->GetAccessFlags() |
kAccClassIsReference | kAccClassIsFinalizerReference);
- mirror::Class* java_lang_ref_PhantomReference = FindSystemClass("Ljava/lang/ref/PhantomReference;");
+ mirror::Class* java_lang_ref_PhantomReference = FindSystemClass(self, "Ljava/lang/ref/PhantomReference;");
java_lang_ref_PhantomReference->SetAccessFlags(
java_lang_ref_PhantomReference->GetAccessFlags() |
kAccClassIsReference | kAccClassIsPhantomReference);
- mirror::Class* java_lang_ref_SoftReference = FindSystemClass("Ljava/lang/ref/SoftReference;");
+ mirror::Class* java_lang_ref_SoftReference = FindSystemClass(self, "Ljava/lang/ref/SoftReference;");
java_lang_ref_SoftReference->SetAccessFlags(
java_lang_ref_SoftReference->GetAccessFlags() | kAccClassIsReference);
- mirror::Class* java_lang_ref_WeakReference = FindSystemClass("Ljava/lang/ref/WeakReference;");
+ mirror::Class* java_lang_ref_WeakReference = FindSystemClass(self, "Ljava/lang/ref/WeakReference;");
java_lang_ref_WeakReference->SetAccessFlags(
java_lang_ref_WeakReference->GetAccessFlags() |
kAccClassIsReference | kAccClassIsWeakReference);
// Setup the ClassLoader, verifying the object_size_.
- mirror::Class* java_lang_ClassLoader = FindSystemClass("Ljava/lang/ClassLoader;");
+ mirror::Class* java_lang_ClassLoader = FindSystemClass(self, "Ljava/lang/ClassLoader;");
CHECK_EQ(java_lang_ClassLoader->GetObjectSize(), sizeof(mirror::ClassLoader));
SetClassRoot(kJavaLangClassLoader, java_lang_ClassLoader);
// Set up java.lang.Throwable, java.lang.ClassNotFoundException, and
// java.lang.StackTraceElement as a convenience.
- SetClassRoot(kJavaLangThrowable, FindSystemClass("Ljava/lang/Throwable;"));
+ SetClassRoot(kJavaLangThrowable, FindSystemClass(self, "Ljava/lang/Throwable;"));
mirror::Throwable::SetClass(GetClassRoot(kJavaLangThrowable));
- SetClassRoot(kJavaLangClassNotFoundException, FindSystemClass("Ljava/lang/ClassNotFoundException;"));
- SetClassRoot(kJavaLangStackTraceElement, FindSystemClass("Ljava/lang/StackTraceElement;"));
- SetClassRoot(kJavaLangStackTraceElementArrayClass, FindSystemClass("[Ljava/lang/StackTraceElement;"));
+ SetClassRoot(kJavaLangClassNotFoundException, FindSystemClass(self, "Ljava/lang/ClassNotFoundException;"));
+ SetClassRoot(kJavaLangStackTraceElement, FindSystemClass(self, "Ljava/lang/StackTraceElement;"));
+ SetClassRoot(kJavaLangStackTraceElementArrayClass, FindSystemClass(self, "[Ljava/lang/StackTraceElement;"));
mirror::StackTraceElement::SetClass(GetClassRoot(kJavaLangStackTraceElement));
- FinishInit();
+ FinishInit(self);
VLOG(startup) << "ClassLinker::InitFromCompiler exiting";
}
-void ClassLinker::FinishInit() {
+void ClassLinker::FinishInit(Thread* self) {
VLOG(startup) << "ClassLinker::FinishInit entering";
// Let the heap know some key offsets into java.lang.ref instances
@@ -473,7 +473,7 @@
// fully initialized
mirror::Class* java_lang_ref_Reference = GetClassRoot(kJavaLangRefReference);
mirror::Class* java_lang_ref_FinalizerReference =
- FindSystemClass("Ljava/lang/ref/FinalizerReference;");
+ FindSystemClass(self, "Ljava/lang/ref/FinalizerReference;");
mirror::ArtField* pendingNext = java_lang_ref_Reference->GetInstanceField(0);
FieldHelper fh(pendingNext);
@@ -543,108 +543,45 @@
const char* oat_cache_filename,
std::string* error_msg) {
Locks::mutator_lock_->AssertNotHeld(Thread::Current()); // Avoid starving GC.
- std::string dex2oat_string(GetAndroidRoot());
- dex2oat_string += (kIsDebugBuild ? "/bin/dex2oatd" : "/bin/dex2oat");
- const char* dex2oat = dex2oat_string.c_str();
-
- const char* class_path = Runtime::Current()->GetClassPathString().c_str();
+ std::string dex2oat(GetAndroidRoot());
+ dex2oat += (kIsDebugBuild ? "/bin/dex2oatd" : "/bin/dex2oat");
gc::Heap* heap = Runtime::Current()->GetHeap();
- std::string boot_image_option_string("--boot-image=");
- boot_image_option_string += heap->GetImageSpace()->GetImageFilename();
- const char* boot_image_option = boot_image_option_string.c_str();
+ std::string boot_image_option("--boot-image=");
+ boot_image_option += heap->GetImageSpace()->GetImageFilename();
- std::string dex_file_option_string("--dex-file=");
- dex_file_option_string += dex_filename;
- const char* dex_file_option = dex_file_option_string.c_str();
+ std::string dex_file_option("--dex-file=");
+ dex_file_option += dex_filename;
- std::string oat_fd_option_string("--oat-fd=");
- StringAppendF(&oat_fd_option_string, "%d", oat_fd);
- const char* oat_fd_option = oat_fd_option_string.c_str();
+ std::string oat_fd_option("--oat-fd=");
+ StringAppendF(&oat_fd_option, "%d", oat_fd);
- std::string oat_location_option_string("--oat-location=");
- oat_location_option_string += oat_cache_filename;
- const char* oat_location_option = oat_location_option_string.c_str();
+ std::string oat_location_option("--oat-location=");
+ oat_location_option += oat_cache_filename;
- std::string oat_compiler_filter_string("-compiler-filter:");
- Runtime::CompilerFilter filter = Runtime::Current()->GetCompilerFilter();
- switch (filter) {
- case Runtime::kInterpretOnly:
- oat_compiler_filter_string += "interpret-only";
- break;
- case Runtime::kSpace:
- oat_compiler_filter_string += "space";
- break;
- case Runtime::kBalanced:
- oat_compiler_filter_string += "balanced";
- break;
- case Runtime::kSpeed:
- oat_compiler_filter_string += "speed";
- break;
- case Runtime::kEverything:
- oat_compiler_filter_string += "everything";
- break;
- default:
- LOG(FATAL) << "Unexpected case: " << filter;
+ std::vector<std::string> argv;
+ argv.push_back(dex2oat);
+ argv.push_back("--runtime-arg");
+ argv.push_back("-Xms64m");
+ argv.push_back("--runtime-arg");
+ argv.push_back("-Xmx64m");
+ argv.push_back("--runtime-arg");
+ argv.push_back("-classpath");
+ argv.push_back("--runtime-arg");
+ argv.push_back(Runtime::Current()->GetClassPathString());
+ if (!kIsTargetBuild) {
+ argv.push_back("--host");
}
- const char* oat_compiler_filter_option = oat_compiler_filter_string.c_str();
-
- // fork and exec dex2oat
- pid_t pid = fork();
- if (pid == 0) {
- // no allocation allowed between fork and exec
-
- // change process groups, so we don't get reaped by ProcessManager
- setpgid(0, 0);
-
- // gLogVerbosity.class_linker = true;
- VLOG(class_linker) << dex2oat
- << " --runtime-arg -Xms64m"
- << " --runtime-arg -Xmx64m"
- << " --runtime-arg -classpath"
- << " --runtime-arg " << class_path
- << " --runtime-arg " << oat_compiler_filter_option
-#if !defined(ART_TARGET)
- << " --host"
-#endif
- << " " << boot_image_option
- << " " << dex_file_option
- << " " << oat_fd_option
- << " " << oat_location_option;
-
- execl(dex2oat, dex2oat,
- "--runtime-arg", "-Xms64m",
- "--runtime-arg", "-Xmx64m",
- "--runtime-arg", "-classpath",
- "--runtime-arg", class_path,
- "--runtime-arg", oat_compiler_filter_option,
-#if !defined(ART_TARGET)
- "--host",
-#endif
- boot_image_option,
- dex_file_option,
- oat_fd_option,
- oat_location_option,
- NULL);
-
- PLOG(FATAL) << "execl(" << dex2oat << ") failed";
- return false;
- } else {
- // wait for dex2oat to finish
- int status;
- pid_t got_pid = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0));
- if (got_pid != pid) {
- *error_msg = StringPrintf("Failed to create oat file. Waitpid failed: wanted %d, got %d",
- pid, got_pid);
- return false;
- }
- if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
- *error_msg = StringPrintf("Failed to create oat file. %s failed with dex-file '%s'",
- dex2oat, dex_filename);
- return false;
- }
+ argv.push_back(boot_image_option);
+ argv.push_back(dex_file_option);
+ argv.push_back(oat_fd_option);
+ argv.push_back(oat_location_option);
+ const std::vector<std::string>& compiler_options = Runtime::Current()->GetCompilerOptions();
+ for (size_t i = 0; compiler_options.size(); ++i) {
+ argv.push_back(compiler_options[i].c_str());
}
- return true;
+
+ return Exec(argv, error_msg);
}
const OatFile* ClassLinker::RegisterOatFile(const OatFile* oat_file) {
@@ -1111,7 +1048,7 @@
mirror::Throwable::SetClass(GetClassRoot(kJavaLangThrowable));
mirror::StackTraceElement::SetClass(GetClassRoot(kJavaLangStackTraceElement));
- FinishInit();
+ FinishInit(self);
VLOG(startup) << "ClassLinker::InitFromImage exiting";
}
@@ -1150,6 +1087,13 @@
}
callback(reinterpret_cast<mirror::Object**>(&array_iftable_), arg, 0, kRootVMInternal);
DCHECK(array_iftable_ != nullptr);
+ for (size_t i = 0; i < kFindArrayCacheSize; ++i) {
+ if (find_array_class_cache_[i] != nullptr) {
+ callback(reinterpret_cast<mirror::Object**>(&find_array_class_cache_[i]), arg, 0,
+ kRootVMInternal);
+ DCHECK(find_array_class_cache_[i] != nullptr);
+ }
+ }
}
void ClassLinker::VisitClasses(ClassVisitor* visitor, void* arg) {
@@ -1307,21 +1251,10 @@
return klass;
}
-bool ClassLinker::IsInBootClassPath(const char* descriptor) {
- DexFile::ClassPathEntry pair = DexFile::FindInClassPath(descriptor, boot_class_path_);
- return pair.second != NULL;
-}
-
-mirror::Class* ClassLinker::FindSystemClass(const char* descriptor) {
- SirtRef<mirror::ClassLoader> class_loader(Thread::Current(), nullptr);
- return FindClass(descriptor, class_loader);
-}
-
-mirror::Class* ClassLinker::FindClass(const char* descriptor,
+mirror::Class* ClassLinker::FindClass(Thread* self, const char* descriptor,
const SirtRef<mirror::ClassLoader>& class_loader) {
DCHECK_NE(*descriptor, '\0') << "descriptor is empty string";
- Thread* self = Thread::Current();
- DCHECK(self != NULL);
+ DCHECK(self != nullptr);
self->AssertNoPendingException();
if (descriptor[1] == '\0') {
// only the descriptors of primitive types should be 1 character long, also avoid class lookup
@@ -1335,7 +1268,7 @@
}
// Class is not yet loaded.
if (descriptor[0] == '[') {
- return CreateArrayClass(descriptor, class_loader);
+ return CreateArrayClass(self, descriptor, class_loader);
} else if (class_loader.get() == nullptr) {
DexFile::ClassPathEntry pair = DexFile::FindInClassPath(descriptor, boot_class_path_);
if (pair.second != NULL) {
@@ -1346,7 +1279,7 @@
// First try the boot class path, we check the descriptor first to avoid an unnecessary
// throw of a NoClassDefFoundError.
if (IsInBootClassPath(descriptor)) {
- mirror::Class* system_class = FindSystemClass(descriptor);
+ mirror::Class* system_class = FindSystemClass(self, descriptor);
CHECK(system_class != NULL);
return system_class;
}
@@ -1365,7 +1298,7 @@
}
} else {
- ScopedObjectAccessUnchecked soa(self->GetJniEnv());
+ ScopedObjectAccessUnchecked soa(self);
ScopedLocalRef<jobject> class_loader_object(soa.Env(),
soa.AddLocalReference<jobject>(class_loader.get()));
std::string class_name_string(DescriptorToDot(descriptor));
@@ -1382,7 +1315,7 @@
WellKnownClasses::java_lang_ClassLoader_loadClass,
class_name_object.get()));
}
- if (soa.Self()->IsExceptionPending()) {
+ if (self->IsExceptionPending()) {
// If the ClassLoader threw, pass that exception up.
return NULL;
} else if (result.get() == NULL) {
@@ -2133,12 +2066,11 @@
// array class; that always comes from the base element class.
//
// Returns NULL with an exception raised on failure.
-mirror::Class* ClassLinker::CreateArrayClass(const char* descriptor,
+mirror::Class* ClassLinker::CreateArrayClass(Thread* self, const char* descriptor,
const SirtRef<mirror::ClassLoader>& class_loader) {
// Identify the underlying component type
CHECK_EQ('[', descriptor[0]);
- Thread* self = Thread::Current();
- SirtRef<mirror::Class> component_type(self, FindClass(descriptor + 1, class_loader));
+ SirtRef<mirror::Class> component_type(self, FindClass(self, descriptor + 1, class_loader));
if (component_type.get() == nullptr) {
DCHECK(self->IsExceptionPending());
return nullptr;
@@ -3242,7 +3174,7 @@
for (int i = super->GetVTable()->GetLength() - 1; i >= 0; --i) {
mirror::ArtMethod* method = klass->GetVTable()->Get(i);
if (method != super->GetVTable()->Get(i) &&
- !IsSameMethodSignatureInDifferentClassContexts(method, super.get(), klass.get())) {
+ !IsSameMethodSignatureInDifferentClassContexts(self, method, super.get(), klass.get())) {
ThrowLinkageError(klass.get(), "Class %s method %s resolves differently in superclass %s",
PrettyDescriptor(klass.get()).c_str(), PrettyMethod(method).c_str(),
PrettyDescriptor(super.get()).c_str());
@@ -3255,7 +3187,7 @@
if (klass->GetClassLoader() != interface->GetClassLoader()) {
for (size_t j = 0; j < interface->NumVirtualMethods(); ++j) {
mirror::ArtMethod* method = klass->GetIfTable()->GetMethodArray(i)->Get(j);
- if (!IsSameMethodSignatureInDifferentClassContexts(method, interface.get(),
+ if (!IsSameMethodSignatureInDifferentClassContexts(self, method, interface.get(),
method->GetDeclaringClass())) {
ThrowLinkageError(klass.get(), "Class %s method %s resolves differently in interface %s",
PrettyDescriptor(method->GetDeclaringClass()).c_str(),
@@ -3271,13 +3203,13 @@
// Returns true if classes referenced by the signature of the method are the
// same classes in klass1 as they are in klass2.
-bool ClassLinker::IsSameMethodSignatureInDifferentClassContexts(mirror::ArtMethod* method,
+bool ClassLinker::IsSameMethodSignatureInDifferentClassContexts(Thread* self,
+ mirror::ArtMethod* method,
mirror::Class* klass1,
mirror::Class* klass2) {
if (klass1 == klass2) {
return true;
}
- Thread* self = Thread::Current();
CHECK(klass1 != nullptr);
CHECK(klass2 != nullptr);
SirtRef<mirror::ClassLoader> loader1(self, klass1->GetClassLoader());
@@ -3292,7 +3224,7 @@
}
if (descriptor[0] == 'L' || descriptor[0] == '[') {
// Found a non-primitive type.
- if (!IsSameDescriptorInDifferentClassContexts(descriptor, loader1, loader2)) {
+ if (!IsSameDescriptorInDifferentClassContexts(self, descriptor, loader1, loader2)) {
return false;
}
}
@@ -3300,7 +3232,7 @@
// Check the return type
const char* descriptor = dex_file.GetReturnTypeDescriptor(proto_id);
if (descriptor[0] == 'L' || descriptor[0] == '[') {
- if (!IsSameDescriptorInDifferentClassContexts(descriptor, loader1, loader2)) {
+ if (!IsSameDescriptorInDifferentClassContexts(self, descriptor, loader1, loader2)) {
return false;
}
}
@@ -3308,16 +3240,15 @@
}
// Returns true if the descriptor resolves to the same class in the context of loader1 and loader2.
-bool ClassLinker::IsSameDescriptorInDifferentClassContexts(const char* descriptor,
+bool ClassLinker::IsSameDescriptorInDifferentClassContexts(Thread* self, const char* descriptor,
SirtRef<mirror::ClassLoader>& loader1,
SirtRef<mirror::ClassLoader>& loader2) {
CHECK(descriptor != nullptr);
- Thread* self = Thread::Current();
- SirtRef<mirror::Class> found1(self, FindClass(descriptor, loader1));
+ SirtRef<mirror::Class> found1(self, FindClass(self, descriptor, loader1));
if (found1.get() == nullptr) {
self->ClearException();
}
- mirror::Class* found2 = FindClass(descriptor, loader2);
+ mirror::Class* found2 = FindClass(self, descriptor, loader2);
if (found2 == nullptr) {
self->ClearException();
}
@@ -4117,22 +4048,22 @@
DCHECK(dex_cache.get() != NULL);
mirror::Class* resolved = dex_cache->GetResolvedType(type_idx);
if (resolved == NULL) {
+ Thread* self = Thread::Current();
const char* descriptor = dex_file.StringByTypeIdx(type_idx);
- resolved = FindClass(descriptor, class_loader);
+ resolved = FindClass(self, descriptor, class_loader);
if (resolved != NULL) {
// TODO: we used to throw here if resolved's class loader was not the
// boot class loader. This was to permit different classes with the
// same name to be loaded simultaneously by different loaders
dex_cache->SetResolvedType(type_idx, resolved);
} else {
- Thread* self = Thread::Current();
CHECK(self->IsExceptionPending())
<< "Expected pending exception for failed resolution of: " << descriptor;
// Convert a ClassNotFoundException to a NoClassDefFoundError.
SirtRef<mirror::Throwable> cause(self, self->GetException(NULL));
if (cause->InstanceOf(GetClassRoot(kJavaLangClassNotFoundException))) {
DCHECK(resolved == NULL); // No SirtRef needed to preserve resolved.
- Thread::Current()->ClearException();
+ self->ClearException();
ThrowNoClassDefFoundError("Failed resolution of: %s", descriptor);
self->GetException(NULL)->SetCause(cause.get());
}
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 0745ee2..f346102 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -72,10 +72,17 @@
// Finds a class by its descriptor, loading it if necessary.
// If class_loader is null, searches boot_class_path_.
- mirror::Class* FindClass(const char* descriptor, const SirtRef<mirror::ClassLoader>& class_loader)
+ mirror::Class* FindClass(Thread* self, const char* descriptor,
+ const SirtRef<mirror::ClassLoader>& class_loader)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- mirror::Class* FindSystemClass(const char* descriptor)
+ // Finds a class by its descriptor using the "system" class loader, ie by searching the
+ // boot_class_path_.
+ mirror::Class* FindSystemClass(Thread* self, const char* descriptor)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ // Finds the array class given for the element class.
+ mirror::Class* FindArrayClass(Thread* self, mirror::Class* element_class)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Reutrns true if the class linker is initialized.
@@ -378,7 +385,7 @@
LOCKS_EXCLUDED(dex_lock_)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void FinishInit() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void FinishInit(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// For early bootstrapping by Init
mirror::Class* AllocClass(Thread* self, mirror::Class* java_lang_Class, size_t class_size)
@@ -399,7 +406,7 @@
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- mirror::Class* CreateArrayClass(const char* descriptor,
+ mirror::Class* CreateArrayClass(Thread* self, const char* descriptor,
const SirtRef<mirror::ClassLoader>& class_loader)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -449,12 +456,12 @@
bool ValidateSuperClassDescriptors(const SirtRef<mirror::Class>& klass)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsSameDescriptorInDifferentClassContexts(const char* descriptor,
+ bool IsSameDescriptorInDifferentClassContexts(Thread* self, const char* descriptor,
SirtRef<mirror::ClassLoader>& class_loader1,
SirtRef<mirror::ClassLoader>& class_loader2)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsSameMethodSignatureInDifferentClassContexts(mirror::ArtMethod* method,
+ bool IsSameMethodSignatureInDifferentClassContexts(Thread* self, mirror::ArtMethod* method,
mirror::Class* klass1,
mirror::Class* klass2)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -617,8 +624,15 @@
return descriptor;
}
+ // The interface table used by all arrays.
mirror::IfTable* array_iftable_;
+ // A cache of the last FindArrayClass results. The cache serves to avoid creating array class
+ // descriptors for the sake of performing FindClass.
+ static constexpr size_t kFindArrayCacheSize = 16;
+ mirror::Class* find_array_class_cache_[kFindArrayCacheSize];
+ size_t find_array_class_cache_next_victim_;
+
bool init_done_;
bool dex_caches_dirty_ GUARDED_BY(dex_lock_);
bool class_table_dirty_ GUARDED_BY(Locks::classlinker_classes_lock_);
diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc
index ebf02fe..d6a67cc 100644
--- a/runtime/class_linker_test.cc
+++ b/runtime/class_linker_test.cc
@@ -41,18 +41,20 @@
protected:
void AssertNonExistentClass(const std::string& descriptor)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- EXPECT_TRUE(class_linker_->FindSystemClass(descriptor.c_str()) == NULL);
Thread* self = Thread::Current();
+ EXPECT_TRUE(class_linker_->FindSystemClass(self, descriptor.c_str()) == NULL);
EXPECT_TRUE(self->IsExceptionPending());
mirror::Object* exception = self->GetException(NULL);
self->ClearException();
- mirror::Class* exception_class = class_linker_->FindSystemClass("Ljava/lang/NoClassDefFoundError;");
+ mirror::Class* exception_class =
+ class_linker_->FindSystemClass(self, "Ljava/lang/NoClassDefFoundError;");
EXPECT_TRUE(exception->InstanceOf(exception_class));
}
void AssertPrimitiveClass(const std::string& descriptor)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- AssertPrimitiveClass(descriptor, class_linker_->FindSystemClass(descriptor.c_str()));
+ Thread* self = Thread::Current();
+ AssertPrimitiveClass(descriptor, class_linker_->FindSystemClass(self, descriptor.c_str()));
}
void AssertPrimitiveClass(const std::string& descriptor, mirror::Class* primitive)
@@ -98,7 +100,7 @@
Thread* self = Thread::Current();
SirtRef<mirror::ClassLoader> loader(self, class_loader);
SirtRef<mirror::Class> array(self,
- class_linker_->FindClass(array_descriptor.c_str(), loader));
+ class_linker_->FindClass(self, array_descriptor.c_str(), loader));
ClassHelper array_component_ch(array->GetComponentType());
EXPECT_STREQ(component_type.c_str(), array_component_ch.GetDescriptor());
EXPECT_EQ(class_loader, array->GetClassLoader());
@@ -115,7 +117,8 @@
EXPECT_TRUE(array->GetClass()->GetSuperClass() != NULL);
ASSERT_STREQ(array_descriptor.c_str(), kh.GetDescriptor());
EXPECT_TRUE(array->GetSuperClass() != NULL);
- EXPECT_EQ(class_linker_->FindSystemClass("Ljava/lang/Object;"), array->GetSuperClass());
+ Thread* self = Thread::Current();
+ EXPECT_EQ(class_linker_->FindSystemClass(self, "Ljava/lang/Object;"), array->GetSuperClass());
EXPECT_TRUE(array->HasSuperClass());
ASSERT_TRUE(array->GetComponentType() != NULL);
kh.ChangeClass(array->GetComponentType());
@@ -147,6 +150,7 @@
kh.ChangeClass(array.get());
kh.ChangeClass(kh.GetDirectInterface(1));
EXPECT_STREQ(kh.GetDescriptor(), "Ljava/io/Serializable;");
+ EXPECT_EQ(class_linker_->FindArrayClass(self, array->GetComponentType()), array.get());
}
void AssertMethod(mirror::ArtMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -300,8 +304,8 @@
void AssertDexFileClass(mirror::ClassLoader* class_loader, const std::string& descriptor)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
ASSERT_TRUE(descriptor != NULL);
- SirtRef<mirror::Class> klass(Thread::Current(),
- class_linker_->FindSystemClass(descriptor.c_str()));
+ Thread* self = Thread::Current();
+ SirtRef<mirror::Class> klass(self, class_linker_->FindSystemClass(self, descriptor.c_str()));
ASSERT_TRUE(klass.get() != nullptr);
EXPECT_STREQ(descriptor.c_str(), ClassHelper(klass.get()).GetDescriptor());
EXPECT_EQ(class_loader, klass->GetClassLoader());
@@ -359,7 +363,9 @@
std::vector<CheckOffset> offsets;
bool Check() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- mirror::Class* klass = Runtime::Current()->GetClassLinker()->FindSystemClass(class_descriptor.c_str());
+ Thread* self = Thread::Current();
+ mirror::Class* klass =
+ Runtime::Current()->GetClassLinker()->FindSystemClass(self, class_descriptor.c_str());
CHECK(klass != NULL) << class_descriptor;
bool error = false;
@@ -646,12 +652,12 @@
ScopedObjectAccess soa(Thread::Current());
SirtRef<mirror::ClassLoader> class_loader(soa.Self(), soa.Decode<mirror::ClassLoader*>(LoadDex("Nested")));
- mirror::Class* outer = class_linker_->FindClass("LNested;", class_loader);
+ mirror::Class* outer = class_linker_->FindClass(soa.Self(), "LNested;", class_loader);
ASSERT_TRUE(outer != NULL);
EXPECT_EQ(0U, outer->NumVirtualMethods());
EXPECT_EQ(1U, outer->NumDirectMethods());
- mirror::Class* inner = class_linker_->FindClass("LNested$Inner;", class_loader);
+ mirror::Class* inner = class_linker_->FindClass(soa.Self(), "LNested$Inner;", class_loader);
ASSERT_TRUE(inner != NULL);
EXPECT_EQ(0U, inner->NumVirtualMethods());
EXPECT_EQ(1U, inner->NumDirectMethods());
@@ -673,7 +679,7 @@
TEST_F(ClassLinkerTest, FindClass) {
ScopedObjectAccess soa(Thread::Current());
- mirror::Class* JavaLangObject = class_linker_->FindSystemClass("Ljava/lang/Object;");
+ mirror::Class* JavaLangObject = class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Object;");
ClassHelper kh(JavaLangObject);
ASSERT_TRUE(JavaLangObject != NULL);
ASSERT_TRUE(JavaLangObject->GetClass() != NULL);
@@ -710,7 +716,7 @@
SirtRef<mirror::ClassLoader> class_loader(soa.Self(), soa.Decode<mirror::ClassLoader*>(LoadDex("MyClass")));
AssertNonExistentClass("LMyClass;");
- mirror::Class* MyClass = class_linker_->FindClass("LMyClass;", class_loader);
+ mirror::Class* MyClass = class_linker_->FindClass(soa.Self(), "LMyClass;", class_loader);
kh.ChangeClass(MyClass);
ASSERT_TRUE(MyClass != NULL);
ASSERT_TRUE(MyClass->GetClass() != NULL);
@@ -761,7 +767,7 @@
// start of the object
TEST_F(ClassLinkerTest, ValidateObjectArrayElementsOffset) {
ScopedObjectAccess soa(Thread::Current());
- mirror::Class* array_class = class_linker_->FindSystemClass("[Ljava/lang/String;");
+ mirror::Class* array_class = class_linker_->FindSystemClass(soa.Self(), "[Ljava/lang/String;");
mirror::ObjectArray<mirror::String>* array =
mirror::ObjectArray<mirror::String>::Alloc(soa.Self(), array_class, 0);
uintptr_t data_offset =
@@ -777,27 +783,27 @@
TEST_F(ClassLinkerTest, ValidatePrimitiveArrayElementsOffset) {
ScopedObjectAccess soa(Thread::Current());
SirtRef<mirror::LongArray> long_array(soa.Self(), mirror::LongArray::Alloc(soa.Self(), 0));
- EXPECT_EQ(class_linker_->FindSystemClass("[J"), long_array->GetClass());
+ EXPECT_EQ(class_linker_->FindSystemClass(soa.Self(), "[J"), long_array->GetClass());
uintptr_t data_offset = reinterpret_cast<uintptr_t>(long_array->GetData());
EXPECT_TRUE(IsAligned<8>(data_offset)); // Longs require 8 byte alignment
SirtRef<mirror::DoubleArray> double_array(soa.Self(), mirror::DoubleArray::Alloc(soa.Self(), 0));
- EXPECT_EQ(class_linker_->FindSystemClass("[D"), double_array->GetClass());
+ EXPECT_EQ(class_linker_->FindSystemClass(soa.Self(), "[D"), double_array->GetClass());
data_offset = reinterpret_cast<uintptr_t>(double_array->GetData());
EXPECT_TRUE(IsAligned<8>(data_offset)); // Doubles require 8 byte alignment
SirtRef<mirror::IntArray> int_array(soa.Self(), mirror::IntArray::Alloc(soa.Self(), 0));
- EXPECT_EQ(class_linker_->FindSystemClass("[I"), int_array->GetClass());
+ EXPECT_EQ(class_linker_->FindSystemClass(soa.Self(), "[I"), int_array->GetClass());
data_offset = reinterpret_cast<uintptr_t>(int_array->GetData());
EXPECT_TRUE(IsAligned<4>(data_offset)); // Ints require 4 byte alignment
SirtRef<mirror::CharArray> char_array(soa.Self(), mirror::CharArray::Alloc(soa.Self(), 0));
- EXPECT_EQ(class_linker_->FindSystemClass("[C"), char_array->GetClass());
+ EXPECT_EQ(class_linker_->FindSystemClass(soa.Self(), "[C"), char_array->GetClass());
data_offset = reinterpret_cast<uintptr_t>(char_array->GetData());
EXPECT_TRUE(IsAligned<2>(data_offset)); // Chars require 2 byte alignment
SirtRef<mirror::ShortArray> short_array(soa.Self(), mirror::ShortArray::Alloc(soa.Self(), 0));
- EXPECT_EQ(class_linker_->FindSystemClass("[S"), short_array->GetClass());
+ EXPECT_EQ(class_linker_->FindSystemClass(soa.Self(), "[S"), short_array->GetClass());
data_offset = reinterpret_cast<uintptr_t>(short_array->GetData());
EXPECT_TRUE(IsAligned<2>(data_offset)); // Shorts require 2 byte alignment
@@ -810,28 +816,28 @@
ScopedObjectAccess soa(Thread::Current());
SirtRef<mirror::ClassLoader> class_loader(soa.Self(), nullptr);
mirror::Class* c;
- c = class_linker_->FindClass("Ljava/lang/Boolean;", class_loader);
+ c = class_linker_->FindClass(soa.Self(), "Ljava/lang/Boolean;", class_loader);
FieldHelper fh(c->GetIFields()->Get(0));
EXPECT_STREQ("value", fh.GetName());
- c = class_linker_->FindClass("Ljava/lang/Byte;", class_loader);
+ c = class_linker_->FindClass(soa.Self(), "Ljava/lang/Byte;", class_loader);
fh.ChangeField(c->GetIFields()->Get(0));
EXPECT_STREQ("value", fh.GetName());
- c = class_linker_->FindClass("Ljava/lang/Character;", class_loader);
+ c = class_linker_->FindClass(soa.Self(), "Ljava/lang/Character;", class_loader);
fh.ChangeField(c->GetIFields()->Get(0));
EXPECT_STREQ("value", fh.GetName());
- c = class_linker_->FindClass("Ljava/lang/Double;", class_loader);
+ c = class_linker_->FindClass(soa.Self(), "Ljava/lang/Double;", class_loader);
fh.ChangeField(c->GetIFields()->Get(0));
EXPECT_STREQ("value", fh.GetName());
- c = class_linker_->FindClass("Ljava/lang/Float;", class_loader);
+ c = class_linker_->FindClass(soa.Self(), "Ljava/lang/Float;", class_loader);
fh.ChangeField(c->GetIFields()->Get(0));
EXPECT_STREQ("value", fh.GetName());
- c = class_linker_->FindClass("Ljava/lang/Integer;", class_loader);
+ c = class_linker_->FindClass(soa.Self(), "Ljava/lang/Integer;", class_loader);
fh.ChangeField(c->GetIFields()->Get(0));
EXPECT_STREQ("value", fh.GetName());
- c = class_linker_->FindClass("Ljava/lang/Long;", class_loader);
+ c = class_linker_->FindClass(soa.Self(), "Ljava/lang/Long;", class_loader);
fh.ChangeField(c->GetIFields()->Get(0));
EXPECT_STREQ("value", fh.GetName());
- c = class_linker_->FindClass("Ljava/lang/Short;", class_loader);
+ c = class_linker_->FindClass(soa.Self(), "Ljava/lang/Short;", class_loader);
fh.ChangeField(c->GetIFields()->Get(0));
EXPECT_STREQ("value", fh.GetName());
}
@@ -840,8 +846,8 @@
ScopedObjectAccess soa(Thread::Current());
SirtRef<mirror::ClassLoader> class_loader_1(soa.Self(), soa.Decode<mirror::ClassLoader*>(LoadDex("MyClass")));
SirtRef<mirror::ClassLoader> class_loader_2(soa.Self(), soa.Decode<mirror::ClassLoader*>(LoadDex("MyClass")));
- mirror::Class* MyClass_1 = class_linker_->FindClass("LMyClass;", class_loader_1);
- mirror::Class* MyClass_2 = class_linker_->FindClass("LMyClass;", class_loader_2);
+ mirror::Class* MyClass_1 = class_linker_->FindClass(soa.Self(), "LMyClass;", class_loader_1);
+ mirror::Class* MyClass_2 = class_linker_->FindClass(soa.Self(), "LMyClass;", class_loader_2);
EXPECT_TRUE(MyClass_1 != NULL);
EXPECT_TRUE(MyClass_2 != NULL);
EXPECT_NE(MyClass_1, MyClass_2);
@@ -849,8 +855,10 @@
TEST_F(ClassLinkerTest, StaticFields) {
ScopedObjectAccess soa(Thread::Current());
- SirtRef<mirror::ClassLoader> class_loader(soa.Self(), soa.Decode<mirror::ClassLoader*>(LoadDex("Statics")));
- SirtRef<mirror::Class> statics(soa.Self(), class_linker_->FindClass("LStatics;", class_loader));
+ SirtRef<mirror::ClassLoader> class_loader(soa.Self(),
+ soa.Decode<mirror::ClassLoader*>(LoadDex("Statics")));
+ SirtRef<mirror::Class> statics(soa.Self(), class_linker_->FindClass(soa.Self(), "LStatics;",
+ class_loader));
class_linker_->EnsureInitialized(statics, true, true);
// Static final primitives that are initialized by a compile-time constant
@@ -933,11 +941,11 @@
TEST_F(ClassLinkerTest, Interfaces) {
ScopedObjectAccess soa(Thread::Current());
SirtRef<mirror::ClassLoader> class_loader(soa.Self(), soa.Decode<mirror::ClassLoader*>(LoadDex("Interfaces")));
- mirror::Class* I = class_linker_->FindClass("LInterfaces$I;", class_loader);
- mirror::Class* J = class_linker_->FindClass("LInterfaces$J;", class_loader);
- mirror::Class* K = class_linker_->FindClass("LInterfaces$K;", class_loader);
- mirror::Class* A = class_linker_->FindClass("LInterfaces$A;", class_loader);
- mirror::Class* B = class_linker_->FindClass("LInterfaces$B;", class_loader);
+ mirror::Class* I = class_linker_->FindClass(soa.Self(), "LInterfaces$I;", class_loader);
+ mirror::Class* J = class_linker_->FindClass(soa.Self(), "LInterfaces$J;", class_loader);
+ mirror::Class* K = class_linker_->FindClass(soa.Self(), "LInterfaces$K;", class_loader);
+ mirror::Class* A = class_linker_->FindClass(soa.Self(), "LInterfaces$A;", class_loader);
+ mirror::Class* B = class_linker_->FindClass(soa.Self(), "LInterfaces$B;", class_loader);
EXPECT_TRUE(I->IsAssignableFrom(A));
EXPECT_TRUE(J->IsAssignableFrom(A));
EXPECT_TRUE(J->IsAssignableFrom(K));
@@ -996,7 +1004,7 @@
SirtRef<mirror::ClassLoader> class_loader(soa.Self(), soa.Decode<mirror::ClassLoader*>(jclass_loader));
const DexFile* dex_file = Runtime::Current()->GetCompileTimeClassPath(jclass_loader)[0];
CHECK(dex_file != NULL);
- mirror::Class* klass = class_linker_->FindClass("LStaticsFromCode;", class_loader);
+ mirror::Class* klass = class_linker_->FindClass(soa.Self(), "LStaticsFromCode;", class_loader);
mirror::ArtMethod* clinit = klass->FindClassInitializer();
mirror::ArtMethod* getS0 = klass->FindDirectMethod("getS0", "()Ljava/lang/Object;");
const DexFile::StringId* string_id = dex_file->FindStringId("LStaticsFromCode;");
@@ -1017,32 +1025,32 @@
mirror::Class* c;
// Object has a finalize method, but we know it's empty.
- c = class_linker_->FindSystemClass("Ljava/lang/Object;");
+ c = class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Object;");
EXPECT_FALSE(c->IsFinalizable());
// Enum has a finalize method to prevent its subclasses from implementing one.
- c = class_linker_->FindSystemClass("Ljava/lang/Enum;");
+ c = class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Enum;");
EXPECT_FALSE(c->IsFinalizable());
// RoundingMode is an enum.
- c = class_linker_->FindSystemClass("Ljava/math/RoundingMode;");
+ c = class_linker_->FindSystemClass(soa.Self(), "Ljava/math/RoundingMode;");
EXPECT_FALSE(c->IsFinalizable());
// RandomAccessFile extends Object and overrides finalize.
- c = class_linker_->FindSystemClass("Ljava/io/RandomAccessFile;");
+ c = class_linker_->FindSystemClass(soa.Self(), "Ljava/io/RandomAccessFile;");
EXPECT_TRUE(c->IsFinalizable());
// FileInputStream is finalizable and extends InputStream which isn't.
- c = class_linker_->FindSystemClass("Ljava/io/InputStream;");
+ c = class_linker_->FindSystemClass(soa.Self(), "Ljava/io/InputStream;");
EXPECT_FALSE(c->IsFinalizable());
- c = class_linker_->FindSystemClass("Ljava/io/FileInputStream;");
+ c = class_linker_->FindSystemClass(soa.Self(), "Ljava/io/FileInputStream;");
EXPECT_TRUE(c->IsFinalizable());
// ScheduledThreadPoolExecutor doesn't have a finalize method but
// extends ThreadPoolExecutor which does.
- c = class_linker_->FindSystemClass("Ljava/util/concurrent/ThreadPoolExecutor;");
+ c = class_linker_->FindSystemClass(soa.Self(), "Ljava/util/concurrent/ThreadPoolExecutor;");
EXPECT_TRUE(c->IsFinalizable());
- c = class_linker_->FindSystemClass("Ljava/util/concurrent/ScheduledThreadPoolExecutor;");
+ c = class_linker_->FindSystemClass(soa.Self(), "Ljava/util/concurrent/ScheduledThreadPoolExecutor;");
EXPECT_TRUE(c->IsFinalizable());
}
diff --git a/runtime/common_test.h b/runtime/common_test.h
index 7f9b6b1..9eaec46 100644
--- a/runtime/common_test.h
+++ b/runtime/common_test.h
@@ -28,7 +28,9 @@
#include "../compiler/compiler_backend.h"
#include "../compiler/dex/quick/dex_file_to_method_inliner_map.h"
#include "../compiler/dex/verification_results.h"
+#include "../compiler/driver/compiler_callbacks_impl.h"
#include "../compiler/driver/compiler_driver.h"
+#include "../compiler/driver/compiler_options.h"
#include "base/macros.h"
#include "base/stl_util.h"
#include "base/stringprintf.h"
@@ -418,8 +420,9 @@
void MakeExecutable(mirror::ClassLoader* class_loader, const char* class_name)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
std::string class_descriptor(DotToDescriptor(class_name));
- SirtRef<mirror::ClassLoader> loader(Thread::Current(), class_loader);
- mirror::Class* klass = class_linker_->FindClass(class_descriptor.c_str(), loader);
+ Thread* self = Thread::Current();
+ SirtRef<mirror::ClassLoader> loader(self, class_loader);
+ mirror::Class* klass = class_linker_->FindClass(self, class_descriptor.c_str(), loader);
CHECK(klass != NULL) << "Class not found " << class_name;
for (size_t i = 0; i < klass->NumDirectMethods(); i++) {
MakeExecutable(klass->GetDirectMethod(i));
@@ -458,11 +461,13 @@
? CompilerBackend::kPortable
: CompilerBackend::kQuick;
- verification_results_.reset(new VerificationResults);
+ compiler_options_.reset(new CompilerOptions);
+ verification_results_.reset(new VerificationResults(compiler_options_.get()));
method_inliner_map_.reset(new DexFileToMethodInlinerMap);
- callbacks_.Reset(verification_results_.get(), method_inliner_map_.get());
+ callbacks_.reset(new CompilerCallbacksImpl(verification_results_.get(),
+ method_inliner_map_.get()));
Runtime::Options options;
- options.push_back(std::make_pair("compilercallbacks", static_cast<CompilerCallbacks*>(&callbacks_)));
+ options.push_back(std::make_pair("compilercallbacks", callbacks_.get()));
options.push_back(std::make_pair("bootclasspath", &boot_class_path_));
options.push_back(std::make_pair("-Xcheck:jni", reinterpret_cast<void*>(NULL)));
options.push_back(std::make_pair(min_heap_string.c_str(), reinterpret_cast<void*>(NULL)));
@@ -472,8 +477,8 @@
return;
}
runtime_.reset(Runtime::Current());
- // Runtime::Create acquired the mutator_lock_ that is normally given away when we Runtime::Start,
- // give it away now and then switch to a more managable ScopedObjectAccess.
+ // Runtime::Create acquired the mutator_lock_ that is normally given away when we
+ // Runtime::Start, give it away now and then switch to a more managable ScopedObjectAccess.
Thread::Current()->TransitionFromRunnableToSuspended(kNative);
{
ScopedObjectAccess soa(Thread::Current());
@@ -512,7 +517,8 @@
}
class_linker_->FixupDexCaches(runtime_->GetResolutionMethod());
timer_.reset(new CumulativeLogger("Compilation times"));
- compiler_driver_.reset(new CompilerDriver(verification_results_.get(),
+ compiler_driver_.reset(new CompilerDriver(compiler_options_.get(),
+ verification_results_.get(),
method_inliner_map_.get(),
compiler_backend, instruction_set,
instruction_set_features,
@@ -563,9 +569,10 @@
compiler_driver_.reset();
timer_.reset();
- callbacks_.Reset(nullptr, nullptr);
+ callbacks_.reset();
method_inliner_map_.reset();
verification_results_.reset();
+ compiler_options_.reset();
STLDeleteElements(&opened_dex_files_);
Runtime::Current()->GetHeap()->VerifyHeap(); // Check for heap corruption after the test
@@ -632,8 +639,9 @@
void CompileClass(mirror::ClassLoader* class_loader, const char* class_name)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
std::string class_descriptor(DotToDescriptor(class_name));
- SirtRef<mirror::ClassLoader> loader(Thread::Current(), class_loader);
- mirror::Class* klass = class_linker_->FindClass(class_descriptor.c_str(), loader);
+ Thread* self = Thread::Current();
+ SirtRef<mirror::ClassLoader> loader(self, class_loader);
+ mirror::Class* klass = class_linker_->FindClass(self, class_descriptor.c_str(), loader);
CHECK(klass != NULL) << "Class not found " << class_name;
for (size_t i = 0; i < klass->NumDirectMethods(); i++) {
CompileMethod(klass->GetDirectMethod(i));
@@ -656,7 +664,8 @@
const char* method_name, const char* signature)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
std::string class_descriptor(DotToDescriptor(class_name));
- mirror::Class* klass = class_linker_->FindClass(class_descriptor.c_str(), class_loader);
+ Thread* self = Thread::Current();
+ mirror::Class* klass = class_linker_->FindClass(self, class_descriptor.c_str(), class_loader);
CHECK(klass != NULL) << "Class not found " << class_name;
mirror::ArtMethod* method = klass->FindDirectMethod(method_name, signature);
CHECK(method != NULL) << "Direct method not found: "
@@ -668,7 +677,8 @@
const char* method_name, const char* signature)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
std::string class_descriptor(DotToDescriptor(class_name));
- mirror::Class* klass = class_linker_->FindClass(class_descriptor.c_str(), class_loader);
+ Thread* self = Thread::Current();
+ mirror::Class* klass = class_linker_->FindClass(self, class_descriptor.c_str(), class_loader);
CHECK(klass != NULL) << "Class not found " << class_name;
mirror::ArtMethod* method = klass->FindVirtualMethod(method_name, signature);
CHECK(method != NULL) << "Virtual method not found: "
@@ -693,36 +703,6 @@
image_reservation_.reset();
}
- class TestCompilerCallbacks : public CompilerCallbacks {
- public:
- TestCompilerCallbacks() : verification_results_(nullptr), method_inliner_map_(nullptr) {}
-
- void Reset(VerificationResults* verification_results,
- DexFileToMethodInlinerMap* method_inliner_map) {
- verification_results_ = verification_results;
- method_inliner_map_ = method_inliner_map;
- }
-
- virtual bool MethodVerified(verifier::MethodVerifier* verifier)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- CHECK(verification_results_);
- bool result = verification_results_->ProcessVerifiedMethod(verifier);
- if (result && method_inliner_map_ != nullptr) {
- MethodReference ref = verifier->GetMethodReference();
- method_inliner_map_->GetMethodInliner(ref.dex_file)
- ->AnalyseMethodCode(verifier);
- }
- return result;
- }
- virtual void ClassRejected(ClassReference ref) {
- verification_results_->AddRejectedClass(ref);
- }
-
- private:
- VerificationResults* verification_results_;
- DexFileToMethodInlinerMap* method_inliner_map_;
- };
-
std::string android_data_;
std::string dalvik_cache_;
const DexFile* java_lang_dex_file_; // owned by runtime_
@@ -730,9 +710,10 @@
UniquePtr<Runtime> runtime_;
// Owned by the runtime
ClassLinker* class_linker_;
+ UniquePtr<CompilerOptions> compiler_options_;
UniquePtr<VerificationResults> verification_results_;
UniquePtr<DexFileToMethodInlinerMap> method_inliner_map_;
- TestCompilerCallbacks callbacks_;
+ UniquePtr<CompilerCallbacksImpl> callbacks_;
UniquePtr<CompilerDriver> compiler_driver_;
UniquePtr<CumulativeLogger> timer_;
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index 89f841e..9f09709 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -289,27 +289,39 @@
return static_cast<JDWP::JdwpTag>(descriptor[0]);
}
-static JDWP::JdwpTag TagFromClass(mirror::Class* c)
+static JDWP::JdwpTag TagFromClass(const ScopedObjectAccessUnchecked& soa, mirror::Class* c)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
CHECK(c != NULL);
if (c->IsArrayClass()) {
return JDWP::JT_ARRAY;
}
-
- ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
if (c->IsStringClass()) {
return JDWP::JT_STRING;
- } else if (c->IsClassClass()) {
- return JDWP::JT_CLASS_OBJECT;
- } else if (class_linker->FindSystemClass("Ljava/lang/Thread;")->IsAssignableFrom(c)) {
- return JDWP::JT_THREAD;
- } else if (class_linker->FindSystemClass("Ljava/lang/ThreadGroup;")->IsAssignableFrom(c)) {
- return JDWP::JT_THREAD_GROUP;
- } else if (class_linker->FindSystemClass("Ljava/lang/ClassLoader;")->IsAssignableFrom(c)) {
- return JDWP::JT_CLASS_LOADER;
- } else {
- return JDWP::JT_OBJECT;
}
+ if (c->IsClassClass()) {
+ return JDWP::JT_CLASS_OBJECT;
+ }
+ {
+ mirror::Class* thread_class = soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_Thread);
+ if (thread_class->IsAssignableFrom(c)) {
+ return JDWP::JT_THREAD;
+ }
+ }
+ {
+ mirror::Class* thread_group_class =
+ soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_ThreadGroup);
+ if (thread_group_class->IsAssignableFrom(c)) {
+ return JDWP::JT_THREAD_GROUP;
+ }
+ }
+ {
+ mirror::Class* class_loader_class =
+ soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_ClassLoader);
+ if (class_loader_class->IsAssignableFrom(c)) {
+ return JDWP::JT_CLASS_LOADER;
+ }
+ }
+ return JDWP::JT_OBJECT;
}
/*
@@ -320,9 +332,9 @@
*
* Null objects are tagged JT_OBJECT.
*/
-static JDWP::JdwpTag TagFromObject(mirror::Object* o)
+static JDWP::JdwpTag TagFromObject(const ScopedObjectAccessUnchecked& soa, mirror::Object* o)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return (o == NULL) ? JDWP::JT_OBJECT : TagFromClass(o->GetClass());
+ return (o == NULL) ? JDWP::JT_OBJECT : TagFromClass(soa, o->GetClass());
}
static bool IsPrimitiveTag(JDWP::JdwpTag tag) {
@@ -587,20 +599,24 @@
runtime->GetThreadList()->SuspendAll();
Thread* self = Thread::Current();
ThreadState old_state = self->SetStateUnsafe(kRunnable);
- {
- // Since we're going to disable deoptimization, we clear the deoptimization requests queue.
- // This prevent us from having any pending deoptimization request when the debugger attaches to
- // us again while no event has been requested yet.
- MutexLock mu(Thread::Current(), *Locks::deoptimization_lock_);
- gDeoptimizationRequests.clear();
+
+ // Debugger may not be active at this point.
+ if (gDebuggerActive) {
+ {
+ // Since we're going to disable deoptimization, we clear the deoptimization requests queue.
+ // This prevents us from having any pending deoptimization request when the debugger attaches
+ // to us again while no event has been requested yet.
+ MutexLock mu(Thread::Current(), *Locks::deoptimization_lock_);
+ gDeoptimizationRequests.clear();
+ }
+ runtime->GetInstrumentation()->RemoveListener(&gDebugInstrumentationListener,
+ instrumentation::Instrumentation::kMethodEntered |
+ instrumentation::Instrumentation::kMethodExited |
+ instrumentation::Instrumentation::kDexPcMoved |
+ instrumentation::Instrumentation::kExceptionCaught);
+ runtime->GetInstrumentation()->DisableDeoptimization();
+ gDebuggerActive = false;
}
- runtime->GetInstrumentation()->RemoveListener(&gDebugInstrumentationListener,
- instrumentation::Instrumentation::kMethodEntered |
- instrumentation::Instrumentation::kMethodExited |
- instrumentation::Instrumentation::kDexPcMoved |
- instrumentation::Instrumentation::kExceptionCaught);
- runtime->GetInstrumentation()->DisableDeoptimization();
- gDebuggerActive = false;
gRegistry->Clear();
gDebuggerConnected = false;
CHECK_EQ(self->SetStateUnsafe(old_state), kRunnable);
@@ -1011,11 +1027,12 @@
}
JDWP::JdwpError Dbg::GetObjectTag(JDWP::ObjectId object_id, uint8_t& tag) {
+ ScopedObjectAccessUnchecked soa(Thread::Current());
mirror::Object* o = gRegistry->Get<mirror::Object*>(object_id);
if (o == ObjectRegistry::kInvalidObject) {
return JDWP::ERR_INVALID_OBJECT;
}
- tag = TagFromObject(o);
+ tag = TagFromObject(soa, o);
return JDWP::ERR_NONE;
}
@@ -1062,7 +1079,7 @@
JDWP::JdwpError Dbg::OutputArray(JDWP::ObjectId array_id, int offset, int count, JDWP::ExpandBuf* pReply) {
JDWP::JdwpError status;
mirror::Array* a = DecodeArray(array_id, status);
- if (a == NULL) {
+ if (a == nullptr) {
return status;
}
@@ -1093,10 +1110,12 @@
memcpy(dst, &src[offset * width], count * width);
}
} else {
+ ScopedObjectAccessUnchecked soa(Thread::Current());
mirror::ObjectArray<mirror::Object>* oa = a->AsObjectArray<mirror::Object>();
for (int i = 0; i < count; ++i) {
mirror::Object* element = oa->Get(offset + i);
- JDWP::JdwpTag specific_tag = (element != NULL) ? TagFromObject(element) : tag;
+ JDWP::JdwpTag specific_tag = (element != nullptr) ? TagFromObject(soa, element)
+ : tag;
expandBufAdd1(pReply, specific_tag);
expandBufAddObjectId(pReply, gRegistry->Add(element));
}
@@ -1639,8 +1658,9 @@
CHECK_EQ(tag, JDWP::JT_VOID);
}
} else {
+ ScopedObjectAccessUnchecked soa(Thread::Current());
mirror::Object* value = return_value->GetL();
- expandBufAdd1(pReply, TagFromObject(value));
+ expandBufAdd1(pReply, TagFromObject(soa, value));
expandBufAddObjectId(pReply, gRegistry->Add(value));
}
}
@@ -1672,7 +1692,7 @@
if (thread_object == ObjectRegistry::kInvalidObject) {
return JDWP::ERR_INVALID_OBJECT;
}
-
+ const char* old_cause = soa.Self()->StartAssertNoThreadSuspension("Debugger: GetThreadGroup");
// Okay, so it's an object, but is it actually a thread?
MutexLock mu(soa.Self(), *Locks::thread_list_lock_);
Thread* thread;
@@ -1685,14 +1705,14 @@
if (error != JDWP::ERR_NONE) {
return error;
}
-
- mirror::Class* c = Runtime::Current()->GetClassLinker()->FindSystemClass("Ljava/lang/Thread;");
- CHECK(c != NULL);
+ mirror::Class* c = soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_Thread);
+ CHECK(c != nullptr);
mirror::ArtField* f = c->FindInstanceField("group", "Ljava/lang/ThreadGroup;");
CHECK(f != NULL);
mirror::Object* group = f->GetObject(thread_object);
CHECK(group != NULL);
JDWP::ObjectId thread_group_id = gRegistry->Add(group);
+ soa.Self()->EndAssertNoThreadSuspension(old_cause);
expandBufAddObjectId(pReply, thread_group_id);
return JDWP::ERR_NONE;
@@ -1701,25 +1721,28 @@
std::string Dbg::GetThreadGroupName(JDWP::ObjectId thread_group_id) {
ScopedObjectAccess soa(Thread::Current());
mirror::Object* thread_group = gRegistry->Get<mirror::Object*>(thread_group_id);
- CHECK(thread_group != NULL);
-
- mirror::Class* c = Runtime::Current()->GetClassLinker()->FindSystemClass("Ljava/lang/ThreadGroup;");
- CHECK(c != NULL);
+ CHECK(thread_group != nullptr);
+ const char* old_cause = soa.Self()->StartAssertNoThreadSuspension("Debugger: GetThreadGroupName");
+ mirror::Class* c = soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_ThreadGroup);
+ CHECK(c != nullptr);
mirror::ArtField* f = c->FindInstanceField("name", "Ljava/lang/String;");
CHECK(f != NULL);
mirror::String* s = reinterpret_cast<mirror::String*>(f->GetObject(thread_group));
+ soa.Self()->EndAssertNoThreadSuspension(old_cause);
return s->ToModifiedUtf8();
}
JDWP::ObjectId Dbg::GetThreadGroupParent(JDWP::ObjectId thread_group_id) {
+ ScopedObjectAccessUnchecked soa(Thread::Current());
mirror::Object* thread_group = gRegistry->Get<mirror::Object*>(thread_group_id);
- CHECK(thread_group != NULL);
-
- mirror::Class* c = Runtime::Current()->GetClassLinker()->FindSystemClass("Ljava/lang/ThreadGroup;");
- CHECK(c != NULL);
+ CHECK(thread_group != nullptr);
+ const char* old_cause = soa.Self()->StartAssertNoThreadSuspension("Debugger: GetThreadGroupParent");
+ mirror::Class* c = soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_ThreadGroup);
+ CHECK(c != nullptr);
mirror::ArtField* f = c->FindInstanceField("parent", "Ljava/lang/ThreadGroup;");
CHECK(f != NULL);
mirror::Object* parent = f->GetObject(thread_group);
+ soa.Self()->EndAssertNoThreadSuspension(old_cause);
return gRegistry->Add(parent);
}
@@ -2090,13 +2113,13 @@
return JDWP::ERR_NONE;
}
-void Dbg::GetLocalValue(JDWP::ObjectId thread_id, JDWP::FrameId frame_id, int slot, JDWP::JdwpTag tag,
- uint8_t* buf, size_t width) {
+void Dbg::GetLocalValue(JDWP::ObjectId thread_id, JDWP::FrameId frame_id, int slot,
+ JDWP::JdwpTag tag, uint8_t* buf, size_t width) {
struct GetLocalVisitor : public StackVisitor {
- GetLocalVisitor(Thread* thread, Context* context, JDWP::FrameId frame_id, int slot,
- JDWP::JdwpTag tag, uint8_t* buf, size_t width)
+ GetLocalVisitor(const ScopedObjectAccessUnchecked& soa, Thread* thread, Context* context,
+ JDWP::FrameId frame_id, int slot, JDWP::JdwpTag tag, uint8_t* buf, size_t width)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
- : StackVisitor(thread, context), frame_id_(frame_id), slot_(slot), tag_(tag),
+ : StackVisitor(thread, context), soa_(soa), frame_id_(frame_id), slot_(slot), tag_(tag),
buf_(buf), width_(width) {}
// TODO: Enable annotalysis. We know lock is held in constructor, but abstraction confuses
@@ -2175,7 +2198,7 @@
if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(o)) {
LOG(FATAL) << "Register " << reg << " expected to hold object: " << o;
}
- tag_ = TagFromObject(o);
+ tag_ = TagFromObject(soa_, o);
JDWP::SetObjectId(buf_+1, gRegistry->Add(o));
}
break;
@@ -2208,7 +2231,7 @@
JDWP::Set1(buf_, tag_);
return false;
}
-
+ const ScopedObjectAccessUnchecked& soa_;
const JDWP::FrameId frame_id_;
const int slot_;
JDWP::JdwpTag tag_;
@@ -2224,7 +2247,7 @@
return;
}
UniquePtr<Context> context(Context::Create());
- GetLocalVisitor visitor(thread, context.get(), frame_id, slot, tag, buf, width);
+ GetLocalVisitor visitor(soa, thread, context.get(), frame_id, slot, tag, buf, width);
visitor.WalkStack();
}
@@ -3037,7 +3060,7 @@
pReq->result_value.SetJ(0);
} else if (pReq->result_tag == JDWP::JT_OBJECT) {
/* if no exception thrown, examine object result more closely */
- JDWP::JdwpTag new_tag = TagFromObject(pReq->result_value.GetL());
+ JDWP::JdwpTag new_tag = TagFromObject(soa, pReq->result_value.GetL());
if (new_tag != pReq->result_tag) {
VLOG(jdwp) << " JDWP promoted result from " << pReq->result_tag << " to " << new_tag;
pReq->result_tag = new_tag;
diff --git a/runtime/entrypoints/entrypoint_utils.h b/runtime/entrypoints/entrypoint_utils.h
index 8b94b5a..2c08351 100644
--- a/runtime/entrypoints/entrypoint_utils.h
+++ b/runtime/entrypoints/entrypoint_utils.h
@@ -18,7 +18,7 @@
#define ART_RUNTIME_ENTRYPOINTS_ENTRYPOINT_UTILS_H_
#include "base/macros.h"
-#include "class_linker.h"
+#include "class_linker-inl.h"
#include "common_throws.h"
#include "dex_file.h"
#include "indirect_reference_table.h"
diff --git a/runtime/exception_test.cc b/runtime/exception_test.cc
index f7b621f..910a817 100644
--- a/runtime/exception_test.cc
+++ b/runtime/exception_test.cc
@@ -28,6 +28,7 @@
#include "sirt_ref.h"
#include "thread.h"
#include "UniquePtr.h"
+#include "vmap_table.h"
namespace art {
@@ -39,7 +40,7 @@
ScopedObjectAccess soa(Thread::Current());
SirtRef<mirror::ClassLoader> class_loader(
soa.Self(), soa.Decode<mirror::ClassLoader*>(LoadDex("ExceptionHandle")));
- my_klass_ = class_linker_->FindClass("LExceptionHandle;", class_loader);
+ my_klass_ = class_linker_->FindClass(soa.Self(), "LExceptionHandle;", class_loader);
ASSERT_TRUE(my_klass_ != NULL);
SirtRef<mirror::Class> sirt_klass(soa.Self(), my_klass_);
class_linker_->EnsureInitialized(sirt_klass, true, true);
@@ -66,7 +67,7 @@
fake_mapping_data_.PushBackUnsigned(3 - 0); // offset 3
fake_mapping_data_.PushBackSigned(3 - 0); // maps to dex offset 3
- fake_vmap_table_data_.PushBackUnsigned(0);
+ fake_vmap_table_data_.PushBackUnsigned(0 + VmapTable::kEntryAdjustment);
fake_gc_map_.push_back(0); // 0 bytes to encode references and native pc offsets.
fake_gc_map_.push_back(0);
diff --git a/runtime/gc/collector/mark_sweep.cc b/runtime/gc/collector/mark_sweep.cc
index fb797e0..cc34689 100644
--- a/runtime/gc/collector/mark_sweep.cc
+++ b/runtime/gc/collector/mark_sweep.cc
@@ -65,6 +65,7 @@
constexpr bool kUseRecursiveMark = false;
constexpr bool kUseMarkStackPrefetch = true;
constexpr size_t kSweepArrayChunkFreeSize = 1024;
+constexpr bool kPreCleanCards = true;
// Parallelism options.
constexpr bool kParallelCardScan = true;
@@ -209,7 +210,7 @@
// Since SweepArray() above resets the (active) allocation
// stack. Need to revoke the thread-local allocation stacks that
// point into it.
- GetHeap()->RevokeAllThreadLocalAllocationStacks(self);
+ RevokeAllThreadLocalAllocationStacks(self);
}
timings_.StartSplit("PreSweepingGcVerification");
@@ -232,6 +233,32 @@
return is_concurrent_;
}
+void MarkSweep::PreCleanCards() {
+ // Don't do this for non concurrent GCs since they don't have any dirty cards.
+ if (kPreCleanCards && IsConcurrent()) {
+ Thread* self = Thread::Current();
+ CHECK(!Locks::mutator_lock_->IsExclusiveHeld(self));
+ // Process dirty cards and add dirty cards to mod union tables, also ages cards.
+ heap_->ProcessCards(timings_);
+ // Required so that we see aged cards before we start scanning the cards.
+ MarkThreadRoots(self);
+ // TODO: Only mark the dirty roots.
+ MarkNonThreadRoots();
+ MarkConcurrentRoots();
+ // Process the newly aged cards.
+ RecursiveMarkDirtyObjects(false, accounting::CardTable::kCardDirty - 1);
+ // TODO: Empty allocation stack to reduce the number of objects we need to test / mark as live
+ // in the next GC.
+ }
+}
+
+void MarkSweep::RevokeAllThreadLocalAllocationStacks(Thread* self) {
+ if (kUseThreadLocalAllocationStack) {
+ Locks::mutator_lock_->AssertExclusiveHeld(self);
+ heap_->RevokeAllThreadLocalAllocationStacks(self);
+ }
+}
+
void MarkSweep::MarkingPhase() {
TimingLogger::ScopedSplit split("MarkingPhase", &timings_);
Thread* self = Thread::Current();
@@ -251,9 +278,7 @@
if (Locks::mutator_lock_->IsExclusiveHeld(self)) {
// If we exclusively hold the mutator lock, all threads must be suspended.
MarkRoots();
- if (kUseThreadLocalAllocationStack) {
- heap_->RevokeAllThreadLocalAllocationStacks(self);
- }
+ RevokeAllThreadLocalAllocationStacks(self);
} else {
MarkThreadRoots(self);
// At this point the live stack should no longer have any mutators which push into it.
@@ -263,6 +288,8 @@
MarkConcurrentRoots();
UpdateAndMarkModUnion();
MarkReachableObjects();
+ // Pre-clean dirtied cards to reduce pauses.
+ PreCleanCards();
}
void MarkSweep::UpdateAndMarkModUnion() {
@@ -313,20 +340,24 @@
TimingLogger::ScopedSplit split("UnMarkAllocStack", &timings_);
WriterMutexLock mu(self, *Locks::heap_bitmap_lock_);
accounting::ObjectStack* allocation_stack = GetHeap()->allocation_stack_.get();
- // The allocation stack contains things allocated since the start of the GC. These may have been
- // marked during this GC meaning they won't be eligible for reclaiming in the next sticky GC.
- // Remove these objects from the mark bitmaps so that they will be eligible for sticky
- // collection.
- // There is a race here which is safely handled. Another thread such as the hprof could
- // have flushed the alloc stack after we resumed the threads. This is safe however, since
- // reseting the allocation stack zeros it out with madvise. This means that we will either
- // read NULLs or attempt to unmark a newly allocated object which will not be marked in the
- // first place.
- mirror::Object** end = allocation_stack->End();
- for (mirror::Object** it = allocation_stack->Begin(); it != end; ++it) {
- const Object* obj = *it;
- if (obj != NULL) {
- UnMarkObjectNonNull(obj);
+ if (!kPreCleanCards) {
+ // The allocation stack contains things allocated since the start of the GC. These may have
+ // been marked during this GC meaning they won't be eligible for reclaiming in the next
+ // sticky GC. Unmark these objects so that they are eligible for reclaiming in the next
+ // sticky GC.
+ // There is a race here which is safely handled. Another thread such as the hprof could
+ // have flushed the alloc stack after we resumed the threads. This is safe however, since
+ // reseting the allocation stack zeros it out with madvise. This means that we will either
+ // read NULLs or attempt to unmark a newly allocated object which will not be marked in the
+ // first place.
+ // We can't do this if we pre-clean cards since we will unmark objects which are no longer on
+ // a dirty card since we aged cards during the pre-cleaning process.
+ mirror::Object** end = allocation_stack->End();
+ for (mirror::Object** it = allocation_stack->Begin(); it != end; ++it) {
+ const Object* obj = *it;
+ if (obj != nullptr) {
+ UnMarkObjectNonNull(obj);
+ }
}
}
}
diff --git a/runtime/gc/collector/mark_sweep.h b/runtime/gc/collector/mark_sweep.h
index 963b9ea..29fafd6 100644
--- a/runtime/gc/collector/mark_sweep.h
+++ b/runtime/gc/collector/mark_sweep.h
@@ -135,6 +135,11 @@
virtual void UpdateAndMarkModUnion()
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ // Pre clean cards to reduce how much work is needed in the pause.
+ void PreCleanCards()
+ EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
// Sweeps unmarked objects to complete the garbage collection.
virtual void Sweep(bool swap_bitmaps) EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_);
@@ -329,6 +334,10 @@
void ClearWhiteReferences(mirror::Object** list)
SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_);
+ // Used to get around thread safety annotations. The call is from MarkingPhase and is guarded by
+ // IsExclusiveHeld.
+ void RevokeAllThreadLocalAllocationStacks(Thread* self) NO_THREAD_SAFETY_ANALYSIS;
+
// Whether or not we count how many of each type of object were scanned.
static const bool kCountScannedTypes = false;
diff --git a/runtime/gc/collector/sticky_mark_sweep.cc b/runtime/gc/collector/sticky_mark_sweep.cc
index 9e3adb4..450445e 100644
--- a/runtime/gc/collector/sticky_mark_sweep.cc
+++ b/runtime/gc/collector/sticky_mark_sweep.cc
@@ -53,6 +53,8 @@
// TODO: Not put these objects in the mark stack in the first place.
mark_stack_->Reset();
RecursiveMarkDirtyObjects(false, accounting::CardTable::kCardDirty - 1);
+ // Pre clean dirtied cards to reduce pauses.
+ PreCleanCards();
}
void StickyMarkSweep::Sweep(bool swap_bitmaps) {
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index b970df3..58db7a8 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -2010,12 +2010,6 @@
}
void Heap::RevokeAllThreadLocalAllocationStacks(Thread* self) {
- if (!Runtime::Current()->IsStarted()) {
- // There's no thread list if the runtime hasn't started (eg
- // dex2oat or a test). Just revoke for self.
- self->RevokeThreadLocalAllocationStack();
- return;
- }
// This must be called only during the pause.
CHECK(Locks::mutator_lock_->IsExclusiveHeld(self));
MutexLock mu(self, *Locks::runtime_shutdown_lock_);
diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h
index 83202a5..5d44ee1 100644
--- a/runtime/gc/heap.h
+++ b/runtime/gc/heap.h
@@ -207,11 +207,9 @@
// Check sanity of all live references.
void VerifyHeap() LOCKS_EXCLUDED(Locks::heap_bitmap_lock_);
bool VerifyHeapReferences()
- EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_);
bool VerifyMissingCardMarks()
- EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_);
// A weaker test than IsLiveObject or VerifyObject that doesn't require the heap lock,
// and doesn't abort on error, allowing the caller to report more
@@ -463,7 +461,8 @@
EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_);
// Revoke all the thread-local allocation stacks.
- void RevokeAllThreadLocalAllocationStacks(Thread* self);
+ void RevokeAllThreadLocalAllocationStacks(Thread* self)
+ EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_);
// Mark all the objects in the allocation stack in the specified bitmap.
void MarkAllocStack(accounting::SpaceBitmap* bitmap1, accounting::SpaceBitmap* bitmap2,
diff --git a/runtime/gc/heap_test.cc b/runtime/gc/heap_test.cc
index b02b8bb..4b86339 100644
--- a/runtime/gc/heap_test.cc
+++ b/runtime/gc/heap_test.cc
@@ -43,7 +43,8 @@
ScopedObjectAccess soa(Thread::Current());
// garbage is created during ClassLinker::Init
- SirtRef<mirror::Class> c(soa.Self(), class_linker_->FindSystemClass("[Ljava/lang/Object;"));
+ SirtRef<mirror::Class> c(soa.Self(), class_linker_->FindSystemClass(soa.Self(),
+ "[Ljava/lang/Object;"));
for (size_t i = 0; i < 1024; ++i) {
SirtRef<mirror::ObjectArray<mirror::Object> > array(soa.Self(),
mirror::ObjectArray<mirror::Object>::Alloc(soa.Self(), c.get(), 2048));
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index ebad8dd..12c5451 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -16,9 +16,6 @@
#include "image_space.h"
-#include <sys/types.h>
-#include <sys/wait.h>
-
#include "base/stl_util.h"
#include "base/unix_file/fd_file.h"
#include "gc/accounting/space_bitmap-inl.h"
@@ -89,52 +86,14 @@
arg_vector.push_back("--host");
}
+ const std::vector<std::string>& compiler_options = Runtime::Current()->GetImageCompilerOptions();
+ for (size_t i = 0; compiler_options.size(); ++i) {
+ arg_vector.push_back(compiler_options[i].c_str());
+ }
+
std::string command_line(Join(arg_vector, ' '));
LOG(INFO) << "GenerateImage: " << command_line;
-
- // Convert the args to char pointers.
- std::vector<char*> char_args;
- for (std::vector<std::string>::iterator it = arg_vector.begin(); it != arg_vector.end();
- ++it) {
- char_args.push_back(const_cast<char*>(it->c_str()));
- }
- char_args.push_back(NULL);
-
- // fork and exec dex2oat
- pid_t pid = fork();
- if (pid == 0) {
- // no allocation allowed between fork and exec
-
- // change process groups, so we don't get reaped by ProcessManager
- setpgid(0, 0);
-
- execv(dex2oat.c_str(), &char_args[0]);
-
- PLOG(FATAL) << "execv(" << dex2oat << ") failed";
- return false;
- } else {
- if (pid == -1) {
- *error_msg = StringPrintf("Failed to generate image '%s' because fork failed: %s",
- image_file_name.c_str(), strerror(errno));
- return false;
- }
-
- // wait for dex2oat to finish
- int status;
- pid_t got_pid = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0));
- if (got_pid != pid) {
- *error_msg = StringPrintf("Failed to generate image '%s' because waitpid failed: "
- "wanted %d, got %d: %s",
- image_file_name.c_str(), pid, got_pid, strerror(errno));
- return false;
- }
- if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
- *error_msg = StringPrintf("Failed to generate image '%s' because dex2oat failed: %s",
- image_file_name.c_str(), command_line.c_str());
- return false;
- }
- }
- return true;
+ return Exec(arg_vector, error_msg);
}
ImageSpace* ImageSpace::Create(const char* original_image_file_name) {
diff --git a/runtime/gc/space/space_test.h b/runtime/gc/space/space_test.h
index d01bf2c..093967e 100644
--- a/runtime/gc/space/space_test.h
+++ b/runtime/gc/space/space_test.h
@@ -43,8 +43,9 @@
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
// Note the minimum size, which is the size of a zero-length byte array.
EXPECT_GE(size, SizeOfZeroLengthByteArray());
- SirtRef<mirror::ClassLoader> null_loader(Thread::Current(), nullptr);
- mirror::Class* byte_array_class = Runtime::Current()->GetClassLinker()->FindClass("[B",
+ Thread* self = Thread::Current();
+ SirtRef<mirror::ClassLoader> null_loader(self, nullptr);
+ mirror::Class* byte_array_class = Runtime::Current()->GetClassLinker()->FindClass(self, "[B",
null_loader);
EXPECT_TRUE(byte_array_class != nullptr);
o->SetClass(byte_array_class);
diff --git a/runtime/indirect_reference_table_test.cc b/runtime/indirect_reference_table_test.cc
index b6c6cb4..78e1992 100644
--- a/runtime/indirect_reference_table_test.cc
+++ b/runtime/indirect_reference_table_test.cc
@@ -48,7 +48,7 @@
static const size_t kTableMax = 20;
IndirectReferenceTable irt(kTableInitial, kTableMax, kGlobal);
- mirror::Class* c = class_linker_->FindSystemClass("Ljava/lang/Object;");
+ mirror::Class* c = class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Object;");
ASSERT_TRUE(c != NULL);
mirror::Object* obj0 = c->AllocObject(soa.Self());
ASSERT_TRUE(obj0 != NULL);
diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc
index 9e1d915..83a1fbc 100644
--- a/runtime/interpreter/interpreter_common.cc
+++ b/runtime/interpreter/interpreter_common.cc
@@ -280,7 +280,7 @@
std::string descriptor(DotToDescriptor(shadow_frame->GetVRegReference(arg_offset)->AsString()->ToModifiedUtf8().c_str()));
SirtRef<ClassLoader> class_loader(self, nullptr); // shadow_frame.GetMethod()->GetDeclaringClass()->GetClassLoader();
- Class* found = Runtime::Current()->GetClassLinker()->FindClass(descriptor.c_str(),
+ Class* found = Runtime::Current()->GetClassLinker()->FindClass(self, descriptor.c_str(),
class_loader);
CHECK(found != NULL) << "Class.forName failed in un-started runtime for class: "
<< PrettyDescriptor(descriptor);
@@ -289,7 +289,7 @@
SirtRef<ClassLoader> class_loader(self, down_cast<mirror::ClassLoader*>(shadow_frame->GetVRegReference(arg_offset)));
std::string descriptor(DotToDescriptor(shadow_frame->GetVRegReference(arg_offset + 1)->AsString()->ToModifiedUtf8().c_str()));
- Class* found = Runtime::Current()->GetClassLinker()->FindClass(descriptor.c_str(),
+ Class* found = Runtime::Current()->GetClassLinker()->FindClass(self, descriptor.c_str(),
class_loader);
result->SetL(found);
} else if (name == "java.lang.Object java.lang.Class.newInstance()") {
diff --git a/runtime/jdwp/jdwp.h b/runtime/jdwp/jdwp.h
index e45cb6e..1ec795f 100644
--- a/runtime/jdwp/jdwp.h
+++ b/runtime/jdwp/jdwp.h
@@ -154,8 +154,9 @@
* release it in the "clear" call.
*/
// ObjectId GetWaitForEventThread();
- void SetWaitForEventThread(ObjectId threadId);
- void ClearWaitForEventThread();
+ void SetWaitForEventThread(ObjectId threadId)
+ LOCKS_EXCLUDED(event_thread_lock_, process_request_lock_);
+ void ClearWaitForEventThread() LOCKS_EXCLUDED(event_thread_lock);
/*
* These notify the debug code that something interesting has happened. This
@@ -346,7 +347,7 @@
// Used to synchronize request processing and event sending (to avoid sending an event before
// sending the reply of a command being processed).
- Mutex process_request_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
+ Mutex process_request_lock_ ACQUIRED_AFTER(event_thread_lock_);
ConditionVariable process_request_cond_ GUARDED_BY(process_request_lock_);
bool processing_request_ GUARDED_BY(process_request_lock_);
diff --git a/runtime/jdwp/jdwp_handler.cc b/runtime/jdwp/jdwp_handler.cc
index 0ff78d0..4b170ba 100644
--- a/runtime/jdwp/jdwp_handler.cc
+++ b/runtime/jdwp/jdwp_handler.cc
@@ -1685,6 +1685,12 @@
SetWaitForEventThread(0);
/*
+ * We do not want events to be sent while we process a request. Indicate the JDWP thread starts
+ * to process a request so other threads wait for it to finish before sending an event.
+ */
+ StartProcessingRequest();
+
+ /*
* Tell the VM that we're running and shouldn't be interrupted by GC.
* Do this after anything that can stall indefinitely.
*/
@@ -1779,9 +1785,15 @@
Thread* self = Thread::Current();
CHECK_NE(self, GetDebugThread()) << "Events should not be posted by debug thread";
MutexLock mu(self, process_request_lock_);
+ bool waited = false;
while (processing_request_) {
+ VLOG(jdwp) << StringPrintf("wait for processing request");
+ waited = true;
process_request_cond_.Wait(self);
}
+ if (waited) {
+ VLOG(jdwp) << StringPrintf("finished waiting for processing request");
+ }
CHECK_EQ(processing_request_, false);
}
diff --git a/runtime/jdwp/jdwp_main.cc b/runtime/jdwp/jdwp_main.cc
index ba49c45..500585d 100644
--- a/runtime/jdwp/jdwp_main.cc
+++ b/runtime/jdwp/jdwp_main.cc
@@ -386,10 +386,14 @@
JdwpNetStateBase* netStateBase = reinterpret_cast<JdwpNetStateBase*>(netState);
JDWP::Request request(netStateBase->input_buffer_, netStateBase->input_count_);
- StartProcessingRequest();
ExpandBuf* pReply = expandBufAlloc();
ProcessRequest(request, pReply);
ssize_t cc = netStateBase->WritePacket(pReply);
+
+ /*
+ * We processed this request and sent its reply. Notify other threads waiting for us they can now
+ * send events.
+ */
EndProcessingRequest();
if (cc != (ssize_t) expandBufGetLength(pReply)) {
diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc
index a0665b5..76aa734 100644
--- a/runtime/jni_internal.cc
+++ b/runtime/jni_internal.cc
@@ -27,7 +27,7 @@
#include "base/mutex.h"
#include "base/stl_util.h"
#include "base/stringpiece.h"
-#include "class_linker.h"
+#include "class_linker-inl.h"
#include "dex_file-inl.h"
#include "gc/accounting/card_table-inl.h"
#include "interpreter/interpreter.h"
@@ -284,7 +284,7 @@
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
if (sig[1] != '\0') {
SirtRef<mirror::ClassLoader> class_loader(soa.Self(), c->GetClassLoader());
- field_type = class_linker->FindClass(sig, class_loader);
+ field_type = class_linker->FindClass(soa.Self(), sig, class_loader);
} else {
field_type = class_linker->FindPrimitiveClass(*sig);
}
@@ -651,9 +651,9 @@
mirror::Class* c = nullptr;
if (runtime->IsStarted()) {
SirtRef<mirror::ClassLoader> class_loader(soa.Self(), GetClassLoader(soa));
- c = class_linker->FindClass(descriptor.c_str(), class_loader);
+ c = class_linker->FindClass(soa.Self(), descriptor.c_str(), class_loader);
} else {
- c = class_linker->FindSystemClass(descriptor.c_str());
+ c = class_linker->FindSystemClass(soa.Self(), descriptor.c_str());
}
return soa.AddLocalReference<jclass>(c);
}
@@ -2140,13 +2140,8 @@
PrettyDescriptor(element_class).c_str());
return nullptr;
}
- std::string descriptor("[");
- descriptor += ClassHelper(element_class).GetDescriptor();
-
- // Find the class.
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- SirtRef<mirror::ClassLoader> class_loader(soa.Self(), element_class->GetClassLoader());
- array_class = class_linker->FindClass(descriptor.c_str(), class_loader);
+ array_class = class_linker->FindArrayClass(soa.Self(), element_class);
if (UNLIKELY(array_class == nullptr)) {
return nullptr;
}
diff --git a/runtime/jni_internal_test.cc b/runtime/jni_internal_test.cc
index 2dd7d96..63bc45c 100644
--- a/runtime/jni_internal_test.cc
+++ b/runtime/jni_internal_test.cc
@@ -107,7 +107,8 @@
class_name);
}
- mirror::Class* c = class_linker_->FindClass(DotToDescriptor(class_name).c_str(), class_loader);
+ mirror::Class* c = class_linker_->FindClass(self, DotToDescriptor(class_name).c_str(),
+ class_loader);
CHECK(c != NULL);
*method = is_static ? c->FindDirectMethod(method_name, method_signature)
@@ -1778,7 +1779,7 @@
class_loader(soa.Self(), soa.Decode<mirror::ClassLoader*>(jclass_loader));
CompileDirectMethod(class_loader, "Main", "main", "([Ljava/lang/String;)V");
- mirror::Class* klass = class_linker_->FindClass("LMain;", class_loader);
+ mirror::Class* klass = class_linker_->FindClass(soa.Self(), "LMain;", class_loader);
ASSERT_TRUE(klass != NULL);
mirror::ArtMethod* method = klass->FindDirectMethod("main", "([Ljava/lang/String;)V");
diff --git a/runtime/mirror/array.cc b/runtime/mirror/array.cc
index 2180857..715f072 100644
--- a/runtime/mirror/array.cc
+++ b/runtime/mirror/array.cc
@@ -18,6 +18,7 @@
#include "class.h"
#include "class-inl.h"
+#include "class_linker-inl.h"
#include "common_throws.h"
#include "dex_file-inl.h"
#include "gc/accounting/card_table-inl.h"
@@ -85,20 +86,22 @@
}
}
- // Generate the full name of the array class.
- std::string descriptor(num_dimensions, '[');
- descriptor += ClassHelper(element_class.get()).GetDescriptor();
-
// Find/generate the array class.
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- SirtRef<mirror::ClassLoader> class_loader(self, element_class->GetClassLoader());
SirtRef<mirror::Class> array_class(self,
- class_linker->FindClass(descriptor.c_str(), class_loader));
+ class_linker->FindArrayClass(self, element_class.get()));
if (UNLIKELY(array_class.get() == nullptr)) {
CHECK(self->IsExceptionPending());
return nullptr;
}
- // create the array
+ for (int32_t i = 1; i < dimensions->GetLength(); ++i) {
+ array_class.reset(class_linker->FindArrayClass(self, array_class.get()));
+ if (UNLIKELY(array_class.get() == nullptr)) {
+ CHECK(self->IsExceptionPending());
+ return nullptr;
+ }
+ }
+ // Create the array.
Array* new_array = RecursiveCreateMultiArray(self, array_class, 0, dimensions);
if (UNLIKELY(new_array == nullptr)) {
CHECK(self->IsExceptionPending());
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index 3208de9..6dbb29d 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -72,7 +72,7 @@
<< PrettyClass(this) << " " << old_status << " -> " << new_status;
}
}
- if (new_status == kStatusError) {
+ if (UNLIKELY(new_status == kStatusError)) {
CHECK_NE(GetStatus(), kStatusError)
<< "Attempt to set as erroneous an already erroneous class " << PrettyClass(this);
@@ -95,7 +95,8 @@
// clear exception to call FindSystemClass
self->ClearException();
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- Class* eiie_class = class_linker->FindSystemClass("Ljava/lang/ExceptionInInitializerError;");
+ Class* eiie_class = class_linker->FindSystemClass(self,
+ "Ljava/lang/ExceptionInInitializerError;");
CHECK(!self->IsExceptionPending());
// Only verification errors, not initialization problems, should set a verify error.
diff --git a/runtime/mirror/object_test.cc b/runtime/mirror/object_test.cc
index 40c3748..34fb15e 100644
--- a/runtime/mirror/object_test.cc
+++ b/runtime/mirror/object_test.cc
@@ -123,7 +123,8 @@
EXPECT_TRUE(oa->Get(0) == oa.get());
EXPECT_TRUE(oa->Get(1) == oa.get());
- Class* aioobe = class_linker_->FindSystemClass("Ljava/lang/ArrayIndexOutOfBoundsException;");
+ Class* aioobe = class_linker_->FindSystemClass(soa.Self(),
+ "Ljava/lang/ArrayIndexOutOfBoundsException;");
EXPECT_TRUE(oa->Get(-1) == NULL);
EXPECT_TRUE(soa.Self()->IsExceptionPending());
@@ -138,21 +139,23 @@
ASSERT_TRUE(oa->GetClass() != NULL);
ClassHelper oa_ch(oa->GetClass());
ASSERT_EQ(2U, oa_ch.NumDirectInterfaces());
- EXPECT_EQ(class_linker_->FindSystemClass("Ljava/lang/Cloneable;"), oa_ch.GetDirectInterface(0));
- EXPECT_EQ(class_linker_->FindSystemClass("Ljava/io/Serializable;"), oa_ch.GetDirectInterface(1));
+ EXPECT_EQ(class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Cloneable;"),
+ oa_ch.GetDirectInterface(0));
+ EXPECT_EQ(class_linker_->FindSystemClass(soa.Self(), "Ljava/io/Serializable;"),
+ oa_ch.GetDirectInterface(1));
}
TEST_F(ObjectTest, AllocArray) {
ScopedObjectAccess soa(Thread::Current());
- Class* c = class_linker_->FindSystemClass("[I");
+ Class* c = class_linker_->FindSystemClass(soa.Self(), "[I");
SirtRef<Array> a(soa.Self(), Array::Alloc<true>(soa.Self(), c, 1));
ASSERT_TRUE(c == a->GetClass());
- c = class_linker_->FindSystemClass("[Ljava/lang/Object;");
+ c = class_linker_->FindSystemClass(soa.Self(), "[Ljava/lang/Object;");
a.reset(Array::Alloc<true>(soa.Self(), c, 1));
ASSERT_TRUE(c == a->GetClass());
- c = class_linker_->FindSystemClass("[[Ljava/lang/Object;");
+ c = class_linker_->FindSystemClass(soa.Self(), "[[Ljava/lang/Object;");
a.reset(Array::Alloc<true>(soa.Self(), c, 1));
ASSERT_TRUE(c == a->GetClass());
}
@@ -173,7 +176,7 @@
EXPECT_EQ(T(123), a->Get(0));
EXPECT_EQ(T(321), a->Get(1));
- Class* aioobe = cl->FindSystemClass("Ljava/lang/ArrayIndexOutOfBoundsException;");
+ Class* aioobe = cl->FindSystemClass(soa.Self(), "Ljava/lang/ArrayIndexOutOfBoundsException;");
EXPECT_EQ(0, a->Get(-1));
EXPECT_TRUE(soa.Self()->IsExceptionPending());
@@ -214,7 +217,7 @@
TEST_F(ObjectTest, CheckAndAllocArrayFromCode) {
// pretend we are trying to call 'new char[3]' from String.toCharArray
ScopedObjectAccess soa(Thread::Current());
- Class* java_util_Arrays = class_linker_->FindSystemClass("Ljava/util/Arrays;");
+ Class* java_util_Arrays = class_linker_->FindSystemClass(soa.Self(), "Ljava/util/Arrays;");
ArtMethod* sort = java_util_Arrays->FindDirectMethod("sort", "([I)V");
const DexFile::StringId* string_id = java_lang_dex_file_->FindStringId("[I");
ASSERT_TRUE(string_id != NULL);
@@ -233,11 +236,11 @@
TEST_F(ObjectTest, CreateMultiArray) {
ScopedObjectAccess soa(Thread::Current());
- SirtRef<Class> c(soa.Self(), class_linker_->FindSystemClass("I"));
+ SirtRef<Class> c(soa.Self(), class_linker_->FindSystemClass(soa.Self(), "I"));
SirtRef<IntArray> dims(soa.Self(), IntArray::Alloc(soa.Self(), 1));
dims->Set<false>(0, 1);
Array* multi = Array::CreateMultiArray(soa.Self(), c, dims);
- EXPECT_TRUE(multi->GetClass() == class_linker_->FindSystemClass("[I"));
+ EXPECT_TRUE(multi->GetClass() == class_linker_->FindSystemClass(soa.Self(), "[I"));
EXPECT_EQ(1, multi->GetLength());
dims->Set<false>(0, -1);
@@ -253,11 +256,11 @@
dims->Set<false>(0, i);
dims->Set<false>(1, j);
multi = Array::CreateMultiArray(soa.Self(), c, dims);
- EXPECT_TRUE(multi->GetClass() == class_linker_->FindSystemClass("[[I"));
+ EXPECT_TRUE(multi->GetClass() == class_linker_->FindSystemClass(soa.Self(), "[[I"));
EXPECT_EQ(i, multi->GetLength());
for (int k = 0; k < i; ++k) {
Array* outer = multi->AsObjectArray<Array>()->Get(k);
- EXPECT_TRUE(outer->GetClass() == class_linker_->FindSystemClass("[I"));
+ EXPECT_TRUE(outer->GetClass() == class_linker_->FindSystemClass(soa.Self(), "[I"));
EXPECT_EQ(j, outer->GetLength());
}
}
@@ -272,8 +275,7 @@
CHECK(dex_file != NULL);
SirtRef<mirror::ClassLoader> loader(soa.Self(), soa.Decode<ClassLoader*>(class_loader));
- Class* klass =
- class_linker_->FindClass("LStaticsFromCode;", loader);
+ Class* klass = class_linker_->FindClass(soa.Self(), "LStaticsFromCode;", loader);
ArtMethod* clinit = klass->FindClassInitializer();
const DexFile::StringId* klass_string_id = dex_file->FindStringId("LStaticsFromCode;");
ASSERT_TRUE(klass_string_id != NULL);
@@ -404,9 +406,9 @@
SirtRef<ClassLoader> class_loader_1(soa.Self(), soa.Decode<ClassLoader*>(jclass_loader_1));
SirtRef<ClassLoader> class_loader_2(soa.Self(), soa.Decode<ClassLoader*>(jclass_loader_2));
- Class* klass1 = linker->FindClass("LProtoCompare;", class_loader_1);
+ Class* klass1 = linker->FindClass(soa.Self(), "LProtoCompare;", class_loader_1);
ASSERT_TRUE(klass1 != NULL);
- Class* klass2 = linker->FindClass("LProtoCompare2;", class_loader_2);
+ Class* klass2 = linker->FindClass(soa.Self(), "LProtoCompare2;", class_loader_2);
ASSERT_TRUE(klass2 != NULL);
ArtMethod* m1_1 = klass1->GetVirtualMethod(0);
@@ -472,8 +474,8 @@
jobject jclass_loader = LoadDex("XandY");
SirtRef<ClassLoader> class_loader(soa.Self(), soa.Decode<ClassLoader*>(jclass_loader));
- Class* X = class_linker_->FindClass("LX;", class_loader);
- Class* Y = class_linker_->FindClass("LY;", class_loader);
+ Class* X = class_linker_->FindClass(soa.Self(), "LX;", class_loader);
+ Class* Y = class_linker_->FindClass(soa.Self(), "LY;", class_loader);
ASSERT_TRUE(X != NULL);
ASSERT_TRUE(Y != NULL);
@@ -487,16 +489,16 @@
EXPECT_TRUE(y->InstanceOf(X));
EXPECT_TRUE(y->InstanceOf(Y));
- Class* java_lang_Class = class_linker_->FindSystemClass("Ljava/lang/Class;");
- Class* Object_array_class = class_linker_->FindSystemClass("[Ljava/lang/Object;");
+ Class* java_lang_Class = class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Class;");
+ Class* Object_array_class = class_linker_->FindSystemClass(soa.Self(), "[Ljava/lang/Object;");
EXPECT_FALSE(java_lang_Class->InstanceOf(Object_array_class));
EXPECT_TRUE(Object_array_class->InstanceOf(java_lang_Class));
// All array classes implement Cloneable and Serializable.
Object* array = ObjectArray<Object>::Alloc(soa.Self(), Object_array_class, 1);
- Class* java_lang_Cloneable = class_linker_->FindSystemClass("Ljava/lang/Cloneable;");
- Class* java_io_Serializable = class_linker_->FindSystemClass("Ljava/io/Serializable;");
+ Class* java_lang_Cloneable = class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Cloneable;");
+ Class* java_io_Serializable = class_linker_->FindSystemClass(soa.Self(), "Ljava/io/Serializable;");
EXPECT_TRUE(array->InstanceOf(java_lang_Cloneable));
EXPECT_TRUE(array->InstanceOf(java_io_Serializable));
}
@@ -505,8 +507,8 @@
ScopedObjectAccess soa(Thread::Current());
jobject jclass_loader = LoadDex("XandY");
SirtRef<ClassLoader> class_loader(soa.Self(), soa.Decode<ClassLoader*>(jclass_loader));
- Class* X = class_linker_->FindClass("LX;", class_loader);
- Class* Y = class_linker_->FindClass("LY;", class_loader);
+ Class* X = class_linker_->FindClass(soa.Self(), "LX;", class_loader);
+ Class* Y = class_linker_->FindClass(soa.Self(), "LY;", class_loader);
EXPECT_TRUE(X->IsAssignableFrom(X));
EXPECT_TRUE(X->IsAssignableFrom(Y));
@@ -514,8 +516,8 @@
EXPECT_TRUE(Y->IsAssignableFrom(Y));
// class final String implements CharSequence, ..
- Class* string = class_linker_->FindSystemClass("Ljava/lang/String;");
- Class* charseq = class_linker_->FindSystemClass("Ljava/lang/CharSequence;");
+ Class* string = class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/String;");
+ Class* charseq = class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/CharSequence;");
// Can String be assigned to CharSequence without a cast?
EXPECT_TRUE(charseq->IsAssignableFrom(string));
// Can CharSequence be assigned to String without a cast?
@@ -542,36 +544,36 @@
ScopedObjectAccess soa(Thread::Current());
jobject jclass_loader = LoadDex("XandY");
SirtRef<ClassLoader> class_loader(soa.Self(), soa.Decode<ClassLoader*>(jclass_loader));
- Class* X = class_linker_->FindClass("LX;", class_loader);
- Class* Y = class_linker_->FindClass("LY;", class_loader);
+ Class* X = class_linker_->FindClass(soa.Self(), "LX;", class_loader);
+ Class* Y = class_linker_->FindClass(soa.Self(), "LY;", class_loader);
ASSERT_TRUE(X != NULL);
ASSERT_TRUE(Y != NULL);
- Class* YA = class_linker_->FindClass("[LY;", class_loader);
- Class* YAA = class_linker_->FindClass("[[LY;", class_loader);
+ Class* YA = class_linker_->FindClass(soa.Self(), "[LY;", class_loader);
+ Class* YAA = class_linker_->FindClass(soa.Self(), "[[LY;", class_loader);
ASSERT_TRUE(YA != NULL);
ASSERT_TRUE(YAA != NULL);
- Class* XAA = class_linker_->FindClass("[[LX;", class_loader);
+ Class* XAA = class_linker_->FindClass(soa.Self(), "[[LX;", class_loader);
ASSERT_TRUE(XAA != NULL);
- Class* O = class_linker_->FindSystemClass("Ljava/lang/Object;");
- Class* OA = class_linker_->FindSystemClass("[Ljava/lang/Object;");
- Class* OAA = class_linker_->FindSystemClass("[[Ljava/lang/Object;");
- Class* OAAA = class_linker_->FindSystemClass("[[[Ljava/lang/Object;");
+ Class* O = class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Object;");
+ Class* OA = class_linker_->FindSystemClass(soa.Self(), "[Ljava/lang/Object;");
+ Class* OAA = class_linker_->FindSystemClass(soa.Self(), "[[Ljava/lang/Object;");
+ Class* OAAA = class_linker_->FindSystemClass(soa.Self(), "[[[Ljava/lang/Object;");
ASSERT_TRUE(O != NULL);
ASSERT_TRUE(OA != NULL);
ASSERT_TRUE(OAA != NULL);
ASSERT_TRUE(OAAA != NULL);
- Class* S = class_linker_->FindSystemClass("Ljava/io/Serializable;");
- Class* SA = class_linker_->FindSystemClass("[Ljava/io/Serializable;");
- Class* SAA = class_linker_->FindSystemClass("[[Ljava/io/Serializable;");
+ Class* S = class_linker_->FindSystemClass(soa.Self(), "Ljava/io/Serializable;");
+ Class* SA = class_linker_->FindSystemClass(soa.Self(), "[Ljava/io/Serializable;");
+ Class* SAA = class_linker_->FindSystemClass(soa.Self(), "[[Ljava/io/Serializable;");
ASSERT_TRUE(S != NULL);
ASSERT_TRUE(SA != NULL);
ASSERT_TRUE(SAA != NULL);
- Class* IA = class_linker_->FindSystemClass("[I");
+ Class* IA = class_linker_->FindSystemClass(soa.Self(), "[I");
ASSERT_TRUE(IA != NULL);
EXPECT_TRUE(YAA->IsAssignableFrom(YAA)); // identity
@@ -616,7 +618,7 @@
// TODO: check that s.count == 3.
// Ensure that we handle superclass fields correctly...
- c = class_linker_->FindSystemClass("Ljava/lang/StringBuilder;");
+ c = class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/StringBuilder;");
ASSERT_TRUE(c != NULL);
// No StringBuilder.count...
EXPECT_TRUE(c->FindDeclaredInstanceField("count", "I") == NULL);
diff --git a/runtime/native/dalvik_system_VMRuntime.cc b/runtime/native/dalvik_system_VMRuntime.cc
index def3292..5779442 100644
--- a/runtime/native/dalvik_system_VMRuntime.cc
+++ b/runtime/native/dalvik_system_VMRuntime.cc
@@ -16,7 +16,7 @@
#include <limits.h>
-#include "class_linker.h"
+#include "class_linker-inl.h"
#include "common_throws.h"
#include "debugger.h"
#include "dex_file-inl.h"
@@ -57,22 +57,22 @@
jint length) {
ScopedFastNativeObjectAccess soa(env);
mirror::Class* element_class = soa.Decode<mirror::Class*>(javaElementClass);
- if (element_class == NULL) {
+ if (UNLIKELY(element_class == nullptr)) {
ThrowNullPointerException(NULL, "element class == null");
- return NULL;
+ return nullptr;
}
- if (length < 0) {
+ if (UNLIKELY(length < 0)) {
ThrowNegativeArraySizeException(length);
- return NULL;
+ return nullptr;
}
- ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- std::string descriptor;
- descriptor += "[";
- descriptor += ClassHelper(element_class).GetDescriptor();
- SirtRef<mirror::ClassLoader> class_loader(soa.Self(), nullptr);
- mirror::Class* array_class = class_linker->FindClass(descriptor.c_str(), class_loader);
+ Runtime* runtime = Runtime::Current();
+ mirror::Class* array_class = runtime->GetClassLinker()->FindArrayClass(soa.Self(), element_class);
+ if (UNLIKELY(array_class == nullptr)) {
+ return nullptr;
+ }
+ gc::AllocatorType allocator = runtime->GetHeap()->GetCurrentNonMovingAllocator();
mirror::Array* result = mirror::Array::Alloc<true>(soa.Self(), array_class, length,
- Runtime::Current()->GetHeap()->GetCurrentNonMovingAllocator());
+ allocator);
return soa.AddLocalReference<jobject>(result);
}
diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc
index 3e3f608..8bf36e7 100644
--- a/runtime/native/java_lang_Class.cc
+++ b/runtime/native/java_lang_Class.cc
@@ -43,7 +43,8 @@
}
// "name" is in "binary name" format, e.g. "dalvik.system.Debug$1".
-static jclass Class_classForName(JNIEnv* env, jclass, jstring javaName, jboolean initialize, jobject javaLoader) {
+static jclass Class_classForName(JNIEnv* env, jclass, jstring javaName, jboolean initialize,
+ jobject javaLoader) {
ScopedObjectAccess soa(env);
ScopedUtfChars name(env, javaName);
if (name.c_str() == nullptr) {
@@ -64,7 +65,8 @@
SirtRef<mirror::ClassLoader> class_loader(soa.Self(),
soa.Decode<mirror::ClassLoader*>(javaLoader));
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- SirtRef<mirror::Class> c(soa.Self(), class_linker->FindClass(descriptor.c_str(), class_loader));
+ SirtRef<mirror::Class> c(soa.Self(), class_linker->FindClass(soa.Self(), descriptor.c_str(),
+ class_loader));
if (c.get() == nullptr) {
ScopedLocalRef<jthrowable> cause(env, env->ExceptionOccurred());
env->ExceptionClear();
diff --git a/runtime/native/java_lang_reflect_Array.cc b/runtime/native/java_lang_reflect_Array.cc
index 2197597..fc30aa6 100644
--- a/runtime/native/java_lang_reflect_Array.cc
+++ b/runtime/native/java_lang_reflect_Array.cc
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "class_linker.h"
+#include "class_linker-inl.h"
#include "common_throws.h"
#include "dex_file-inl.h"
#include "jni_internal.h"
@@ -50,12 +50,8 @@
ThrowNegativeArraySizeException(length);
return NULL;
}
- std::string descriptor("[");
- descriptor += ClassHelper(element_class).GetDescriptor();
-
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- SirtRef<mirror::ClassLoader> class_loader(soa.Self(), element_class->GetClassLoader());
- mirror::Class* array_class = class_linker->FindClass(descriptor.c_str(), class_loader);
+ mirror::Class* array_class = class_linker->FindArrayClass(soa.Self(), element_class);
if (UNLIKELY(array_class == NULL)) {
CHECK(soa.Self()->IsExceptionPending());
return NULL;
diff --git a/runtime/oat.cc b/runtime/oat.cc
index 81d4540..945cd77 100644
--- a/runtime/oat.cc
+++ b/runtime/oat.cc
@@ -22,7 +22,7 @@
namespace art {
const uint8_t OatHeader::kOatMagic[] = { 'o', 'a', 't', '\n' };
-const uint8_t OatHeader::kOatVersion[] = { '0', '1', '4', '\0' };
+const uint8_t OatHeader::kOatVersion[] = { '0', '1', '5', '\0' };
OatHeader::OatHeader() {
memset(this, 0, sizeof(*this));
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc
index 00a8506..61f023c 100644
--- a/runtime/oat_file.cc
+++ b/runtime/oat_file.cc
@@ -84,6 +84,7 @@
// This won't work for portable runtime execution because it doesn't process relocations.
UniquePtr<File> file(OS::OpenFileForReading(filename.c_str()));
if (file.get() == NULL) {
+ *error_msg = StringPrintf("Failed to open oat filename for reading: %s", strerror(errno));
return NULL;
}
return OpenElfFile(file.get(), location, requested_base, false, executable, error_msg);
diff --git a/runtime/object_utils.h b/runtime/object_utils.h
index a981fab..4eac291 100644
--- a/runtime/object_utils.h
+++ b/runtime/object_utils.h
@@ -17,7 +17,7 @@
#ifndef ART_RUNTIME_OBJECT_UTILS_H_
#define ART_RUNTIME_OBJECT_UTILS_H_
-#include "class_linker-inl.h"
+#include "class_linker.h"
#include "dex_file.h"
#include "monitor.h"
#include "mirror/art_field.h"
@@ -158,10 +158,10 @@
DCHECK(!klass_->IsPrimitive());
if (klass_->IsArrayClass()) {
if (idx == 0) {
- return GetClassLinker()->FindSystemClass("Ljava/lang/Cloneable;");
+ return GetClassLinker()->FindSystemClass(Thread::Current(), "Ljava/lang/Cloneable;");
} else {
DCHECK_EQ(1U, idx);
- return GetClassLinker()->FindSystemClass("Ljava/io/Serializable;");
+ return GetClassLinker()->FindSystemClass(Thread::Current(), "Ljava/io/Serializable;");
}
} else if (klass_->IsProxyClass()) {
return klass_->GetIfTable()->GetInterface(idx);
@@ -251,7 +251,7 @@
mirror::Class* GetType(bool resolve = true) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
uint32_t field_index = field_->GetDexFieldIndex();
if (UNLIKELY(field_->GetDeclaringClass()->IsProxyClass())) {
- return GetClassLinker()->FindSystemClass(GetTypeDescriptor());
+ return GetClassLinker()->FindSystemClass(Thread::Current(), GetTypeDescriptor());
}
const DexFile& dex_file = GetDexFile();
const DexFile::FieldId& field_id = dex_file.GetFieldId(field_index);
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 3ccea36..1ef15f7 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -77,13 +77,6 @@
is_zygote_(false),
is_concurrent_gc_enabled_(true),
is_explicit_gc_disabled_(false),
- compiler_filter_(kSpeed),
- huge_method_threshold_(0),
- large_method_threshold_(0),
- small_method_threshold_(0),
- tiny_method_threshold_(0),
- num_dex_methods_threshold_(0),
- sea_ir_mode_(false),
default_stack_size_(0),
heap_(nullptr),
max_spins_before_thin_lock_inflation_(Monitor::kDefaultMaxSpinsBeforeThinLockInflation),
@@ -452,14 +445,6 @@
parsed->hook_exit_ = exit;
parsed->hook_abort_ = NULL; // We don't call abort(3) by default; see Runtime::Abort.
- parsed->compiler_filter_ = Runtime::kDefaultCompilerFilter;
- parsed->huge_method_threshold_ = Runtime::kDefaultHugeMethodThreshold;
- parsed->large_method_threshold_ = Runtime::kDefaultLargeMethodThreshold;
- parsed->small_method_threshold_ = Runtime::kDefaultSmallMethodThreshold;
- parsed->tiny_method_threshold_ = Runtime::kDefaultTinyMethodThreshold;
- parsed->num_dex_methods_threshold_ = Runtime::kDefaultNumDexMethodsThreshold;
-
- parsed->sea_ir_mode_ = false;
// gLogVerbosity.class_linker = true; // TODO: don't check this in!
// gLogVerbosity.compiler = true; // TODO: don't check this in!
// gLogVerbosity.verifier = true; // TODO: don't check this in!
@@ -721,28 +706,22 @@
} else if (StartsWith(option, "-Xprofile-backoff:")) {
parsed->profile_backoff_coefficient_ = ParseDoubleOrDie(
option, ':', 1.0, 10.0, ignore_unrecognized, parsed->profile_backoff_coefficient_);
- } else if (option == "-compiler-filter:interpret-only") {
- parsed->compiler_filter_ = kInterpretOnly;
- } else if (option == "-compiler-filter:space") {
- parsed->compiler_filter_ = kSpace;
- } else if (option == "-compiler-filter:balanced") {
- parsed->compiler_filter_ = kBalanced;
- } else if (option == "-compiler-filter:speed") {
- parsed->compiler_filter_ = kSpeed;
- } else if (option == "-compiler-filter:everything") {
- parsed->compiler_filter_ = kEverything;
- } else if (option == "-sea_ir") {
- parsed->sea_ir_mode_ = true;
- } else if (StartsWith(option, "-huge-method-max:")) {
- parsed->huge_method_threshold_ = ParseIntegerOrDie(option, ':');
- } else if (StartsWith(option, "-large-method-max:")) {
- parsed->large_method_threshold_ = ParseIntegerOrDie(option, ':');
- } else if (StartsWith(option, "-small-method-max:")) {
- parsed->small_method_threshold_ = ParseIntegerOrDie(option, ':');
- } else if (StartsWith(option, "-tiny-method-max:")) {
- parsed->tiny_method_threshold_ = ParseIntegerOrDie(option, ':');
- } else if (StartsWith(option, "-num-dex-methods-max:")) {
- parsed->num_dex_methods_threshold_ = ParseIntegerOrDie(option, ':');
+ } else if (option == "-Xcompiler-option") {
+ i++;
+ if (i == options.size()) {
+ // TODO: usage
+ LOG(FATAL) << "Missing required compiler option for " << option;
+ return NULL;
+ }
+ parsed->compiler_options_.push_back(options[i].first);
+ } else if (option == "-Ximage-compiler-option") {
+ i++;
+ if (i == options.size()) {
+ // TODO: usage
+ LOG(FATAL) << "Missing required compiler option for " << option;
+ return NULL;
+ }
+ parsed->image_compiler_options_.push_back(options[i].first);
} else {
if (!ignore_unrecognized) {
// TODO: print usage via vfprintf
@@ -988,14 +967,6 @@
is_zygote_ = options->is_zygote_;
is_explicit_gc_disabled_ = options->is_explicit_gc_disabled_;
- compiler_filter_ = options->compiler_filter_;
- huge_method_threshold_ = options->huge_method_threshold_;
- large_method_threshold_ = options->large_method_threshold_;
- small_method_threshold_ = options->small_method_threshold_;
- tiny_method_threshold_ = options->tiny_method_threshold_;
- num_dex_methods_threshold_ = options->num_dex_methods_threshold_;
-
- sea_ir_mode_ = options->sea_ir_mode_;
vfprintf_ = options->hook_vfprintf_;
exit_ = options->hook_exit_;
abort_ = options->hook_abort_;
diff --git a/runtime/runtime.h b/runtime/runtime.h
index 223b8d5..8924921 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -72,26 +72,6 @@
public:
typedef std::vector<std::pair<std::string, const void*> > Options;
- enum CompilerFilter {
- kInterpretOnly, // Compile nothing.
- kSpace, // Maximize space savings.
- kBalanced, // Try to get the best performance return on compilation investment.
- kSpeed, // Maximize runtime performance.
- kEverything // Force compilation (Note: excludes compilaton of class initializers).
- };
-
- // Guide heuristics to determine whether to compile method if profile data not available.
-#if ART_SMALL_MODE
- static const CompilerFilter kDefaultCompilerFilter = kInterpretOnly;
-#else
- static const CompilerFilter kDefaultCompilerFilter = kSpeed;
-#endif
- static const size_t kDefaultHugeMethodThreshold = 10000;
- static const size_t kDefaultLargeMethodThreshold = 600;
- static const size_t kDefaultSmallMethodThreshold = 60;
- static const size_t kDefaultTinyMethodThreshold = 20;
- static const size_t kDefaultNumDexMethodsThreshold = 900;
-
class ParsedOptions {
public:
// returns null if problem parsing and ignore_unrecognized is false
@@ -140,13 +120,8 @@
void (*hook_exit_)(jint status);
void (*hook_abort_)();
std::vector<std::string> properties_;
- CompilerFilter compiler_filter_;
- size_t huge_method_threshold_;
- size_t large_method_threshold_;
- size_t small_method_threshold_;
- size_t tiny_method_threshold_;
- size_t num_dex_methods_threshold_;
- bool sea_ir_mode_;
+ std::vector<std::string> compiler_options_;
+ std::vector<std::string> image_compiler_options_;
bool profile_;
std::string profile_output_filename_;
int profile_period_s_;
@@ -178,42 +153,12 @@
return is_explicit_gc_disabled_;
}
-#ifdef ART_SEA_IR_MODE
- bool IsSeaIRMode() const {
- return sea_ir_mode_;
- }
-#endif
-
- void SetSeaIRMode(bool sea_ir_mode) {
- sea_ir_mode_ = sea_ir_mode;
+ const std::vector<std::string>& GetCompilerOptions() const {
+ return compiler_options_;
}
- CompilerFilter GetCompilerFilter() const {
- return compiler_filter_;
- }
-
- void SetCompilerFilter(CompilerFilter compiler_filter) {
- compiler_filter_ = compiler_filter;
- }
-
- size_t GetHugeMethodThreshold() const {
- return huge_method_threshold_;
- }
-
- size_t GetLargeMethodThreshold() const {
- return large_method_threshold_;
- }
-
- size_t GetSmallMethodThreshold() const {
- return small_method_threshold_;
- }
-
- size_t GetTinyMethodThreshold() const {
- return tiny_method_threshold_;
- }
-
- size_t GetNumDexMethodsThreshold() const {
- return num_dex_methods_threshold_;
+ const std::vector<std::string>& GetImageCompilerOptions() const {
+ return image_compiler_options_;
}
const std::string& GetHostPrefix() const {
@@ -525,14 +470,8 @@
bool is_concurrent_gc_enabled_;
bool is_explicit_gc_disabled_;
- CompilerFilter compiler_filter_;
- size_t huge_method_threshold_;
- size_t large_method_threshold_;
- size_t small_method_threshold_;
- size_t tiny_method_threshold_;
- size_t num_dex_methods_threshold_;
-
- bool sea_ir_mode_;
+ std::vector<std::string> compiler_options_;
+ std::vector<std::string> image_compiler_options_;
// The host prefix is used during cross compilation. It is removed
// from the start of host paths such as:
diff --git a/runtime/scoped_thread_state_change.h b/runtime/scoped_thread_state_change.h
index 2f959db..f0f5ed2 100644
--- a/runtime/scoped_thread_state_change.h
+++ b/runtime/scoped_thread_state_change.h
@@ -122,6 +122,7 @@
: ScopedThreadStateChange(ThreadForEnv(env), kRunnable),
env_(down_cast<JNIEnvExt*>(env)), vm_(env_->vm) {
self_->VerifyStack();
+ Locks::mutator_lock_->AssertSharedHeld(self_);
}
explicit ScopedObjectAccessUnchecked(Thread* self)
@@ -130,6 +131,7 @@
env_(down_cast<JNIEnvExt*>(self->GetJniEnv())),
vm_(env_ != NULL ? env_->vm : NULL) {
self_->VerifyStack();
+ Locks::mutator_lock_->AssertSharedHeld(self_);
}
// Used when we want a scoped JNI thread state but have no thread/JNIEnv. Consequently doesn't
@@ -139,6 +141,7 @@
// Here purely to force inlining.
~ScopedObjectAccessUnchecked() ALWAYS_INLINE {
+ Locks::mutator_lock_->AssertSharedHeld(self_);
}
JNIEnvExt* Env() const {
@@ -250,14 +253,12 @@
LOCKS_EXCLUDED(Locks::thread_suspend_count_lock_)
SHARED_LOCK_FUNCTION(Locks::mutator_lock_) ALWAYS_INLINE
: ScopedObjectAccessUnchecked(env) {
- Locks::mutator_lock_->AssertSharedHeld(Self());
}
explicit ScopedObjectAccess(Thread* self)
LOCKS_EXCLUDED(Locks::thread_suspend_count_lock_)
SHARED_LOCK_FUNCTION(Locks::mutator_lock_)
: ScopedObjectAccessUnchecked(self) {
- Locks::mutator_lock_->AssertSharedHeld(Self());
}
~ScopedObjectAccess() UNLOCK_FUNCTION(Locks::mutator_lock_) ALWAYS_INLINE {
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 8949a5b..8b93b91 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -1529,7 +1529,7 @@
}
SirtRef<mirror::ClassLoader> class_loader(this, cl);
SirtRef<mirror::Class>
- exception_class(this, runtime->GetClassLinker()->FindClass(exception_class_descriptor,
+ exception_class(this, runtime->GetClassLinker()->FindClass(this, exception_class_descriptor,
class_loader));
if (UNLIKELY(exception_class.get() == nullptr)) {
CHECK(IsExceptionPending());
diff --git a/runtime/thread_list.cc b/runtime/thread_list.cc
index 74e6f1c..d311945 100644
--- a/runtime/thread_list.cc
+++ b/runtime/thread_list.cc
@@ -269,6 +269,7 @@
void ThreadList::SuspendAll() {
Thread* self = Thread::Current();
+ DCHECK(self != nullptr);
VLOG(threads) << *self << " SuspendAll starting...";
diff --git a/runtime/transaction_test.cc b/runtime/transaction_test.cc
index dcfa24b..9dc7b44 100644
--- a/runtime/transaction_test.cc
+++ b/runtime/transaction_test.cc
@@ -29,7 +29,7 @@
TEST_F(TransactionTest, Object_class) {
ScopedObjectAccess soa(Thread::Current());
SirtRef<mirror::Class> sirt_klass(soa.Self(),
- class_linker_->FindSystemClass("Ljava/lang/Object;"));
+ class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Object;"));
ASSERT_TRUE(sirt_klass.get() != nullptr);
Transaction transaction;
@@ -47,7 +47,8 @@
TEST_F(TransactionTest, Object_monitor) {
ScopedObjectAccess soa(Thread::Current());
SirtRef<mirror::Class> sirt_klass(soa.Self(),
- class_linker_->FindSystemClass("Ljava/lang/Object;"));
+ class_linker_->FindSystemClass(soa.Self(),
+ "Ljava/lang/Object;"));
ASSERT_TRUE(sirt_klass.get() != nullptr);
SirtRef<mirror::Object> sirt_obj(soa.Self(), sirt_klass->AllocObject(soa.Self()));
ASSERT_TRUE(sirt_obj.get() != nullptr);
@@ -74,7 +75,8 @@
TEST_F(TransactionTest, Array_length) {
ScopedObjectAccess soa(Thread::Current());
SirtRef<mirror::Class> sirt_klass(soa.Self(),
- class_linker_->FindSystemClass("[Ljava/lang/Object;"));
+ class_linker_->FindSystemClass(soa.Self(),
+ "[Ljava/lang/Object;"));
ASSERT_TRUE(sirt_klass.get() != nullptr);
constexpr int32_t kArraySize = 2;
@@ -101,7 +103,8 @@
ASSERT_TRUE(class_loader.get() != nullptr);
SirtRef<mirror::Class> sirt_klass(soa.Self(),
- class_linker_->FindClass("LStaticFieldsTest;", class_loader));
+ class_linker_->FindClass(soa.Self(), "LStaticFieldsTest;",
+ class_loader));
ASSERT_TRUE(sirt_klass.get() != nullptr);
class_linker_->EnsureInitialized(sirt_klass, true, true);
ASSERT_TRUE(sirt_klass->IsInitialized());
@@ -147,13 +150,16 @@
ASSERT_EQ(FieldHelper(doubleField).GetTypeAsPrimitiveType(), Primitive::kPrimDouble);
ASSERT_EQ(doubleField->GetDouble(sirt_klass.get()), static_cast<double>(0.0));
- mirror::ArtField* objectField = sirt_klass->FindDeclaredStaticField("objectField", "Ljava/lang/Object;");
+ mirror::ArtField* objectField = sirt_klass->FindDeclaredStaticField("objectField",
+ "Ljava/lang/Object;");
ASSERT_TRUE(objectField != nullptr);
ASSERT_EQ(FieldHelper(objectField).GetTypeAsPrimitiveType(), Primitive::kPrimNot);
ASSERT_EQ(objectField->GetObject(sirt_klass.get()), nullptr);
// Create a java.lang.Object instance to set objectField.
- SirtRef<mirror::Class> object_klass(soa.Self(), class_linker_->FindSystemClass("Ljava/lang/Object;"));
+ SirtRef<mirror::Class> object_klass(soa.Self(),
+ class_linker_->FindSystemClass(soa.Self(),
+ "Ljava/lang/Object;"));
ASSERT_TRUE(object_klass.get() != nullptr);
SirtRef<mirror::Object> sirt_obj(soa.Self(), sirt_klass->AllocObject(soa.Self()));
ASSERT_TRUE(sirt_obj.get() != nullptr);
@@ -193,7 +199,8 @@
ASSERT_TRUE(class_loader.get() != nullptr);
SirtRef<mirror::Class> sirt_klass(soa.Self(),
- class_linker_->FindClass("LInstanceFieldsTest;", class_loader));
+ class_linker_->FindClass(soa.Self(), "LInstanceFieldsTest;",
+ class_loader));
ASSERT_TRUE(sirt_klass.get() != nullptr);
class_linker_->EnsureInitialized(sirt_klass, true, true);
ASSERT_TRUE(sirt_klass->IsInitialized());
@@ -243,13 +250,16 @@
ASSERT_EQ(FieldHelper(doubleField).GetTypeAsPrimitiveType(), Primitive::kPrimDouble);
ASSERT_EQ(doubleField->GetDouble(sirt_instance.get()), static_cast<double>(0.0));
- mirror::ArtField* objectField = sirt_klass->FindDeclaredInstanceField("objectField", "Ljava/lang/Object;");
+ mirror::ArtField* objectField = sirt_klass->FindDeclaredInstanceField("objectField",
+ "Ljava/lang/Object;");
ASSERT_TRUE(objectField != nullptr);
ASSERT_EQ(FieldHelper(objectField).GetTypeAsPrimitiveType(), Primitive::kPrimNot);
ASSERT_EQ(objectField->GetObject(sirt_instance.get()), nullptr);
// Create a java.lang.Object instance to set objectField.
- SirtRef<mirror::Class> object_klass(soa.Self(), class_linker_->FindSystemClass("Ljava/lang/Object;"));
+ SirtRef<mirror::Class> object_klass(soa.Self(),
+ class_linker_->FindSystemClass(soa.Self(),
+ "Ljava/lang/Object;"));
ASSERT_TRUE(object_klass.get() != nullptr);
SirtRef<mirror::Object> sirt_obj(soa.Self(), sirt_klass->AllocObject(soa.Self()));
ASSERT_TRUE(sirt_obj.get() != nullptr);
@@ -290,7 +300,8 @@
ASSERT_TRUE(class_loader.get() != nullptr);
SirtRef<mirror::Class> sirt_klass(soa.Self(),
- class_linker_->FindClass("LStaticArrayFieldsTest;", class_loader));
+ class_linker_->FindClass(soa.Self(), "LStaticArrayFieldsTest;",
+ class_loader));
ASSERT_TRUE(sirt_klass.get() != nullptr);
class_linker_->EnsureInitialized(sirt_klass, true, true);
ASSERT_TRUE(sirt_klass->IsInitialized());
@@ -352,15 +363,19 @@
ASSERT_EQ(doubleArray->GetLength(), 1);
ASSERT_EQ(doubleArray->GetWithoutChecks(0), static_cast<double>(0.0f));
- mirror::ArtField* objectArrayField = sirt_klass->FindDeclaredStaticField("objectArrayField", "[Ljava/lang/Object;");
+ mirror::ArtField* objectArrayField = sirt_klass->FindDeclaredStaticField("objectArrayField",
+ "[Ljava/lang/Object;");
ASSERT_TRUE(objectArrayField != nullptr);
- mirror::ObjectArray<mirror::Object>* objectArray = objectArrayField->GetObject(sirt_klass.get())->AsObjectArray<mirror::Object>();
+ mirror::ObjectArray<mirror::Object>* objectArray =
+ objectArrayField->GetObject(sirt_klass.get())->AsObjectArray<mirror::Object>();
ASSERT_TRUE(objectArray != nullptr);
ASSERT_EQ(objectArray->GetLength(), 1);
ASSERT_EQ(objectArray->GetWithoutChecks(0), nullptr);
// Create a java.lang.Object instance to set objectField.
- SirtRef<mirror::Class> object_klass(soa.Self(), class_linker_->FindSystemClass("Ljava/lang/Object;"));
+ SirtRef<mirror::Class> object_klass(soa.Self(),
+ class_linker_->FindSystemClass(soa.Self(),
+ "Ljava/lang/Object;"));
ASSERT_TRUE(object_klass.get() != nullptr);
SirtRef<mirror::Object> sirt_obj(soa.Self(), sirt_klass->AllocObject(soa.Self()));
ASSERT_TRUE(sirt_obj.get() != nullptr);
@@ -400,7 +415,9 @@
ASSERT_TRUE(class_loader.get() != nullptr);
SirtRef<mirror::Class> sirt_klass(soa.Self(),
- class_linker_->FindClass("LTransaction$EmptyStatic;", class_loader));
+ class_linker_->FindClass(soa.Self(),
+ "LTransaction$EmptyStatic;",
+ class_loader));
ASSERT_TRUE(sirt_klass.get() != nullptr);
class_linker_->VerifyClass(sirt_klass);
ASSERT_TRUE(sirt_klass->IsVerified());
@@ -419,7 +436,9 @@
ASSERT_TRUE(class_loader.get() != nullptr);
SirtRef<mirror::Class> sirt_klass(soa.Self(),
- class_linker_->FindClass("LTransaction$StaticFieldClass;", class_loader));
+ class_linker_->FindClass(soa.Self(),
+ "LTransaction$StaticFieldClass;",
+ class_loader));
ASSERT_TRUE(sirt_klass.get() != nullptr);
class_linker_->VerifyClass(sirt_klass);
ASSERT_TRUE(sirt_klass->IsVerified());
@@ -441,22 +460,25 @@
// Load and verify java.lang.ExceptionInInitializerError and java.lang.InternalError which will
// be thrown by class initialization due to native call.
SirtRef<mirror::Class> sirt_klass(soa.Self(),
- class_linker_->FindSystemClass("Ljava/lang/ExceptionInInitializerError;"));
+ class_linker_->FindSystemClass(soa.Self(),
+ "Ljava/lang/ExceptionInInitializerError;"));
ASSERT_TRUE(sirt_klass.get() != nullptr);
class_linker_->VerifyClass(sirt_klass);
ASSERT_TRUE(sirt_klass->IsVerified());
- sirt_klass.reset(class_linker_->FindSystemClass("Ljava/lang/InternalError;"));
+ sirt_klass.reset(class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/InternalError;"));
ASSERT_TRUE(sirt_klass.get() != nullptr);
class_linker_->VerifyClass(sirt_klass);
ASSERT_TRUE(sirt_klass->IsVerified());
// Load and verify Transaction$NativeSupport used in class initialization.
- sirt_klass.reset(class_linker_->FindClass("LTransaction$NativeSupport;", class_loader));
+ sirt_klass.reset(class_linker_->FindClass(soa.Self(), "LTransaction$NativeSupport;",
+ class_loader));
ASSERT_TRUE(sirt_klass.get() != nullptr);
class_linker_->VerifyClass(sirt_klass);
ASSERT_TRUE(sirt_klass->IsVerified());
- sirt_klass.reset(class_linker_->FindClass("LTransaction$BlacklistedClass;", class_loader));
+ sirt_klass.reset(class_linker_->FindClass(soa.Self(), "LTransaction$BlacklistedClass;",
+ class_loader));
ASSERT_TRUE(sirt_klass.get() != nullptr);
class_linker_->VerifyClass(sirt_klass);
ASSERT_TRUE(sirt_klass->IsVerified());
diff --git a/runtime/utils.cc b/runtime/utils.cc
index aad21bc..68d8417 100644
--- a/runtime/utils.cc
+++ b/runtime/utils.cc
@@ -21,9 +21,12 @@
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/types.h>
+#include <sys/wait.h>
+
#include <unistd.h>
#include "UniquePtr.h"
+#include "base/stl_util.h"
#include "base/unix_file/fd_file.h"
#include "dex_file-inl.h"
#include "mirror/art_field-inl.h"
@@ -1203,4 +1206,57 @@
sizeof(OatHeader::kOatMagic)) == 0);
}
+bool Exec(std::vector<std::string>& arg_vector, std::string* error_msg) {
+ const std::string command_line(Join(arg_vector, ' '));
+
+ CHECK_GE(arg_vector.size(), 1U) << command_line;
+
+ // Convert the args to char pointers.
+ const char* program = arg_vector[0].c_str();
+ std::vector<char*> args;
+ for (size_t i = 0; i < arg_vector.size(); ++i) {
+ const std::string& arg = arg_vector[i];
+ char* arg_str = const_cast<char*>(arg.c_str());
+ CHECK(arg_str != nullptr) << i;
+ args.push_back(arg_str);
+ }
+ args.push_back(NULL);
+
+ // fork and exec
+ pid_t pid = fork();
+ if (pid == 0) {
+ // no allocation allowed between fork and exec
+
+ // change process groups, so we don't get reaped by ProcessManager
+ setpgid(0, 0);
+
+ execv(program, &args[0]);
+
+ *error_msg = StringPrintf("Failed to execv(%s): %s", command_line.c_str(), strerror(errno));
+ return false;
+ } else {
+ if (pid == -1) {
+ *error_msg = StringPrintf("Failed to execv(%s) because fork failed: %s",
+ command_line.c_str(), strerror(errno));
+ return false;
+ }
+
+ // wait for subprocess to finish
+ int status;
+ pid_t got_pid = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0));
+ if (got_pid != pid) {
+ *error_msg = StringPrintf("Failed after fork for execv(%s) because waitpid failed: "
+ "wanted %d, got %d: %s",
+ command_line.c_str(), pid, got_pid, strerror(errno));
+ return false;
+ }
+ if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
+ *error_msg = StringPrintf("Failed execv(%s) because non-0 exit status",
+ command_line.c_str());
+ return false;
+ }
+ }
+ return true;
+}
+
} // namespace art
diff --git a/runtime/utils.h b/runtime/utils.h
index e2d8966..0bb06de 100644
--- a/runtime/utils.h
+++ b/runtime/utils.h
@@ -396,6 +396,9 @@
bool IsDexMagic(uint32_t magic);
bool IsOatMagic(uint32_t magic);
+// Wrapper on fork/execv to run a command in a subprocess.
+bool Exec(std::vector<std::string>& arg_vector, std::string* error_msg);
+
class VoidFunctor {
public:
template <typename A>
diff --git a/runtime/utils_test.cc b/runtime/utils_test.cc
index b43177b..0d237e2 100644
--- a/runtime/utils_test.cc
+++ b/runtime/utils_test.cc
@@ -99,7 +99,7 @@
SirtRef<mirror::ShortArray> a(soa.Self(), mirror::ShortArray::Alloc(soa.Self(), 2));
EXPECT_EQ("short[]", PrettyTypeOf(a.get()));
- mirror::Class* c = class_linker_->FindSystemClass("[Ljava/lang/String;");
+ mirror::Class* c = class_linker_->FindSystemClass(soa.Self(), "[Ljava/lang/String;");
ASSERT_TRUE(c != NULL);
mirror::Object* o = mirror::ObjectArray<mirror::String>::Alloc(soa.Self(), c, 0);
EXPECT_EQ("java.lang.String[]", PrettyTypeOf(o));
@@ -109,7 +109,7 @@
TEST_F(UtilsTest, PrettyClass) {
ScopedObjectAccess soa(Thread::Current());
EXPECT_EQ("null", PrettyClass(NULL));
- mirror::Class* c = class_linker_->FindSystemClass("[Ljava/lang/String;");
+ mirror::Class* c = class_linker_->FindSystemClass(soa.Self(), "[Ljava/lang/String;");
ASSERT_TRUE(c != NULL);
mirror::Object* o = mirror::ObjectArray<mirror::String>::Alloc(soa.Self(), c, 0);
EXPECT_EQ("java.lang.Class<java.lang.String[]>", PrettyClass(o->GetClass()));
@@ -118,7 +118,7 @@
TEST_F(UtilsTest, PrettyClassAndClassLoader) {
ScopedObjectAccess soa(Thread::Current());
EXPECT_EQ("null", PrettyClassAndClassLoader(NULL));
- mirror::Class* c = class_linker_->FindSystemClass("[Ljava/lang/String;");
+ mirror::Class* c = class_linker_->FindSystemClass(soa.Self(), "[Ljava/lang/String;");
ASSERT_TRUE(c != NULL);
mirror::Object* o = mirror::ObjectArray<mirror::String>::Alloc(soa.Self(), c, 0);
EXPECT_EQ("java.lang.Class<java.lang.String[],null>", PrettyClassAndClassLoader(o->GetClass()));
@@ -128,7 +128,8 @@
ScopedObjectAccess soa(Thread::Current());
EXPECT_EQ("null", PrettyField(NULL));
- mirror::Class* java_lang_String = class_linker_->FindSystemClass("Ljava/lang/String;");
+ mirror::Class* java_lang_String = class_linker_->FindSystemClass(soa.Self(),
+ "Ljava/lang/String;");
mirror::ArtField* f;
f = java_lang_String->FindDeclaredInstanceField("count", "I");
@@ -197,7 +198,7 @@
TEST_F(UtilsTest, JniShortName_JniLongName) {
ScopedObjectAccess soa(Thread::Current());
- mirror::Class* c = class_linker_->FindSystemClass("Ljava/lang/String;");
+ mirror::Class* c = class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/String;");
ASSERT_TRUE(c != NULL);
mirror::ArtMethod* m;
@@ -349,4 +350,26 @@
CheckGetDalvikCacheFilenameOrDie("/system/framework/boot.art", "system@framework@boot.art");
}
+TEST_F(UtilsTest, ExecSuccess) {
+ std::vector<std::string> command;
+ if (kIsTargetBuild) {
+ command.push_back("/system/bin/id");
+ } else {
+ command.push_back("/usr/bin/id");
+ }
+ std::string error_msg;
+ EXPECT_TRUE(Exec(command, &error_msg));
+ EXPECT_EQ(0U, error_msg.size()) << error_msg;
+}
+
+// TODO: Disabled due to hang tearing down CommonTest.
+// Renable after splitting into RuntimeTest and CompilerTest.
+TEST_F(UtilsTest, DISABLED_ExecError) {
+ std::vector<std::string> command;
+ command.push_back("bogus");
+ std::string error_msg;
+ EXPECT_FALSE(Exec(command, &error_msg));
+ EXPECT_NE(0U, error_msg.size());
+}
+
} // namespace art
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index ab943a6..ffa8b9e 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -3129,14 +3129,15 @@
this_class = actual_arg_type.GetClass();
} else {
const std::string& descriptor(actual_arg_type.GetDescriptor());
+ Thread* self = Thread::Current();
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- this_class = class_linker->FindClass(descriptor.c_str(), *class_loader_);
+ this_class = class_linker->FindClass(self, descriptor.c_str(), *class_loader_);
if (this_class == NULL) {
Thread* self = Thread::Current();
self->ClearException();
// Look for a system class
SirtRef<mirror::ClassLoader> null_class_loader(self, nullptr);
- this_class = class_linker->FindClass(descriptor.c_str(), null_class_loader);
+ this_class = class_linker->FindClass(self, descriptor.c_str(), null_class_loader);
}
}
if (this_class == NULL) {
@@ -3638,7 +3639,7 @@
// Returns the access field of a quick field access (iget/iput-quick) or NULL
// if it cannot be found.
mirror::ArtField* MethodVerifier::GetQuickFieldAccess(const Instruction* inst,
- RegisterLine* reg_line) {
+ RegisterLine* reg_line) {
DCHECK(inst->Opcode() == Instruction::IGET_QUICK ||
inst->Opcode() == Instruction::IGET_WIDE_QUICK ||
inst->Opcode() == Instruction::IGET_OBJECT_QUICK ||
@@ -3654,12 +3655,12 @@
const std::string& descriptor(object_type.GetDescriptor());
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Thread* self = Thread::Current();
- object_class = class_linker->FindClass(descriptor.c_str(), *class_loader_);
+ object_class = class_linker->FindClass(self, descriptor.c_str(), *class_loader_);
if (object_class == NULL) {
self->ClearException();
// Look for a system class
SirtRef<mirror::ClassLoader> null_class_loader(self, nullptr);
- object_class = class_linker->FindClass(descriptor.c_str(), null_class_loader);
+ object_class = class_linker->FindClass(self, descriptor.c_str(), null_class_loader);
}
}
if (object_class == NULL) {
diff --git a/runtime/verifier/method_verifier_test.cc b/runtime/verifier/method_verifier_test.cc
index a56abba..ffa2455 100644
--- a/runtime/verifier/method_verifier_test.cc
+++ b/runtime/verifier/method_verifier_test.cc
@@ -30,7 +30,7 @@
void VerifyClass(const std::string& descriptor)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
ASSERT_TRUE(descriptor != NULL);
- mirror::Class* klass = class_linker_->FindSystemClass(descriptor.c_str());
+ mirror::Class* klass = class_linker_->FindSystemClass(Thread::Current(), descriptor.c_str());
// Verify the class
std::string error_msg;
diff --git a/runtime/verifier/reg_type.cc b/runtime/verifier/reg_type.cc
index 630ef8a..63f0ff4 100644
--- a/runtime/verifier/reg_type.cc
+++ b/runtime/verifier/reg_type.cc
@@ -18,6 +18,7 @@
#include "base/casts.h"
+#include "class_linker-inl.h"
#include "dex_file-inl.h"
#include "mirror/class.h"
#include "mirror/class-inl.h"
@@ -928,11 +929,7 @@
}
mirror::Class* common_elem = ClassJoin(s_ct, t_ct);
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- Thread* self = Thread::Current();
- SirtRef<mirror::ClassLoader> class_loader(self, s->GetClassLoader());
- std::string descriptor("[");
- descriptor += ClassHelper(common_elem).GetDescriptor();
- mirror::Class* array_class = class_linker->FindClass(descriptor.c_str(), class_loader);
+ mirror::Class* array_class = class_linker->FindArrayClass(Thread::Current(), common_elem);
DCHECK(array_class != NULL);
return array_class;
} else {
diff --git a/runtime/verifier/reg_type_cache.cc b/runtime/verifier/reg_type_cache.cc
index 5e894ed..9dd57b8 100644
--- a/runtime/verifier/reg_type_cache.cc
+++ b/runtime/verifier/reg_type_cache.cc
@@ -17,6 +17,7 @@
#include "reg_type_cache-inl.h"
#include "base/casts.h"
+#include "class_linker-inl.h"
#include "dex_file-inl.h"
#include "mirror/class-inl.h"
#include "mirror/object-inl.h"
@@ -140,10 +141,11 @@
// Class was not found, must create new type.
// Try resolving class
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- SirtRef<mirror::ClassLoader> class_loader(Thread::Current(), loader);
+ Thread* self = Thread::Current();
+ SirtRef<mirror::ClassLoader> class_loader(self, loader);
mirror::Class* klass = NULL;
if (can_load_classes_) {
- klass = class_linker->FindClass(descriptor, class_loader);
+ klass = class_linker->FindClass(self, descriptor, class_loader);
} else {
klass = class_linker->LookupClass(descriptor, loader);
if (klass != NULL && !klass->IsLoaded()) {
@@ -277,7 +279,8 @@
mirror::Class* klass = NULL;
// Try loading the class from linker.
if (!descriptor.empty()) {
- klass = art::Runtime::Current()->GetClassLinker()->FindSystemClass(descriptor.c_str());
+ klass = art::Runtime::Current()->GetClassLinker()->FindSystemClass(Thread::Current(),
+ descriptor.c_str());
}
Type* entry = Type::CreateInstance(klass, descriptor, RegTypeCache::primitive_count_);
RegTypeCache::primitive_count_++;
diff --git a/runtime/vmap_table.h b/runtime/vmap_table.h
index abc50b9..2fbaebe 100644
--- a/runtime/vmap_table.h
+++ b/runtime/vmap_table.h
@@ -25,6 +25,10 @@
class VmapTable {
public:
+ // For efficient encoding of special values, entries are adjusted by 2.
+ static constexpr uint16_t kEntryAdjustment = 2u;
+ static constexpr uint16_t kAdjustedFpMarker = static_cast<uint16_t>(0xffffu + kEntryAdjustment);
+
explicit VmapTable(const uint8_t* table) : table_(table) {
}
@@ -33,11 +37,11 @@
const uint8_t* table = table_;
size_t size = DecodeUnsignedLeb128(&table);
CHECK_LT(n, size);
- uint16_t entry = DecodeUnsignedLeb128(&table);
+ uint16_t adjusted_entry = DecodeUnsignedLeb128(&table);
for (size_t i = 0; i < n; ++i) {
- entry = DecodeUnsignedLeb128(&table);
+ adjusted_entry = DecodeUnsignedLeb128(&table);
}
- return entry;
+ return adjusted_entry - kEntryAdjustment;
}
size_t Size() const {
@@ -58,16 +62,17 @@
bool is_float = (kind == kFloatVReg) || (kind == kDoubleLoVReg) || (kind == kDoubleHiVReg);
bool in_floats = false;
const uint8_t* table = table_;
+ uint16_t adjusted_vreg = vreg + kEntryAdjustment;
size_t end = DecodeUnsignedLeb128(&table);
for (size_t i = 0; i < end; ++i) {
// Stop if we find what we are are looking for.
- uint16_t entry = DecodeUnsignedLeb128(&table);
- if ((entry == vreg) && (in_floats == is_float)) {
+ uint16_t adjusted_entry = DecodeUnsignedLeb128(&table);
+ if ((adjusted_entry == adjusted_vreg) && (in_floats == is_float)) {
*vmap_offset = i;
return true;
}
// 0xffff is the marker for LR (return PC on x86), following it are spilled float registers.
- if (entry == 0xffff) {
+ if (adjusted_entry == kAdjustedFpMarker) {
in_floats = true;
}
}
@@ -89,7 +94,7 @@
if (UNLIKELY(is_float)) {
const uint8_t* table = table_;
DecodeUnsignedLeb128(&table); // Skip size.
- while (DecodeUnsignedLeb128(&table) != 0xffff) {
+ while (DecodeUnsignedLeb128(&table) != kAdjustedFpMarker) {
matches++;
}
matches++;