Merge "Fix mutex issue"
diff --git a/runtime/gc/accounting/read_barrier_table.h b/runtime/gc/accounting/read_barrier_table.h
index 86266e2..e77a5b8 100644
--- a/runtime/gc/accounting/read_barrier_table.h
+++ b/runtime/gc/accounting/read_barrier_table.h
@@ -80,7 +80,7 @@
}
// This should match RegionSpace::kRegionSize. static_assert'ed in concurrent_copying.h.
- static constexpr size_t kRegionSize = 1 * MB;
+ static constexpr size_t kRegionSize = 256 * KB;
private:
static constexpr uint64_t kHeapCapacity = 4ULL * GB; // low 4gb.
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index 12b9701..b857ea3 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -3559,11 +3559,8 @@
collector::GcType gc_type = collector_ran->GetGcType();
const double multiplier = HeapGrowthMultiplier(); // Use the multiplier to grow more for
// foreground.
- // Ensure at least 2.5 MB to temporarily fix excessive GC caused by TLAB ergonomics.
- const uint64_t adjusted_min_free = std::max(static_cast<uint64_t>(min_free_ * multiplier),
- static_cast<uint64_t>(5 * MB / 2));
- const uint64_t adjusted_max_free = std::max(static_cast<uint64_t>(max_free_ * multiplier),
- static_cast<uint64_t>(5 * MB / 2));
+ const uint64_t adjusted_min_free = static_cast<uint64_t>(min_free_ * multiplier);
+ const uint64_t adjusted_max_free = static_cast<uint64_t>(max_free_ * multiplier);
if (gc_type != collector::kGcTypeSticky) {
// Grow the heap for non sticky GC.
ssize_t delta = bytes_allocated / GetTargetHeapUtilization() - bytes_allocated;
diff --git a/runtime/gc/space/region_space-inl.h b/runtime/gc/space/region_space-inl.h
index 5d282f1..fffcee6 100644
--- a/runtime/gc/space/region_space-inl.h
+++ b/runtime/gc/space/region_space-inl.h
@@ -78,7 +78,7 @@
for (size_t i = 0; i < num_regions_; ++i) {
Region* r = ®ions_[i];
if (r->IsFree()) {
- r->Unfree(time_);
+ r->Unfree(this, time_);
r->SetNewlyAllocated();
++num_non_free_regions_;
obj = r->Alloc(num_bytes, bytes_allocated, usable_size, bytes_tl_bulk_allocated);
@@ -91,7 +91,7 @@
for (size_t i = 0; i < num_regions_; ++i) {
Region* r = ®ions_[i];
if (r->IsFree()) {
- r->Unfree(time_);
+ r->Unfree(this, time_);
++num_non_free_regions_;
obj = r->Alloc(num_bytes, bytes_allocated, usable_size, bytes_tl_bulk_allocated);
CHECK(obj != nullptr);
@@ -314,13 +314,13 @@
DCHECK_EQ(left + num_regs, right);
Region* first_reg = ®ions_[left];
DCHECK(first_reg->IsFree());
- first_reg->UnfreeLarge(time_);
+ first_reg->UnfreeLarge(this, time_);
++num_non_free_regions_;
first_reg->SetTop(first_reg->Begin() + num_bytes);
for (size_t p = left + 1; p < right; ++p) {
DCHECK_LT(p, num_regions_);
DCHECK(regions_[p].IsFree());
- regions_[p].UnfreeLargeTail(time_);
+ regions_[p].UnfreeLargeTail(this, time_);
++num_non_free_regions_;
}
*bytes_allocated = num_bytes;
diff --git a/runtime/gc/space/region_space.cc b/runtime/gc/space/region_space.cc
index 321524c..560abe1 100644
--- a/runtime/gc/space/region_space.cc
+++ b/runtime/gc/space/region_space.cc
@@ -86,6 +86,7 @@
num_regions_ = mem_map_size / kRegionSize;
num_non_free_regions_ = 0U;
DCHECK_GT(num_regions_, 0U);
+ non_free_region_index_limit_ = 0U;
regions_.reset(new Region[num_regions_]);
uint8_t* region_addr = mem_map->Begin();
for (size_t i = 0; i < num_regions_; ++i, region_addr += kRegionSize) {
@@ -192,7 +193,11 @@
MutexLock mu(Thread::Current(), region_lock_);
size_t num_expected_large_tails = 0;
bool prev_large_evacuated = false;
- for (size_t i = 0; i < num_regions_; ++i) {
+ VerifyNonFreeRegionLimit();
+ const size_t iter_limit = kUseTableLookupReadBarrier
+ ? num_regions_
+ : std::min(num_regions_, non_free_region_index_limit_);
+ for (size_t i = 0; i < iter_limit; ++i) {
Region* r = ®ions_[i];
RegionState state = r->State();
RegionType type = r->Type();
@@ -236,13 +241,16 @@
}
}
}
+ DCHECK_EQ(num_expected_large_tails, 0U);
current_region_ = &full_region_;
evac_region_ = &full_region_;
}
void RegionSpace::ClearFromSpace() {
MutexLock mu(Thread::Current(), region_lock_);
- for (size_t i = 0; i < num_regions_; ++i) {
+ VerifyNonFreeRegionLimit();
+ size_t new_non_free_region_index_limit = 0;
+ for (size_t i = 0; i < std::min(num_regions_, non_free_region_index_limit_); ++i) {
Region* r = ®ions_[i];
if (r->IsInFromSpace()) {
r->Clear();
@@ -255,6 +263,7 @@
cur->LiveBytes() != static_cast<size_t>(cur->Top() - cur->Begin())) {
break;
}
+ DCHECK(cur->IsInUnevacFromSpace());
if (full_count != 0) {
cur->SetUnevacFromSpaceAsToSpace();
}
@@ -271,7 +280,15 @@
i += full_count - 1;
}
}
+ // Note r != last_checked_region if r->IsInUnevacFromSpace() was true above.
+ Region* last_checked_region = ®ions_[i];
+ if (!last_checked_region->IsFree()) {
+ new_non_free_region_index_limit = std::max(new_non_free_region_index_limit,
+ last_checked_region->Idx() + 1);
+ }
}
+ // Update non_free_region_index_limit_.
+ SetNonFreeRegionLimit(new_non_free_region_index_limit);
evac_region_ = nullptr;
}
@@ -324,6 +341,7 @@
}
r->Clear();
}
+ SetNonFreeRegionLimit(0);
current_region_ = &full_region_;
evac_region_ = &full_region_;
}
@@ -390,7 +408,7 @@
for (size_t i = 0; i < num_regions_; ++i) {
Region* r = ®ions_[i];
if (r->IsFree()) {
- r->Unfree(time_);
+ r->Unfree(this, time_);
++num_non_free_regions_;
r->SetNewlyAllocated();
r->SetTop(r->End());
diff --git a/runtime/gc/space/region_space.h b/runtime/gc/space/region_space.h
index da36f5c..95f293b 100644
--- a/runtime/gc/space/region_space.h
+++ b/runtime/gc/space/region_space.h
@@ -167,7 +167,7 @@
// Object alignment within the space.
static constexpr size_t kAlignment = kObjectAlignment;
// The region size.
- static constexpr size_t kRegionSize = 1 * MB;
+ static constexpr size_t kRegionSize = 256 * KB;
bool IsInFromSpace(mirror::Object* ref) {
if (HasAddress(ref)) {
@@ -308,25 +308,31 @@
}
// Given a free region, declare it non-free (allocated).
- void Unfree(uint32_t alloc_time) {
+ void Unfree(RegionSpace* region_space, uint32_t alloc_time)
+ REQUIRES(region_space->region_lock_) {
DCHECK(IsFree());
state_ = RegionState::kRegionStateAllocated;
type_ = RegionType::kRegionTypeToSpace;
alloc_time_ = alloc_time;
+ region_space->AdjustNonFreeRegionLimit(idx_);
}
- void UnfreeLarge(uint32_t alloc_time) {
+ void UnfreeLarge(RegionSpace* region_space, uint32_t alloc_time)
+ REQUIRES(region_space->region_lock_) {
DCHECK(IsFree());
state_ = RegionState::kRegionStateLarge;
type_ = RegionType::kRegionTypeToSpace;
alloc_time_ = alloc_time;
+ region_space->AdjustNonFreeRegionLimit(idx_);
}
- void UnfreeLargeTail(uint32_t alloc_time) {
+ void UnfreeLargeTail(RegionSpace* region_space, uint32_t alloc_time)
+ REQUIRES(region_space->region_lock_) {
DCHECK(IsFree());
state_ = RegionState::kRegionStateLargeTail;
type_ = RegionType::kRegionTypeToSpace;
alloc_time_ = alloc_time;
+ region_space->AdjustNonFreeRegionLimit(idx_);
}
void SetNewlyAllocated() {
@@ -342,7 +348,7 @@
bool IsLarge() const {
bool is_large = state_ == RegionState::kRegionStateLarge;
if (is_large) {
- DCHECK_LT(begin_ + 1 * MB, Top());
+ DCHECK_LT(begin_ + kRegionSize, Top());
}
return is_large;
}
@@ -429,7 +435,7 @@
size_t ObjectsAllocated() const {
if (IsLarge()) {
- DCHECK_LT(begin_ + 1 * MB, Top());
+ DCHECK_LT(begin_ + kRegionSize, Top());
DCHECK_EQ(objects_allocated_.LoadRelaxed(), 0U);
return 1;
} else if (IsLargeTail()) {
@@ -520,6 +526,27 @@
mirror::Object* GetNextObject(mirror::Object* obj)
REQUIRES_SHARED(Locks::mutator_lock_);
+ void AdjustNonFreeRegionLimit(size_t new_non_free_region_index) REQUIRES(region_lock_) {
+ DCHECK_LT(new_non_free_region_index, num_regions_);
+ non_free_region_index_limit_ = std::max(non_free_region_index_limit_,
+ new_non_free_region_index + 1);
+ VerifyNonFreeRegionLimit();
+ }
+
+ void SetNonFreeRegionLimit(size_t new_non_free_region_index_limit) REQUIRES(region_lock_) {
+ DCHECK_LE(new_non_free_region_index_limit, num_regions_);
+ non_free_region_index_limit_ = new_non_free_region_index_limit;
+ VerifyNonFreeRegionLimit();
+ }
+
+ void VerifyNonFreeRegionLimit() REQUIRES(region_lock_) {
+ if (kIsDebugBuild && non_free_region_index_limit_ < num_regions_) {
+ for (size_t i = non_free_region_index_limit_; i < num_regions_; ++i) {
+ CHECK(regions_[i].IsFree());
+ }
+ }
+ }
+
Mutex region_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
uint32_t time_; // The time as the number of collections since the startup.
@@ -527,6 +554,10 @@
size_t num_non_free_regions_; // The number of non-free regions in this space.
std::unique_ptr<Region[]> regions_ GUARDED_BY(region_lock_);
// The pointer to the region array.
+ // The upper-bound index of the non-free regions. Used to avoid scanning all regions in
+ // SetFromSpace(). Invariant: for all i >= non_free_region_index_limit_, regions_[i].IsFree() is
+ // true.
+ size_t non_free_region_index_limit_ GUARDED_BY(region_lock_);
Region* current_region_; // The region that's being allocated currently.
Region* evac_region_; // The region that's being evacuated to currently.
Region full_region_; // The dummy/sentinel region that looks full.
diff --git a/runtime/interpreter/mterp/arm/op_sget.S b/runtime/interpreter/mterp/arm/op_sget.S
index 2b81f50..3c813ef 100644
--- a/runtime/interpreter/mterp/arm/op_sget.S
+++ b/runtime/interpreter/mterp/arm/op_sget.S
@@ -1,4 +1,4 @@
-%default { "is_object":"0", "helper":"artGet32StaticFromCode" }
+%default { "is_object":"0", "helper":"MterpGet32Static" }
/*
* General SGET handler wrapper.
*
diff --git a/runtime/interpreter/mterp/arm/op_sget_boolean.S b/runtime/interpreter/mterp/arm/op_sget_boolean.S
index ebfb44c..eb06aa8 100644
--- a/runtime/interpreter/mterp/arm/op_sget_boolean.S
+++ b/runtime/interpreter/mterp/arm/op_sget_boolean.S
@@ -1 +1 @@
-%include "arm/op_sget.S" {"helper":"artGetBooleanStaticFromCode"}
+%include "arm/op_sget.S" {"helper":"MterpGetBooleanStatic"}
diff --git a/runtime/interpreter/mterp/arm/op_sget_byte.S b/runtime/interpreter/mterp/arm/op_sget_byte.S
index d76862e..9f4c904 100644
--- a/runtime/interpreter/mterp/arm/op_sget_byte.S
+++ b/runtime/interpreter/mterp/arm/op_sget_byte.S
@@ -1 +1 @@
-%include "arm/op_sget.S" {"helper":"artGetByteStaticFromCode"}
+%include "arm/op_sget.S" {"helper":"MterpGetByteStatic"}
diff --git a/runtime/interpreter/mterp/arm/op_sget_char.S b/runtime/interpreter/mterp/arm/op_sget_char.S
index b7fcfc2..dd8c991 100644
--- a/runtime/interpreter/mterp/arm/op_sget_char.S
+++ b/runtime/interpreter/mterp/arm/op_sget_char.S
@@ -1 +1 @@
-%include "arm/op_sget.S" {"helper":"artGetCharStaticFromCode"}
+%include "arm/op_sget.S" {"helper":"MterpGetCharStatic"}
diff --git a/runtime/interpreter/mterp/arm/op_sget_object.S b/runtime/interpreter/mterp/arm/op_sget_object.S
index 8e7d075..e1d9eae 100644
--- a/runtime/interpreter/mterp/arm/op_sget_object.S
+++ b/runtime/interpreter/mterp/arm/op_sget_object.S
@@ -1 +1 @@
-%include "arm/op_sget.S" {"is_object":"1", "helper":"artGetObjStaticFromCode"}
+%include "arm/op_sget.S" {"is_object":"1", "helper":"MterpGetObjStatic"}
diff --git a/runtime/interpreter/mterp/arm/op_sget_short.S b/runtime/interpreter/mterp/arm/op_sget_short.S
index 3e80f0d..c0d61c4 100644
--- a/runtime/interpreter/mterp/arm/op_sget_short.S
+++ b/runtime/interpreter/mterp/arm/op_sget_short.S
@@ -1 +1 @@
-%include "arm/op_sget.S" {"helper":"artGetShortStaticFromCode"}
+%include "arm/op_sget.S" {"helper":"MterpGetShortStatic"}
diff --git a/runtime/interpreter/mterp/arm/op_sget_wide.S b/runtime/interpreter/mterp/arm/op_sget_wide.S
index 4f2f89d..aeee016 100644
--- a/runtime/interpreter/mterp/arm/op_sget_wide.S
+++ b/runtime/interpreter/mterp/arm/op_sget_wide.S
@@ -4,12 +4,12 @@
*/
/* sget-wide vAA, field@BBBB */
- .extern artGet64StaticFromCode
+ .extern MterpGet64Static
EXPORT_PC
FETCH r0, 1 @ r0<- field ref BBBB
ldr r1, [rFP, #OFF_FP_METHOD]
mov r2, rSELF
- bl artGet64StaticFromCode
+ bl MterpGet64Static
ldr r3, [rSELF, #THREAD_EXCEPTION_OFFSET]
mov r9, rINST, lsr #8 @ r9<- AA
VREG_INDEX_TO_ADDR lr, r9 @ r9<- &fp[AA]
diff --git a/runtime/interpreter/mterp/arm/op_sput.S b/runtime/interpreter/mterp/arm/op_sput.S
index 7e0c1a6..494df8a 100644
--- a/runtime/interpreter/mterp/arm/op_sput.S
+++ b/runtime/interpreter/mterp/arm/op_sput.S
@@ -1,4 +1,4 @@
-%default { "helper":"artSet32StaticFromCode"}
+%default { "helper":"MterpSet32Static"}
/*
* General SPUT handler wrapper.
*
diff --git a/runtime/interpreter/mterp/arm/op_sput_boolean.S b/runtime/interpreter/mterp/arm/op_sput_boolean.S
index e3bbf2b..47bed0a 100644
--- a/runtime/interpreter/mterp/arm/op_sput_boolean.S
+++ b/runtime/interpreter/mterp/arm/op_sput_boolean.S
@@ -1 +1 @@
-%include "arm/op_sput.S" {"helper":"artSet8StaticFromCode"}
+%include "arm/op_sput.S" {"helper":"MterpSetBooleanStatic"}
diff --git a/runtime/interpreter/mterp/arm/op_sput_byte.S b/runtime/interpreter/mterp/arm/op_sput_byte.S
index e3bbf2b..b4d22b4 100644
--- a/runtime/interpreter/mterp/arm/op_sput_byte.S
+++ b/runtime/interpreter/mterp/arm/op_sput_byte.S
@@ -1 +1 @@
-%include "arm/op_sput.S" {"helper":"artSet8StaticFromCode"}
+%include "arm/op_sput.S" {"helper":"MterpSetByteStatic"}
diff --git a/runtime/interpreter/mterp/arm/op_sput_char.S b/runtime/interpreter/mterp/arm/op_sput_char.S
index d8d65cb..58a957d 100644
--- a/runtime/interpreter/mterp/arm/op_sput_char.S
+++ b/runtime/interpreter/mterp/arm/op_sput_char.S
@@ -1 +1 @@
-%include "arm/op_sput.S" {"helper":"artSet16StaticFromCode"}
+%include "arm/op_sput.S" {"helper":"MterpSetCharStatic"}
diff --git a/runtime/interpreter/mterp/arm/op_sput_short.S b/runtime/interpreter/mterp/arm/op_sput_short.S
index d8d65cb..88c3211 100644
--- a/runtime/interpreter/mterp/arm/op_sput_short.S
+++ b/runtime/interpreter/mterp/arm/op_sput_short.S
@@ -1 +1 @@
-%include "arm/op_sput.S" {"helper":"artSet16StaticFromCode"}
+%include "arm/op_sput.S" {"helper":"MterpSetShortStatic"}
diff --git a/runtime/interpreter/mterp/arm/op_sput_wide.S b/runtime/interpreter/mterp/arm/op_sput_wide.S
index 8d8ed8c..1e8fcc9 100644
--- a/runtime/interpreter/mterp/arm/op_sput_wide.S
+++ b/runtime/interpreter/mterp/arm/op_sput_wide.S
@@ -3,15 +3,15 @@
*
*/
/* sput-wide vAA, field@BBBB */
- .extern artSet64IndirectStaticFromMterp
+ .extern MterpSet64Static
EXPORT_PC
FETCH r0, 1 @ r0<- field ref BBBB
- ldr r1, [rFP, #OFF_FP_METHOD]
- mov r2, rINST, lsr #8 @ r3<- AA
- VREG_INDEX_TO_ADDR r2, r2
+ mov r1, rINST, lsr #8 @ r1<- AA
+ VREG_INDEX_TO_ADDR r1, r1
+ ldr r2, [rFP, #OFF_FP_METHOD]
mov r3, rSELF
PREFETCH_INST 2 @ Get next inst, but don't advance rPC
- bl artSet64IndirectStaticFromMterp
+ bl MterpSet64Static
cmp r0, #0 @ 0 on success, -1 on failure
bne MterpException
ADVANCE 2 @ Past exception point - now advance rPC
diff --git a/runtime/interpreter/mterp/arm64/op_sget.S b/runtime/interpreter/mterp/arm64/op_sget.S
index 6352ce0..84e71ac 100644
--- a/runtime/interpreter/mterp/arm64/op_sget.S
+++ b/runtime/interpreter/mterp/arm64/op_sget.S
@@ -1,4 +1,4 @@
-%default { "is_object":"0", "helper":"artGet32StaticFromCode", "extend":"" }
+%default { "is_object":"0", "helper":"MterpGet32Static", "extend":"" }
/*
* General SGET handler wrapper.
*
diff --git a/runtime/interpreter/mterp/arm64/op_sget_boolean.S b/runtime/interpreter/mterp/arm64/op_sget_boolean.S
index c40dbdd..868f41c 100644
--- a/runtime/interpreter/mterp/arm64/op_sget_boolean.S
+++ b/runtime/interpreter/mterp/arm64/op_sget_boolean.S
@@ -1 +1 @@
-%include "arm64/op_sget.S" {"helper":"artGetBooleanStaticFromCode", "extend":"uxtb w0, w0"}
+%include "arm64/op_sget.S" {"helper":"MterpGetBooleanStatic", "extend":"uxtb w0, w0"}
diff --git a/runtime/interpreter/mterp/arm64/op_sget_byte.S b/runtime/interpreter/mterp/arm64/op_sget_byte.S
index 6cf69a3..e135aa7 100644
--- a/runtime/interpreter/mterp/arm64/op_sget_byte.S
+++ b/runtime/interpreter/mterp/arm64/op_sget_byte.S
@@ -1 +1 @@
-%include "arm64/op_sget.S" {"helper":"artGetByteStaticFromCode", "extend":"sxtb w0, w0"}
+%include "arm64/op_sget.S" {"helper":"MterpGetByteStatic", "extend":"sxtb w0, w0"}
diff --git a/runtime/interpreter/mterp/arm64/op_sget_char.S b/runtime/interpreter/mterp/arm64/op_sget_char.S
index 8924a34..05d57ac 100644
--- a/runtime/interpreter/mterp/arm64/op_sget_char.S
+++ b/runtime/interpreter/mterp/arm64/op_sget_char.S
@@ -1 +1 @@
-%include "arm64/op_sget.S" {"helper":"artGetCharStaticFromCode", "extend":"uxth w0, w0"}
+%include "arm64/op_sget.S" {"helper":"MterpGetCharStatic", "extend":"uxth w0, w0"}
diff --git a/runtime/interpreter/mterp/arm64/op_sget_object.S b/runtime/interpreter/mterp/arm64/op_sget_object.S
index 620b0ba..1faaf6e 100644
--- a/runtime/interpreter/mterp/arm64/op_sget_object.S
+++ b/runtime/interpreter/mterp/arm64/op_sget_object.S
@@ -1 +1 @@
-%include "arm64/op_sget.S" {"is_object":"1", "helper":"artGetObjStaticFromCode"}
+%include "arm64/op_sget.S" {"is_object":"1", "helper":"MterpGetObjStatic"}
diff --git a/runtime/interpreter/mterp/arm64/op_sget_short.S b/runtime/interpreter/mterp/arm64/op_sget_short.S
index 19dbba6..5900231 100644
--- a/runtime/interpreter/mterp/arm64/op_sget_short.S
+++ b/runtime/interpreter/mterp/arm64/op_sget_short.S
@@ -1 +1 @@
-%include "arm64/op_sget.S" {"helper":"artGetShortStaticFromCode", "extend":"sxth w0, w0"}
+%include "arm64/op_sget.S" {"helper":"MterpGetShortStatic", "extend":"sxth w0, w0"}
diff --git a/runtime/interpreter/mterp/arm64/op_sget_wide.S b/runtime/interpreter/mterp/arm64/op_sget_wide.S
index 287f66d..92f3f7d 100644
--- a/runtime/interpreter/mterp/arm64/op_sget_wide.S
+++ b/runtime/interpreter/mterp/arm64/op_sget_wide.S
@@ -4,12 +4,12 @@
*/
/* sget-wide vAA, field//BBBB */
- .extern artGet64StaticFromCode
+ .extern MterpGet64StaticFromCode
EXPORT_PC
FETCH w0, 1 // w0<- field ref BBBB
ldr x1, [xFP, #OFF_FP_METHOD]
mov x2, xSELF
- bl artGet64StaticFromCode
+ bl MterpGet64Static
ldr x3, [xSELF, #THREAD_EXCEPTION_OFFSET]
lsr w4, wINST, #8 // w4<- AA
cbnz x3, MterpException // bail out
diff --git a/runtime/interpreter/mterp/arm64/op_sput.S b/runtime/interpreter/mterp/arm64/op_sput.S
index 75f27ab..e322af0 100644
--- a/runtime/interpreter/mterp/arm64/op_sput.S
+++ b/runtime/interpreter/mterp/arm64/op_sput.S
@@ -1,4 +1,4 @@
-%default { "helper":"artSet32StaticFromCode"}
+%default { "helper":"MterpSet32Static"}
/*
* General SPUT handler wrapper.
*
diff --git a/runtime/interpreter/mterp/arm64/op_sput_boolean.S b/runtime/interpreter/mterp/arm64/op_sput_boolean.S
index 11c55e5..9928f31 100644
--- a/runtime/interpreter/mterp/arm64/op_sput_boolean.S
+++ b/runtime/interpreter/mterp/arm64/op_sput_boolean.S
@@ -1 +1 @@
-%include "arm64/op_sput.S" {"helper":"artSet8StaticFromCode"}
+%include "arm64/op_sput.S" {"helper":"MterpSetBooleanStatic"}
diff --git a/runtime/interpreter/mterp/arm64/op_sput_byte.S b/runtime/interpreter/mterp/arm64/op_sput_byte.S
index 11c55e5..16d6ba9 100644
--- a/runtime/interpreter/mterp/arm64/op_sput_byte.S
+++ b/runtime/interpreter/mterp/arm64/op_sput_byte.S
@@ -1 +1 @@
-%include "arm64/op_sput.S" {"helper":"artSet8StaticFromCode"}
+%include "arm64/op_sput.S" {"helper":"MterpSetByteStatic"}
diff --git a/runtime/interpreter/mterp/arm64/op_sput_char.S b/runtime/interpreter/mterp/arm64/op_sput_char.S
index b4dd5aa..ab5e815 100644
--- a/runtime/interpreter/mterp/arm64/op_sput_char.S
+++ b/runtime/interpreter/mterp/arm64/op_sput_char.S
@@ -1 +1 @@
-%include "arm64/op_sput.S" {"helper":"artSet16StaticFromCode"}
+%include "arm64/op_sput.S" {"helper":"MterpSetCharStatic"}
diff --git a/runtime/interpreter/mterp/arm64/op_sput_short.S b/runtime/interpreter/mterp/arm64/op_sput_short.S
index b4dd5aa..b54f88a 100644
--- a/runtime/interpreter/mterp/arm64/op_sput_short.S
+++ b/runtime/interpreter/mterp/arm64/op_sput_short.S
@@ -1 +1 @@
-%include "arm64/op_sput.S" {"helper":"artSet16StaticFromCode"}
+%include "arm64/op_sput.S" {"helper":"MterpSetShortStatic"}
diff --git a/runtime/interpreter/mterp/arm64/op_sput_wide.S b/runtime/interpreter/mterp/arm64/op_sput_wide.S
index a79b1a6..4aeb8ff 100644
--- a/runtime/interpreter/mterp/arm64/op_sput_wide.S
+++ b/runtime/interpreter/mterp/arm64/op_sput_wide.S
@@ -3,15 +3,15 @@
*
*/
/* sput-wide vAA, field//BBBB */
- .extern artSet64IndirectStaticFromMterp
+ .extern MterpSet64Static
EXPORT_PC
FETCH w0, 1 // w0<- field ref BBBB
- ldr x1, [xFP, #OFF_FP_METHOD]
- lsr w2, wINST, #8 // w3<- AA
- VREG_INDEX_TO_ADDR x2, w2
+ lsr w1, wINST, #8 // w1<- AA
+ VREG_INDEX_TO_ADDR x1, w1
+ ldr x2, [xFP, #OFF_FP_METHOD]
mov x3, xSELF
PREFETCH_INST 2 // Get next inst, but don't advance rPC
- bl artSet64IndirectStaticFromMterp
+ bl MterpSet64Static
cbnz w0, MterpException // 0 on success, -1 on failure
ADVANCE 2 // Past exception point - now advance rPC
GET_INST_OPCODE ip // extract opcode from wINST
diff --git a/runtime/interpreter/mterp/mips/op_sget.S b/runtime/interpreter/mterp/mips/op_sget.S
index 64ece1e..635df8a 100644
--- a/runtime/interpreter/mterp/mips/op_sget.S
+++ b/runtime/interpreter/mterp/mips/op_sget.S
@@ -1,4 +1,4 @@
-%default { "is_object":"0", "helper":"artGet32StaticFromCode" }
+%default { "is_object":"0", "helper":"MterpGet32Static" }
/*
* General SGET handler.
*
diff --git a/runtime/interpreter/mterp/mips/op_sget_boolean.S b/runtime/interpreter/mterp/mips/op_sget_boolean.S
index 45a5a70..7829970 100644
--- a/runtime/interpreter/mterp/mips/op_sget_boolean.S
+++ b/runtime/interpreter/mterp/mips/op_sget_boolean.S
@@ -1 +1 @@
-%include "mips/op_sget.S" {"helper":"artGetBooleanStaticFromCode"}
+%include "mips/op_sget.S" {"helper":"MterpGetBooleanStatic"}
diff --git a/runtime/interpreter/mterp/mips/op_sget_byte.S b/runtime/interpreter/mterp/mips/op_sget_byte.S
index 319122c..ee08342 100644
--- a/runtime/interpreter/mterp/mips/op_sget_byte.S
+++ b/runtime/interpreter/mterp/mips/op_sget_byte.S
@@ -1 +1 @@
-%include "mips/op_sget.S" {"helper":"artGetByteStaticFromCode"}
+%include "mips/op_sget.S" {"helper":"MterpGetByteStatic"}
diff --git a/runtime/interpreter/mterp/mips/op_sget_char.S b/runtime/interpreter/mterp/mips/op_sget_char.S
index 7103847..d8b477a 100644
--- a/runtime/interpreter/mterp/mips/op_sget_char.S
+++ b/runtime/interpreter/mterp/mips/op_sget_char.S
@@ -1 +1 @@
-%include "mips/op_sget.S" {"helper":"artGetCharStaticFromCode"}
+%include "mips/op_sget.S" {"helper":"MterpGetCharStatic"}
diff --git a/runtime/interpreter/mterp/mips/op_sget_object.S b/runtime/interpreter/mterp/mips/op_sget_object.S
index b205f51..2dc00c3 100644
--- a/runtime/interpreter/mterp/mips/op_sget_object.S
+++ b/runtime/interpreter/mterp/mips/op_sget_object.S
@@ -1 +1 @@
-%include "mips/op_sget.S" {"is_object":"1", "helper":"artGetObjStaticFromCode"}
+%include "mips/op_sget.S" {"is_object":"1", "helper":"MterpGetObjStatic"}
diff --git a/runtime/interpreter/mterp/mips/op_sget_short.S b/runtime/interpreter/mterp/mips/op_sget_short.S
index 3301823..ab55d93 100644
--- a/runtime/interpreter/mterp/mips/op_sget_short.S
+++ b/runtime/interpreter/mterp/mips/op_sget_short.S
@@ -1 +1 @@
-%include "mips/op_sget.S" {"helper":"artGetShortStaticFromCode"}
+%include "mips/op_sget.S" {"helper":"MterpGetShortStatic"}
diff --git a/runtime/interpreter/mterp/mips/op_sget_wide.S b/runtime/interpreter/mterp/mips/op_sget_wide.S
index c729250..ec4295a 100644
--- a/runtime/interpreter/mterp/mips/op_sget_wide.S
+++ b/runtime/interpreter/mterp/mips/op_sget_wide.S
@@ -2,12 +2,12 @@
* 64-bit SGET handler.
*/
/* sget-wide vAA, field@BBBB */
- .extern artGet64StaticFromCode
+ .extern MterpGet64Static
EXPORT_PC()
FETCH(a0, 1) # a0 <- field ref BBBB
lw a1, OFF_FP_METHOD(rFP) # a1 <- method
move a2, rSELF # a2 <- self
- JAL(artGet64StaticFromCode)
+ JAL(MterpGet64Static)
lw a3, THREAD_EXCEPTION_OFFSET(rSELF)
bnez a3, MterpException
GET_OPA(a1) # a1 <- AA
diff --git a/runtime/interpreter/mterp/mips/op_sput.S b/runtime/interpreter/mterp/mips/op_sput.S
index 7034a0e..37f8687 100644
--- a/runtime/interpreter/mterp/mips/op_sput.S
+++ b/runtime/interpreter/mterp/mips/op_sput.S
@@ -1,4 +1,4 @@
-%default { "helper":"artSet32StaticFromCode"}
+%default { "helper":"MterpSet32Static"}
/*
* General SPUT handler.
*
diff --git a/runtime/interpreter/mterp/mips/op_sput_boolean.S b/runtime/interpreter/mterp/mips/op_sput_boolean.S
index 7909ef5..6426cd4 100644
--- a/runtime/interpreter/mterp/mips/op_sput_boolean.S
+++ b/runtime/interpreter/mterp/mips/op_sput_boolean.S
@@ -1 +1 @@
-%include "mips/op_sput.S" {"helper":"artSet8StaticFromCode"}
+%include "mips/op_sput.S" {"helper":"MterpSetBooleanStatic"}
diff --git a/runtime/interpreter/mterp/mips/op_sput_byte.S b/runtime/interpreter/mterp/mips/op_sput_byte.S
index 7909ef5..c68d18f 100644
--- a/runtime/interpreter/mterp/mips/op_sput_byte.S
+++ b/runtime/interpreter/mterp/mips/op_sput_byte.S
@@ -1 +1 @@
-%include "mips/op_sput.S" {"helper":"artSet8StaticFromCode"}
+%include "mips/op_sput.S" {"helper":"MterpSetByteStatic"}
diff --git a/runtime/interpreter/mterp/mips/op_sput_char.S b/runtime/interpreter/mterp/mips/op_sput_char.S
index 188195c..9b8983e 100644
--- a/runtime/interpreter/mterp/mips/op_sput_char.S
+++ b/runtime/interpreter/mterp/mips/op_sput_char.S
@@ -1 +1 @@
-%include "mips/op_sput.S" {"helper":"artSet16StaticFromCode"}
+%include "mips/op_sput.S" {"helper":"MterpSetCharStatic"}
diff --git a/runtime/interpreter/mterp/mips/op_sput_short.S b/runtime/interpreter/mterp/mips/op_sput_short.S
index 188195c..5a57ed9 100644
--- a/runtime/interpreter/mterp/mips/op_sput_short.S
+++ b/runtime/interpreter/mterp/mips/op_sput_short.S
@@ -1 +1 @@
-%include "mips/op_sput.S" {"helper":"artSet16StaticFromCode"}
+%include "mips/op_sput.S" {"helper":"MterpSetShortStatic"}
diff --git a/runtime/interpreter/mterp/mips/op_sput_wide.S b/runtime/interpreter/mterp/mips/op_sput_wide.S
index 3b347fc..c090007 100644
--- a/runtime/interpreter/mterp/mips/op_sput_wide.S
+++ b/runtime/interpreter/mterp/mips/op_sput_wide.S
@@ -2,15 +2,15 @@
* 64-bit SPUT handler.
*/
/* sput-wide vAA, field@BBBB */
- .extern artSet64IndirectStaticFromMterp
+ .extern MterpSet64Static
EXPORT_PC()
FETCH(a0, 1) # a0 <- field ref CCCC
- lw a1, OFF_FP_METHOD(rFP) # a1 <- method
- GET_OPA(a2) # a2 <- AA
- EAS2(a2, rFP, a2) # a2 <- &fp[AA]
+ GET_OPA(a1) # a1 <- AA
+ EAS2(a1, rFP, a1) # a1 <- &fp[AA]
+ lw a2, OFF_FP_METHOD(rFP) # a2 <- method
move a3, rSELF # a3 <- self
PREFETCH_INST(2) # load rINST
- JAL(artSet64IndirectStaticFromMterp)
+ JAL(MterpSet64Static)
bnez v0, MterpException # bail out
ADVANCE(2) # advance rPC
GET_INST_OPCODE(t0) # extract opcode from rINST
diff --git a/runtime/interpreter/mterp/mips64/op_sget.S b/runtime/interpreter/mterp/mips64/op_sget.S
index bd2cfe3..71046db 100644
--- a/runtime/interpreter/mterp/mips64/op_sget.S
+++ b/runtime/interpreter/mterp/mips64/op_sget.S
@@ -1,4 +1,4 @@
-%default { "is_object":"0", "helper":"artGet32StaticFromCode", "extend":"" }
+%default { "is_object":"0", "helper":"MterpGet32Static", "extend":"" }
/*
* General SGET handler wrapper.
*
diff --git a/runtime/interpreter/mterp/mips64/op_sget_boolean.S b/runtime/interpreter/mterp/mips64/op_sget_boolean.S
index e7b1844..ec1ce9e 100644
--- a/runtime/interpreter/mterp/mips64/op_sget_boolean.S
+++ b/runtime/interpreter/mterp/mips64/op_sget_boolean.S
@@ -1 +1 @@
-%include "mips64/op_sget.S" {"helper":"artGetBooleanStaticFromCode", "extend":"and v0, v0, 0xff"}
+%include "mips64/op_sget.S" {"helper":"MterpGetBooleanStatic", "extend":"and v0, v0, 0xff"}
diff --git a/runtime/interpreter/mterp/mips64/op_sget_byte.S b/runtime/interpreter/mterp/mips64/op_sget_byte.S
index 52a2e4a..6a802f6 100644
--- a/runtime/interpreter/mterp/mips64/op_sget_byte.S
+++ b/runtime/interpreter/mterp/mips64/op_sget_byte.S
@@ -1 +1 @@
-%include "mips64/op_sget.S" {"helper":"artGetByteStaticFromCode", "extend":"seb v0, v0"}
+%include "mips64/op_sget.S" {"helper":"MterpGetByteStatic", "extend":"seb v0, v0"}
diff --git a/runtime/interpreter/mterp/mips64/op_sget_char.S b/runtime/interpreter/mterp/mips64/op_sget_char.S
index 873d82a..483d085 100644
--- a/runtime/interpreter/mterp/mips64/op_sget_char.S
+++ b/runtime/interpreter/mterp/mips64/op_sget_char.S
@@ -1 +1 @@
-%include "mips64/op_sget.S" {"helper":"artGetCharStaticFromCode", "extend":"and v0, v0, 0xffff"}
+%include "mips64/op_sget.S" {"helper":"MterpGetCharStatic", "extend":"and v0, v0, 0xffff"}
diff --git a/runtime/interpreter/mterp/mips64/op_sget_object.S b/runtime/interpreter/mterp/mips64/op_sget_object.S
index 3108417..2250696 100644
--- a/runtime/interpreter/mterp/mips64/op_sget_object.S
+++ b/runtime/interpreter/mterp/mips64/op_sget_object.S
@@ -1 +1 @@
-%include "mips64/op_sget.S" {"is_object":"1", "helper":"artGetObjStaticFromCode"}
+%include "mips64/op_sget.S" {"is_object":"1", "helper":"MterpGetObjStatic"}
diff --git a/runtime/interpreter/mterp/mips64/op_sget_short.S b/runtime/interpreter/mterp/mips64/op_sget_short.S
index fed4e76..b257bbb 100644
--- a/runtime/interpreter/mterp/mips64/op_sget_short.S
+++ b/runtime/interpreter/mterp/mips64/op_sget_short.S
@@ -1 +1 @@
-%include "mips64/op_sget.S" {"helper":"artGetShortStaticFromCode", "extend":"seh v0, v0"}
+%include "mips64/op_sget.S" {"helper":"MterpGetShortStatic", "extend":"seh v0, v0"}
diff --git a/runtime/interpreter/mterp/mips64/op_sget_wide.S b/runtime/interpreter/mterp/mips64/op_sget_wide.S
index 77124d1..ace64f8 100644
--- a/runtime/interpreter/mterp/mips64/op_sget_wide.S
+++ b/runtime/interpreter/mterp/mips64/op_sget_wide.S
@@ -3,12 +3,12 @@
*
*/
/* sget-wide vAA, field//BBBB */
- .extern artGet64StaticFromCode
+ .extern MterpGet64Static
EXPORT_PC
lhu a0, 2(rPC) # a0 <- field ref BBBB
ld a1, OFF_FP_METHOD(rFP)
move a2, rSELF
- jal artGet64StaticFromCode
+ jal MterpGet64Static
ld a3, THREAD_EXCEPTION_OFFSET(rSELF)
srl a4, rINST, 8 # a4 <- AA
bnez a3, MterpException # bail out
diff --git a/runtime/interpreter/mterp/mips64/op_sput.S b/runtime/interpreter/mterp/mips64/op_sput.S
index 142f18f..466f333 100644
--- a/runtime/interpreter/mterp/mips64/op_sput.S
+++ b/runtime/interpreter/mterp/mips64/op_sput.S
@@ -1,4 +1,4 @@
-%default { "helper":"artSet32StaticFromCode" }
+%default { "helper":"MterpSet32Static" }
/*
* General SPUT handler wrapper.
*
diff --git a/runtime/interpreter/mterp/mips64/op_sput_boolean.S b/runtime/interpreter/mterp/mips64/op_sput_boolean.S
index f5b8dbf..eba58f7 100644
--- a/runtime/interpreter/mterp/mips64/op_sput_boolean.S
+++ b/runtime/interpreter/mterp/mips64/op_sput_boolean.S
@@ -1 +1 @@
-%include "mips64/op_sput.S" {"helper":"artSet8StaticFromCode"}
+%include "mips64/op_sput.S" {"helper":"MterpSetBooleanStatic"}
diff --git a/runtime/interpreter/mterp/mips64/op_sput_byte.S b/runtime/interpreter/mterp/mips64/op_sput_byte.S
index f5b8dbf..80a26c0 100644
--- a/runtime/interpreter/mterp/mips64/op_sput_byte.S
+++ b/runtime/interpreter/mterp/mips64/op_sput_byte.S
@@ -1 +1 @@
-%include "mips64/op_sput.S" {"helper":"artSet8StaticFromCode"}
+%include "mips64/op_sput.S" {"helper":"MterpSetByteStatic"}
diff --git a/runtime/interpreter/mterp/mips64/op_sput_char.S b/runtime/interpreter/mterp/mips64/op_sput_char.S
index c4d195c..c0d5bf3 100644
--- a/runtime/interpreter/mterp/mips64/op_sput_char.S
+++ b/runtime/interpreter/mterp/mips64/op_sput_char.S
@@ -1 +1 @@
-%include "mips64/op_sput.S" {"helper":"artSet16StaticFromCode"}
+%include "mips64/op_sput.S" {"helper":"MterpSetCharStatic"}
diff --git a/runtime/interpreter/mterp/mips64/op_sput_short.S b/runtime/interpreter/mterp/mips64/op_sput_short.S
index c4d195c..b001832 100644
--- a/runtime/interpreter/mterp/mips64/op_sput_short.S
+++ b/runtime/interpreter/mterp/mips64/op_sput_short.S
@@ -1 +1 @@
-%include "mips64/op_sput.S" {"helper":"artSet16StaticFromCode"}
+%include "mips64/op_sput.S" {"helper":"MterpSetShortStatic"}
diff --git a/runtime/interpreter/mterp/mips64/op_sput_wide.S b/runtime/interpreter/mterp/mips64/op_sput_wide.S
index 828ddc1..aa3d5b4 100644
--- a/runtime/interpreter/mterp/mips64/op_sput_wide.S
+++ b/runtime/interpreter/mterp/mips64/op_sput_wide.S
@@ -3,15 +3,15 @@
*
*/
/* sput-wide vAA, field//BBBB */
- .extern artSet64IndirectStaticFromMterp
+ .extern MterpSet64Static
EXPORT_PC
lhu a0, 2(rPC) # a0 <- field ref BBBB
- ld a1, OFF_FP_METHOD(rFP)
- srl a2, rINST, 8 # a2 <- AA
- dlsa a2, a2, rFP, 2
+ srl a1, rINST, 8 # a2 <- AA
+ dlsa a1, a1, rFP, 2
+ ld a2, OFF_FP_METHOD(rFP)
move a3, rSELF
PREFETCH_INST 2 # Get next inst, but don't advance rPC
- jal artSet64IndirectStaticFromMterp
+ jal MterpSet64Static
bnezc v0, MterpException # 0 on success, -1 on failure
ADVANCE 2 # Past exception point - now advance rPC
GET_INST_OPCODE v0 # extract opcode from rINST
diff --git a/runtime/interpreter/mterp/mterp.cc b/runtime/interpreter/mterp/mterp.cc
index 75ab91a..8bf094e 100644
--- a/runtime/interpreter/mterp/mterp.cc
+++ b/runtime/interpreter/mterp/mterp.cc
@@ -587,27 +587,6 @@
return MterpShouldSwitchInterpreters();
}
-extern "C" ssize_t artSet64IndirectStaticFromMterp(uint32_t field_idx,
- ArtMethod* referrer,
- uint64_t* new_value,
- Thread* self)
- REQUIRES_SHARED(Locks::mutator_lock_) {
- ScopedQuickEntrypointChecks sqec(self);
- ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite, sizeof(int64_t));
- if (LIKELY(field != nullptr)) {
- // Compiled code can't use transactional mode.
- field->Set64<false>(field->GetDeclaringClass(), *new_value);
- return 0; // success
- }
- field = FindFieldFromCode<StaticPrimitiveWrite, true>(field_idx, referrer, self, sizeof(int64_t));
- if (LIKELY(field != nullptr)) {
- // Compiled code can't use transactional mode.
- field->Set64<false>(field->GetDeclaringClass(), *new_value);
- return 0; // success
- }
- return -1; // failure
-}
-
extern "C" ssize_t artSet8InstanceFromMterp(uint32_t field_idx,
mirror::Object* obj,
uint8_t new_value,
@@ -689,7 +668,187 @@
return -1; // failure
}
-extern "C" mirror::Object* artAGetObjectFromMterp(mirror::Object* arr, int32_t index)
+template <typename return_type, Primitive::Type primitive_type>
+ALWAYS_INLINE return_type MterpGetStatic(uint32_t field_idx,
+ ArtMethod* referrer,
+ Thread* self,
+ return_type (ArtField::*func)(ObjPtr<mirror::Object>))
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ return_type res = 0; // On exception, the result will be ignored.
+ ArtField* f =
+ FindFieldFromCode<StaticPrimitiveRead, false>(field_idx,
+ referrer,
+ self,
+ primitive_type);
+ if (LIKELY(f != nullptr)) {
+ ObjPtr<mirror::Object> obj = f->GetDeclaringClass();
+ res = (f->*func)(obj);
+ }
+ return res;
+}
+
+extern "C" int32_t MterpGetBooleanStatic(uint32_t field_idx,
+ ArtMethod* referrer,
+ Thread* self)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ return MterpGetStatic<uint8_t, Primitive::kPrimBoolean>(field_idx,
+ referrer,
+ self,
+ &ArtField::GetBoolean);
+}
+
+extern "C" int32_t MterpGetByteStatic(uint32_t field_idx,
+ ArtMethod* referrer,
+ Thread* self)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ return MterpGetStatic<int8_t, Primitive::kPrimByte>(field_idx,
+ referrer,
+ self,
+ &ArtField::GetByte);
+}
+
+extern "C" uint32_t MterpGetCharStatic(uint32_t field_idx,
+ ArtMethod* referrer,
+ Thread* self)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ return MterpGetStatic<uint16_t, Primitive::kPrimChar>(field_idx,
+ referrer,
+ self,
+ &ArtField::GetChar);
+}
+
+extern "C" int32_t MterpGetShortStatic(uint32_t field_idx,
+ ArtMethod* referrer,
+ Thread* self)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ return MterpGetStatic<int16_t, Primitive::kPrimShort>(field_idx,
+ referrer,
+ self,
+ &ArtField::GetShort);
+}
+
+extern "C" mirror::Object* MterpGetObjStatic(uint32_t field_idx,
+ ArtMethod* referrer,
+ Thread* self)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ return MterpGetStatic<ObjPtr<mirror::Object>, Primitive::kPrimNot>(field_idx,
+ referrer,
+ self,
+ &ArtField::GetObject).Ptr();
+}
+
+extern "C" int32_t MterpGet32Static(uint32_t field_idx,
+ ArtMethod* referrer,
+ Thread* self)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ return MterpGetStatic<int32_t, Primitive::kPrimInt>(field_idx,
+ referrer,
+ self,
+ &ArtField::GetInt);
+}
+
+extern "C" int64_t MterpGet64Static(uint32_t field_idx, ArtMethod* referrer, Thread* self)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ return MterpGetStatic<int64_t, Primitive::kPrimLong>(field_idx,
+ referrer,
+ self,
+ &ArtField::GetLong);
+}
+
+
+template <typename field_type, Primitive::Type primitive_type>
+int MterpSetStatic(uint32_t field_idx,
+ field_type new_value,
+ ArtMethod* referrer,
+ Thread* self,
+ void (ArtField::*func)(ObjPtr<mirror::Object>, field_type val))
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ int res = 0; // Assume success (following quick_field_entrypoints conventions)
+ ArtField* f =
+ FindFieldFromCode<StaticPrimitiveWrite, false>(field_idx, referrer, self, primitive_type);
+ if (LIKELY(f != nullptr)) {
+ ObjPtr<mirror::Object> obj = f->GetDeclaringClass();
+ (f->*func)(obj, new_value);
+ } else {
+ res = -1; // Failure
+ }
+ return res;
+}
+
+extern "C" int MterpSetBooleanStatic(uint32_t field_idx,
+ uint8_t new_value,
+ ArtMethod* referrer,
+ Thread* self)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ return MterpSetStatic<uint8_t, Primitive::kPrimBoolean>(field_idx,
+ new_value,
+ referrer,
+ self,
+ &ArtField::SetBoolean<false>);
+}
+
+extern "C" int MterpSetByteStatic(uint32_t field_idx,
+ int8_t new_value,
+ ArtMethod* referrer,
+ Thread* self)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ return MterpSetStatic<int8_t, Primitive::kPrimByte>(field_idx,
+ new_value,
+ referrer,
+ self,
+ &ArtField::SetByte<false>);
+}
+
+extern "C" int MterpSetCharStatic(uint32_t field_idx,
+ uint16_t new_value,
+ ArtMethod* referrer,
+ Thread* self)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ return MterpSetStatic<uint16_t, Primitive::kPrimChar>(field_idx,
+ new_value,
+ referrer,
+ self,
+ &ArtField::SetChar<false>);
+}
+
+extern "C" int MterpSetShortStatic(uint32_t field_idx,
+ int16_t new_value,
+ ArtMethod* referrer,
+ Thread* self)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ return MterpSetStatic<int16_t, Primitive::kPrimShort>(field_idx,
+ new_value,
+ referrer,
+ self,
+ &ArtField::SetShort<false>);
+}
+
+extern "C" int MterpSet32Static(uint32_t field_idx,
+ int32_t new_value,
+ ArtMethod* referrer,
+ Thread* self)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ return MterpSetStatic<int32_t, Primitive::kPrimInt>(field_idx,
+ new_value,
+ referrer,
+ self,
+ &ArtField::SetInt<false>);
+}
+
+extern "C" int MterpSet64Static(uint32_t field_idx,
+ int64_t* new_value,
+ ArtMethod* referrer,
+ Thread* self)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ return MterpSetStatic<int64_t, Primitive::kPrimLong>(field_idx,
+ *new_value,
+ referrer,
+ self,
+ &ArtField::SetLong<false>);
+}
+
+extern "C" mirror::Object* artAGetObjectFromMterp(mirror::Object* arr,
+ int32_t index)
REQUIRES_SHARED(Locks::mutator_lock_) {
if (UNLIKELY(arr == nullptr)) {
ThrowNullPointerExceptionFromInterpreter();
@@ -703,7 +862,8 @@
}
}
-extern "C" mirror::Object* artIGetObjectFromMterp(mirror::Object* obj, uint32_t field_offset)
+extern "C" mirror::Object* artIGetObjectFromMterp(mirror::Object* obj,
+ uint32_t field_offset)
REQUIRES_SHARED(Locks::mutator_lock_) {
if (UNLIKELY(obj == nullptr)) {
ThrowNullPointerExceptionFromInterpreter();
diff --git a/runtime/interpreter/mterp/out/mterp_arm.S b/runtime/interpreter/mterp/out/mterp_arm.S
index 576020f..e2b693f 100644
--- a/runtime/interpreter/mterp/out/mterp_arm.S
+++ b/runtime/interpreter/mterp/out/mterp_arm.S
@@ -2631,12 +2631,12 @@
*/
/* op vAA, field@BBBB */
- .extern artGet32StaticFromCode
+ .extern MterpGet32Static
EXPORT_PC
FETCH r0, 1 @ r0<- field ref BBBB
ldr r1, [rFP, #OFF_FP_METHOD]
mov r2, rSELF
- bl artGet32StaticFromCode
+ bl MterpGet32Static
ldr r3, [rSELF, #THREAD_EXCEPTION_OFFSET]
mov r2, rINST, lsr #8 @ r2<- AA
PREFETCH_INST 2
@@ -2661,12 +2661,12 @@
*/
/* sget-wide vAA, field@BBBB */
- .extern artGet64StaticFromCode
+ .extern MterpGet64Static
EXPORT_PC
FETCH r0, 1 @ r0<- field ref BBBB
ldr r1, [rFP, #OFF_FP_METHOD]
mov r2, rSELF
- bl artGet64StaticFromCode
+ bl MterpGet64Static
ldr r3, [rSELF, #THREAD_EXCEPTION_OFFSET]
mov r9, rINST, lsr #8 @ r9<- AA
VREG_INDEX_TO_ADDR lr, r9 @ r9<- &fp[AA]
@@ -2690,12 +2690,12 @@
*/
/* op vAA, field@BBBB */
- .extern artGetObjStaticFromCode
+ .extern MterpGetObjStatic
EXPORT_PC
FETCH r0, 1 @ r0<- field ref BBBB
ldr r1, [rFP, #OFF_FP_METHOD]
mov r2, rSELF
- bl artGetObjStaticFromCode
+ bl MterpGetObjStatic
ldr r3, [rSELF, #THREAD_EXCEPTION_OFFSET]
mov r2, rINST, lsr #8 @ r2<- AA
PREFETCH_INST 2
@@ -2723,12 +2723,12 @@
*/
/* op vAA, field@BBBB */
- .extern artGetBooleanStaticFromCode
+ .extern MterpGetBooleanStatic
EXPORT_PC
FETCH r0, 1 @ r0<- field ref BBBB
ldr r1, [rFP, #OFF_FP_METHOD]
mov r2, rSELF
- bl artGetBooleanStaticFromCode
+ bl MterpGetBooleanStatic
ldr r3, [rSELF, #THREAD_EXCEPTION_OFFSET]
mov r2, rINST, lsr #8 @ r2<- AA
PREFETCH_INST 2
@@ -2756,12 +2756,12 @@
*/
/* op vAA, field@BBBB */
- .extern artGetByteStaticFromCode
+ .extern MterpGetByteStatic
EXPORT_PC
FETCH r0, 1 @ r0<- field ref BBBB
ldr r1, [rFP, #OFF_FP_METHOD]
mov r2, rSELF
- bl artGetByteStaticFromCode
+ bl MterpGetByteStatic
ldr r3, [rSELF, #THREAD_EXCEPTION_OFFSET]
mov r2, rINST, lsr #8 @ r2<- AA
PREFETCH_INST 2
@@ -2789,12 +2789,12 @@
*/
/* op vAA, field@BBBB */
- .extern artGetCharStaticFromCode
+ .extern MterpGetCharStatic
EXPORT_PC
FETCH r0, 1 @ r0<- field ref BBBB
ldr r1, [rFP, #OFF_FP_METHOD]
mov r2, rSELF
- bl artGetCharStaticFromCode
+ bl MterpGetCharStatic
ldr r3, [rSELF, #THREAD_EXCEPTION_OFFSET]
mov r2, rINST, lsr #8 @ r2<- AA
PREFETCH_INST 2
@@ -2822,12 +2822,12 @@
*/
/* op vAA, field@BBBB */
- .extern artGetShortStaticFromCode
+ .extern MterpGetShortStatic
EXPORT_PC
FETCH r0, 1 @ r0<- field ref BBBB
ldr r1, [rFP, #OFF_FP_METHOD]
mov r2, rSELF
- bl artGetShortStaticFromCode
+ bl MterpGetShortStatic
ldr r3, [rSELF, #THREAD_EXCEPTION_OFFSET]
mov r2, rINST, lsr #8 @ r2<- AA
PREFETCH_INST 2
@@ -2860,7 +2860,7 @@
ldr r2, [rFP, #OFF_FP_METHOD]
mov r3, rSELF
PREFETCH_INST 2 @ Get next inst, but don't advance rPC
- bl artSet32StaticFromCode
+ bl MterpSet32Static
cmp r0, #0 @ 0 on success, -1 on failure
bne MterpException
ADVANCE 2 @ Past exception point - now advance rPC
@@ -2876,15 +2876,15 @@
*
*/
/* sput-wide vAA, field@BBBB */
- .extern artSet64IndirectStaticFromMterp
+ .extern MterpSet64Static
EXPORT_PC
FETCH r0, 1 @ r0<- field ref BBBB
- ldr r1, [rFP, #OFF_FP_METHOD]
- mov r2, rINST, lsr #8 @ r3<- AA
- VREG_INDEX_TO_ADDR r2, r2
+ mov r1, rINST, lsr #8 @ r1<- AA
+ VREG_INDEX_TO_ADDR r1, r1
+ ldr r2, [rFP, #OFF_FP_METHOD]
mov r3, rSELF
PREFETCH_INST 2 @ Get next inst, but don't advance rPC
- bl artSet64IndirectStaticFromMterp
+ bl MterpSet64Static
cmp r0, #0 @ 0 on success, -1 on failure
bne MterpException
ADVANCE 2 @ Past exception point - now advance rPC
@@ -2925,7 +2925,7 @@
ldr r2, [rFP, #OFF_FP_METHOD]
mov r3, rSELF
PREFETCH_INST 2 @ Get next inst, but don't advance rPC
- bl artSet8StaticFromCode
+ bl MterpSetBooleanStatic
cmp r0, #0 @ 0 on success, -1 on failure
bne MterpException
ADVANCE 2 @ Past exception point - now advance rPC
@@ -2951,7 +2951,7 @@
ldr r2, [rFP, #OFF_FP_METHOD]
mov r3, rSELF
PREFETCH_INST 2 @ Get next inst, but don't advance rPC
- bl artSet8StaticFromCode
+ bl MterpSetByteStatic
cmp r0, #0 @ 0 on success, -1 on failure
bne MterpException
ADVANCE 2 @ Past exception point - now advance rPC
@@ -2977,7 +2977,7 @@
ldr r2, [rFP, #OFF_FP_METHOD]
mov r3, rSELF
PREFETCH_INST 2 @ Get next inst, but don't advance rPC
- bl artSet16StaticFromCode
+ bl MterpSetCharStatic
cmp r0, #0 @ 0 on success, -1 on failure
bne MterpException
ADVANCE 2 @ Past exception point - now advance rPC
@@ -3003,7 +3003,7 @@
ldr r2, [rFP, #OFF_FP_METHOD]
mov r3, rSELF
PREFETCH_INST 2 @ Get next inst, but don't advance rPC
- bl artSet16StaticFromCode
+ bl MterpSetShortStatic
cmp r0, #0 @ 0 on success, -1 on failure
bne MterpException
ADVANCE 2 @ Past exception point - now advance rPC
diff --git a/runtime/interpreter/mterp/out/mterp_arm64.S b/runtime/interpreter/mterp/out/mterp_arm64.S
index a7b5587..ef5a4da 100644
--- a/runtime/interpreter/mterp/out/mterp_arm64.S
+++ b/runtime/interpreter/mterp/out/mterp_arm64.S
@@ -2543,12 +2543,12 @@
*/
/* op vAA, field//BBBB */
- .extern artGet32StaticFromCode
+ .extern MterpGet32Static
EXPORT_PC
FETCH w0, 1 // w0<- field ref BBBB
ldr x1, [xFP, #OFF_FP_METHOD]
mov x2, xSELF
- bl artGet32StaticFromCode
+ bl MterpGet32Static
ldr x3, [xSELF, #THREAD_EXCEPTION_OFFSET]
lsr w2, wINST, #8 // w2<- AA
@@ -2573,12 +2573,12 @@
*/
/* sget-wide vAA, field//BBBB */
- .extern artGet64StaticFromCode
+ .extern MterpGet64StaticFromCode
EXPORT_PC
FETCH w0, 1 // w0<- field ref BBBB
ldr x1, [xFP, #OFF_FP_METHOD]
mov x2, xSELF
- bl artGet64StaticFromCode
+ bl MterpGet64Static
ldr x3, [xSELF, #THREAD_EXCEPTION_OFFSET]
lsr w4, wINST, #8 // w4<- AA
cbnz x3, MterpException // bail out
@@ -2599,12 +2599,12 @@
*/
/* op vAA, field//BBBB */
- .extern artGetObjStaticFromCode
+ .extern MterpGetObjStatic
EXPORT_PC
FETCH w0, 1 // w0<- field ref BBBB
ldr x1, [xFP, #OFF_FP_METHOD]
mov x2, xSELF
- bl artGetObjStaticFromCode
+ bl MterpGetObjStatic
ldr x3, [xSELF, #THREAD_EXCEPTION_OFFSET]
lsr w2, wINST, #8 // w2<- AA
@@ -2632,12 +2632,12 @@
*/
/* op vAA, field//BBBB */
- .extern artGetBooleanStaticFromCode
+ .extern MterpGetBooleanStatic
EXPORT_PC
FETCH w0, 1 // w0<- field ref BBBB
ldr x1, [xFP, #OFF_FP_METHOD]
mov x2, xSELF
- bl artGetBooleanStaticFromCode
+ bl MterpGetBooleanStatic
ldr x3, [xSELF, #THREAD_EXCEPTION_OFFSET]
lsr w2, wINST, #8 // w2<- AA
uxtb w0, w0
@@ -2665,12 +2665,12 @@
*/
/* op vAA, field//BBBB */
- .extern artGetByteStaticFromCode
+ .extern MterpGetByteStatic
EXPORT_PC
FETCH w0, 1 // w0<- field ref BBBB
ldr x1, [xFP, #OFF_FP_METHOD]
mov x2, xSELF
- bl artGetByteStaticFromCode
+ bl MterpGetByteStatic
ldr x3, [xSELF, #THREAD_EXCEPTION_OFFSET]
lsr w2, wINST, #8 // w2<- AA
sxtb w0, w0
@@ -2698,12 +2698,12 @@
*/
/* op vAA, field//BBBB */
- .extern artGetCharStaticFromCode
+ .extern MterpGetCharStatic
EXPORT_PC
FETCH w0, 1 // w0<- field ref BBBB
ldr x1, [xFP, #OFF_FP_METHOD]
mov x2, xSELF
- bl artGetCharStaticFromCode
+ bl MterpGetCharStatic
ldr x3, [xSELF, #THREAD_EXCEPTION_OFFSET]
lsr w2, wINST, #8 // w2<- AA
uxth w0, w0
@@ -2731,12 +2731,12 @@
*/
/* op vAA, field//BBBB */
- .extern artGetShortStaticFromCode
+ .extern MterpGetShortStatic
EXPORT_PC
FETCH w0, 1 // w0<- field ref BBBB
ldr x1, [xFP, #OFF_FP_METHOD]
mov x2, xSELF
- bl artGetShortStaticFromCode
+ bl MterpGetShortStatic
ldr x3, [xSELF, #THREAD_EXCEPTION_OFFSET]
lsr w2, wINST, #8 // w2<- AA
sxth w0, w0
@@ -2769,7 +2769,7 @@
ldr x2, [xFP, #OFF_FP_METHOD]
mov x3, xSELF
PREFETCH_INST 2 // Get next inst, but don't advance rPC
- bl artSet32StaticFromCode
+ bl MterpSet32Static
cbnz w0, MterpException // 0 on success
ADVANCE 2 // Past exception point - now advance rPC
GET_INST_OPCODE ip // extract opcode from rINST
@@ -2784,15 +2784,15 @@
*
*/
/* sput-wide vAA, field//BBBB */
- .extern artSet64IndirectStaticFromMterp
+ .extern MterpSet64Static
EXPORT_PC
FETCH w0, 1 // w0<- field ref BBBB
- ldr x1, [xFP, #OFF_FP_METHOD]
- lsr w2, wINST, #8 // w3<- AA
- VREG_INDEX_TO_ADDR x2, w2
+ lsr w1, wINST, #8 // w1<- AA
+ VREG_INDEX_TO_ADDR x1, w1
+ ldr x2, [xFP, #OFF_FP_METHOD]
mov x3, xSELF
PREFETCH_INST 2 // Get next inst, but don't advance rPC
- bl artSet64IndirectStaticFromMterp
+ bl MterpSet64Static
cbnz w0, MterpException // 0 on success, -1 on failure
ADVANCE 2 // Past exception point - now advance rPC
GET_INST_OPCODE ip // extract opcode from wINST
@@ -2831,7 +2831,7 @@
ldr x2, [xFP, #OFF_FP_METHOD]
mov x3, xSELF
PREFETCH_INST 2 // Get next inst, but don't advance rPC
- bl artSet8StaticFromCode
+ bl MterpSetBooleanStatic
cbnz w0, MterpException // 0 on success
ADVANCE 2 // Past exception point - now advance rPC
GET_INST_OPCODE ip // extract opcode from rINST
@@ -2856,7 +2856,7 @@
ldr x2, [xFP, #OFF_FP_METHOD]
mov x3, xSELF
PREFETCH_INST 2 // Get next inst, but don't advance rPC
- bl artSet8StaticFromCode
+ bl MterpSetByteStatic
cbnz w0, MterpException // 0 on success
ADVANCE 2 // Past exception point - now advance rPC
GET_INST_OPCODE ip // extract opcode from rINST
@@ -2881,7 +2881,7 @@
ldr x2, [xFP, #OFF_FP_METHOD]
mov x3, xSELF
PREFETCH_INST 2 // Get next inst, but don't advance rPC
- bl artSet16StaticFromCode
+ bl MterpSetCharStatic
cbnz w0, MterpException // 0 on success
ADVANCE 2 // Past exception point - now advance rPC
GET_INST_OPCODE ip // extract opcode from rINST
@@ -2906,7 +2906,7 @@
ldr x2, [xFP, #OFF_FP_METHOD]
mov x3, xSELF
PREFETCH_INST 2 // Get next inst, but don't advance rPC
- bl artSet16StaticFromCode
+ bl MterpSetShortStatic
cbnz w0, MterpException // 0 on success
ADVANCE 2 // Past exception point - now advance rPC
GET_INST_OPCODE ip // extract opcode from rINST
diff --git a/runtime/interpreter/mterp/out/mterp_mips.S b/runtime/interpreter/mterp/out/mterp_mips.S
index b47c019..579afc2 100644
--- a/runtime/interpreter/mterp/out/mterp_mips.S
+++ b/runtime/interpreter/mterp/out/mterp_mips.S
@@ -3038,12 +3038,12 @@
* for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
*/
/* op vAA, field@BBBB */
- .extern artGet32StaticFromCode
+ .extern MterpGet32Static
EXPORT_PC()
FETCH(a0, 1) # a0 <- field ref BBBB
lw a1, OFF_FP_METHOD(rFP) # a1 <- method
move a2, rSELF # a2 <- self
- JAL(artGet32StaticFromCode)
+ JAL(MterpGet32Static)
lw a3, THREAD_EXCEPTION_OFFSET(rSELF)
GET_OPA(a2) # a2 <- AA
PREFETCH_INST(2)
@@ -3064,12 +3064,12 @@
* 64-bit SGET handler.
*/
/* sget-wide vAA, field@BBBB */
- .extern artGet64StaticFromCode
+ .extern MterpGet64Static
EXPORT_PC()
FETCH(a0, 1) # a0 <- field ref BBBB
lw a1, OFF_FP_METHOD(rFP) # a1 <- method
move a2, rSELF # a2 <- self
- JAL(artGet64StaticFromCode)
+ JAL(MterpGet64Static)
lw a3, THREAD_EXCEPTION_OFFSET(rSELF)
bnez a3, MterpException
GET_OPA(a1) # a1 <- AA
@@ -3088,12 +3088,12 @@
* for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
*/
/* op vAA, field@BBBB */
- .extern artGetObjStaticFromCode
+ .extern MterpGetObjStatic
EXPORT_PC()
FETCH(a0, 1) # a0 <- field ref BBBB
lw a1, OFF_FP_METHOD(rFP) # a1 <- method
move a2, rSELF # a2 <- self
- JAL(artGetObjStaticFromCode)
+ JAL(MterpGetObjStatic)
lw a3, THREAD_EXCEPTION_OFFSET(rSELF)
GET_OPA(a2) # a2 <- AA
PREFETCH_INST(2)
@@ -3118,12 +3118,12 @@
* for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
*/
/* op vAA, field@BBBB */
- .extern artGetBooleanStaticFromCode
+ .extern MterpGetBooleanStatic
EXPORT_PC()
FETCH(a0, 1) # a0 <- field ref BBBB
lw a1, OFF_FP_METHOD(rFP) # a1 <- method
move a2, rSELF # a2 <- self
- JAL(artGetBooleanStaticFromCode)
+ JAL(MterpGetBooleanStatic)
lw a3, THREAD_EXCEPTION_OFFSET(rSELF)
GET_OPA(a2) # a2 <- AA
PREFETCH_INST(2)
@@ -3148,12 +3148,12 @@
* for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
*/
/* op vAA, field@BBBB */
- .extern artGetByteStaticFromCode
+ .extern MterpGetByteStatic
EXPORT_PC()
FETCH(a0, 1) # a0 <- field ref BBBB
lw a1, OFF_FP_METHOD(rFP) # a1 <- method
move a2, rSELF # a2 <- self
- JAL(artGetByteStaticFromCode)
+ JAL(MterpGetByteStatic)
lw a3, THREAD_EXCEPTION_OFFSET(rSELF)
GET_OPA(a2) # a2 <- AA
PREFETCH_INST(2)
@@ -3178,12 +3178,12 @@
* for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
*/
/* op vAA, field@BBBB */
- .extern artGetCharStaticFromCode
+ .extern MterpGetCharStatic
EXPORT_PC()
FETCH(a0, 1) # a0 <- field ref BBBB
lw a1, OFF_FP_METHOD(rFP) # a1 <- method
move a2, rSELF # a2 <- self
- JAL(artGetCharStaticFromCode)
+ JAL(MterpGetCharStatic)
lw a3, THREAD_EXCEPTION_OFFSET(rSELF)
GET_OPA(a2) # a2 <- AA
PREFETCH_INST(2)
@@ -3208,12 +3208,12 @@
* for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
*/
/* op vAA, field@BBBB */
- .extern artGetShortStaticFromCode
+ .extern MterpGetShortStatic
EXPORT_PC()
FETCH(a0, 1) # a0 <- field ref BBBB
lw a1, OFF_FP_METHOD(rFP) # a1 <- method
move a2, rSELF # a2 <- self
- JAL(artGetShortStaticFromCode)
+ JAL(MterpGetShortStatic)
lw a3, THREAD_EXCEPTION_OFFSET(rSELF)
GET_OPA(a2) # a2 <- AA
PREFETCH_INST(2)
@@ -3244,7 +3244,7 @@
lw a2, OFF_FP_METHOD(rFP) # a2 <- method
move a3, rSELF # a3 <- self
PREFETCH_INST(2) # load rINST
- JAL(artSet32StaticFromCode)
+ JAL(MterpSet32Static)
bnez v0, MterpException # bail out
ADVANCE(2) # advance rPC
GET_INST_OPCODE(t0) # extract opcode from rINST
@@ -3258,15 +3258,15 @@
* 64-bit SPUT handler.
*/
/* sput-wide vAA, field@BBBB */
- .extern artSet64IndirectStaticFromMterp
+ .extern MterpSet64Static
EXPORT_PC()
FETCH(a0, 1) # a0 <- field ref CCCC
- lw a1, OFF_FP_METHOD(rFP) # a1 <- method
- GET_OPA(a2) # a2 <- AA
- EAS2(a2, rFP, a2) # a2 <- &fp[AA]
+ GET_OPA(a1) # a1 <- AA
+ EAS2(a1, rFP, a1) # a1 <- &fp[AA]
+ lw a2, OFF_FP_METHOD(rFP) # a2 <- method
move a3, rSELF # a3 <- self
PREFETCH_INST(2) # load rINST
- JAL(artSet64IndirectStaticFromMterp)
+ JAL(MterpSet64Static)
bnez v0, MterpException # bail out
ADVANCE(2) # advance rPC
GET_INST_OPCODE(t0) # extract opcode from rINST
@@ -3311,7 +3311,7 @@
lw a2, OFF_FP_METHOD(rFP) # a2 <- method
move a3, rSELF # a3 <- self
PREFETCH_INST(2) # load rINST
- JAL(artSet8StaticFromCode)
+ JAL(MterpSetBooleanStatic)
bnez v0, MterpException # bail out
ADVANCE(2) # advance rPC
GET_INST_OPCODE(t0) # extract opcode from rINST
@@ -3336,7 +3336,7 @@
lw a2, OFF_FP_METHOD(rFP) # a2 <- method
move a3, rSELF # a3 <- self
PREFETCH_INST(2) # load rINST
- JAL(artSet8StaticFromCode)
+ JAL(MterpSetByteStatic)
bnez v0, MterpException # bail out
ADVANCE(2) # advance rPC
GET_INST_OPCODE(t0) # extract opcode from rINST
@@ -3361,7 +3361,7 @@
lw a2, OFF_FP_METHOD(rFP) # a2 <- method
move a3, rSELF # a3 <- self
PREFETCH_INST(2) # load rINST
- JAL(artSet16StaticFromCode)
+ JAL(MterpSetCharStatic)
bnez v0, MterpException # bail out
ADVANCE(2) # advance rPC
GET_INST_OPCODE(t0) # extract opcode from rINST
@@ -3386,7 +3386,7 @@
lw a2, OFF_FP_METHOD(rFP) # a2 <- method
move a3, rSELF # a3 <- self
PREFETCH_INST(2) # load rINST
- JAL(artSet16StaticFromCode)
+ JAL(MterpSetShortStatic)
bnez v0, MterpException # bail out
ADVANCE(2) # advance rPC
GET_INST_OPCODE(t0) # extract opcode from rINST
diff --git a/runtime/interpreter/mterp/out/mterp_mips64.S b/runtime/interpreter/mterp/out/mterp_mips64.S
index e1867d0..3656df9 100644
--- a/runtime/interpreter/mterp/out/mterp_mips64.S
+++ b/runtime/interpreter/mterp/out/mterp_mips64.S
@@ -2585,12 +2585,12 @@
* for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
*/
/* op vAA, field//BBBB */
- .extern artGet32StaticFromCode
+ .extern MterpGet32Static
EXPORT_PC
lhu a0, 2(rPC) # a0 <- field ref BBBB
ld a1, OFF_FP_METHOD(rFP)
move a2, rSELF
- jal artGet32StaticFromCode
+ jal MterpGet32Static
ld a3, THREAD_EXCEPTION_OFFSET(rSELF)
srl a2, rINST, 8 # a2 <- AA
@@ -2614,12 +2614,12 @@
*
*/
/* sget-wide vAA, field//BBBB */
- .extern artGet64StaticFromCode
+ .extern MterpGet64Static
EXPORT_PC
lhu a0, 2(rPC) # a0 <- field ref BBBB
ld a1, OFF_FP_METHOD(rFP)
move a2, rSELF
- jal artGet64StaticFromCode
+ jal MterpGet64Static
ld a3, THREAD_EXCEPTION_OFFSET(rSELF)
srl a4, rINST, 8 # a4 <- AA
bnez a3, MterpException # bail out
@@ -2639,12 +2639,12 @@
* for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
*/
/* op vAA, field//BBBB */
- .extern artGetObjStaticFromCode
+ .extern MterpGetObjStatic
EXPORT_PC
lhu a0, 2(rPC) # a0 <- field ref BBBB
ld a1, OFF_FP_METHOD(rFP)
move a2, rSELF
- jal artGetObjStaticFromCode
+ jal MterpGetObjStatic
ld a3, THREAD_EXCEPTION_OFFSET(rSELF)
srl a2, rINST, 8 # a2 <- AA
@@ -2671,12 +2671,12 @@
* for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
*/
/* op vAA, field//BBBB */
- .extern artGetBooleanStaticFromCode
+ .extern MterpGetBooleanStatic
EXPORT_PC
lhu a0, 2(rPC) # a0 <- field ref BBBB
ld a1, OFF_FP_METHOD(rFP)
move a2, rSELF
- jal artGetBooleanStaticFromCode
+ jal MterpGetBooleanStatic
ld a3, THREAD_EXCEPTION_OFFSET(rSELF)
srl a2, rINST, 8 # a2 <- AA
and v0, v0, 0xff
@@ -2703,12 +2703,12 @@
* for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
*/
/* op vAA, field//BBBB */
- .extern artGetByteStaticFromCode
+ .extern MterpGetByteStatic
EXPORT_PC
lhu a0, 2(rPC) # a0 <- field ref BBBB
ld a1, OFF_FP_METHOD(rFP)
move a2, rSELF
- jal artGetByteStaticFromCode
+ jal MterpGetByteStatic
ld a3, THREAD_EXCEPTION_OFFSET(rSELF)
srl a2, rINST, 8 # a2 <- AA
seb v0, v0
@@ -2735,12 +2735,12 @@
* for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
*/
/* op vAA, field//BBBB */
- .extern artGetCharStaticFromCode
+ .extern MterpGetCharStatic
EXPORT_PC
lhu a0, 2(rPC) # a0 <- field ref BBBB
ld a1, OFF_FP_METHOD(rFP)
move a2, rSELF
- jal artGetCharStaticFromCode
+ jal MterpGetCharStatic
ld a3, THREAD_EXCEPTION_OFFSET(rSELF)
srl a2, rINST, 8 # a2 <- AA
and v0, v0, 0xffff
@@ -2767,12 +2767,12 @@
* for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
*/
/* op vAA, field//BBBB */
- .extern artGetShortStaticFromCode
+ .extern MterpGetShortStatic
EXPORT_PC
lhu a0, 2(rPC) # a0 <- field ref BBBB
ld a1, OFF_FP_METHOD(rFP)
move a2, rSELF
- jal artGetShortStaticFromCode
+ jal MterpGetShortStatic
ld a3, THREAD_EXCEPTION_OFFSET(rSELF)
srl a2, rINST, 8 # a2 <- AA
seh v0, v0
@@ -2798,7 +2798,7 @@
* for: sput, sput-boolean, sput-byte, sput-char, sput-short
*/
/* op vAA, field//BBBB */
- .extern artSet32StaticFromCode
+ .extern MterpSet32Static
EXPORT_PC
lhu a0, 2(rPC) # a0 <- field ref BBBB
srl a3, rINST, 8 # a3 <- AA
@@ -2806,7 +2806,7 @@
ld a2, OFF_FP_METHOD(rFP)
move a3, rSELF
PREFETCH_INST 2 # Get next inst, but don't advance rPC
- jal artSet32StaticFromCode
+ jal MterpSet32Static
bnezc v0, MterpException # 0 on success
ADVANCE 2 # Past exception point - now advance rPC
GET_INST_OPCODE v0 # extract opcode from rINST
@@ -2821,15 +2821,15 @@
*
*/
/* sput-wide vAA, field//BBBB */
- .extern artSet64IndirectStaticFromMterp
+ .extern MterpSet64Static
EXPORT_PC
lhu a0, 2(rPC) # a0 <- field ref BBBB
- ld a1, OFF_FP_METHOD(rFP)
- srl a2, rINST, 8 # a2 <- AA
- dlsa a2, a2, rFP, 2
+ srl a1, rINST, 8 # a2 <- AA
+ dlsa a1, a1, rFP, 2
+ ld a2, OFF_FP_METHOD(rFP)
move a3, rSELF
PREFETCH_INST 2 # Get next inst, but don't advance rPC
- jal artSet64IndirectStaticFromMterp
+ jal MterpSet64Static
bnezc v0, MterpException # 0 on success, -1 on failure
ADVANCE 2 # Past exception point - now advance rPC
GET_INST_OPCODE v0 # extract opcode from rINST
@@ -2862,7 +2862,7 @@
* for: sput, sput-boolean, sput-byte, sput-char, sput-short
*/
/* op vAA, field//BBBB */
- .extern artSet8StaticFromCode
+ .extern MterpSetBooleanStatic
EXPORT_PC
lhu a0, 2(rPC) # a0 <- field ref BBBB
srl a3, rINST, 8 # a3 <- AA
@@ -2870,7 +2870,7 @@
ld a2, OFF_FP_METHOD(rFP)
move a3, rSELF
PREFETCH_INST 2 # Get next inst, but don't advance rPC
- jal artSet8StaticFromCode
+ jal MterpSetBooleanStatic
bnezc v0, MterpException # 0 on success
ADVANCE 2 # Past exception point - now advance rPC
GET_INST_OPCODE v0 # extract opcode from rINST
@@ -2888,7 +2888,7 @@
* for: sput, sput-boolean, sput-byte, sput-char, sput-short
*/
/* op vAA, field//BBBB */
- .extern artSet8StaticFromCode
+ .extern MterpSetByteStatic
EXPORT_PC
lhu a0, 2(rPC) # a0 <- field ref BBBB
srl a3, rINST, 8 # a3 <- AA
@@ -2896,7 +2896,7 @@
ld a2, OFF_FP_METHOD(rFP)
move a3, rSELF
PREFETCH_INST 2 # Get next inst, but don't advance rPC
- jal artSet8StaticFromCode
+ jal MterpSetByteStatic
bnezc v0, MterpException # 0 on success
ADVANCE 2 # Past exception point - now advance rPC
GET_INST_OPCODE v0 # extract opcode from rINST
@@ -2914,7 +2914,7 @@
* for: sput, sput-boolean, sput-byte, sput-char, sput-short
*/
/* op vAA, field//BBBB */
- .extern artSet16StaticFromCode
+ .extern MterpSetCharStatic
EXPORT_PC
lhu a0, 2(rPC) # a0 <- field ref BBBB
srl a3, rINST, 8 # a3 <- AA
@@ -2922,7 +2922,7 @@
ld a2, OFF_FP_METHOD(rFP)
move a3, rSELF
PREFETCH_INST 2 # Get next inst, but don't advance rPC
- jal artSet16StaticFromCode
+ jal MterpSetCharStatic
bnezc v0, MterpException # 0 on success
ADVANCE 2 # Past exception point - now advance rPC
GET_INST_OPCODE v0 # extract opcode from rINST
@@ -2940,7 +2940,7 @@
* for: sput, sput-boolean, sput-byte, sput-char, sput-short
*/
/* op vAA, field//BBBB */
- .extern artSet16StaticFromCode
+ .extern MterpSetShortStatic
EXPORT_PC
lhu a0, 2(rPC) # a0 <- field ref BBBB
srl a3, rINST, 8 # a3 <- AA
@@ -2948,7 +2948,7 @@
ld a2, OFF_FP_METHOD(rFP)
move a3, rSELF
PREFETCH_INST 2 # Get next inst, but don't advance rPC
- jal artSet16StaticFromCode
+ jal MterpSetShortStatic
bnezc v0, MterpException # 0 on success
ADVANCE 2 # Past exception point - now advance rPC
GET_INST_OPCODE v0 # extract opcode from rINST
diff --git a/runtime/interpreter/mterp/out/mterp_x86.S b/runtime/interpreter/mterp/out/mterp_x86.S
index aab20f5..21d9671 100644
--- a/runtime/interpreter/mterp/out/mterp_x86.S
+++ b/runtime/interpreter/mterp/out/mterp_x86.S
@@ -2535,7 +2535,7 @@
* for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
*/
/* op vAA, field@BBBB */
- .extern artGet32StaticFromCode
+ .extern MterpGet32Static
EXPORT_PC
movzwl 2(rPC), %eax
movl %eax, OUT_ARG0(%esp) # field ref CCCC
@@ -2543,7 +2543,7 @@
movl %eax, OUT_ARG1(%esp) # referrer
movl rSELF, %ecx
movl %ecx, OUT_ARG2(%esp) # self
- call SYMBOL(artGet32StaticFromCode)
+ call SYMBOL(MterpGet32Static)
movl rSELF, %ecx
RESTORE_IBASE_FROM_SELF %ecx
cmpl $0, THREAD_EXCEPTION_OFFSET(%ecx)
@@ -2564,7 +2564,7 @@
*
*/
/* sget-wide vAA, field@BBBB */
- .extern artGet64StaticFromCode
+ .extern MterpGet64Static
EXPORT_PC
movzwl 2(rPC), %eax
movl %eax, OUT_ARG0(%esp) # field ref CCCC
@@ -2572,7 +2572,7 @@
movl %eax, OUT_ARG1(%esp) # referrer
movl rSELF, %ecx
movl %ecx, OUT_ARG2(%esp) # self
- call SYMBOL(artGet64StaticFromCode)
+ call SYMBOL(MterpGet64Static)
movl rSELF, %ecx
cmpl $0, THREAD_EXCEPTION_OFFSET(%ecx)
jnz MterpException
@@ -2592,7 +2592,7 @@
* for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
*/
/* op vAA, field@BBBB */
- .extern artGetObjStaticFromCode
+ .extern MterpGetObjStatic
EXPORT_PC
movzwl 2(rPC), %eax
movl %eax, OUT_ARG0(%esp) # field ref CCCC
@@ -2600,7 +2600,7 @@
movl %eax, OUT_ARG1(%esp) # referrer
movl rSELF, %ecx
movl %ecx, OUT_ARG2(%esp) # self
- call SYMBOL(artGetObjStaticFromCode)
+ call SYMBOL(MterpGetObjStatic)
movl rSELF, %ecx
RESTORE_IBASE_FROM_SELF %ecx
cmpl $0, THREAD_EXCEPTION_OFFSET(%ecx)
@@ -2624,7 +2624,7 @@
* for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
*/
/* op vAA, field@BBBB */
- .extern artGetBooleanStaticFromCode
+ .extern MterpGetBooleanStatic
EXPORT_PC
movzwl 2(rPC), %eax
movl %eax, OUT_ARG0(%esp) # field ref CCCC
@@ -2632,7 +2632,7 @@
movl %eax, OUT_ARG1(%esp) # referrer
movl rSELF, %ecx
movl %ecx, OUT_ARG2(%esp) # self
- call SYMBOL(artGetBooleanStaticFromCode)
+ call SYMBOL(MterpGetBooleanStatic)
movl rSELF, %ecx
RESTORE_IBASE_FROM_SELF %ecx
cmpl $0, THREAD_EXCEPTION_OFFSET(%ecx)
@@ -2656,7 +2656,7 @@
* for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
*/
/* op vAA, field@BBBB */
- .extern artGetByteStaticFromCode
+ .extern MterpGetByteStatic
EXPORT_PC
movzwl 2(rPC), %eax
movl %eax, OUT_ARG0(%esp) # field ref CCCC
@@ -2664,7 +2664,7 @@
movl %eax, OUT_ARG1(%esp) # referrer
movl rSELF, %ecx
movl %ecx, OUT_ARG2(%esp) # self
- call SYMBOL(artGetByteStaticFromCode)
+ call SYMBOL(MterpGetByteStatic)
movl rSELF, %ecx
RESTORE_IBASE_FROM_SELF %ecx
cmpl $0, THREAD_EXCEPTION_OFFSET(%ecx)
@@ -2688,7 +2688,7 @@
* for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
*/
/* op vAA, field@BBBB */
- .extern artGetCharStaticFromCode
+ .extern MterpGetCharStatic
EXPORT_PC
movzwl 2(rPC), %eax
movl %eax, OUT_ARG0(%esp) # field ref CCCC
@@ -2696,7 +2696,7 @@
movl %eax, OUT_ARG1(%esp) # referrer
movl rSELF, %ecx
movl %ecx, OUT_ARG2(%esp) # self
- call SYMBOL(artGetCharStaticFromCode)
+ call SYMBOL(MterpGetCharStatic)
movl rSELF, %ecx
RESTORE_IBASE_FROM_SELF %ecx
cmpl $0, THREAD_EXCEPTION_OFFSET(%ecx)
@@ -2720,7 +2720,7 @@
* for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
*/
/* op vAA, field@BBBB */
- .extern artGetShortStaticFromCode
+ .extern MterpGetShortStatic
EXPORT_PC
movzwl 2(rPC), %eax
movl %eax, OUT_ARG0(%esp) # field ref CCCC
@@ -2728,7 +2728,7 @@
movl %eax, OUT_ARG1(%esp) # referrer
movl rSELF, %ecx
movl %ecx, OUT_ARG2(%esp) # self
- call SYMBOL(artGetShortStaticFromCode)
+ call SYMBOL(MterpGetShortStatic)
movl rSELF, %ecx
RESTORE_IBASE_FROM_SELF %ecx
cmpl $0, THREAD_EXCEPTION_OFFSET(%ecx)
@@ -2751,7 +2751,7 @@
* for: sput, sput-boolean, sput-byte, sput-char, sput-short
*/
/* op vAA, field@BBBB */
- .extern artSet32StaticFromCode
+ .extern MterpSet32Static
EXPORT_PC
movzwl 2(rPC), %eax
movl %eax, OUT_ARG0(%esp) # field ref BBBB
@@ -2761,7 +2761,7 @@
movl %eax, OUT_ARG2(%esp) # referrer
movl rSELF, %ecx
movl %ecx, OUT_ARG3(%esp) # self
- call SYMBOL(artSet32StaticFromCode)
+ call SYMBOL(MterpSet32Static)
testb %al, %al
jnz MterpException
RESTORE_IBASE
@@ -2776,17 +2776,17 @@
*
*/
/* sput-wide vAA, field@BBBB */
- .extern artSet64IndirectStaticFromMterp
+ .extern MterpSet64Static
EXPORT_PC
movzwl 2(rPC), %eax
movl %eax, OUT_ARG0(%esp) # field ref BBBB
- movl OFF_FP_METHOD(rFP), %eax
- movl %eax, OUT_ARG1(%esp) # referrer
leal VREG_ADDRESS(rINST), %eax
- movl %eax, OUT_ARG2(%esp) # &fp[AA]
+ movl %eax, OUT_ARG1(%esp) # &fp[AA]
+ movl OFF_FP_METHOD(rFP), %eax
+ movl %eax, OUT_ARG2(%esp) # referrer
movl rSELF, %ecx
movl %ecx, OUT_ARG3(%esp) # self
- call SYMBOL(artSet64IndirectStaticFromMterp)
+ call SYMBOL(MterpSet64Static)
testb %al, %al
jnz MterpException
RESTORE_IBASE
@@ -2821,7 +2821,7 @@
* for: sput, sput-boolean, sput-byte, sput-char, sput-short
*/
/* op vAA, field@BBBB */
- .extern artSet8StaticFromCode
+ .extern MterpSetBooleanStatic
EXPORT_PC
movzwl 2(rPC), %eax
movl %eax, OUT_ARG0(%esp) # field ref BBBB
@@ -2831,7 +2831,7 @@
movl %eax, OUT_ARG2(%esp) # referrer
movl rSELF, %ecx
movl %ecx, OUT_ARG3(%esp) # self
- call SYMBOL(artSet8StaticFromCode)
+ call SYMBOL(MterpSetBooleanStatic)
testb %al, %al
jnz MterpException
RESTORE_IBASE
@@ -2849,7 +2849,7 @@
* for: sput, sput-boolean, sput-byte, sput-char, sput-short
*/
/* op vAA, field@BBBB */
- .extern artSet8StaticFromCode
+ .extern MterpSetByteStatic
EXPORT_PC
movzwl 2(rPC), %eax
movl %eax, OUT_ARG0(%esp) # field ref BBBB
@@ -2859,7 +2859,7 @@
movl %eax, OUT_ARG2(%esp) # referrer
movl rSELF, %ecx
movl %ecx, OUT_ARG3(%esp) # self
- call SYMBOL(artSet8StaticFromCode)
+ call SYMBOL(MterpSetByteStatic)
testb %al, %al
jnz MterpException
RESTORE_IBASE
@@ -2877,7 +2877,7 @@
* for: sput, sput-boolean, sput-byte, sput-char, sput-short
*/
/* op vAA, field@BBBB */
- .extern artSet16StaticFromCode
+ .extern MterpSetCharStatic
EXPORT_PC
movzwl 2(rPC), %eax
movl %eax, OUT_ARG0(%esp) # field ref BBBB
@@ -2887,7 +2887,7 @@
movl %eax, OUT_ARG2(%esp) # referrer
movl rSELF, %ecx
movl %ecx, OUT_ARG3(%esp) # self
- call SYMBOL(artSet16StaticFromCode)
+ call SYMBOL(MterpSetCharStatic)
testb %al, %al
jnz MterpException
RESTORE_IBASE
@@ -2905,7 +2905,7 @@
* for: sput, sput-boolean, sput-byte, sput-char, sput-short
*/
/* op vAA, field@BBBB */
- .extern artSet16StaticFromCode
+ .extern MterpSetShortStatic
EXPORT_PC
movzwl 2(rPC), %eax
movl %eax, OUT_ARG0(%esp) # field ref BBBB
@@ -2915,7 +2915,7 @@
movl %eax, OUT_ARG2(%esp) # referrer
movl rSELF, %ecx
movl %ecx, OUT_ARG3(%esp) # self
- call SYMBOL(artSet16StaticFromCode)
+ call SYMBOL(MterpSetShortStatic)
testb %al, %al
jnz MterpException
RESTORE_IBASE
diff --git a/runtime/interpreter/mterp/out/mterp_x86_64.S b/runtime/interpreter/mterp/out/mterp_x86_64.S
index eb57066..b5a5ae5 100644
--- a/runtime/interpreter/mterp/out/mterp_x86_64.S
+++ b/runtime/interpreter/mterp/out/mterp_x86_64.S
@@ -2445,12 +2445,12 @@
* for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short, sget-wide
*/
/* op vAA, field@BBBB */
- .extern artGet32StaticFromCode
+ .extern MterpGet32Static
EXPORT_PC
movzwq 2(rPC), OUT_ARG0 # field ref CCCC
movq OFF_FP_METHOD(rFP), OUT_ARG1 # referrer
movq rSELF, OUT_ARG2 # self
- call SYMBOL(artGet32StaticFromCode)
+ call SYMBOL(MterpGet32Static)
movq rSELF, %rcx
cmpl $0, THREAD_EXCEPTION_OFFSET(%rcx)
jnz MterpException
@@ -2476,12 +2476,12 @@
* for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short, sget-wide
*/
/* op vAA, field@BBBB */
- .extern artGet64StaticFromCode
+ .extern MterpGet64Static
EXPORT_PC
movzwq 2(rPC), OUT_ARG0 # field ref CCCC
movq OFF_FP_METHOD(rFP), OUT_ARG1 # referrer
movq rSELF, OUT_ARG2 # self
- call SYMBOL(artGet64StaticFromCode)
+ call SYMBOL(MterpGet64Static)
movq rSELF, %rcx
cmpl $0, THREAD_EXCEPTION_OFFSET(%rcx)
jnz MterpException
@@ -2508,12 +2508,12 @@
* for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short, sget-wide
*/
/* op vAA, field@BBBB */
- .extern artGetObjStaticFromCode
+ .extern MterpGetObjStatic
EXPORT_PC
movzwq 2(rPC), OUT_ARG0 # field ref CCCC
movq OFF_FP_METHOD(rFP), OUT_ARG1 # referrer
movq rSELF, OUT_ARG2 # self
- call SYMBOL(artGetObjStaticFromCode)
+ call SYMBOL(MterpGetObjStatic)
movq rSELF, %rcx
cmpl $0, THREAD_EXCEPTION_OFFSET(%rcx)
jnz MterpException
@@ -2540,12 +2540,12 @@
* for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short, sget-wide
*/
/* op vAA, field@BBBB */
- .extern artGetBooleanStaticFromCode
+ .extern MterpGetBooleanStatic
EXPORT_PC
movzwq 2(rPC), OUT_ARG0 # field ref CCCC
movq OFF_FP_METHOD(rFP), OUT_ARG1 # referrer
movq rSELF, OUT_ARG2 # self
- call SYMBOL(artGetBooleanStaticFromCode)
+ call SYMBOL(MterpGetBooleanStatic)
movq rSELF, %rcx
cmpl $0, THREAD_EXCEPTION_OFFSET(%rcx)
jnz MterpException
@@ -2572,12 +2572,12 @@
* for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short, sget-wide
*/
/* op vAA, field@BBBB */
- .extern artGetByteStaticFromCode
+ .extern MterpGetByteStatic
EXPORT_PC
movzwq 2(rPC), OUT_ARG0 # field ref CCCC
movq OFF_FP_METHOD(rFP), OUT_ARG1 # referrer
movq rSELF, OUT_ARG2 # self
- call SYMBOL(artGetByteStaticFromCode)
+ call SYMBOL(MterpGetByteStatic)
movq rSELF, %rcx
cmpl $0, THREAD_EXCEPTION_OFFSET(%rcx)
jnz MterpException
@@ -2604,12 +2604,12 @@
* for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short, sget-wide
*/
/* op vAA, field@BBBB */
- .extern artGetCharStaticFromCode
+ .extern MterpGetCharStatic
EXPORT_PC
movzwq 2(rPC), OUT_ARG0 # field ref CCCC
movq OFF_FP_METHOD(rFP), OUT_ARG1 # referrer
movq rSELF, OUT_ARG2 # self
- call SYMBOL(artGetCharStaticFromCode)
+ call SYMBOL(MterpGetCharStatic)
movq rSELF, %rcx
cmpl $0, THREAD_EXCEPTION_OFFSET(%rcx)
jnz MterpException
@@ -2636,12 +2636,12 @@
* for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short, sget-wide
*/
/* op vAA, field@BBBB */
- .extern artGetShortStaticFromCode
+ .extern MterpGetShortStatic
EXPORT_PC
movzwq 2(rPC), OUT_ARG0 # field ref CCCC
movq OFF_FP_METHOD(rFP), OUT_ARG1 # referrer
movq rSELF, OUT_ARG2 # self
- call SYMBOL(artGetShortStaticFromCode)
+ call SYMBOL(MterpGetShortStatic)
movq rSELF, %rcx
cmpl $0, THREAD_EXCEPTION_OFFSET(%rcx)
jnz MterpException
@@ -2667,13 +2667,13 @@
* for: sput, sput-boolean, sput-byte, sput-char, sput-short
*/
/* op vAA, field@BBBB */
- .extern artSet32StaticFromCode
+ .extern MterpSet32Static
EXPORT_PC
movzwq 2(rPC), OUT_ARG0 # field ref BBBB
GET_VREG OUT_32_ARG1, rINSTq # fp[AA]
movq OFF_FP_METHOD(rFP), OUT_ARG2 # referrer
movq rSELF, OUT_ARG3 # self
- call SYMBOL(artSet32StaticFromCode)
+ call SYMBOL(MterpSet32Static)
testb %al, %al
jnz MterpException
ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
@@ -2687,13 +2687,13 @@
*
*/
/* sput-wide vAA, field@BBBB */
- .extern artSet64IndirectStaticFromMterp
+ .extern MterpSet64Static
EXPORT_PC
movzwq 2(rPC), OUT_ARG0 # field ref BBBB
- movq OFF_FP_METHOD(rFP), OUT_ARG1 # referrer
- leaq VREG_ADDRESS(rINSTq), OUT_ARG2 # &fp[AA]
+ leaq VREG_ADDRESS(rINSTq), OUT_ARG1 # &fp[AA]
+ movq OFF_FP_METHOD(rFP), OUT_ARG2 # referrer
movq rSELF, OUT_ARG3 # self
- call SYMBOL(artSet64IndirectStaticFromMterp)
+ call SYMBOL(MterpSet64Static)
testb %al, %al
jnz MterpException
ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
@@ -2724,13 +2724,13 @@
* for: sput, sput-boolean, sput-byte, sput-char, sput-short
*/
/* op vAA, field@BBBB */
- .extern artSet8StaticFromCode
+ .extern MterpSetBooleanStatic
EXPORT_PC
movzwq 2(rPC), OUT_ARG0 # field ref BBBB
GET_VREG OUT_32_ARG1, rINSTq # fp[AA]
movq OFF_FP_METHOD(rFP), OUT_ARG2 # referrer
movq rSELF, OUT_ARG3 # self
- call SYMBOL(artSet8StaticFromCode)
+ call SYMBOL(MterpSetBooleanStatic)
testb %al, %al
jnz MterpException
ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
@@ -2747,13 +2747,13 @@
* for: sput, sput-boolean, sput-byte, sput-char, sput-short
*/
/* op vAA, field@BBBB */
- .extern artSet8StaticFromCode
+ .extern MterpSetByteStatic
EXPORT_PC
movzwq 2(rPC), OUT_ARG0 # field ref BBBB
GET_VREG OUT_32_ARG1, rINSTq # fp[AA]
movq OFF_FP_METHOD(rFP), OUT_ARG2 # referrer
movq rSELF, OUT_ARG3 # self
- call SYMBOL(artSet8StaticFromCode)
+ call SYMBOL(MterpSetByteStatic)
testb %al, %al
jnz MterpException
ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
@@ -2770,13 +2770,13 @@
* for: sput, sput-boolean, sput-byte, sput-char, sput-short
*/
/* op vAA, field@BBBB */
- .extern artSet16StaticFromCode
+ .extern MterpSetCharStatic
EXPORT_PC
movzwq 2(rPC), OUT_ARG0 # field ref BBBB
GET_VREG OUT_32_ARG1, rINSTq # fp[AA]
movq OFF_FP_METHOD(rFP), OUT_ARG2 # referrer
movq rSELF, OUT_ARG3 # self
- call SYMBOL(artSet16StaticFromCode)
+ call SYMBOL(MterpSetCharStatic)
testb %al, %al
jnz MterpException
ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
@@ -2793,13 +2793,13 @@
* for: sput, sput-boolean, sput-byte, sput-char, sput-short
*/
/* op vAA, field@BBBB */
- .extern artSet16StaticFromCode
+ .extern MterpSetShortStatic
EXPORT_PC
movzwq 2(rPC), OUT_ARG0 # field ref BBBB
GET_VREG OUT_32_ARG1, rINSTq # fp[AA]
movq OFF_FP_METHOD(rFP), OUT_ARG2 # referrer
movq rSELF, OUT_ARG3 # self
- call SYMBOL(artSet16StaticFromCode)
+ call SYMBOL(MterpSetShortStatic)
testb %al, %al
jnz MterpException
ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
diff --git a/runtime/interpreter/mterp/x86/op_sget.S b/runtime/interpreter/mterp/x86/op_sget.S
index 0e9a3d8..6e42d32 100644
--- a/runtime/interpreter/mterp/x86/op_sget.S
+++ b/runtime/interpreter/mterp/x86/op_sget.S
@@ -1,4 +1,4 @@
-%default { "is_object":"0", "helper":"artGet32StaticFromCode" }
+%default { "is_object":"0", "helper":"MterpGet32Static" }
/*
* General SGET handler wrapper.
*
diff --git a/runtime/interpreter/mterp/x86/op_sget_boolean.S b/runtime/interpreter/mterp/x86/op_sget_boolean.S
index f058dd8..5fa2bf0 100644
--- a/runtime/interpreter/mterp/x86/op_sget_boolean.S
+++ b/runtime/interpreter/mterp/x86/op_sget_boolean.S
@@ -1 +1 @@
-%include "x86/op_sget.S" {"helper":"artGetBooleanStaticFromCode"}
+%include "x86/op_sget.S" {"helper":"MterpGetBooleanStatic"}
diff --git a/runtime/interpreter/mterp/x86/op_sget_byte.S b/runtime/interpreter/mterp/x86/op_sget_byte.S
index c952f40..ef812f1 100644
--- a/runtime/interpreter/mterp/x86/op_sget_byte.S
+++ b/runtime/interpreter/mterp/x86/op_sget_byte.S
@@ -1 +1 @@
-%include "x86/op_sget.S" {"helper":"artGetByteStaticFromCode"}
+%include "x86/op_sget.S" {"helper":"MterpGetByteStatic"}
diff --git a/runtime/interpreter/mterp/x86/op_sget_char.S b/runtime/interpreter/mterp/x86/op_sget_char.S
index d7bd410..3bc34ef 100644
--- a/runtime/interpreter/mterp/x86/op_sget_char.S
+++ b/runtime/interpreter/mterp/x86/op_sget_char.S
@@ -1 +1 @@
-%include "x86/op_sget.S" {"helper":"artGetCharStaticFromCode"}
+%include "x86/op_sget.S" {"helper":"MterpGetCharStatic"}
diff --git a/runtime/interpreter/mterp/x86/op_sget_object.S b/runtime/interpreter/mterp/x86/op_sget_object.S
index 1c95f9a..b829e75 100644
--- a/runtime/interpreter/mterp/x86/op_sget_object.S
+++ b/runtime/interpreter/mterp/x86/op_sget_object.S
@@ -1 +1 @@
-%include "x86/op_sget.S" {"is_object":"1", "helper":"artGetObjStaticFromCode"}
+%include "x86/op_sget.S" {"is_object":"1", "helper":"MterpGetObjStatic"}
diff --git a/runtime/interpreter/mterp/x86/op_sget_short.S b/runtime/interpreter/mterp/x86/op_sget_short.S
index 6475306..449cf6f 100644
--- a/runtime/interpreter/mterp/x86/op_sget_short.S
+++ b/runtime/interpreter/mterp/x86/op_sget_short.S
@@ -1 +1 @@
-%include "x86/op_sget.S" {"helper":"artGetShortStaticFromCode"}
+%include "x86/op_sget.S" {"helper":"MterpGetShortStatic"}
diff --git a/runtime/interpreter/mterp/x86/op_sget_wide.S b/runtime/interpreter/mterp/x86/op_sget_wide.S
index 2b60303..a605bcf 100644
--- a/runtime/interpreter/mterp/x86/op_sget_wide.S
+++ b/runtime/interpreter/mterp/x86/op_sget_wide.S
@@ -3,7 +3,7 @@
*
*/
/* sget-wide vAA, field@BBBB */
- .extern artGet64StaticFromCode
+ .extern MterpGet64Static
EXPORT_PC
movzwl 2(rPC), %eax
movl %eax, OUT_ARG0(%esp) # field ref CCCC
@@ -11,7 +11,7 @@
movl %eax, OUT_ARG1(%esp) # referrer
movl rSELF, %ecx
movl %ecx, OUT_ARG2(%esp) # self
- call SYMBOL(artGet64StaticFromCode)
+ call SYMBOL(MterpGet64Static)
movl rSELF, %ecx
cmpl $$0, THREAD_EXCEPTION_OFFSET(%ecx)
jnz MterpException
diff --git a/runtime/interpreter/mterp/x86/op_sput.S b/runtime/interpreter/mterp/x86/op_sput.S
index 0b5de09..99f6088 100644
--- a/runtime/interpreter/mterp/x86/op_sput.S
+++ b/runtime/interpreter/mterp/x86/op_sput.S
@@ -1,4 +1,4 @@
-%default { "helper":"artSet32StaticFromCode"}
+%default { "helper":"MterpSet32Static"}
/*
* General SPUT handler wrapper.
*
diff --git a/runtime/interpreter/mterp/x86/op_sput_boolean.S b/runtime/interpreter/mterp/x86/op_sput_boolean.S
index 63601bd..a7fffda 100644
--- a/runtime/interpreter/mterp/x86/op_sput_boolean.S
+++ b/runtime/interpreter/mterp/x86/op_sput_boolean.S
@@ -1 +1 @@
-%include "x86/op_sput.S" {"helper":"artSet8StaticFromCode"}
+%include "x86/op_sput.S" {"helper":"MterpSetBooleanStatic"}
diff --git a/runtime/interpreter/mterp/x86/op_sput_byte.S b/runtime/interpreter/mterp/x86/op_sput_byte.S
index 63601bd..3a5ff92 100644
--- a/runtime/interpreter/mterp/x86/op_sput_byte.S
+++ b/runtime/interpreter/mterp/x86/op_sput_byte.S
@@ -1 +1 @@
-%include "x86/op_sput.S" {"helper":"artSet8StaticFromCode"}
+%include "x86/op_sput.S" {"helper":"MterpSetByteStatic"}
diff --git a/runtime/interpreter/mterp/x86/op_sput_char.S b/runtime/interpreter/mterp/x86/op_sput_char.S
index 1749f7c..565cc2a 100644
--- a/runtime/interpreter/mterp/x86/op_sput_char.S
+++ b/runtime/interpreter/mterp/x86/op_sput_char.S
@@ -1 +1 @@
-%include "x86/op_sput.S" {"helper":"artSet16StaticFromCode"}
+%include "x86/op_sput.S" {"helper":"MterpSetCharStatic"}
diff --git a/runtime/interpreter/mterp/x86/op_sput_short.S b/runtime/interpreter/mterp/x86/op_sput_short.S
index 1749f7c..85c3441 100644
--- a/runtime/interpreter/mterp/x86/op_sput_short.S
+++ b/runtime/interpreter/mterp/x86/op_sput_short.S
@@ -1 +1 @@
-%include "x86/op_sput.S" {"helper":"artSet16StaticFromCode"}
+%include "x86/op_sput.S" {"helper":"MterpSetShortStatic"}
diff --git a/runtime/interpreter/mterp/x86/op_sput_wide.S b/runtime/interpreter/mterp/x86/op_sput_wide.S
index 19cff0d..8cc7e28 100644
--- a/runtime/interpreter/mterp/x86/op_sput_wide.S
+++ b/runtime/interpreter/mterp/x86/op_sput_wide.S
@@ -3,17 +3,17 @@
*
*/
/* sput-wide vAA, field@BBBB */
- .extern artSet64IndirectStaticFromMterp
+ .extern MterpSet64Static
EXPORT_PC
movzwl 2(rPC), %eax
movl %eax, OUT_ARG0(%esp) # field ref BBBB
- movl OFF_FP_METHOD(rFP), %eax
- movl %eax, OUT_ARG1(%esp) # referrer
leal VREG_ADDRESS(rINST), %eax
- movl %eax, OUT_ARG2(%esp) # &fp[AA]
+ movl %eax, OUT_ARG1(%esp) # &fp[AA]
+ movl OFF_FP_METHOD(rFP), %eax
+ movl %eax, OUT_ARG2(%esp) # referrer
movl rSELF, %ecx
movl %ecx, OUT_ARG3(%esp) # self
- call SYMBOL(artSet64IndirectStaticFromMterp)
+ call SYMBOL(MterpSet64Static)
testb %al, %al
jnz MterpException
RESTORE_IBASE
diff --git a/runtime/interpreter/mterp/x86_64/op_sget.S b/runtime/interpreter/mterp/x86_64/op_sget.S
index d39e6c4..e996c77 100644
--- a/runtime/interpreter/mterp/x86_64/op_sget.S
+++ b/runtime/interpreter/mterp/x86_64/op_sget.S
@@ -1,4 +1,4 @@
-%default { "is_object":"0", "helper":"artGet32StaticFromCode", "wide":"0" }
+%default { "is_object":"0", "helper":"MterpGet32Static", "wide":"0" }
/*
* General SGET handler wrapper.
*
diff --git a/runtime/interpreter/mterp/x86_64/op_sget_boolean.S b/runtime/interpreter/mterp/x86_64/op_sget_boolean.S
index 7d358da..ee772ad 100644
--- a/runtime/interpreter/mterp/x86_64/op_sget_boolean.S
+++ b/runtime/interpreter/mterp/x86_64/op_sget_boolean.S
@@ -1 +1 @@
-%include "x86_64/op_sget.S" {"helper":"artGetBooleanStaticFromCode"}
+%include "x86_64/op_sget.S" {"helper":"MterpGetBooleanStatic"}
diff --git a/runtime/interpreter/mterp/x86_64/op_sget_byte.S b/runtime/interpreter/mterp/x86_64/op_sget_byte.S
index 79d9ff4..f65ea49 100644
--- a/runtime/interpreter/mterp/x86_64/op_sget_byte.S
+++ b/runtime/interpreter/mterp/x86_64/op_sget_byte.S
@@ -1 +1 @@
-%include "x86_64/op_sget.S" {"helper":"artGetByteStaticFromCode"}
+%include "x86_64/op_sget.S" {"helper":"MterpGetByteStatic"}
diff --git a/runtime/interpreter/mterp/x86_64/op_sget_char.S b/runtime/interpreter/mterp/x86_64/op_sget_char.S
index 4488610..3972551 100644
--- a/runtime/interpreter/mterp/x86_64/op_sget_char.S
+++ b/runtime/interpreter/mterp/x86_64/op_sget_char.S
@@ -1 +1 @@
-%include "x86_64/op_sget.S" {"helper":"artGetCharStaticFromCode"}
+%include "x86_64/op_sget.S" {"helper":"MterpGetCharStatic"}
diff --git a/runtime/interpreter/mterp/x86_64/op_sget_object.S b/runtime/interpreter/mterp/x86_64/op_sget_object.S
index 09b627e..a0bbfd8 100644
--- a/runtime/interpreter/mterp/x86_64/op_sget_object.S
+++ b/runtime/interpreter/mterp/x86_64/op_sget_object.S
@@ -1 +1 @@
-%include "x86_64/op_sget.S" {"is_object":"1", "helper":"artGetObjStaticFromCode"}
+%include "x86_64/op_sget.S" {"is_object":"1", "helper":"MterpGetObjStatic"}
diff --git a/runtime/interpreter/mterp/x86_64/op_sget_short.S b/runtime/interpreter/mterp/x86_64/op_sget_short.S
index 47ac238..df212dc 100644
--- a/runtime/interpreter/mterp/x86_64/op_sget_short.S
+++ b/runtime/interpreter/mterp/x86_64/op_sget_short.S
@@ -1 +1 @@
-%include "x86_64/op_sget.S" {"helper":"artGetShortStaticFromCode"}
+%include "x86_64/op_sget.S" {"helper":"MterpGetShortStatic"}
diff --git a/runtime/interpreter/mterp/x86_64/op_sget_wide.S b/runtime/interpreter/mterp/x86_64/op_sget_wide.S
index aa22343..1e98e28 100644
--- a/runtime/interpreter/mterp/x86_64/op_sget_wide.S
+++ b/runtime/interpreter/mterp/x86_64/op_sget_wide.S
@@ -1 +1 @@
-%include "x86_64/op_sget.S" {"helper":"artGet64StaticFromCode", "wide":"1"}
+%include "x86_64/op_sget.S" {"helper":"MterpGet64Static", "wide":"1"}
diff --git a/runtime/interpreter/mterp/x86_64/op_sput.S b/runtime/interpreter/mterp/x86_64/op_sput.S
index e92b032..9705619 100644
--- a/runtime/interpreter/mterp/x86_64/op_sput.S
+++ b/runtime/interpreter/mterp/x86_64/op_sput.S
@@ -1,4 +1,4 @@
-%default { "helper":"artSet32StaticFromCode"}
+%default { "helper":"MterpSet32Static"}
/*
* General SPUT handler wrapper.
*
diff --git a/runtime/interpreter/mterp/x86_64/op_sput_boolean.S b/runtime/interpreter/mterp/x86_64/op_sput_boolean.S
index 8718915..8bf4a62 100644
--- a/runtime/interpreter/mterp/x86_64/op_sput_boolean.S
+++ b/runtime/interpreter/mterp/x86_64/op_sput_boolean.S
@@ -1 +1 @@
-%include "x86_64/op_sput.S" {"helper":"artSet8StaticFromCode"}
+%include "x86_64/op_sput.S" {"helper":"MterpSetBooleanStatic"}
diff --git a/runtime/interpreter/mterp/x86_64/op_sput_byte.S b/runtime/interpreter/mterp/x86_64/op_sput_byte.S
index 8718915..5bb26eb 100644
--- a/runtime/interpreter/mterp/x86_64/op_sput_byte.S
+++ b/runtime/interpreter/mterp/x86_64/op_sput_byte.S
@@ -1 +1 @@
-%include "x86_64/op_sput.S" {"helper":"artSet8StaticFromCode"}
+%include "x86_64/op_sput.S" {"helper":"MterpSetByteStatic"}
diff --git a/runtime/interpreter/mterp/x86_64/op_sput_char.S b/runtime/interpreter/mterp/x86_64/op_sput_char.S
index 2fe9d14..42b244e 100644
--- a/runtime/interpreter/mterp/x86_64/op_sput_char.S
+++ b/runtime/interpreter/mterp/x86_64/op_sput_char.S
@@ -1 +1 @@
-%include "x86_64/op_sput.S" {"helper":"artSet16StaticFromCode"}
+%include "x86_64/op_sput.S" {"helper":"MterpSetCharStatic"}
diff --git a/runtime/interpreter/mterp/x86_64/op_sput_short.S b/runtime/interpreter/mterp/x86_64/op_sput_short.S
index 2fe9d14..9670092 100644
--- a/runtime/interpreter/mterp/x86_64/op_sput_short.S
+++ b/runtime/interpreter/mterp/x86_64/op_sput_short.S
@@ -1 +1 @@
-%include "x86_64/op_sput.S" {"helper":"artSet16StaticFromCode"}
+%include "x86_64/op_sput.S" {"helper":"MterpSetShortStatic"}
diff --git a/runtime/interpreter/mterp/x86_64/op_sput_wide.S b/runtime/interpreter/mterp/x86_64/op_sput_wide.S
index c4bc269..a21bcb5 100644
--- a/runtime/interpreter/mterp/x86_64/op_sput_wide.S
+++ b/runtime/interpreter/mterp/x86_64/op_sput_wide.S
@@ -3,13 +3,13 @@
*
*/
/* sput-wide vAA, field@BBBB */
- .extern artSet64IndirectStaticFromMterp
+ .extern MterpSet64Static
EXPORT_PC
movzwq 2(rPC), OUT_ARG0 # field ref BBBB
- movq OFF_FP_METHOD(rFP), OUT_ARG1 # referrer
- leaq VREG_ADDRESS(rINSTq), OUT_ARG2 # &fp[AA]
+ leaq VREG_ADDRESS(rINSTq), OUT_ARG1 # &fp[AA]
+ movq OFF_FP_METHOD(rFP), OUT_ARG2 # referrer
movq rSELF, OUT_ARG3 # self
- call SYMBOL(artSet64IndirectStaticFromMterp)
+ call SYMBOL(MterpSet64Static)
testb %al, %al
jnz MterpException
ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
diff --git a/runtime/openjdkjvmti/ti_heap.cc b/runtime/openjdkjvmti/ti_heap.cc
index c7294a9..5f59489 100644
--- a/runtime/openjdkjvmti/ti_heap.cc
+++ b/runtime/openjdkjvmti/ti_heap.cc
@@ -162,6 +162,439 @@
return 0;
}
+template <typename UserData>
+bool VisitorFalse(art::ObjPtr<art::mirror::Object> obj ATTRIBUTE_UNUSED,
+ art::ObjPtr<art::mirror::Class> klass ATTRIBUTE_UNUSED,
+ art::ArtField& field ATTRIBUTE_UNUSED,
+ size_t field_index ATTRIBUTE_UNUSED,
+ UserData* user_data ATTRIBUTE_UNUSED) {
+ return false;
+}
+
+template <typename StaticPrimitiveVisitor,
+ typename StaticReferenceVisitor,
+ typename InstancePrimitiveVisitor,
+ typename InstanceReferenceVisitor,
+ typename UserData,
+ bool kCallVisitorOnRecursion>
+class FieldVisitor {
+ public:
+ // Report the contents of a primitive fields of the given object, if a callback is set.
+ static bool ReportFields(art::ObjPtr<art::mirror::Object> obj,
+ UserData* user_data,
+ StaticPrimitiveVisitor& static_prim_visitor,
+ StaticReferenceVisitor& static_ref_visitor,
+ InstancePrimitiveVisitor& instance_prim_visitor,
+ InstanceReferenceVisitor& instance_ref_visitor)
+ REQUIRES_SHARED(art::Locks::mutator_lock_) {
+ FieldVisitor fv(user_data);
+
+ if (obj->IsClass()) {
+ // When visiting a class, we only visit the static fields of the given class. No field of
+ // superclasses is visited.
+ art::ObjPtr<art::mirror::Class> klass = obj->AsClass();
+ // Only report fields on resolved classes. We need valid field data.
+ if (!klass->IsResolved()) {
+ return false;
+ }
+ return fv.ReportFieldsImpl(nullptr,
+ obj->AsClass(),
+ obj->AsClass()->IsInterface(),
+ static_prim_visitor,
+ static_ref_visitor,
+ instance_prim_visitor,
+ instance_ref_visitor);
+ } else {
+ // See comment above. Just double-checking here, but an instance *should* mean the class was
+ // resolved.
+ DCHECK(obj->GetClass()->IsResolved() || obj->GetClass()->IsErroneousResolved());
+ return fv.ReportFieldsImpl(obj,
+ obj->GetClass(),
+ false,
+ static_prim_visitor,
+ static_ref_visitor,
+ instance_prim_visitor,
+ instance_ref_visitor);
+ }
+ }
+
+ private:
+ explicit FieldVisitor(UserData* user_data) : user_data_(user_data) {}
+
+ // Report the contents of fields of the given object. If obj is null, report the static fields,
+ // otherwise the instance fields.
+ bool ReportFieldsImpl(art::ObjPtr<art::mirror::Object> obj,
+ art::ObjPtr<art::mirror::Class> klass,
+ bool skip_java_lang_object,
+ StaticPrimitiveVisitor& static_prim_visitor,
+ StaticReferenceVisitor& static_ref_visitor,
+ InstancePrimitiveVisitor& instance_prim_visitor,
+ InstanceReferenceVisitor& instance_ref_visitor)
+ REQUIRES_SHARED(art::Locks::mutator_lock_) {
+ // Compute the offset of field indices.
+ size_t interface_field_count = CountInterfaceFields(klass);
+
+ size_t tmp;
+ bool aborted = ReportFieldsRecursive(obj,
+ klass,
+ interface_field_count,
+ skip_java_lang_object,
+ static_prim_visitor,
+ static_ref_visitor,
+ instance_prim_visitor,
+ instance_ref_visitor,
+ &tmp);
+ return aborted;
+ }
+
+ // Visit primitive fields in an object (instance). Return true if the visit was aborted.
+ bool ReportFieldsRecursive(art::ObjPtr<art::mirror::Object> obj,
+ art::ObjPtr<art::mirror::Class> klass,
+ size_t interface_fields,
+ bool skip_java_lang_object,
+ StaticPrimitiveVisitor& static_prim_visitor,
+ StaticReferenceVisitor& static_ref_visitor,
+ InstancePrimitiveVisitor& instance_prim_visitor,
+ InstanceReferenceVisitor& instance_ref_visitor,
+ size_t* field_index_out)
+ REQUIRES_SHARED(art::Locks::mutator_lock_) {
+ DCHECK(klass != nullptr);
+ size_t field_index;
+ if (klass->GetSuperClass() == nullptr) {
+ // j.l.Object. Start with the fields from interfaces.
+ field_index = interface_fields;
+ if (skip_java_lang_object) {
+ *field_index_out = field_index;
+ return false;
+ }
+ } else {
+ // Report superclass fields.
+ if (kCallVisitorOnRecursion) {
+ if (ReportFieldsRecursive(obj,
+ klass->GetSuperClass(),
+ interface_fields,
+ skip_java_lang_object,
+ static_prim_visitor,
+ static_ref_visitor,
+ instance_prim_visitor,
+ instance_ref_visitor,
+ &field_index)) {
+ return true;
+ }
+ } else {
+ // Still call, but with empty visitor. This is required for correct counting.
+ ReportFieldsRecursive(obj,
+ klass->GetSuperClass(),
+ interface_fields,
+ skip_java_lang_object,
+ VisitorFalse<UserData>,
+ VisitorFalse<UserData>,
+ VisitorFalse<UserData>,
+ VisitorFalse<UserData>,
+ &field_index);
+ }
+ }
+
+ // Now visit fields for the current klass.
+
+ for (auto& static_field : klass->GetSFields()) {
+ if (static_field.IsPrimitiveType()) {
+ if (static_prim_visitor(obj,
+ klass,
+ static_field,
+ field_index,
+ user_data_)) {
+ return true;
+ }
+ } else {
+ if (static_ref_visitor(obj,
+ klass,
+ static_field,
+ field_index,
+ user_data_)) {
+ return true;
+ }
+ }
+ field_index++;
+ }
+
+ for (auto& instance_field : klass->GetIFields()) {
+ if (instance_field.IsPrimitiveType()) {
+ if (instance_prim_visitor(obj,
+ klass,
+ instance_field,
+ field_index,
+ user_data_)) {
+ return true;
+ }
+ } else {
+ if (instance_ref_visitor(obj,
+ klass,
+ instance_field,
+ field_index,
+ user_data_)) {
+ return true;
+ }
+ }
+ field_index++;
+ }
+
+ *field_index_out = field_index;
+ return false;
+ }
+
+ // Implements a visit of the implemented interfaces of a given class.
+ template <typename T>
+ struct RecursiveInterfaceVisit {
+ static void VisitStatic(art::Thread* self, art::ObjPtr<art::mirror::Class> klass, T& visitor)
+ REQUIRES_SHARED(art::Locks::mutator_lock_) {
+ RecursiveInterfaceVisit rv;
+ rv.Visit(self, klass, visitor);
+ }
+
+ void Visit(art::Thread* self, art::ObjPtr<art::mirror::Class> klass, T& visitor)
+ REQUIRES_SHARED(art::Locks::mutator_lock_) {
+ // First visit the parent, to get the order right.
+ // (We do this in preparation for actual visiting of interface fields.)
+ if (klass->GetSuperClass() != nullptr) {
+ Visit(self, klass->GetSuperClass(), visitor);
+ }
+ for (uint32_t i = 0; i != klass->NumDirectInterfaces(); ++i) {
+ art::ObjPtr<art::mirror::Class> inf_klass =
+ art::mirror::Class::GetDirectInterface(self, klass, i);
+ DCHECK(inf_klass != nullptr);
+ VisitInterface(self, inf_klass, visitor);
+ }
+ }
+
+ void VisitInterface(art::Thread* self, art::ObjPtr<art::mirror::Class> inf_klass, T& visitor)
+ REQUIRES_SHARED(art::Locks::mutator_lock_) {
+ auto it = visited_interfaces.find(inf_klass.Ptr());
+ if (it != visited_interfaces.end()) {
+ return;
+ }
+ visited_interfaces.insert(inf_klass.Ptr());
+
+ // Let the visitor know about this one. Note that this order is acceptable, as the ordering
+ // of these fields never matters for known visitors.
+ visitor(inf_klass);
+
+ // Now visit the superinterfaces.
+ for (uint32_t i = 0; i != inf_klass->NumDirectInterfaces(); ++i) {
+ art::ObjPtr<art::mirror::Class> super_inf_klass =
+ art::mirror::Class::GetDirectInterface(self, inf_klass, i);
+ DCHECK(super_inf_klass != nullptr);
+ VisitInterface(self, super_inf_klass, visitor);
+ }
+ }
+
+ std::unordered_set<art::mirror::Class*> visited_interfaces;
+ };
+
+ // Counting interface fields. Note that we cannot use the interface table, as that only contains
+ // "non-marker" interfaces (= interfaces with methods).
+ static size_t CountInterfaceFields(art::ObjPtr<art::mirror::Class> klass)
+ REQUIRES_SHARED(art::Locks::mutator_lock_) {
+ size_t count = 0;
+ auto visitor = [&count](art::ObjPtr<art::mirror::Class> inf_klass)
+ REQUIRES_SHARED(art::Locks::mutator_lock_) {
+ DCHECK(inf_klass->IsInterface());
+ DCHECK_EQ(0u, inf_klass->NumInstanceFields());
+ count += inf_klass->NumStaticFields();
+ };
+ RecursiveInterfaceVisit<decltype(visitor)>::VisitStatic(art::Thread::Current(), klass, visitor);
+ return count;
+
+ // TODO: Implement caching.
+ }
+
+ UserData* user_data_;
+};
+
+// Debug helper. Prints the structure of an object.
+template <bool kStatic, bool kRef>
+struct DumpVisitor {
+ static bool Callback(art::ObjPtr<art::mirror::Object> obj ATTRIBUTE_UNUSED,
+ art::ObjPtr<art::mirror::Class> klass ATTRIBUTE_UNUSED,
+ art::ArtField& field,
+ size_t field_index,
+ void* user_data ATTRIBUTE_UNUSED)
+ REQUIRES_SHARED(art::Locks::mutator_lock_) {
+ LOG(ERROR) << (kStatic ? "static " : "instance ")
+ << (kRef ? "ref " : "primitive ")
+ << field.PrettyField()
+ << " @ "
+ << field_index;
+ return false;
+ }
+};
+ATTRIBUTE_UNUSED
+void DumpObjectFields(art::ObjPtr<art::mirror::Object> obj)
+ REQUIRES_SHARED(art::Locks::mutator_lock_) {
+ if (obj->IsClass()) {
+ FieldVisitor<decltype(DumpVisitor<true, false>::Callback),
+ decltype(DumpVisitor<true, true>::Callback),
+ decltype(DumpVisitor<false, false>::Callback),
+ decltype(DumpVisitor<false, true>::Callback),
+ void,
+ false>::
+ ReportFields(obj,
+ nullptr,
+ DumpVisitor<true, false>::Callback,
+ DumpVisitor<true, true>::Callback,
+ DumpVisitor<false, false>::Callback,
+ DumpVisitor<false, true>::Callback);
+ } else {
+ FieldVisitor<decltype(DumpVisitor<true, false>::Callback),
+ decltype(DumpVisitor<true, true>::Callback),
+ decltype(DumpVisitor<false, false>::Callback),
+ decltype(DumpVisitor<false, true>::Callback),
+ void,
+ true>::
+ ReportFields(obj,
+ nullptr,
+ DumpVisitor<true, false>::Callback,
+ DumpVisitor<true, true>::Callback,
+ DumpVisitor<false, false>::Callback,
+ DumpVisitor<false, true>::Callback);
+ }
+}
+
+class ReportPrimitiveField {
+ public:
+ static bool Report(art::ObjPtr<art::mirror::Object> obj,
+ ObjectTagTable* tag_table,
+ const jvmtiHeapCallbacks* cb,
+ const void* user_data)
+ REQUIRES_SHARED(art::Locks::mutator_lock_) {
+ if (UNLIKELY(cb->primitive_field_callback != nullptr)) {
+ jlong class_tag = tag_table->GetTagOrZero(obj->GetClass());
+ ReportPrimitiveField rpf(tag_table, class_tag, cb, user_data);
+ if (obj->IsClass()) {
+ return FieldVisitor<decltype(ReportPrimitiveFieldCallback<true>),
+ decltype(VisitorFalse<ReportPrimitiveField>),
+ decltype(VisitorFalse<ReportPrimitiveField>),
+ decltype(VisitorFalse<ReportPrimitiveField>),
+ ReportPrimitiveField,
+ false>::
+ ReportFields(obj,
+ &rpf,
+ ReportPrimitiveFieldCallback<true>,
+ VisitorFalse<ReportPrimitiveField>,
+ VisitorFalse<ReportPrimitiveField>,
+ VisitorFalse<ReportPrimitiveField>);
+ } else {
+ return FieldVisitor<decltype(VisitorFalse<ReportPrimitiveField>),
+ decltype(VisitorFalse<ReportPrimitiveField>),
+ decltype(ReportPrimitiveFieldCallback<false>),
+ decltype(VisitorFalse<ReportPrimitiveField>),
+ ReportPrimitiveField,
+ true>::
+ ReportFields(obj,
+ &rpf,
+ VisitorFalse<ReportPrimitiveField>,
+ VisitorFalse<ReportPrimitiveField>,
+ ReportPrimitiveFieldCallback<false>,
+ VisitorFalse<ReportPrimitiveField>);
+ }
+ }
+ return false;
+ }
+
+
+ private:
+ ReportPrimitiveField(ObjectTagTable* tag_table,
+ jlong class_tag,
+ const jvmtiHeapCallbacks* cb,
+ const void* user_data)
+ : tag_table_(tag_table), class_tag_(class_tag), cb_(cb), user_data_(user_data) {}
+
+ template <bool kReportStatic>
+ static bool ReportPrimitiveFieldCallback(art::ObjPtr<art::mirror::Object> obj,
+ art::ObjPtr<art::mirror::Class> klass,
+ art::ArtField& field,
+ size_t field_index,
+ ReportPrimitiveField* user_data)
+ REQUIRES_SHARED(art::Locks::mutator_lock_) {
+ art::Primitive::Type art_prim_type = field.GetTypeAsPrimitiveType();
+ jvmtiPrimitiveType prim_type =
+ static_cast<jvmtiPrimitiveType>(art::Primitive::Descriptor(art_prim_type)[0]);
+ DCHECK(prim_type == JVMTI_PRIMITIVE_TYPE_BOOLEAN ||
+ prim_type == JVMTI_PRIMITIVE_TYPE_BYTE ||
+ prim_type == JVMTI_PRIMITIVE_TYPE_CHAR ||
+ prim_type == JVMTI_PRIMITIVE_TYPE_SHORT ||
+ prim_type == JVMTI_PRIMITIVE_TYPE_INT ||
+ prim_type == JVMTI_PRIMITIVE_TYPE_LONG ||
+ prim_type == JVMTI_PRIMITIVE_TYPE_FLOAT ||
+ prim_type == JVMTI_PRIMITIVE_TYPE_DOUBLE);
+ jvmtiHeapReferenceInfo info;
+ info.field.index = field_index;
+
+ jvalue value;
+ memset(&value, 0, sizeof(jvalue));
+ art::ObjPtr<art::mirror::Object> src = kReportStatic ? klass : obj;
+ switch (art_prim_type) {
+ case art::Primitive::Type::kPrimBoolean:
+ value.z = field.GetBoolean(src) == 0 ? JNI_FALSE : JNI_TRUE;
+ break;
+ case art::Primitive::Type::kPrimByte:
+ value.b = field.GetByte(src);
+ break;
+ case art::Primitive::Type::kPrimChar:
+ value.c = field.GetChar(src);
+ break;
+ case art::Primitive::Type::kPrimShort:
+ value.s = field.GetShort(src);
+ break;
+ case art::Primitive::Type::kPrimInt:
+ value.i = field.GetInt(src);
+ break;
+ case art::Primitive::Type::kPrimLong:
+ value.j = field.GetLong(src);
+ break;
+ case art::Primitive::Type::kPrimFloat:
+ value.f = field.GetFloat(src);
+ break;
+ case art::Primitive::Type::kPrimDouble:
+ value.d = field.GetDouble(src);
+ break;
+ case art::Primitive::Type::kPrimVoid:
+ case art::Primitive::Type::kPrimNot: {
+ LOG(FATAL) << "Should not reach here";
+ UNREACHABLE();
+ }
+ }
+
+ jlong obj_tag = user_data->tag_table_->GetTagOrZero(src.Ptr());
+ const jlong saved_obj_tag = obj_tag;
+
+ jint ret = user_data->cb_->primitive_field_callback(kReportStatic
+ ? JVMTI_HEAP_REFERENCE_STATIC_FIELD
+ : JVMTI_HEAP_REFERENCE_FIELD,
+ &info,
+ user_data->class_tag_,
+ &obj_tag,
+ value,
+ prim_type,
+ const_cast<void*>(user_data->user_data_));
+
+ if (saved_obj_tag != obj_tag) {
+ user_data->tag_table_->Set(src.Ptr(), obj_tag);
+ }
+
+ if ((ret & JVMTI_VISIT_ABORT) != 0) {
+ return true;
+ }
+
+ return false;
+ }
+
+ ObjectTagTable* tag_table_;
+ jlong class_tag_;
+ const jvmtiHeapCallbacks* cb_;
+ const void* user_data_;
+};
+
struct HeapFilter {
explicit HeapFilter(jint heap_filter)
: filter_out_tagged((heap_filter & JVMTI_HEAP_FILTER_TAGGED) != 0),
@@ -292,7 +725,12 @@
ithd->stop_reports = (array_ret & JVMTI_VISIT_ABORT) != 0;
}
- // TODO Implement primitive field callback.
+ if (!ithd->stop_reports) {
+ ithd->stop_reports = ReportPrimitiveField::Report(obj,
+ ithd->heap_util->GetTags(),
+ ithd->callbacks,
+ ithd->user_data);
+ }
}
jvmtiError HeapUtil::IterateThroughHeap(jvmtiEnv* env,
@@ -626,6 +1064,10 @@
jint string_ret = ReportString(obj, env, tag_table_, callbacks_, user_data_);
stop_reports_ = (string_ret & JVMTI_VISIT_ABORT) != 0;
}
+
+ if (!stop_reports_) {
+ stop_reports_ = ReportPrimitiveField::Report(obj, tag_table_, callbacks_, user_data_);
+ }
}
void VisitArray(art::mirror::Object* array)
@@ -739,6 +1181,10 @@
}
}
}
+
+ if (!stop_reports_) {
+ stop_reports_ = ReportPrimitiveField::Report(klass, tag_table_, callbacks_, user_data_);
+ }
}
void MaybeEnqueue(art::mirror::Object* obj) REQUIRES_SHARED(art::Locks::mutator_lock_) {
diff --git a/test/154-gc-loop/src/Main.java b/test/154-gc-loop/src/Main.java
index 3a256c1..2228ca2 100644
--- a/test/154-gc-loop/src/Main.java
+++ b/test/154-gc-loop/src/Main.java
@@ -38,7 +38,7 @@
}
} catch (Exception e) {}
System.out.println("Finalize count too large: " +
- ((finalizeCounter >= 10) ? Integer.toString(finalizeCounter) : "false"));
+ ((finalizeCounter >= 12) ? Integer.toString(finalizeCounter) : "false"));
}
private static native void backgroundProcessState();
diff --git a/test/906-iterate-heap/expected.txt b/test/906-iterate-heap/expected.txt
index 3e857ab..b6af843 100644
--- a/test/906-iterate-heap/expected.txt
+++ b/test/906-iterate-heap/expected.txt
@@ -18,3 +18,27 @@
2
1@0 (32, 2xD '0000000000000000000000000000f03f')
2
+10000@0 (static, int, index=3) 0000000000000000
+10001
+10000@0 (static, int, index=11) 0000000000000000
+10001
+10000@0 (static, int, index=0) 0000000000000000
+10001
+10000@0 (static, int, index=1) 0000000000000000
+10001
+10000@0 (instance, int, index=2) 0000000000000000
+10001@0 (instance, byte, index=4) 0000000000000001
+10002@0 (instance, char, index=5) 0000000000000061
+10003@0 (instance, int, index=6) 0000000000000003
+10004@0 (instance, long, index=7) 0000000000000004
+10005@0 (instance, short, index=9) 0000000000000002
+10006
+10000@0 (instance, int, index=3) 0000000000000000
+10001@0 (instance, byte, index=5) 0000000000000001
+10002@0 (instance, char, index=6) 0000000000000061
+10003@0 (instance, int, index=7) 0000000000000003
+10004@0 (instance, long, index=8) 0000000000000004
+10005@0 (instance, short, index=10) 0000000000000002
+10006@0 (instance, double, index=12) 3ff3ae147ae147ae
+10007@0 (instance, float, index=13) 000000003f9d70a4
+10008
diff --git a/test/906-iterate-heap/iterate_heap.cc b/test/906-iterate-heap/iterate_heap.cc
index 890220e..13c3562 100644
--- a/test/906-iterate-heap/iterate_heap.cc
+++ b/test/906-iterate-heap/iterate_heap.cc
@@ -322,5 +322,92 @@
return env->NewStringUTF(fac.data.c_str());
}
+static constexpr const char* GetPrimitiveTypeName(jvmtiPrimitiveType type) {
+ switch (type) {
+ case JVMTI_PRIMITIVE_TYPE_BOOLEAN:
+ return "boolean";
+ case JVMTI_PRIMITIVE_TYPE_BYTE:
+ return "byte";
+ case JVMTI_PRIMITIVE_TYPE_CHAR:
+ return "char";
+ case JVMTI_PRIMITIVE_TYPE_SHORT:
+ return "short";
+ case JVMTI_PRIMITIVE_TYPE_INT:
+ return "int";
+ case JVMTI_PRIMITIVE_TYPE_FLOAT:
+ return "float";
+ case JVMTI_PRIMITIVE_TYPE_LONG:
+ return "long";
+ case JVMTI_PRIMITIVE_TYPE_DOUBLE:
+ return "double";
+ }
+ LOG(FATAL) << "Unknown type " << static_cast<size_t>(type);
+ UNREACHABLE();
+}
+
+extern "C" JNIEXPORT jstring JNICALL Java_Main_iterateThroughHeapPrimitiveFields(
+ JNIEnv* env, jclass klass ATTRIBUTE_UNUSED, jlong tag) {
+ struct FindFieldCallbacks {
+ explicit FindFieldCallbacks(jlong t) : tag_to_find(t) {}
+
+ static jint JNICALL HeapIterationCallback(jlong class_tag ATTRIBUTE_UNUSED,
+ jlong size ATTRIBUTE_UNUSED,
+ jlong* tag_ptr ATTRIBUTE_UNUSED,
+ jint length ATTRIBUTE_UNUSED,
+ void* user_data ATTRIBUTE_UNUSED) {
+ return 0;
+ }
+
+ static jint JNICALL PrimitiveFieldValueCallback(jvmtiHeapReferenceKind kind,
+ const jvmtiHeapReferenceInfo* info,
+ jlong class_tag,
+ jlong* tag_ptr,
+ jvalue value,
+ jvmtiPrimitiveType value_type,
+ void* user_data) {
+ FindFieldCallbacks* p = reinterpret_cast<FindFieldCallbacks*>(user_data);
+ if (*tag_ptr >= p->tag_to_find) {
+ std::ostringstream oss;
+ oss << *tag_ptr
+ << '@'
+ << class_tag
+ << " ("
+ << (kind == JVMTI_HEAP_REFERENCE_FIELD ? "instance, " : "static, ")
+ << GetPrimitiveTypeName(value_type)
+ << ", index="
+ << info->field.index
+ << ") ";
+ // Be lazy, always print eight bytes.
+ static_assert(sizeof(jvalue) == sizeof(uint64_t), "Unexpected jvalue size");
+ uint64_t val;
+ memcpy(&val, &value, sizeof(uint64_t)); // To avoid undefined behavior.
+ oss << android::base::StringPrintf("%016" PRIx64, val);
+
+ if (!p->data.empty()) {
+ p->data += "\n";
+ }
+ p->data += oss.str();
+ *tag_ptr = *tag_ptr + 1;
+ }
+ return 0;
+ }
+
+ std::string data;
+ const jlong tag_to_find;
+ };
+
+ jvmtiHeapCallbacks callbacks;
+ memset(&callbacks, 0, sizeof(jvmtiHeapCallbacks));
+ callbacks.heap_iteration_callback = FindFieldCallbacks::HeapIterationCallback;
+ callbacks.primitive_field_callback = FindFieldCallbacks::PrimitiveFieldValueCallback;
+
+ FindFieldCallbacks ffc(tag);
+ jvmtiError ret = jvmti_env->IterateThroughHeap(0, nullptr, &callbacks, &ffc);
+ if (JvmtiErrorToException(env, ret)) {
+ return nullptr;
+ }
+ return env->NewStringUTF(ffc.data.c_str());
+}
+
} // namespace Test906IterateHeap
} // namespace art
diff --git a/test/906-iterate-heap/src/Main.java b/test/906-iterate-heap/src/Main.java
index d499886..365ce0f 100644
--- a/test/906-iterate-heap/src/Main.java
+++ b/test/906-iterate-heap/src/Main.java
@@ -119,6 +119,60 @@
setTag(dArray, 1);
System.out.println(iterateThroughHeapPrimitiveArray(getTag(dArray)));
System.out.println(getTag(dArray));
+
+ // Force GCs to clean up dirt.
+ Runtime.getRuntime().gc();
+ Runtime.getRuntime().gc();
+
+ doTestPrimitiveFieldsClasses();
+
+ doTestPrimitiveFieldsIntegral();
+
+ // Force GCs to clean up dirt.
+ Runtime.getRuntime().gc();
+ Runtime.getRuntime().gc();
+
+ doTestPrimitiveFieldsFloat();
+
+ // Force GCs to clean up dirt.
+ Runtime.getRuntime().gc();
+ Runtime.getRuntime().gc();
+ }
+
+ private static void doTestPrimitiveFieldsClasses() {
+ setTag(IntObject.class, 10000);
+ System.out.println(iterateThroughHeapPrimitiveFields(10000));
+ System.out.println(getTag(IntObject.class));
+ setTag(IntObject.class, 0);
+
+ setTag(FloatObject.class, 10000);
+ System.out.println(iterateThroughHeapPrimitiveFields(10000));
+ System.out.println(getTag(FloatObject.class));
+ setTag(FloatObject.class, 0);
+
+ setTag(Inf1.class, 10000);
+ System.out.println(iterateThroughHeapPrimitiveFields(10000));
+ System.out.println(getTag(Inf1.class));
+ setTag(Inf1.class, 0);
+
+ setTag(Inf2.class, 10000);
+ System.out.println(iterateThroughHeapPrimitiveFields(10000));
+ System.out.println(getTag(Inf2.class));
+ setTag(Inf2.class, 0);
+ }
+
+ private static void doTestPrimitiveFieldsIntegral() {
+ IntObject intObject = new IntObject();
+ setTag(intObject, 10000);
+ System.out.println(iterateThroughHeapPrimitiveFields(10000));
+ System.out.println(getTag(intObject));
+ }
+
+ private static void doTestPrimitiveFieldsFloat() {
+ FloatObject floatObject = new FloatObject();
+ setTag(floatObject, 10000);
+ System.out.println(iterateThroughHeapPrimitiveFields(10000));
+ System.out.println(getTag(floatObject));
}
static class A {
@@ -172,6 +226,31 @@
return ret;
}
+ private static interface Inf1 {
+ public final static int A = 1;
+ }
+
+ private static interface Inf2 extends Inf1 {
+ public final static int B = 1;
+ }
+
+ private static class IntObject implements Inf1 {
+ byte b = (byte)1;
+ char c= 'a';
+ short s = (short)2;
+ int i = 3;
+ long l = 4;
+ Object o = new Object();
+ static int sI = 5;
+ }
+
+ private static class FloatObject extends IntObject implements Inf2 {
+ float f = 1.23f;
+ double d = 1.23;
+ Object p = new Object();
+ static int sI = 6;
+ }
+
private static native void setTag(Object o, long tag);
private static native long getTag(Object o);
@@ -188,4 +267,5 @@
Class<?> klassFilter);
private static native String iterateThroughHeapString(long tag);
private static native String iterateThroughHeapPrimitiveArray(long tag);
+ private static native String iterateThroughHeapPrimitiveFields(long tag);
}
diff --git a/test/913-heaps/expected.txt b/test/913-heaps/expected.txt
index c96edef..437b7b8 100644
--- a/test/913-heaps/expected.txt
+++ b/test/913-heaps/expected.txt
@@ -91,6 +91,30 @@
4@0 (18, 3xS '010002000300')
1@0 (14, 2xZ '0001')
23456789
+10000@0 (static, int, index=3) 0000000000000000
+10001
+10000@0 (static, int, index=11) 0000000000000000
+10001
+10000@0 (static, int, index=0) 0000000000000000
+10001
+10000@0 (static, int, index=1) 0000000000000000
+10001
+10000@0 (instance, int, index=2) 0000000000000000
+10001@0 (instance, byte, index=4) 0000000000000001
+10002@0 (instance, char, index=5) 0000000000000061
+10003@0 (instance, int, index=6) 0000000000000003
+10004@0 (instance, long, index=7) 0000000000000004
+10005@0 (instance, short, index=9) 0000000000000002
+10006
+10000@0 (instance, int, index=3) 0000000000000000
+10001@0 (instance, byte, index=5) 0000000000000001
+10002@0 (instance, char, index=6) 0000000000000061
+10003@0 (instance, int, index=7) 0000000000000003
+10004@0 (instance, long, index=8) 0000000000000004
+10005@0 (instance, short, index=10) 0000000000000002
+10006@0 (instance, double, index=12) 3ff3ae147ae147ae
+10007@0 (instance, float, index=13) 000000003f9d70a4
+10008
--- klass ---
root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestNonRoot,vreg=13,location= 32])--> 1@1000 [size=16, length=-1]
0@0 --(array-element@0)--> 1@1000 [size=16, length=-1]
diff --git a/test/913-heaps/heaps.cc b/test/913-heaps/heaps.cc
index 99bc48e..39fa000 100644
--- a/test/913-heaps/heaps.cc
+++ b/test/913-heaps/heaps.cc
@@ -654,5 +654,95 @@
return env->NewStringUTF(fac.data.c_str());
}
+static constexpr const char* GetPrimitiveTypeName(jvmtiPrimitiveType type) {
+ switch (type) {
+ case JVMTI_PRIMITIVE_TYPE_BOOLEAN:
+ return "boolean";
+ case JVMTI_PRIMITIVE_TYPE_BYTE:
+ return "byte";
+ case JVMTI_PRIMITIVE_TYPE_CHAR:
+ return "char";
+ case JVMTI_PRIMITIVE_TYPE_SHORT:
+ return "short";
+ case JVMTI_PRIMITIVE_TYPE_INT:
+ return "int";
+ case JVMTI_PRIMITIVE_TYPE_FLOAT:
+ return "float";
+ case JVMTI_PRIMITIVE_TYPE_LONG:
+ return "long";
+ case JVMTI_PRIMITIVE_TYPE_DOUBLE:
+ return "double";
+ }
+ LOG(FATAL) << "Unknown type " << static_cast<size_t>(type);
+ UNREACHABLE();
+}
+
+extern "C" JNIEXPORT jstring JNICALL Java_Main_followReferencesPrimitiveFields(
+ JNIEnv* env, jclass klass ATTRIBUTE_UNUSED, jobject initial_object) {
+ struct FindFieldCallbacks {
+ static jint JNICALL FollowReferencesCallback(
+ jvmtiHeapReferenceKind reference_kind ATTRIBUTE_UNUSED,
+ const jvmtiHeapReferenceInfo* reference_info ATTRIBUTE_UNUSED,
+ jlong class_tag ATTRIBUTE_UNUSED,
+ jlong referrer_class_tag ATTRIBUTE_UNUSED,
+ jlong size ATTRIBUTE_UNUSED,
+ jlong* tag_ptr ATTRIBUTE_UNUSED,
+ jlong* referrer_tag_ptr ATTRIBUTE_UNUSED,
+ jint length ATTRIBUTE_UNUSED,
+ void* user_data ATTRIBUTE_UNUSED) {
+ return JVMTI_VISIT_OBJECTS; // Continue visiting.
+ }
+
+ static jint JNICALL PrimitiveFieldValueCallback(jvmtiHeapReferenceKind kind,
+ const jvmtiHeapReferenceInfo* info,
+ jlong class_tag,
+ jlong* tag_ptr,
+ jvalue value,
+ jvmtiPrimitiveType value_type,
+ void* user_data) {
+ FindFieldCallbacks* p = reinterpret_cast<FindFieldCallbacks*>(user_data);
+ if (*tag_ptr != 0) {
+ std::ostringstream oss;
+ oss << *tag_ptr
+ << '@'
+ << class_tag
+ << " ("
+ << (kind == JVMTI_HEAP_REFERENCE_FIELD ? "instance, " : "static, ")
+ << GetPrimitiveTypeName(value_type)
+ << ", index="
+ << info->field.index
+ << ") ";
+ // Be lazy, always print eight bytes.
+ static_assert(sizeof(jvalue) == sizeof(uint64_t), "Unexpected jvalue size");
+ uint64_t val;
+ memcpy(&val, &value, sizeof(uint64_t)); // To avoid undefined behavior.
+ oss << android::base::StringPrintf("%016" PRIx64, val);
+
+ if (!p->data.empty()) {
+ p->data += "\n";
+ }
+ p->data += oss.str();
+ // Update the tag to test whether that works.
+ *tag_ptr = *tag_ptr + 1;
+ }
+ return 0;
+ }
+
+ std::string data;
+ };
+
+ jvmtiHeapCallbacks callbacks;
+ memset(&callbacks, 0, sizeof(jvmtiHeapCallbacks));
+ callbacks.heap_reference_callback = FindFieldCallbacks::FollowReferencesCallback;
+ callbacks.primitive_field_callback = FindFieldCallbacks::PrimitiveFieldValueCallback;
+
+ FindFieldCallbacks ffc;
+ jvmtiError ret = jvmti_env->FollowReferences(0, nullptr, initial_object, &callbacks, &ffc);
+ if (JvmtiErrorToException(env, ret)) {
+ return nullptr;
+ }
+ return env->NewStringUTF(ffc.data.c_str());
+}
+
} // namespace Test913Heaps
} // namespace art
diff --git a/test/913-heaps/src/Main.java b/test/913-heaps/src/Main.java
index 14ee268..66f6883 100644
--- a/test/913-heaps/src/Main.java
+++ b/test/913-heaps/src/Main.java
@@ -34,6 +34,7 @@
Runtime.getRuntime().gc();
doPrimitiveArrayTest();
+ doPrimitiveFieldTest();
Runtime.getRuntime().gc();
Runtime.getRuntime().gc();
@@ -124,6 +125,62 @@
System.out.println(getTag(dArray));
}
+ public static void doPrimitiveFieldTest() throws Exception {
+ // Force GCs to clean up dirt.
+ Runtime.getRuntime().gc();
+ Runtime.getRuntime().gc();
+
+ doTestPrimitiveFieldsClasses();
+
+ doTestPrimitiveFieldsIntegral();
+
+ // Force GCs to clean up dirt.
+ Runtime.getRuntime().gc();
+ Runtime.getRuntime().gc();
+
+ doTestPrimitiveFieldsFloat();
+
+ // Force GCs to clean up dirt.
+ Runtime.getRuntime().gc();
+ Runtime.getRuntime().gc();
+ }
+
+ private static void doTestPrimitiveFieldsClasses() {
+ setTag(IntObject.class, 10000);
+ System.out.println(followReferencesPrimitiveFields(IntObject.class));
+ System.out.println(getTag(IntObject.class));
+ setTag(IntObject.class, 0);
+
+ setTag(FloatObject.class, 10000);
+ System.out.println(followReferencesPrimitiveFields(FloatObject.class));
+ System.out.println(getTag(FloatObject.class));
+ setTag(FloatObject.class, 0);
+
+ setTag(Inf1.class, 10000);
+ System.out.println(followReferencesPrimitiveFields(Inf1.class));
+ System.out.println(getTag(Inf1.class));
+ setTag(Inf1.class, 0);
+
+ setTag(Inf2.class, 10000);
+ System.out.println(followReferencesPrimitiveFields(Inf2.class));
+ System.out.println(getTag(Inf2.class));
+ setTag(Inf2.class, 0);
+ }
+
+ private static void doTestPrimitiveFieldsIntegral() {
+ IntObject intObject = new IntObject();
+ setTag(intObject, 10000);
+ System.out.println(followReferencesPrimitiveFields(intObject));
+ System.out.println(getTag(intObject));
+ }
+
+ private static void doTestPrimitiveFieldsFloat() {
+ FloatObject floatObject = new FloatObject();
+ setTag(floatObject, 10000);
+ System.out.println(followReferencesPrimitiveFields(floatObject));
+ System.out.println(getTag(floatObject));
+ }
+
private static void run() {
clearStats();
forceGarbageCollection();
@@ -315,6 +372,31 @@
}
}
+ private static interface Inf1 {
+ public final static int A = 1;
+ }
+
+ private static interface Inf2 extends Inf1 {
+ public final static int B = 1;
+ }
+
+ private static class IntObject implements Inf1 {
+ byte b = (byte)1;
+ char c= 'a';
+ short s = (short)2;
+ int i = 3;
+ long l = 4;
+ Object o = new Object();
+ static int sI = 5;
+ }
+
+ private static class FloatObject extends IntObject implements Inf2 {
+ float f = 1.23f;
+ double d = 1.23;
+ Object p = new Object();
+ static int sI = 6;
+ }
+
public static class Verifier {
// Should roots with vreg=-1 be printed?
public final static boolean PRINT_ROOTS_WITH_UNKNOWN_VREG = false;
@@ -508,4 +590,5 @@
Object initialObject, int stopAfter, int followSet, Object jniRef);
public static native String[] followReferencesString(Object initialObject);
public static native String followReferencesPrimitiveArray(Object initialObject);
+ public static native String followReferencesPrimitiveFields(Object initialObject);
}
diff --git a/test/Android.run-test.mk b/test/Android.run-test.mk
index 95967b5..b575d55 100644
--- a/test/Android.run-test.mk
+++ b/test/Android.run-test.mk
@@ -368,6 +368,7 @@
# Tests that are broken with GC stress.
# * 137-cfi needs to unwind a second forked process. We're using a primitive sleep to wait till we
# hope the second process got into the expected state. The slowness of gcstress makes this bad.
+# * 152-dead-large-object requires a heap larger than what gcstress uses.
# * 908-gc-start-finish expects GCs only to be run at clear points. The reduced heap size makes
# this non-deterministic. Same for 913.
# * 961-default-iface-resolution-gen and 964-default-iface-init-genare very long tests that often
@@ -375,6 +376,7 @@
# slows down allocations significantly which these tests do a lot.
TEST_ART_BROKEN_GCSTRESS_RUN_TESTS := \
137-cfi \
+ 152-dead-large-object \
154-gc-loop \
908-gc-start-finish \
913-heaps \
diff --git a/test/knownfailures.json b/test/knownfailures.json
index 784f49c..6caf7b0 100644
--- a/test/knownfailures.json
+++ b/test/knownfailures.json
@@ -106,6 +106,11 @@
"slowness of gcstress makes this bad."]
},
{
+ "test": "152-dead-large-object",
+ "variant": "gcstress",
+ "description": ["152-dead-large-object requires a heap larger than what gcstress uses."]
+ },
+ {
"tests": ["908-gc-start-finish",
"913-heaps"],
"variant": "gcstress",