diff options
| -rw-r--r-- | Android.mk | 12 | ||||
| -rw-r--r-- | build/Android.executable.mk | 3 | ||||
| -rw-r--r-- | compiler/common_compiler_test.h | 2 | ||||
| -rw-r--r-- | compiler/dex/frontend.cc | 10 | ||||
| -rw-r--r-- | compiler/dex/mir_analysis.cc | 2 | ||||
| -rw-r--r-- | compiler/dex/quick/arm/target_arm.cc | 7 | ||||
| -rw-r--r-- | compiler/driver/compiler_driver.cc | 7 | ||||
| -rw-r--r-- | compiler/driver/compiler_options.h | 12 | ||||
| -rw-r--r-- | dex2oat/Android.mk | 4 | ||||
| -rw-r--r-- | dex2oat/dex2oat.cc | 23 | ||||
| -rw-r--r-- | runtime/Android.mk | 6 | ||||
| -rw-r--r-- | runtime/class_linker.cc | 38 | ||||
| -rw-r--r-- | runtime/gc/accounting/space_bitmap-inl.h | 125 | ||||
| -rw-r--r-- | runtime/gc/accounting/space_bitmap.cc | 27 | ||||
| -rw-r--r-- | runtime/gc/accounting/space_bitmap.h | 12 | ||||
| -rw-r--r-- | runtime/gc/space/image_space.cc | 32 | ||||
| -rw-r--r-- | runtime/instruction_set.cc | 32 | ||||
| -rw-r--r-- | runtime/instruction_set.h | 20 | ||||
| -rw-r--r-- | runtime/oat.cc | 2 | ||||
| -rw-r--r-- | runtime/parsed_options.cc | 13 | ||||
| -rw-r--r-- | runtime/parsed_options.h | 1 | ||||
| -rw-r--r-- | runtime/runtime.cc | 59 | ||||
| -rw-r--r-- | runtime/runtime.h | 25 |
23 files changed, 287 insertions, 187 deletions
diff --git a/Android.mk b/Android.mk index 5325abd82d..6139cb9ae2 100644 --- a/Android.mk +++ b/Android.mk @@ -435,6 +435,18 @@ use-art-interpret-only: adb shell setprop persist.sys.dalvik.vm.lib.1 libart.so adb shell start +.PHONY: use-art-verify-none +use-art-verify-none: + adb root && sleep 3 + adb shell stop + adb shell rm $(ART_DALVIK_CACHE_DIR)/*.dex + adb shell rm $(ART_DALVIK_CACHE_DIR)/*.oat + adb shell rm $(ART_DALVIK_CACHE_DIR)/*.art + adb shell setprop dalvik.vm.dex2oat-flags "--compiler-filter=verify-none" + adb shell setprop dalvik.vm.image-dex2oat-flags "--compiler-filter=verify-none" + adb shell setprop persist.sys.dalvik.vm.lib.1 libart.so + adb shell start + ######################################################################## endif # !art_dont_bother diff --git a/build/Android.executable.mk b/build/Android.executable.mk index 88ca47eee0..27d687c529 100644 --- a/build/Android.executable.mk +++ b/build/Android.executable.mk @@ -30,6 +30,7 @@ endif # $(4): extra include directories # $(5): target or host # $(6): ndebug or debug +# $(7): value for LOCAL_MULTILIB (empty means default) define build-art-executable ifneq ($(5),target) ifneq ($(5),host) @@ -48,6 +49,7 @@ define build-art-executable art_c_includes := $(4) art_target_or_host := $(5) art_ndebug_or_debug := $(6) + art_multilib := $(7) include $(CLEAR_VARS) ifeq ($$(art_target_or_host),target) @@ -98,6 +100,7 @@ define build-art-executable ifeq ($$(art_target_or_host),target) LOCAL_MODULE_TARGET_ARCH := $(ART_SUPPORTED_ARCH) + LOCAL_MULTILIB := $$(art_multilib) endif ifeq ($$(art_target_or_host),target) diff --git a/compiler/common_compiler_test.h b/compiler/common_compiler_test.h index 6aa85d40de..9a21da070a 100644 --- a/compiler/common_compiler_test.h +++ b/compiler/common_compiler_test.h @@ -291,7 +291,7 @@ class CommonCompilerTest : public CommonRuntimeTest { // Take the default set of instruction features from the build. InstructionSetFeatures instruction_set_features = - ParseFeatureList(STRINGIFY(ART_DEFAULT_INSTRUCTION_SET_FEATURES)); + ParseFeatureList(Runtime::GetDefaultInstructionSetFeatures()); #if defined(__arm__) instruction_set = kThumb2; diff --git a/compiler/dex/frontend.cc b/compiler/dex/frontend.cc index 3f122de623..cc616f6caa 100644 --- a/compiler/dex/frontend.cc +++ b/compiler/dex/frontend.cc @@ -145,9 +145,7 @@ static CompiledMethod* CompileMethod(CompilerDriver& driver, return NULL; } - const CompilerOptions& compiler_options = driver.GetCompilerOptions(); - CompilerOptions::CompilerFilter compiler_filter = compiler_options.GetCompilerFilter(); - if (compiler_filter == CompilerOptions::kInterpretOnly) { + if (!driver.GetCompilerOptions().IsCompilationEnabled()) { return nullptr; } @@ -230,10 +228,8 @@ static CompiledMethod* CompileMethod(CompilerDriver& driver, class_loader, dex_file); cu.NewTimingSplit("MIROpt:CheckFilters"); - if (compiler_filter != CompilerOptions::kInterpretOnly) { - if (cu.mir_graph->SkipCompilation()) { - return NULL; - } + if (cu.mir_graph->SkipCompilation()) { + return NULL; } /* Create the pass driver and launch it */ diff --git a/compiler/dex/mir_analysis.cc b/compiler/dex/mir_analysis.cc index b96c40de7f..200795e535 100644 --- a/compiler/dex/mir_analysis.cc +++ b/compiler/dex/mir_analysis.cc @@ -1013,7 +1013,7 @@ bool MIRGraph::SkipCompilation() { return true; } - if (compiler_filter == CompilerOptions::kInterpretOnly || compiler_filter == CompilerOptions::kProfiled) { + if (!compiler_options.IsCompilationEnabled() || compiler_filter == CompilerOptions::kProfiled) { return true; } diff --git a/compiler/dex/quick/arm/target_arm.cc b/compiler/dex/quick/arm/target_arm.cc index 5ebe0a37c4..5e9a8b0b5c 100644 --- a/compiler/dex/quick/arm/target_arm.cc +++ b/compiler/dex/quick/arm/target_arm.cc @@ -559,10 +559,13 @@ void ArmMir2Lir::CompilerInitializeRegAlloc() { (arena_->Alloc(num_fp_regs * sizeof(*reg_pool_->FPRegs), kArenaAllocRegAlloc)); CompilerInitPool(reg_pool_->core_regs, core_regs, reg_pool_->num_core_regs); CompilerInitPool(reg_pool_->FPRegs, FpRegs, reg_pool_->num_fp_regs); + // Keep special registers from being allocated + // Don't reserve the r4 if we are doing implicit suspend checks. + bool no_suspend = NO_SUSPEND || !Runtime::Current()->ExplicitSuspendChecks(); for (int i = 0; i < num_reserved; i++) { - if (NO_SUSPEND && (ReservedRegs[i] == rARM_SUSPEND)) { - // To measure cost of suspend check + if (no_suspend && (ReservedRegs[i] == rARM_SUSPEND)) { + // Don't reserve the suspend register. continue; } MarkInUse(ReservedRegs[i]); diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc index c10dd84226..a120d054c0 100644 --- a/compiler/driver/compiler_driver.cc +++ b/compiler/driver/compiler_driver.cc @@ -598,6 +598,11 @@ void CompilerDriver::PreCompile(jobject class_loader, const std::vector<const De ThreadPool* thread_pool, TimingLogger* timings) { LoadImageClasses(timings); + if (!compiler_options_->IsVerificationEnabled()) { + VLOG(compiler) << "Verify none mode specified, skipping pre-compilation"; + return; + } + Resolve(class_loader, dex_files, thread_pool, timings); Verify(class_loader, dex_files, thread_pool, timings); @@ -1872,7 +1877,7 @@ void CompilerDriver::CompileMethod(const DexFile::CodeItem* code_item, uint32_t if ((access_flags & kAccNative) != 0) { // Are we interpreting only and have support for generic JNI down calls? - if ((compiler_options_->GetCompilerFilter() == CompilerOptions::kInterpretOnly) && + if (!compiler_options_->IsCompilationEnabled() && (instruction_set_ == kX86_64 || instruction_set_ == kArm64)) { // Leaving this empty will trigger the generic JNI version } else { diff --git a/compiler/driver/compiler_options.h b/compiler/driver/compiler_options.h index 0cca1e9705..20c6bc8e4e 100644 --- a/compiler/driver/compiler_options.h +++ b/compiler/driver/compiler_options.h @@ -22,7 +22,8 @@ namespace art { class CompilerOptions { public: enum CompilerFilter { - kInterpretOnly, // Compile nothing. + kVerifyNone, // Skip verification and compile nothing except JNI stubs. + kInterpretOnly, // Compile nothing except JNI stubs. kProfiled, // Compile based on profile. kSpace, // Maximize space savings. kBalanced, // Try to get the best performance return on compilation investment. @@ -86,6 +87,15 @@ class CompilerOptions { compiler_filter_ = compiler_filter; } + bool IsCompilationEnabled() const { + return ((compiler_filter_ != CompilerOptions::kVerifyNone) && + (compiler_filter_ != CompilerOptions::kInterpretOnly)); + } + + bool IsVerificationEnabled() const { + return (compiler_filter_ != CompilerOptions::kVerifyNone); + } + size_t GetHugeMethodThreshold() const { return huge_method_threshold_; } diff --git a/dex2oat/Android.mk b/dex2oat/Android.mk index 6cd0538c43..038f0a77fd 100644 --- a/dex2oat/Android.mk +++ b/dex2oat/Android.mk @@ -22,10 +22,10 @@ DEX2OAT_SRC_FILES := \ dex2oat.cc ifeq ($(ART_BUILD_TARGET_NDEBUG),true) - $(eval $(call build-art-executable,dex2oat,$(DEX2OAT_SRC_FILES),libcutils libart-compiler,art/compiler,target,ndebug)) + $(eval $(call build-art-executable,dex2oat,$(DEX2OAT_SRC_FILES),libcutils libart-compiler,art/compiler,target,ndebug,32)) endif ifeq ($(ART_BUILD_TARGET_DEBUG),true) - $(eval $(call build-art-executable,dex2oat,$(DEX2OAT_SRC_FILES),libcutils libartd-compiler,art/compiler,target,debug)) + $(eval $(call build-art-executable,dex2oat,$(DEX2OAT_SRC_FILES),libcutils libartd-compiler,art/compiler,target,debug,32)) endif ifeq ($(WITH_HOST_DALVIK),true) diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc index 72effded06..f665f5c767 100644 --- a/dex2oat/dex2oat.cc +++ b/dex2oat/dex2oat.cc @@ -153,8 +153,8 @@ static void Usage(const char* fmt, ...) { UsageError(" Example: --compiler-backend=Portable"); UsageError(" Default: Quick"); UsageError(""); - UsageError(" --compiler-filter=(interpret-only|space|balanced|speed|everything): select"); - UsageError(" compiler filter."); + UsageError(" --compiler-filter=(verify-none|interpret-only|space|balanced|speed|everything):"); + UsageError(" select compiler filter."); UsageError(" Example: --compiler-filter=everything"); #if ART_SMALL_MODE UsageError(" Default: interpret-only"); @@ -189,7 +189,8 @@ static void Usage(const char* fmt, ...) { 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(" and the filter is not interpret-only or verify-none, overrides the"); + UsageError(" filter to use speed"); UsageError(" Example: --num-dex-method=%d", CompilerOptions::kDefaultNumDexMethodsThreshold); UsageError(" Default: %d", CompilerOptions::kDefaultNumDexMethodsThreshold); UsageError(""); @@ -201,8 +202,8 @@ static void Usage(const char* fmt, ...) { UsageError(" such as initial heap size, maximum heap size, and verbose output."); UsageError(" Use a separate --runtime-arg switch for each argument."); UsageError(" Example: --runtime-arg -Xms256m"); - UsageError(""); - UsageError(" --profile-file=<filename>: specify profiler output file to use for compilation."); + UsageError(""); + UsageError(" --profile-file=<filename>: specify profiler output file to use for compilation."); UsageError(""); UsageError(" --print-pass-names: print a list of pass names"); UsageError(""); @@ -740,7 +741,7 @@ static int dex2oat(int argc, char** argv) { // Take the default set of instruction features from the build. InstructionSetFeatures instruction_set_features = - ParseFeatureList(STRINGIFY(ART_DEFAULT_INSTRUCTION_SET_FEATURES)); + ParseFeatureList(Runtime::GetDefaultInstructionSetFeatures()); #if defined(__arm__) InstructionSet instruction_set = kThumb2; @@ -1037,7 +1038,9 @@ static int dex2oat(int argc, char** argv) { } CHECK(compiler_filter_string != nullptr); CompilerOptions::CompilerFilter compiler_filter = CompilerOptions::kDefaultCompilerFilter; - if (strcmp(compiler_filter_string, "interpret-only") == 0) { + if (strcmp(compiler_filter_string, "verify-none") == 0) { + compiler_filter = CompilerOptions::kVerifyNone; + } else if (strcmp(compiler_filter_string, "interpret-only") == 0) { compiler_filter = CompilerOptions::kInterpretOnly; } else if (strcmp(compiler_filter_string, "space") == 0) { compiler_filter = CompilerOptions::kSpace; @@ -1208,10 +1211,10 @@ static int dex2oat(int argc, char** argv) { } /* - * 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 we're not in interpret-only or verify-none mode, go ahead and compile small applications. + * Don't bother to check if we're doing the image. */ - if (!image && (compiler_options.GetCompilerFilter() != CompilerOptions::kInterpretOnly)) { + if (!image && compiler_options.IsCompilationEnabled()) { size_t num_methods = 0; for (size_t i = 0; i != dex_files.size(); ++i) { const DexFile* dex_file = dex_files[i]; diff --git a/runtime/Android.mk b/runtime/Android.mk index 697d1a327e..cf7f895ef3 100644 --- a/runtime/Android.mk +++ b/runtime/Android.mk @@ -73,6 +73,7 @@ LIBART_COMMON_SRC_FILES := \ hprof/hprof.cc \ image.cc \ indirect_reference_table.cc \ + instruction_set.cc \ instrumentation.cc \ intern_table.cc \ interpreter/interpreter.cc \ @@ -436,6 +437,11 @@ $$(ENUM_OPERATOR_OUT_GEN): $$(GENERATED_SRC_DIR)/%_operator_out.cc : $(LOCAL_PAT endif ifeq ($$(art_target_or_host),target) + ifneq ($$(art_ndebug_or_debug),debug) + # Leave the symbols in the shared library so that stack unwinders can + # produce meaningful name resolution. + LOCAL_STRIP_MODULE := keep_symbols + endif include $(BUILD_SHARED_LIBRARY) else # host include $(BUILD_HOST_SHARED_LIBRARY) diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 3957493947..6c5406ec1b 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -567,40 +567,16 @@ bool ClassLinker::GenerateOatFile(const char* dex_filename, argv.push_back("--runtime-arg"); argv.push_back(Runtime::Current()->GetClassPathString()); - argv.push_back("--runtime-arg"); - std::string checkstr = "-implicit-checks"; - - int nchecks = 0; - char checksep = ':'; - - if (!Runtime::Current()->ExplicitNullChecks()) { - checkstr += checksep; - checksep = ','; - checkstr += "null"; - ++nchecks; - } - if (!Runtime::Current()->ExplicitSuspendChecks()) { - checkstr += checksep; - checksep = ','; - checkstr += "suspend"; - ++nchecks; - } + Runtime::Current()->AddCurrentRuntimeFeaturesAsDex2OatArguments(&argv); - if (!Runtime::Current()->ExplicitStackOverflowChecks()) { - checkstr += checksep; - checksep = ','; - checkstr += "stack"; - ++nchecks; + if (!Runtime::Current()->IsVerificationEnabled()) { + argv.push_back("--compiler-filter=verify-none"); } - if (nchecks == 0) { - checkstr += ":none"; - } - argv.push_back(checkstr); - if (!kIsTargetBuild) { argv.push_back("--host"); } + argv.push_back(boot_image_option); argv.push_back(dex_file_option); argv.push_back(oat_fd_option); @@ -2561,6 +2537,12 @@ void ClassLinker::VerifyClass(const SirtRef<mirror::Class>& klass) { klass->SetStatus(mirror::Class::kStatusVerifyingAtRuntime, self); } + // Skip verification if disabled. + if (!Runtime::Current()->IsVerificationEnabled()) { + klass->SetStatus(mirror::Class::kStatusVerified, self); + return; + } + // Verify super class. SirtRef<mirror::Class> super(self, klass->GetSuperClass()); if (super.get() != NULL) { diff --git a/runtime/gc/accounting/space_bitmap-inl.h b/runtime/gc/accounting/space_bitmap-inl.h index d6d1b3e8aa..0fbd27c14b 100644 --- a/runtime/gc/accounting/space_bitmap-inl.h +++ b/runtime/gc/accounting/space_bitmap-inl.h @@ -29,10 +29,10 @@ inline bool SpaceBitmap::AtomicTestAndSet(const mirror::Object* obj) { DCHECK_GE(addr, heap_begin_); const uintptr_t offset = addr - heap_begin_; const size_t index = OffsetToIndex(offset); - const word mask = OffsetToMask(offset); - word* const address = &bitmap_begin_[index]; + const uword mask = OffsetToMask(offset); + uword* const address = &bitmap_begin_[index]; DCHECK_LT(index, bitmap_size_ / kWordSize) << " bitmap_size_ = " << bitmap_size_; - word old_word; + uword old_word; do { old_word = *address; // Fast path: The bit is already set. @@ -58,74 +58,79 @@ template <typename Visitor> void SpaceBitmap::VisitMarkedRange(uintptr_t visit_begin, uintptr_t visit_end, const Visitor& visitor) const { DCHECK_LT(visit_begin, visit_end); -#ifdef __LP64__ - // TODO: make the optimized code below work in the 64bit case. - for (uintptr_t i = visit_begin; i < visit_end; i += kAlignment) { - mirror::Object* obj = reinterpret_cast<mirror::Object*>(i); - if (Test(obj)) { - visitor(obj); - } - } -#else - const size_t bit_index_start = (visit_begin - heap_begin_) / kAlignment; - const size_t bit_index_end = (visit_end - heap_begin_ - 1) / kAlignment; + DCHECK_LE(heap_begin_, visit_begin); + DCHECK_LE(visit_end, HeapLimit()); - size_t word_start = bit_index_start / kBitsPerWord; - size_t word_end = bit_index_end / kBitsPerWord; - DCHECK_LT(word_end * kWordSize, Size()); + const uintptr_t offset_start = visit_begin - heap_begin_; + const uintptr_t offset_end = visit_end - heap_begin_; - // Trim off left_bits of left bits. - size_t edge_word = bitmap_begin_[word_start]; + const uintptr_t index_start = OffsetToIndex(offset_start); + const uintptr_t index_end = OffsetToIndex(offset_end); - // Handle bits on the left first as a special case - size_t left_bits = bit_index_start & (kBitsPerWord - 1); - if (left_bits != 0) { - edge_word &= (1 << (kBitsPerWord - left_bits)) - 1; - } + const size_t bit_start = (offset_start / kAlignment) % kBitsPerWord; + const size_t bit_end = (offset_end / kAlignment) % kBitsPerWord; - // If word_start == word_end then handle this case at the same place we handle the right edge. - if (edge_word != 0 && word_start < word_end) { - uintptr_t ptr_base = IndexToOffset(word_start) + heap_begin_; - do { - const size_t shift = CLZ(edge_word); - mirror::Object* obj = reinterpret_cast<mirror::Object*>(ptr_base + shift * kAlignment); - visitor(obj); - edge_word ^= static_cast<size_t>(kWordHighBitMask) >> shift; - } while (edge_word != 0); - } - word_start++; + // Index(begin) ... Index(end) + // [xxxxx???][........][????yyyy] + // ^ ^ + // | #---- Bit of visit_end + // #---- Bit of visit_begin + // + + // Left edge. + uword left_edge = bitmap_begin_[index_start]; + // Mark of lower bits that are not in range. + left_edge &= ~((static_cast<uword>(1) << bit_start) - 1); - for (size_t i = word_start; i < word_end; i++) { - size_t w = bitmap_begin_[i]; - if (w != 0) { - uintptr_t ptr_base = IndexToOffset(i) + heap_begin_; + // Right edge. Either unique, or left_edge. + uword right_edge; + + if (index_start < index_end) { + // Left edge != right edge. + + // Traverse left edge. + if (left_edge != 0) { + const uintptr_t ptr_base = IndexToOffset(index_start) + heap_begin_; do { - const size_t shift = CLZ(w); + const size_t shift = CTZ(left_edge); mirror::Object* obj = reinterpret_cast<mirror::Object*>(ptr_base + shift * kAlignment); visitor(obj); - w ^= static_cast<size_t>(kWordHighBitMask) >> shift; - } while (w != 0); + left_edge ^= (static_cast<uword>(1)) << shift; + } while (left_edge != 0); } - } - // Handle the right edge, and also the left edge if both edges are on the same word. - size_t right_bits = bit_index_end & (kBitsPerWord - 1); + // Traverse the middle, full part. + for (size_t i = index_start + 1; i < index_end; ++i) { + uword w = bitmap_begin_[i]; + if (w != 0) { + const uintptr_t ptr_base = IndexToOffset(i) + heap_begin_; + do { + const size_t shift = CTZ(w); + mirror::Object* obj = reinterpret_cast<mirror::Object*>(ptr_base + shift * kAlignment); + visitor(obj); + w ^= (static_cast<uword>(1)) << shift; + } while (w != 0); + } + } - // If word_start == word_end then we need to use the word which we removed the left bits. - if (word_start <= word_end) { - edge_word = bitmap_begin_[word_end]; + // Right edge is unique. + right_edge = bitmap_begin_[index_end]; + } else { + // Right edge = left edge. + right_edge = left_edge; } - // Bits that we trim off the right. - edge_word &= ~((static_cast<size_t>(kWordHighBitMask) >> right_bits) - 1); - uintptr_t ptr_base = IndexToOffset(word_end) + heap_begin_; - while (edge_word != 0) { - const size_t shift = CLZ(edge_word); - mirror::Object* obj = reinterpret_cast<mirror::Object*>(ptr_base + shift * kAlignment); - visitor(obj); - edge_word ^= static_cast<size_t>(kWordHighBitMask) >> shift; + // Right edge handling. + right_edge &= ((static_cast<uword>(1) << bit_end) - 1) | (static_cast<uword>(1) << bit_end); + if (right_edge != 0) { + const uintptr_t ptr_base = IndexToOffset(index_end) + heap_begin_; + do { + const size_t shift = CTZ(right_edge); + mirror::Object* obj = reinterpret_cast<mirror::Object*>(ptr_base + shift * kAlignment); + visitor(obj); + right_edge ^= (static_cast<uword>(1)) << shift; + } while (right_edge != 0); } -#endif } inline bool SpaceBitmap::Modify(const mirror::Object* obj, bool do_set) { @@ -133,10 +138,10 @@ inline bool SpaceBitmap::Modify(const mirror::Object* obj, bool do_set) { DCHECK_GE(addr, heap_begin_); const uintptr_t offset = addr - heap_begin_; const size_t index = OffsetToIndex(offset); - const word mask = OffsetToMask(offset); + const uword mask = OffsetToMask(offset); DCHECK_LT(index, bitmap_size_ / kWordSize) << " bitmap_size_ = " << bitmap_size_; - word* address = &bitmap_begin_[index]; - word old_word = *address; + uword* address = &bitmap_begin_[index]; + uword old_word = *address; if (do_set) { *address = old_word | mask; } else { diff --git a/runtime/gc/accounting/space_bitmap.cc b/runtime/gc/accounting/space_bitmap.cc index ad4ff1baff..1957c21058 100644 --- a/runtime/gc/accounting/space_bitmap.cc +++ b/runtime/gc/accounting/space_bitmap.cc @@ -53,7 +53,7 @@ void ObjectSet::Walk(ObjectCallback* callback, void* arg) { SpaceBitmap* SpaceBitmap::CreateFromMemMap(const std::string& name, MemMap* mem_map, byte* heap_begin, size_t heap_capacity) { CHECK(mem_map != nullptr); - word* bitmap_begin = reinterpret_cast<word*>(mem_map->Begin()); + uword* bitmap_begin = reinterpret_cast<uword*>(mem_map->Begin()); size_t bitmap_size = OffsetToIndex(RoundUp(heap_capacity, kAlignment * kBitsPerWord)) * kWordSize; return new SpaceBitmap(name, mem_map, bitmap_begin, bitmap_size, heap_begin); } @@ -107,16 +107,16 @@ void SpaceBitmap::Walk(ObjectCallback* callback, void* arg) { CHECK(callback != NULL); uintptr_t end = OffsetToIndex(HeapLimit() - heap_begin_ - 1); - word* bitmap_begin = bitmap_begin_; + uword* bitmap_begin = bitmap_begin_; for (uintptr_t i = 0; i <= end; ++i) { - word w = bitmap_begin[i]; + uword w = bitmap_begin[i]; if (w != 0) { uintptr_t ptr_base = IndexToOffset(i) + heap_begin_; do { - const size_t shift = CLZ(w); + const size_t shift = CTZ(w); mirror::Object* obj = reinterpret_cast<mirror::Object*>(ptr_base + shift * kAlignment); (*callback)(obj, arg); - w ^= static_cast<size_t>(kWordHighBitMask) >> shift; + w ^= (static_cast<uword>(1)) << shift; } while (w != 0); } } @@ -150,15 +150,15 @@ void SpaceBitmap::SweepWalk(const SpaceBitmap& live_bitmap, size_t start = OffsetToIndex(sweep_begin - live_bitmap.heap_begin_); size_t end = OffsetToIndex(sweep_end - live_bitmap.heap_begin_ - 1); CHECK_LT(end, live_bitmap.Size() / kWordSize); - word* live = live_bitmap.bitmap_begin_; - word* mark = mark_bitmap.bitmap_begin_; + uword* live = live_bitmap.bitmap_begin_; + uword* mark = mark_bitmap.bitmap_begin_; for (size_t i = start; i <= end; i++) { - word garbage = live[i] & ~mark[i]; + uword garbage = live[i] & ~mark[i]; if (UNLIKELY(garbage != 0)) { uintptr_t ptr_base = IndexToOffset(i) + live_bitmap.heap_begin_; do { - const size_t shift = CLZ(garbage); - garbage ^= static_cast<size_t>(kWordHighBitMask) >> shift; + const size_t shift = CTZ(garbage); + garbage ^= (static_cast<uword>(1)) << shift; *pb++ = reinterpret_cast<mirror::Object*>(ptr_base + shift * kAlignment); } while (garbage != 0); // Make sure that there are always enough slots available for an @@ -254,14 +254,15 @@ void SpaceBitmap::InOrderWalk(ObjectCallback* callback, void* arg) { CHECK(callback != NULL); uintptr_t end = Size() / kWordSize; for (uintptr_t i = 0; i < end; ++i) { - word w = bitmap_begin_[i]; + // Need uint for unsigned shift. + uword w = bitmap_begin_[i]; if (UNLIKELY(w != 0)) { uintptr_t ptr_base = IndexToOffset(i) + heap_begin_; while (w != 0) { - const size_t shift = CLZ(w); + const size_t shift = CTZ(w); mirror::Object* obj = reinterpret_cast<mirror::Object*>(ptr_base + shift * kAlignment); WalkFieldsInOrder(visited.get(), callback, obj, arg); - w ^= static_cast<size_t>(kWordHighBitMask) >> shift; + w ^= (static_cast<uword>(1)) << shift; } } } diff --git a/runtime/gc/accounting/space_bitmap.h b/runtime/gc/accounting/space_bitmap.h index 5fd2bce8af..aa24b0324c 100644 --- a/runtime/gc/accounting/space_bitmap.h +++ b/runtime/gc/accounting/space_bitmap.h @@ -70,9 +70,9 @@ class SpaceBitmap { return static_cast<uintptr_t>(index * kAlignment * kBitsPerWord); } - // Pack the bits in backwards so they come out in address order when using CLZ. - static word OffsetToMask(uintptr_t offset) { - return static_cast<uintptr_t>(kWordHighBitMask) >> ((offset / kAlignment) % kBitsPerWord); + // Bits are packed in the obvious way. + static uword OffsetToMask(uintptr_t offset) { + return (static_cast<size_t>(1)) << ((offset / kAlignment) % kBitsPerWord); } inline bool Set(const mirror::Object* obj) { @@ -140,7 +140,7 @@ class SpaceBitmap { void CopyFrom(SpaceBitmap* source_bitmap); // Starting address of our internal storage. - word* Begin() { + uword* Begin() { return bitmap_begin_; } @@ -181,7 +181,7 @@ class SpaceBitmap { private: // TODO: heap_end_ is initialized so that the heap bitmap is empty, this doesn't require the -1, // however, we document that this is expected on heap_end_ - SpaceBitmap(const std::string& name, MemMap* mem_map, word* bitmap_begin, size_t bitmap_size, + SpaceBitmap(const std::string& name, MemMap* mem_map, uword* bitmap_begin, size_t bitmap_size, const void* heap_begin) : mem_map_(mem_map), bitmap_begin_(bitmap_begin), bitmap_size_(bitmap_size), heap_begin_(reinterpret_cast<uintptr_t>(heap_begin)), @@ -193,7 +193,7 @@ class SpaceBitmap { UniquePtr<MemMap> mem_map_; // This bitmap itself, word sized for efficiency in scanning. - word* const bitmap_begin_; + uword* const bitmap_begin_; // Size of this bitmap. size_t bitmap_size_; diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc index 9a2815a1df..faa539ff1d 100644 --- a/runtime/gc/space/image_space.cc +++ b/runtime/gc/space/image_space.cc @@ -67,36 +67,6 @@ static bool GenerateImage(const std::string& image_file_name, std::string* error arg_vector.push_back("--runtime-arg"); arg_vector.push_back("-Xmx64m"); - arg_vector.push_back("--runtime-arg"); - std::string checkstr = "-implicit-checks"; - int nchecks = 0; - char checksep = ':'; - - if (!Runtime::Current()->ExplicitNullChecks()) { - checkstr += checksep; - checksep = ','; - checkstr += "null"; - ++nchecks; - } - if (!Runtime::Current()->ExplicitSuspendChecks()) { - checkstr += checksep; - checksep = ','; - checkstr += "suspend"; - ++nchecks; - } - - if (!Runtime::Current()->ExplicitStackOverflowChecks()) { - checkstr += checksep; - checksep = ','; - checkstr += "stack"; - ++nchecks; - } - - if (nchecks == 0) { - checkstr += ":none"; - } - - arg_vector.push_back(checkstr); for (size_t i = 0; i < boot_class_path.size(); i++) { arg_vector.push_back(std::string("--dex-file=") + boot_class_path[i]); @@ -108,6 +78,8 @@ static bool GenerateImage(const std::string& image_file_name, std::string* error oat_file_option_string += "oat"; arg_vector.push_back(oat_file_option_string); + Runtime::Current()->AddCurrentRuntimeFeaturesAsDex2OatArguments(&arg_vector); + arg_vector.push_back(StringPrintf("--base=0x%x", ART_BASE_ADDRESS)); if (kIsTargetBuild) { diff --git a/runtime/instruction_set.cc b/runtime/instruction_set.cc new file mode 100644 index 0000000000..c96462915b --- /dev/null +++ b/runtime/instruction_set.cc @@ -0,0 +1,32 @@ +/* + * 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. + */ + +#include "instruction_set.h" + +namespace art { + +std::string InstructionSetFeatures::GetFeatureString() const { + std::string result; + if ((mask_ & kHwDiv) != 0) { + result += "div"; + } + if (result.size() == 0) { + result = "none"; + } + return result; +} + +} // namespace art diff --git a/runtime/instruction_set.h b/runtime/instruction_set.h index cbc991273d..c5a4ec8eb6 100644 --- a/runtime/instruction_set.h +++ b/runtime/instruction_set.h @@ -33,6 +33,7 @@ enum InstructionSet { kX86_64, kMips }; +std::ostream& operator<<(std::ostream& os, const InstructionSet& rhs); enum InstructionFeatures { kHwDiv = 1 // Supports hardware divide. @@ -44,6 +45,8 @@ class PACKED(4) InstructionSetFeatures { InstructionSetFeatures() : mask_(0) {} explicit InstructionSetFeatures(uint32_t mask) : mask_(mask) {} + static InstructionSetFeatures GuessInstructionSetFeatures(); + bool HasDivideInstruction() const { return (mask_ & kHwDiv) != 0; } @@ -52,20 +55,7 @@ class PACKED(4) InstructionSetFeatures { mask_ = (mask_ & ~kHwDiv) | (v ? kHwDiv : 0); } - std::string GetFeatureString() const { - std::string result; - if ((mask_ & kHwDiv) != 0) { - result += "div"; - } - if (result.size() == 0) { - result = "none"; - } - return result; - } - - uint32_t get_mask() const { - return mask_; - } + std::string GetFeatureString() const; // Other features in here. @@ -81,8 +71,6 @@ class PACKED(4) InstructionSetFeatures { uint32_t mask_; }; -std::ostream& operator<<(std::ostream& os, const InstructionSet& rhs); - } // namespace art #endif // ART_RUNTIME_INSTRUCTION_SET_H_ diff --git a/runtime/oat.cc b/runtime/oat.cc index f9707899bb..246e090f22 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', '9', '\0' }; +const uint8_t OatHeader::kOatVersion[] = { '0', '2', '0', '\0' }; OatHeader::OatHeader() { memset(this, 0, sizeof(*this)); diff --git a/runtime/parsed_options.cc b/runtime/parsed_options.cc index e2086f1069..08a674fddb 100644 --- a/runtime/parsed_options.cc +++ b/runtime/parsed_options.cc @@ -196,6 +196,8 @@ bool ParsedOptions::Parse(const Runtime::Options& options, bool ignore_unrecogni profile_backoff_coefficient_ = 2.0; profile_clock_source_ = kDefaultProfilerClockSource; + verify_ = true; + // Default to explicit checks. Switch off with -implicit-checks:. // or setprop dalvik.vm.implicit_checks check1,check2,... #ifdef HAVE_ANDROID_OS @@ -569,6 +571,16 @@ bool ParsedOptions::Parse(const Runtime::Options& options, bool ignore_unrecogni return false; } image_compiler_options_.push_back(options[i].first); + } else if (StartsWith(option, "-Xverify:")) { + std::string verify_mode = option.substr(strlen("-Xverify:")); + if (verify_mode == "none") { + verify_ = false; + } else if (verify_mode == "remote" || verify_mode == "all") { + verify_ = true; + } else { + Usage("Unknown -Xverify option %s", verify_mode.c_str()); + return false; + } } else if (StartsWith(option, "-ea:") || StartsWith(option, "-da:") || StartsWith(option, "-enableassertions:") || @@ -578,7 +590,6 @@ bool ParsedOptions::Parse(const Runtime::Options& options, bool ignore_unrecogni (option == "-dsa") || (option == "-enablesystemassertions") || (option == "-disablesystemassertions") || - StartsWith(option, "-Xverify:") || (option == "-Xrs") || StartsWith(option, "-Xint:") || StartsWith(option, "-Xdexopt:") || diff --git a/runtime/parsed_options.h b/runtime/parsed_options.h index d6516a80ad..416bc78e61 100644 --- a/runtime/parsed_options.h +++ b/runtime/parsed_options.h @@ -80,6 +80,7 @@ class ParsedOptions { uint32_t profile_interval_us_; double profile_backoff_coefficient_; ProfilerClockSource profile_clock_source_; + bool verify_; static constexpr uint32_t kExplicitNullCheck = 1; static constexpr uint32_t kExplicitSuspendCheck = 2; diff --git a/runtime/runtime.cc b/runtime/runtime.cc index a830018936..1b3c996150 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc @@ -79,6 +79,8 @@ namespace art { static constexpr bool kEnableJavaStackTraceHandler = true; +const char* Runtime::kDefaultInstructionSetFeatures = + STRINGIFY(ART_DEFAULT_INSTRUCTION_SET_FEATURES); Runtime* Runtime::instance_ = NULL; Runtime::Runtime() @@ -130,7 +132,8 @@ Runtime::Runtime() preinitialization_transaction_(nullptr), null_pointer_handler_(nullptr), suspend_handler_(nullptr), - stack_overflow_handler_(nullptr) { + stack_overflow_handler_(nullptr), + verify_(false) { for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) { callee_save_methods_[i] = nullptr; } @@ -519,6 +522,7 @@ bool Runtime::Init(const Options& raw_options, bool ignore_unrecognized) { thread_list_ = new ThreadList; intern_table_ = new InternTable; + verify_ = options->verify_; if (options->interpreter_only_) { GetInstrumentation()->ForceInterpretOnly(); @@ -1216,6 +1220,59 @@ void Runtime::SetFaultMessage(const std::string& message) { fault_message_ = message; } +void Runtime::AddCurrentRuntimeFeaturesAsDex2OatArguments(std::vector<std::string>* argv) + const { + argv->push_back("--runtime-arg"); + std::string checkstr = "-implicit-checks"; + + int nchecks = 0; + char checksep = ':'; + + if (!ExplicitNullChecks()) { + checkstr += checksep; + checksep = ','; + checkstr += "null"; + ++nchecks; + } + if (!ExplicitSuspendChecks()) { + checkstr += checksep; + checksep = ','; + checkstr += "suspend"; + ++nchecks; + } + + if (!ExplicitStackOverflowChecks()) { + checkstr += checksep; + checksep = ','; + checkstr += "stack"; + ++nchecks; + } + + if (nchecks == 0) { + checkstr += ":none"; + } + argv->push_back(checkstr); + + // Make the dex2oat instruction set match that of the launching runtime. If we have multiple + // architecture support, dex2oat may be compiled as a different instruction-set than that + // currently being executed. +#if defined(__arm__) + argv->push_back("--instruction-set=arm"); +#elif defined(__aarch64__) + argv->push_back("--instruction-set=arm64"); +#elif defined(__i386__) + argv->push_back("--instruction-set=x86"); +#elif defined(__x86_64__) + argv->push_back("--instruction-set=x86_64"); +#elif defined(__mips__) + argv->push_back("--instruction-set=mips"); +#endif + + std::string features("--instruction-set-features="); + features += GetDefaultInstructionSetFeatures(); + argv->push_back(features); +} + void Runtime::UpdateProfilerState(int state) { LOG(DEBUG) << "Profiler state updated to " << state; } diff --git a/runtime/runtime.h b/runtime/runtime.h index ed60d4d8a3..7b3e04c930 100644 --- a/runtime/runtime.h +++ b/runtime/runtime.h @@ -407,6 +407,8 @@ class Runtime { return fault_message_; } + void AddCurrentRuntimeFeaturesAsDex2OatArguments(std::vector<std::string>* arg_vector) const; + bool ExplicitNullChecks() const { return null_pointer_handler_ == nullptr; } @@ -419,10 +421,18 @@ class Runtime { return stack_overflow_handler_ == nullptr; } + bool IsVerificationEnabled() const { + return verify_; + } + bool RunningOnValgrind() const { return running_on_valgrind_; } + static const char* GetDefaultInstructionSetFeatures() { + return kDefaultInstructionSetFeatures; + } + private: static void InitPlatformSignalHandlers(); @@ -439,15 +449,15 @@ class Runtime { void StartDaemonThreads(); void StartSignalCatcher(); - // NOTE: these must match the gc::ProcessState values as they come directly - // from the framework. - static constexpr int kProfileForground = 0; - static constexpr int kProfileBackgrouud = 1; - - // A pointer to the active runtime or NULL. static Runtime* instance_; + static const char* kDefaultInstructionSetFeatures; + + // NOTE: these must match the gc::ProcessState values as they come directly from the framework. + static constexpr int kProfileForground = 0; + static constexpr int kProfileBackgrouud = 1; + mirror::ArtMethod* callee_save_methods_[kLastCalleeSaveType]; mirror::Throwable* pre_allocated_OutOfMemoryError_; mirror::ArtMethod* resolution_method_; @@ -557,6 +567,9 @@ class Runtime { SuspensionHandler* suspend_handler_; StackOverflowHandler* stack_overflow_handler_; + // If false, verification is disabled. True by default. + bool verify_; + DISALLOW_COPY_AND_ASSIGN(Runtime); }; |