Merge "Use temp register in Unsafe Get/Put intrisics for displaced offset."
diff --git a/Android.mk b/Android.mk
index 5325abd..6139cb9 100644
--- a/Android.mk
+++ b/Android.mk
@@ -435,6 +435,18 @@
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 88ca47e..27d687c 100644
--- a/build/Android.executable.mk
+++ b/build/Android.executable.mk
@@ -30,6 +30,7 @@
# $(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 @@
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 @@
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 6aa85d4..9a21da0 100644
--- a/compiler/common_compiler_test.h
+++ b/compiler/common_compiler_test.h
@@ -291,7 +291,7 @@
// 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 3f122de..cc616f6 100644
--- a/compiler/dex/frontend.cc
+++ b/compiler/dex/frontend.cc
@@ -145,9 +145,7 @@
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 @@
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 b96c40d..200795e 100644
--- a/compiler/dex/mir_analysis.cc
+++ b/compiler/dex/mir_analysis.cc
@@ -1013,7 +1013,7 @@
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 5ebe0a3..5e9a8b0 100644
--- a/compiler/dex/quick/arm/target_arm.cc
+++ b/compiler/dex/quick/arm/target_arm.cc
@@ -559,10 +559,13 @@
(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 c10dd84..a120d05 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -598,6 +598,11 @@
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 @@
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 0cca1e9..20c6bc8 100644
--- a/compiler/driver/compiler_options.h
+++ b/compiler/driver/compiler_options.h
@@ -22,7 +22,8 @@
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 @@
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 6cd0538..038f0a7 100644
--- a/dex2oat/Android.mk
+++ b/dex2oat/Android.mk
@@ -22,10 +22,10 @@
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 72effde..f665f5c 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -153,8 +153,8 @@
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 @@
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 @@
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 @@
// 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 @@
}
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 @@
}
/*
- * 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 697d1a3..cf7f895 100644
--- a/runtime/Android.mk
+++ b/runtime/Android.mk
@@ -73,6 +73,7 @@
hprof/hprof.cc \
image.cc \
indirect_reference_table.cc \
+ instruction_set.cc \
instrumentation.cc \
intern_table.cc \
interpreter/interpreter.cc \
@@ -436,6 +437,11 @@
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 3957493..6c5406e 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -567,40 +567,16 @@
argv.push_back("--runtime-arg");
argv.push_back(Runtime::Current()->GetClassPathString());
- argv.push_back("--runtime-arg");
- std::string checkstr = "-implicit-checks";
+ Runtime::Current()->AddCurrentRuntimeFeaturesAsDex2OatArguments(&argv);
- int nchecks = 0;
- char checksep = ':';
-
- if (!Runtime::Current()->ExplicitNullChecks()) {
- checkstr += checksep;
- checksep = ',';
- checkstr += "null";
- ++nchecks;
+ if (!Runtime::Current()->IsVerificationEnabled()) {
+ argv.push_back("--compiler-filter=verify-none");
}
- 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";
- }
- 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 @@
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 d6d1b3e..0fbd27c 100644
--- a/runtime/gc/accounting/space_bitmap-inl.h
+++ b/runtime/gc/accounting/space_bitmap-inl.h
@@ -29,10 +29,10 @@
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 @@
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
+ //
- 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_;
+ // 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);
+
+ // 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);
}
+
+ // 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);
+ }
+ }
+
+ // Right edge is unique.
+ right_edge = bitmap_begin_[index_end];
+ } else {
+ // Right edge = left edge.
+ right_edge = left_edge;
}
- // 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);
-
- // 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 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);
}
-
- // 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;
- }
-#endif
}
inline bool SpaceBitmap::Modify(const mirror::Object* obj, bool do_set) {
@@ -133,10 +138,10 @@
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 ad4ff1b..1957c21 100644
--- a/runtime/gc/accounting/space_bitmap.cc
+++ b/runtime/gc/accounting/space_bitmap.cc
@@ -53,7 +53,7 @@
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 @@
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 @@
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 @@
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 5fd2bce..aa24b03 100644
--- a/runtime/gc/accounting/space_bitmap.h
+++ b/runtime/gc/accounting/space_bitmap.h
@@ -70,9 +70,9 @@
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 @@
void CopyFrom(SpaceBitmap* source_bitmap);
// Starting address of our internal storage.
- word* Begin() {
+ uword* Begin() {
return bitmap_begin_;
}
@@ -181,7 +181,7 @@
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 @@
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 9a2815a..faa539f 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -67,36 +67,6 @@
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 @@
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 0000000..c964629
--- /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 cbc9912..c5a4ec8 100644
--- a/runtime/instruction_set.h
+++ b/runtime/instruction_set.h
@@ -33,6 +33,7 @@
kX86_64,
kMips
};
+std::ostream& operator<<(std::ostream& os, const InstructionSet& rhs);
enum InstructionFeatures {
kHwDiv = 1 // Supports hardware divide.
@@ -44,6 +45,8 @@
InstructionSetFeatures() : mask_(0) {}
explicit InstructionSetFeatures(uint32_t mask) : mask_(mask) {}
+ static InstructionSetFeatures GuessInstructionSetFeatures();
+
bool HasDivideInstruction() const {
return (mask_ & kHwDiv) != 0;
}
@@ -52,20 +55,7 @@
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 @@
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 f970789..246e090 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 e2086f1..08a674f 100644
--- a/runtime/parsed_options.cc
+++ b/runtime/parsed_options.cc
@@ -196,6 +196,8 @@
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 @@
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 @@
(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 d6516a8..416bc78 100644
--- a/runtime/parsed_options.h
+++ b/runtime/parsed_options.h
@@ -80,6 +80,7 @@
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 a830018..1b3c996 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 @@
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 @@
thread_list_ = new ThreadList;
intern_table_ = new InternTable;
+ verify_ = options->verify_;
if (options->interpreter_only_) {
GetInstrumentation()->ForceInterpretOnly();
@@ -1216,6 +1220,59 @@
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 ed60d4d..7b3e04c 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -407,6 +407,8 @@
return fault_message_;
}
+ void AddCurrentRuntimeFeaturesAsDex2OatArguments(std::vector<std::string>* arg_vector) const;
+
bool ExplicitNullChecks() const {
return null_pointer_handler_ == nullptr;
}
@@ -419,10 +421,18 @@
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 @@
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 @@
SuspensionHandler* suspend_handler_;
StackOverflowHandler* stack_overflow_handler_;
+ // If false, verification is disabled. True by default.
+ bool verify_;
+
DISALLOW_COPY_AND_ASSIGN(Runtime);
};