Merge changes I2ea008b7,Ibd7a643d
* changes:
Add new style String operations during compilation init
Fix non-range String init calls
diff --git a/Android.mk b/Android.mk
index e7623c6..3467f1d 100644
--- a/Android.mk
+++ b/Android.mk
@@ -55,16 +55,16 @@
clean-oat-target:
adb root
adb wait-for-device remount
- adb shell sh -c "rm -rf $(ART_TARGET_NATIVETEST_DIR)"
- adb shell sh -c "rm -rf $(ART_TARGET_TEST_DIR)"
- adb shell sh -c "rm -rf $(ART_TARGET_DALVIK_CACHE_DIR)/*/*"
- adb shell sh -c "rm -rf $(DEXPREOPT_BOOT_JAR_DIR)/$(DEX2OAT_TARGET_ARCH)"
- adb shell sh -c "rm -rf system/app/$(DEX2OAT_TARGET_ARCH)"
+ adb shell rm -rf $(ART_TARGET_NATIVETEST_DIR)
+ adb shell rm -rf $(ART_TARGET_TEST_DIR)
+ adb shell rm -rf $(ART_TARGET_DALVIK_CACHE_DIR)/*/*
+ adb shell rm -rf $(DEXPREOPT_BOOT_JAR_DIR)/$(DEX2OAT_TARGET_ARCH)
+ adb shell rm -rf system/app/$(DEX2OAT_TARGET_ARCH)
ifdef TARGET_2ND_ARCH
- adb shell sh -c "rm -rf $(DEXPREOPT_BOOT_JAR_DIR)/$($(TARGET_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_ARCH)"
- adb shell sh -c "rm -rf system/app/$($(TARGET_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_ARCH)"
+ adb shell rm -rf $(DEXPREOPT_BOOT_JAR_DIR)/$($(TARGET_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_ARCH)
+ adb shell rm -rf system/app/$($(TARGET_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_ARCH)
endif
- adb shell sh -c "rm -rf data/run-test/test-*/dalvik-cache/*"
+ adb shell rm -rf data/run-test/test-*/dalvik-cache/*
ifneq ($(art_dont_bother),true)
@@ -404,9 +404,9 @@
use-art-full:
adb root
adb wait-for-device shell stop
- adb shell sh -c "rm -rf $(ART_TARGET_DALVIK_CACHE_DIR)/*"
- adb shell setprop dalvik.vm.dex2oat-filter ""
- adb shell setprop dalvik.vm.image-dex2oat-filter ""
+ adb shell rm -rf $(ART_TARGET_DALVIK_CACHE_DIR)/*
+ adb shell setprop dalvik.vm.dex2oat-filter \"\"
+ adb shell setprop dalvik.vm.image-dex2oat-filter \"\"
adb shell setprop persist.sys.dalvik.vm.lib.2 libart.so
adb shell start
@@ -414,9 +414,9 @@
use-artd-full:
adb root
adb wait-for-device shell stop
- adb shell sh -c "rm -rf $(ART_TARGET_DALVIK_CACHE_DIR)/*"
- adb shell setprop dalvik.vm.dex2oat-filter ""
- adb shell setprop dalvik.vm.image-dex2oat-filter ""
+ adb shell rm -rf $(ART_TARGET_DALVIK_CACHE_DIR)/*
+ adb shell setprop dalvik.vm.dex2oat-filter \"\"
+ adb shell setprop dalvik.vm.image-dex2oat-filter \"\"
adb shell setprop persist.sys.dalvik.vm.lib.2 libartd.so
adb shell start
@@ -424,7 +424,7 @@
use-art-verify-at-runtime:
adb root
adb wait-for-device shell stop
- adb shell sh -c "rm -rf $(ART_TARGET_DALVIK_CACHE_DIR)/*"
+ adb shell rm -rf $(ART_TARGET_DALVIK_CACHE_DIR)/*
adb shell setprop dalvik.vm.dex2oat-filter "verify-at-runtime"
adb shell setprop dalvik.vm.image-dex2oat-filter "verify-at-runtime"
adb shell setprop persist.sys.dalvik.vm.lib.2 libart.so
@@ -434,7 +434,7 @@
use-art-interpret-only:
adb root
adb wait-for-device shell stop
- adb shell sh -c "rm -rf $(ART_TARGET_DALVIK_CACHE_DIR)/*"
+ adb shell rm -rf $(ART_TARGET_DALVIK_CACHE_DIR)/*
adb shell setprop dalvik.vm.dex2oat-filter "interpret-only"
adb shell setprop dalvik.vm.image-dex2oat-filter "interpret-only"
adb shell setprop persist.sys.dalvik.vm.lib.2 libart.so
@@ -444,7 +444,7 @@
use-artd-interpret-only:
adb root
adb wait-for-device shell stop
- adb shell sh -c "rm -rf $(ART_TARGET_DALVIK_CACHE_DIR)/*"
+ adb shell rm -rf $(ART_TARGET_DALVIK_CACHE_DIR)/*
adb shell setprop dalvik.vm.dex2oat-filter "interpret-only"
adb shell setprop dalvik.vm.image-dex2oat-filter "interpret-only"
adb shell setprop persist.sys.dalvik.vm.lib.2 libartd.so
@@ -454,7 +454,7 @@
use-art-verify-none:
adb root
adb wait-for-device shell stop
- adb shell sh -c "rm -rf $(ART_TARGET_DALVIK_CACHE_DIR)/*"
+ adb shell rm -rf $(ART_TARGET_DALVIK_CACHE_DIR)/*
adb shell setprop dalvik.vm.dex2oat-filter "verify-none"
adb shell setprop dalvik.vm.image-dex2oat-filter "verify-none"
adb shell setprop persist.sys.dalvik.vm.lib.2 libart.so
diff --git a/compiler/dex/gvn_dead_code_elimination.cc b/compiler/dex/gvn_dead_code_elimination.cc
index 915fbcd..6d8a7da 100644
--- a/compiler/dex/gvn_dead_code_elimination.cc
+++ b/compiler/dex/gvn_dead_code_elimination.cc
@@ -58,14 +58,12 @@
low_def_over_high_word = prev_data->low_def_over_high_word;
} else {
prev_value = prev_data->prev_value_high;
- low_def_over_high_word =
- prev_data->prev_value_high.value != kNPos && !prev_data->high_def_over_low_word;
+ low_def_over_high_word = !prev_data->high_def_over_low_word;
}
} else {
if (prev_data->vreg_def == v_reg) {
prev_value_high = prev_data->prev_value;
- high_def_over_low_word =
- prev_data->prev_value.value != kNPos && !prev_data->low_def_over_high_word;
+ high_def_over_low_word = !prev_data->low_def_over_high_word;
} else {
prev_value_high = prev_data->prev_value_high;
high_def_over_low_word = prev_data->high_def_over_low_word;
@@ -340,8 +338,7 @@
DCHECK_EQ(vreg_high_words_.IsBitSet(v_reg), v_reg == data->vreg_def + 1);
if (data->vreg_def == v_reg && data->low_def_over_high_word) {
vreg_high_words_.SetBit(v_reg);
- } else if (data->vreg_def != v_reg &&
- (data->high_def_over_low_word || data->prev_value_high.value == kNoValue)) {
+ } else if (data->vreg_def != v_reg && data->high_def_over_low_word) {
vreg_high_words_.ClearBit(v_reg);
}
} else {
diff --git a/compiler/dex/gvn_dead_code_elimination_test.cc b/compiler/dex/gvn_dead_code_elimination_test.cc
index 4f81273..de591d0 100644
--- a/compiler/dex/gvn_dead_code_elimination_test.cc
+++ b/compiler/dex/gvn_dead_code_elimination_test.cc
@@ -1931,4 +1931,56 @@
}
}
+TEST_F(GvnDeadCodeEliminationTestSimple, MixedOverlaps1) {
+ static const MIRDef mirs[] = {
+ DEF_CONST(3, Instruction::CONST, 0u, 1000u),
+ DEF_MOVE(3, Instruction::MOVE, 1u, 0u),
+ DEF_CONST(3, Instruction::CONST, 2u, 2000u),
+ { 3, Instruction::INT_TO_LONG, 0, 0u, 1, { 2u }, 2, { 3u, 4u} },
+ DEF_MOVE_WIDE(3, Instruction::MOVE_WIDE, 5u, 3u),
+ DEF_CONST(3, Instruction::CONST, 7u, 3000u),
+ DEF_CONST(3, Instruction::CONST, 8u, 4000u),
+ };
+
+ static const int32_t sreg_to_vreg_map[] = { 1, 2, 0, 0, 1, 3, 4, 0, 1 };
+ PrepareSRegToVRegMap(sreg_to_vreg_map);
+
+ PrepareMIRs(mirs);
+ static const int32_t wide_sregs[] = { 3, 5 };
+ MarkAsWideSRegs(wide_sregs);
+ PerformGVN_DCE();
+
+ ASSERT_EQ(arraysize(mirs), value_names_.size());
+ static const size_t diff_indexes[] = { 0, 2, 3, 5, 6 };
+ ExpectValueNamesNE(diff_indexes);
+ EXPECT_EQ(value_names_[0], value_names_[1]);
+ EXPECT_EQ(value_names_[3], value_names_[4]);
+
+ static const bool eliminated[] = {
+ false, true, false, false, true, false, false,
+ };
+ static_assert(arraysize(eliminated) == arraysize(mirs), "array size mismatch");
+ for (size_t i = 0; i != arraysize(eliminated); ++i) {
+ bool actually_eliminated = (static_cast<int>(mirs_[i].dalvikInsn.opcode) == kMirOpNop);
+ EXPECT_EQ(eliminated[i], actually_eliminated) << i;
+ }
+ // Check renamed registers in CONST.
+ MIR* cst = &mirs_[0];
+ ASSERT_EQ(Instruction::CONST, cst->dalvikInsn.opcode);
+ ASSERT_EQ(0, cst->ssa_rep->num_uses);
+ ASSERT_EQ(1, cst->ssa_rep->num_defs);
+ EXPECT_EQ(1, cst->ssa_rep->defs[0]);
+ EXPECT_EQ(2u, cst->dalvikInsn.vA);
+ // Check renamed registers in INT_TO_LONG.
+ MIR* int_to_long = &mirs_[3];
+ ASSERT_EQ(Instruction::INT_TO_LONG, int_to_long->dalvikInsn.opcode);
+ ASSERT_EQ(1, int_to_long->ssa_rep->num_uses);
+ EXPECT_EQ(2, int_to_long->ssa_rep->uses[0]);
+ ASSERT_EQ(2, int_to_long->ssa_rep->num_defs);
+ EXPECT_EQ(5, int_to_long->ssa_rep->defs[0]);
+ EXPECT_EQ(6, int_to_long->ssa_rep->defs[1]);
+ EXPECT_EQ(3u, int_to_long->dalvikInsn.vA);
+ EXPECT_EQ(0u, int_to_long->dalvikInsn.vB);
+}
+
} // namespace art
diff --git a/runtime/art_field.cc b/runtime/art_field.cc
index 2aed440..47d5a76 100644
--- a/runtime/art_field.cc
+++ b/runtime/art_field.cc
@@ -63,6 +63,17 @@
FindInstanceFieldWithOffset(klass->GetSuperClass(), field_offset) : nullptr;
}
+ArtField* ArtField::FindStaticFieldWithOffset(mirror::Class* klass, uint32_t field_offset) {
+ DCHECK(klass != nullptr);
+ auto* static_fields = klass->GetSFields();
+ for (size_t i = 0, count = klass->NumStaticFields(); i < count; ++i) {
+ if (static_fields[i].GetOffset().Uint32Value() == field_offset) {
+ return &static_fields[i];
+ }
+ }
+ return nullptr;
+}
+
mirror::Class* ArtField::ProxyFindSystemClass(const char* descriptor) {
DCHECK(GetDeclaringClass()->IsProxyClass());
return Runtime::Current()->GetClassLinker()->FindSystemClass(Thread::Current(), descriptor);
diff --git a/runtime/art_field.h b/runtime/art_field.h
index c0620bf..9d3dbd9 100644
--- a/runtime/art_field.h
+++ b/runtime/art_field.h
@@ -161,6 +161,9 @@
// Returns an instance field with this offset in the given class or null if not found.
static ArtField* FindInstanceFieldWithOffset(mirror::Class* klass, uint32_t field_offset)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ // Returns a static field with this offset in the given class or null if not found.
+ static ArtField* FindStaticFieldWithOffset(mirror::Class* klass, uint32_t field_offset)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
const char* GetName() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
diff --git a/runtime/gc/accounting/heap_bitmap.h b/runtime/gc/accounting/heap_bitmap.h
index 245e074..1648aef 100644
--- a/runtime/gc/accounting/heap_bitmap.h
+++ b/runtime/gc/accounting/heap_bitmap.h
@@ -39,9 +39,11 @@
void Clear(const mirror::Object* obj) EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_);
template<typename LargeObjectSetVisitor>
bool Set(const mirror::Object* obj, const LargeObjectSetVisitor& visitor)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_) ALWAYS_INLINE;
template<typename LargeObjectSetVisitor>
bool AtomicTestAndSet(const mirror::Object* obj, const LargeObjectSetVisitor& visitor)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_) ALWAYS_INLINE;
ContinuousSpaceBitmap* GetContinuousSpaceBitmap(const mirror::Object* obj) const;
LargeObjectBitmap* GetLargeObjectBitmap(const mirror::Object* obj) const;
diff --git a/runtime/gc/collector/mark_sweep.cc b/runtime/gc/collector/mark_sweep.cc
index 55a8411..53e56da 100644
--- a/runtime/gc/collector/mark_sweep.cc
+++ b/runtime/gc/collector/mark_sweep.cc
@@ -368,10 +368,13 @@
class MarkSweepMarkObjectSlowPath {
public:
- explicit MarkSweepMarkObjectSlowPath(MarkSweep* mark_sweep) : mark_sweep_(mark_sweep) {
+ explicit MarkSweepMarkObjectSlowPath(MarkSweep* mark_sweep, Object* holder = nullptr,
+ MemberOffset offset = MemberOffset(0))
+ : mark_sweep_(mark_sweep), holder_(holder), offset_(offset) {
}
- void operator()(const Object* obj) const ALWAYS_INLINE {
+ void operator()(const Object* obj) const ALWAYS_INLINE
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
if (kProfileLargeObjects) {
// TODO: Differentiate between marking and testing somehow.
++mark_sweep_->large_object_test_;
@@ -384,6 +387,13 @@
LOG(INTERNAL_FATAL) << "Tried to mark " << obj << " not contained by any spaces";
LOG(INTERNAL_FATAL) << "Attempting see if it's a bad root";
mark_sweep_->VerifyRoots();
+ if (holder_ != nullptr) {
+ ArtField* field = holder_->FindFieldByOffset(offset_);
+ LOG(INTERNAL_FATAL) << "Field info: holder=" << holder_
+ << " holder_type=" << PrettyTypeOf(holder_)
+ << " offset=" << offset_.Uint32Value()
+ << " field=" << (field != nullptr ? field->GetName() : "nullptr");
+ }
PrintFileToLog("/proc/self/maps", LogSeverity::INTERNAL_FATAL);
MemMap::DumpMaps(LOG(INTERNAL_FATAL), true);
LOG(FATAL) << "Can't mark invalid object";
@@ -392,9 +402,11 @@
private:
MarkSweep* const mark_sweep_;
+ mirror::Object* const holder_;
+ MemberOffset offset_;
};
-inline void MarkSweep::MarkObjectNonNull(Object* obj) {
+inline void MarkSweep::MarkObjectNonNull(Object* obj, Object* holder, MemberOffset offset) {
DCHECK(obj != nullptr);
if (kUseBakerOrBrooksReadBarrier) {
// Verify all the objects have the correct pointer installed.
@@ -416,7 +428,7 @@
if (kCountMarkedObjects) {
++mark_slowpath_count_;
}
- MarkSweepMarkObjectSlowPath visitor(this);
+ MarkSweepMarkObjectSlowPath visitor(this, holder, offset);
// TODO: We already know that the object is not in the current_space_bitmap_ but MarkBitmap::Set
// will check again.
if (!mark_bitmap_->Set(obj, visitor)) {
@@ -456,9 +468,9 @@
}
// Used to mark objects when processing the mark stack. If an object is null, it is not marked.
-inline void MarkSweep::MarkObject(Object* obj) {
+inline void MarkSweep::MarkObject(Object* obj, Object* holder, MemberOffset offset) {
if (obj != nullptr) {
- MarkObjectNonNull(obj);
+ MarkObjectNonNull(obj, holder, offset);
} else if (kCountMarkedObjects) {
++mark_null_count_;
}
@@ -1209,7 +1221,7 @@
Locks::mutator_lock_->AssertSharedHeld(Thread::Current());
Locks::heap_bitmap_lock_->AssertExclusiveHeld(Thread::Current());
}
- mark_sweep_->MarkObject(obj->GetFieldObject<mirror::Object>(offset));
+ mark_sweep_->MarkObject(obj->GetFieldObject<mirror::Object>(offset), obj, offset);
}
private:
diff --git a/runtime/gc/collector/mark_sweep.h b/runtime/gc/collector/mark_sweep.h
index 7e1af7b..d29d87a 100644
--- a/runtime/gc/collector/mark_sweep.h
+++ b/runtime/gc/collector/mark_sweep.h
@@ -199,7 +199,8 @@
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Marks an object.
- void MarkObject(mirror::Object* obj)
+ void MarkObject(mirror::Object* obj, mirror::Object* holder = nullptr,
+ MemberOffset offset = MemberOffset(0))
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_);
@@ -222,7 +223,8 @@
static void VerifyImageRootVisitor(mirror::Object* root, void* arg)
SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_);
- void MarkObjectNonNull(mirror::Object* obj)
+ void MarkObjectNonNull(mirror::Object* obj, mirror::Object* holder = nullptr,
+ MemberOffset offset = MemberOffset(0))
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_);
diff --git a/runtime/hprof/hprof.cc b/runtime/hprof/hprof.cc
index d0eb083..868cb23 100644
--- a/runtime/hprof/hprof.cc
+++ b/runtime/hprof/hprof.cc
@@ -981,7 +981,11 @@
// ClassObjects have their static fields appended, so aren't all the same size.
// But they're at least this size.
__ AddU4(sizeof(mirror::Class)); // instance size
- } else if (klass->IsArrayClass() || klass->IsStringClass() || klass->IsPrimitive()) {
+ } else if (klass->IsStringClass()) {
+ // Strings are variable length with character data at the end like arrays.
+ // This outputs the size of an empty string.
+ __ AddU4(sizeof(mirror::String));
+ } else if (klass->IsArrayClass() || klass->IsPrimitive()) {
__ AddU4(0);
} else {
__ AddU4(klass->GetObjectSize()); // instance size
diff --git a/runtime/mirror/object.cc b/runtime/mirror/object.cc
index 5dac985..f9740bb 100644
--- a/runtime/mirror/object.cc
+++ b/runtime/mirror/object.cc
@@ -244,5 +244,10 @@
UNREACHABLE();
}
+ArtField* Object::FindFieldByOffset(MemberOffset offset) {
+ return IsClass() ? ArtField::FindStaticFieldWithOffset(AsClass(), offset.Uint32Value())
+ : ArtField::FindInstanceFieldWithOffset(GetClass(), offset.Uint32Value());
+}
+
} // namespace mirror
} // namespace art
diff --git a/runtime/mirror/object.h b/runtime/mirror/object.h
index f2d879f..5afe99f 100644
--- a/runtime/mirror/object.h
+++ b/runtime/mirror/object.h
@@ -439,6 +439,8 @@
void VisitReferences(const Visitor& visitor, const JavaLangRefVisitor& ref_visitor)
NO_THREAD_SAFETY_ANALYSIS;
+ ArtField* FindFieldByOffset(MemberOffset offset) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
// Used by object_test.
static void SetHashCodeSeed(uint32_t new_seed);
// Generate an identity hash code. Public for object test.