diff options
| -rw-r--r-- | compiler/optimizing/instruction_builder.cc | 54 | ||||
| -rw-r--r-- | compiler/optimizing/instruction_builder.h | 1 | ||||
| -rw-r--r-- | compiler/optimizing/intrinsics_mips64.cc | 89 | ||||
| -rw-r--r-- | runtime/class_linker.cc | 23 | ||||
| -rw-r--r-- | test/099-vmdebug/src/Main.java | 6 | ||||
| -rw-r--r-- | test/444-checker-nce/src/Main.java | 16 | ||||
| -rw-r--r-- | test/572-checker-array-get-regression/src/Main.java | 8 | ||||
| -rw-r--r-- | tools/ahat/README.txt | 7 | ||||
| -rw-r--r-- | tools/ahat/src/AhatSnapshot.java | 84 | ||||
| -rw-r--r-- | tools/ahat/src/InstanceUtils.java | 6 | ||||
| -rw-r--r-- | tools/ahat/src/ObjectHandler.java | 8 |
11 files changed, 204 insertions, 98 deletions
diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc index 12cb826395..00cd2f659d 100644 --- a/compiler/optimizing/instruction_builder.cc +++ b/compiler/optimizing/instruction_builder.cc @@ -215,6 +215,17 @@ void HInstructionBuilder::InitializeInstruction(HInstruction* instruction) { } } +HInstruction* HInstructionBuilder::LoadNullCheckedLocal(uint32_t register_index, uint32_t dex_pc) { + HInstruction* ref = LoadLocal(register_index, Primitive::kPrimNot); + if (!ref->CanBeNull()) { + return ref; + } + + HNullCheck* null_check = new (arena_) HNullCheck(ref, dex_pc); + AppendInstruction(null_check); + return null_check; +} + void HInstructionBuilder::SetLoopHeaderPhiInputs() { for (size_t i = loop_headers_.size(); i > 0; --i) { HBasicBlock* block = loop_headers_[i - 1]; @@ -1084,10 +1095,9 @@ bool HInstructionBuilder::HandleInvoke(HInvoke* invoke, size_t start_index = 0; size_t argument_index = 0; if (invoke->GetOriginalInvokeType() != InvokeType::kStatic) { // Instance call. - HInstruction* arg = LoadLocal(is_range ? register_index : args[0], Primitive::kPrimNot); - HNullCheck* null_check = new (arena_) HNullCheck(arg, invoke->GetDexPc()); - AppendInstruction(null_check); - invoke->SetArgumentAt(0, null_check); + HInstruction* arg = LoadNullCheckedLocal(is_range ? register_index : args[0], + invoke->GetDexPc()); + invoke->SetArgumentAt(0, arg); start_index = 1; argument_index = 1; } @@ -1193,9 +1203,7 @@ bool HInstructionBuilder::BuildInstanceFieldAccess(const Instruction& instructio compiler_driver_->ComputeInstanceFieldInfo(field_index, dex_compilation_unit_, is_put, soa); - HInstruction* object = LoadLocal(obj_reg, Primitive::kPrimNot); - HInstruction* null_check = new (arena_) HNullCheck(object, dex_pc); - AppendInstruction(null_check); + HInstruction* object = LoadNullCheckedLocal(obj_reg, dex_pc); Primitive::Type field_type = (resolved_field == nullptr) ? GetFieldAccessType(*dex_file_, field_index) @@ -1205,14 +1213,14 @@ bool HInstructionBuilder::BuildInstanceFieldAccess(const Instruction& instructio HInstruction* field_set = nullptr; if (resolved_field == nullptr) { MaybeRecordStat(MethodCompilationStat::kUnresolvedField); - field_set = new (arena_) HUnresolvedInstanceFieldSet(null_check, + field_set = new (arena_) HUnresolvedInstanceFieldSet(object, value, field_type, field_index, dex_pc); } else { uint16_t class_def_index = resolved_field->GetDeclaringClass()->GetDexClassDefIndex(); - field_set = new (arena_) HInstanceFieldSet(null_check, + field_set = new (arena_) HInstanceFieldSet(object, value, field_type, resolved_field->GetOffset(), @@ -1228,13 +1236,13 @@ bool HInstructionBuilder::BuildInstanceFieldAccess(const Instruction& instructio HInstruction* field_get = nullptr; if (resolved_field == nullptr) { MaybeRecordStat(MethodCompilationStat::kUnresolvedField); - field_get = new (arena_) HUnresolvedInstanceFieldGet(null_check, + field_get = new (arena_) HUnresolvedInstanceFieldGet(object, field_type, field_index, dex_pc); } else { uint16_t class_def_index = resolved_field->GetDeclaringClass()->GetDexClassDefIndex(); - field_get = new (arena_) HInstanceFieldGet(null_check, + field_get = new (arena_) HInstanceFieldGet(object, field_type, resolved_field->GetOffset(), resolved_field->IsVolatile(), @@ -1449,10 +1457,7 @@ void HInstructionBuilder::BuildArrayAccess(const Instruction& instruction, uint8_t array_reg = instruction.VRegB_23x(); uint8_t index_reg = instruction.VRegC_23x(); - HInstruction* object = LoadLocal(array_reg, Primitive::kPrimNot); - object = new (arena_) HNullCheck(object, dex_pc); - AppendInstruction(object); - + HInstruction* object = LoadNullCheckedLocal(array_reg, dex_pc); HInstruction* length = new (arena_) HArrayLength(object, dex_pc); AppendInstruction(length); HInstruction* index = LoadLocal(index_reg, Primitive::kPrimInt); @@ -1527,11 +1532,8 @@ void HInstructionBuilder::BuildFillArrayData(HInstruction* object, } void HInstructionBuilder::BuildFillArrayData(const Instruction& instruction, uint32_t dex_pc) { - HInstruction* array = LoadLocal(instruction.VRegA_31t(), Primitive::kPrimNot); - HNullCheck* null_check = new (arena_) HNullCheck(array, dex_pc); - AppendInstruction(null_check); - - HInstruction* length = new (arena_) HArrayLength(null_check, dex_pc); + HInstruction* array = LoadNullCheckedLocal(instruction.VRegA_31t(), dex_pc); + HInstruction* length = new (arena_) HArrayLength(array, dex_pc); AppendInstruction(length); int32_t payload_offset = instruction.VRegB_31t() + dex_pc; @@ -1547,28 +1549,28 @@ void HInstructionBuilder::BuildFillArrayData(const Instruction& instruction, uin switch (payload->element_width) { case 1: - BuildFillArrayData(null_check, + BuildFillArrayData(array, reinterpret_cast<const int8_t*>(data), element_count, Primitive::kPrimByte, dex_pc); break; case 2: - BuildFillArrayData(null_check, + BuildFillArrayData(array, reinterpret_cast<const int16_t*>(data), element_count, Primitive::kPrimShort, dex_pc); break; case 4: - BuildFillArrayData(null_check, + BuildFillArrayData(array, reinterpret_cast<const int32_t*>(data), element_count, Primitive::kPrimInt, dex_pc); break; case 8: - BuildFillWideArrayData(null_check, + BuildFillWideArrayData(array, reinterpret_cast<const int64_t*>(data), element_count, dex_pc); @@ -2575,9 +2577,7 @@ bool HInstructionBuilder::ProcessDexInstruction(const Instruction& instruction, ARRAY_XX(_SHORT, Primitive::kPrimShort); case Instruction::ARRAY_LENGTH: { - HInstruction* object = LoadLocal(instruction.VRegB_12x(), Primitive::kPrimNot); - object = new (arena_) HNullCheck(object, dex_pc); - AppendInstruction(object); + HInstruction* object = LoadNullCheckedLocal(instruction.VRegB_12x(), dex_pc); AppendInstruction(new (arena_) HArrayLength(object, dex_pc)); UpdateLocal(instruction.VRegA_12x(), current_block_->GetLastInstruction()); break; diff --git a/compiler/optimizing/instruction_builder.h b/compiler/optimizing/instruction_builder.h index 070f7da80e..0e3e5a7c34 100644 --- a/compiler/optimizing/instruction_builder.h +++ b/compiler/optimizing/instruction_builder.h @@ -87,6 +87,7 @@ class HInstructionBuilder : public ValueObject { ArenaVector<HInstruction*>* GetLocalsFor(HBasicBlock* block); HInstruction* ValueOfLocalAt(HBasicBlock* block, size_t local); HInstruction* LoadLocal(uint32_t register_index, Primitive::Type type) const; + HInstruction* LoadNullCheckedLocal(uint32_t register_index, uint32_t dex_pc); void UpdateLocal(uint32_t register_index, HInstruction* instruction); void AppendInstruction(HInstruction* instruction); diff --git a/compiler/optimizing/intrinsics_mips64.cc b/compiler/optimizing/intrinsics_mips64.cc index cf973aa841..1524e1e011 100644 --- a/compiler/optimizing/intrinsics_mips64.cc +++ b/compiler/optimizing/intrinsics_mips64.cc @@ -385,6 +385,92 @@ static void CreateFPToFPLocations(ArenaAllocator* arena, HInvoke* invoke) { locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap); } +static void GenBitCount(LocationSummary* locations, + const Primitive::Type type, + Mips64Assembler* assembler) { + GpuRegister out = locations->Out().AsRegister<GpuRegister>(); + GpuRegister in = locations->InAt(0).AsRegister<GpuRegister>(); + + DCHECK(type == Primitive::kPrimInt || type == Primitive::kPrimLong); + + // https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel + // + // A generalization of the best bit counting method to integers of + // bit-widths up to 128 (parameterized by type T) is this: + // + // v = v - ((v >> 1) & (T)~(T)0/3); // temp + // v = (v & (T)~(T)0/15*3) + ((v >> 2) & (T)~(T)0/15*3); // temp + // v = (v + (v >> 4)) & (T)~(T)0/255*15; // temp + // c = (T)(v * ((T)~(T)0/255)) >> (sizeof(T) - 1) * BITS_PER_BYTE; // count + // + // For comparison, for 32-bit quantities, this algorithm can be executed + // using 20 MIPS instructions (the calls to LoadConst32() generate two + // machine instructions each for the values being used in this algorithm). + // A(n unrolled) loop-based algorithm requires 25 instructions. + // + // For a 64-bit operand this can be performed in 24 instructions compared + // to a(n unrolled) loop based algorithm which requires 38 instructions. + // + // There are algorithms which are faster in the cases where very few + // bits are set but the algorithm here attempts to minimize the total + // number of instructions executed even when a large number of bits + // are set. + + if (type == Primitive::kPrimInt) { + __ Srl(TMP, in, 1); + __ LoadConst32(AT, 0x55555555); + __ And(TMP, TMP, AT); + __ Subu(TMP, in, TMP); + __ LoadConst32(AT, 0x33333333); + __ And(out, TMP, AT); + __ Srl(TMP, TMP, 2); + __ And(TMP, TMP, AT); + __ Addu(TMP, out, TMP); + __ Srl(out, TMP, 4); + __ Addu(out, out, TMP); + __ LoadConst32(AT, 0x0F0F0F0F); + __ And(out, out, AT); + __ LoadConst32(TMP, 0x01010101); + __ MulR6(out, out, TMP); + __ Srl(out, out, 24); + } else if (type == Primitive::kPrimLong) { + __ Dsrl(TMP, in, 1); + __ LoadConst64(AT, 0x5555555555555555L); + __ And(TMP, TMP, AT); + __ Dsubu(TMP, in, TMP); + __ LoadConst64(AT, 0x3333333333333333L); + __ And(out, TMP, AT); + __ Dsrl(TMP, TMP, 2); + __ And(TMP, TMP, AT); + __ Daddu(TMP, out, TMP); + __ Dsrl(out, TMP, 4); + __ Daddu(out, out, TMP); + __ LoadConst64(AT, 0x0F0F0F0F0F0F0F0FL); + __ And(out, out, AT); + __ LoadConst64(TMP, 0x0101010101010101L); + __ Dmul(out, out, TMP); + __ Dsrl32(out, out, 24); + } +} + +// int java.lang.Integer.bitCount(int) +void IntrinsicLocationsBuilderMIPS64::VisitIntegerBitCount(HInvoke* invoke) { + CreateIntToIntLocations(arena_, invoke); +} + +void IntrinsicCodeGeneratorMIPS64::VisitIntegerBitCount(HInvoke* invoke) { + GenBitCount(invoke->GetLocations(), Primitive::kPrimInt, GetAssembler()); +} + +// int java.lang.Long.bitCount(long) +void IntrinsicLocationsBuilderMIPS64::VisitLongBitCount(HInvoke* invoke) { + CreateIntToIntLocations(arena_, invoke); +} + +void IntrinsicCodeGeneratorMIPS64::VisitLongBitCount(HInvoke* invoke) { + GenBitCount(invoke->GetLocations(), Primitive::kPrimLong, GetAssembler()); +} + static void MathAbsFP(LocationSummary* locations, bool is64bit, Mips64Assembler* assembler) { FpuRegister in = locations->InAt(0).AsFpuRegister<FpuRegister>(); FpuRegister out = locations->Out().AsFpuRegister<FpuRegister>(); @@ -1693,9 +1779,6 @@ void IntrinsicCodeGeneratorMIPS64::VisitDoubleIsInfinite(HInvoke* invoke) { GenIsInfinite(invoke->GetLocations(), /* is64bit */ true, GetAssembler()); } -UNIMPLEMENTED_INTRINSIC(MIPS64, IntegerBitCount) -UNIMPLEMENTED_INTRINSIC(MIPS64, LongBitCount) - UNIMPLEMENTED_INTRINSIC(MIPS64, MathRoundDouble) UNIMPLEMENTED_INTRINSIC(MIPS64, MathRoundFloat) diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 1e7ee65eac..fa0107af8e 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -4442,7 +4442,20 @@ bool ClassLinker::InitializeClass(Thread* self, Handle<mirror::Class> klass, // We failed to verify, expect either the klass to be erroneous or verification failed at // compile time. if (klass->IsErroneous()) { - CHECK(self->IsExceptionPending()); + // The class is erroneous. This may be a verifier error, or another thread attempted + // verification and/or initialization and failed. We can distinguish those cases by + // whether an exception is already pending. + if (self->IsExceptionPending()) { + // Check that it's a VerifyError. + DCHECK_EQ("java.lang.Class<java.lang.VerifyError>", + PrettyClass(self->GetException()->GetClass())); + } else { + // Check that another thread attempted initialization. + DCHECK_NE(0, klass->GetClinitThreadId()); + DCHECK_NE(self->GetTid(), klass->GetClinitThreadId()); + // Need to rethrow the previous failure now. + ThrowEarlierClassFailure(klass.Get(), true); + } VlogClassInitializationFailure(klass); } else { CHECK(Runtime::Current()->IsAotCompiler()); @@ -4452,6 +4465,14 @@ bool ClassLinker::InitializeClass(Thread* self, Handle<mirror::Class> klass, } else { self->AssertNoPendingException(); } + + // A separate thread could have moved us all the way to initialized. A "simple" example + // involves a subclass of the current class being initialized at the same time (which + // will implicitly initialize the superclass, if scheduled that way). b/28254258 + DCHECK_NE(mirror::Class::kStatusError, klass->GetStatus()); + if (klass->IsInitialized()) { + return true; + } } // If the class is kStatusInitializing, either this thread is diff --git a/test/099-vmdebug/src/Main.java b/test/099-vmdebug/src/Main.java index 1be5765155..8068721219 100644 --- a/test/099-vmdebug/src/Main.java +++ b/test/099-vmdebug/src/Main.java @@ -133,7 +133,7 @@ public class Main { System.out.println("Got null string"); return; } - long n = Long.valueOf(s); + long n = Long.parseLong(s); if (n < 0) { System.out.println("Got negative number " + n); } @@ -157,8 +157,8 @@ public class Main { System.out.println("Got bad bucket " + bucket); continue; } - long key = Long.valueOf(kv[0]); - long value = Long.valueOf(kv[1]); + long key = Long.parseLong(kv[0]); + long value = Long.parseLong(kv[1]); if (key < 0 || value < 0) { System.out.println("Got negative key or value " + bucket); continue; diff --git a/test/444-checker-nce/src/Main.java b/test/444-checker-nce/src/Main.java index c96b18c71b..ddc2f77e89 100644 --- a/test/444-checker-nce/src/Main.java +++ b/test/444-checker-nce/src/Main.java @@ -28,10 +28,6 @@ public class Main { } /// CHECK-START: Main Main.thisTest() builder (after) - /// CHECK: NullCheck - /// CHECK: InvokeStaticOrDirect - - /// CHECK-START: Main Main.thisTest() instruction_simplifier (after) /// CHECK-NOT: NullCheck /// CHECK: InvokeStaticOrDirect public Main thisTest() { @@ -40,12 +36,10 @@ public class Main { /// CHECK-START: Main Main.newInstanceRemoveTest() builder (after) /// CHECK: NewInstance - /// CHECK: NullCheck /// CHECK: InvokeStaticOrDirect - /// CHECK: NullCheck /// CHECK: InvokeStaticOrDirect - /// CHECK-START: Main Main.newInstanceRemoveTest() instruction_simplifier (after) + /// CHECK-START: Main Main.newInstanceRemoveTest() builder (after) /// CHECK-NOT: NullCheck public Main newInstanceRemoveTest() { Main m = new Main(); @@ -54,13 +48,10 @@ public class Main { /// CHECK-START: Main Main.newArrayRemoveTest() builder (after) /// CHECK: NewArray - /// CHECK: NullCheck /// CHECK: ArrayGet - /// CHECK-START: Main Main.newArrayRemoveTest() instruction_simplifier (after) - /// CHECK: NewArray + /// CHECK-START: Main Main.newArrayRemoveTest() builder (after) /// CHECK-NOT: NullCheck - /// CHECK: ArrayGet public Main newArrayRemoveTest() { Main[] ms = new Main[1]; return ms[0]; @@ -179,9 +170,6 @@ public class Main { } /// CHECK-START: Main Main.scopeRemoveTest(int, Main) builder (after) - /// CHECK: NullCheck - - /// CHECK-START: Main Main.scopeRemoveTest(int, Main) instruction_simplifier (after) /// CHECK-NOT: NullCheck public Main scopeRemoveTest(int count, Main a) { Main m = null; diff --git a/test/572-checker-array-get-regression/src/Main.java b/test/572-checker-array-get-regression/src/Main.java index b55be706f4..89b97ed316 100644 --- a/test/572-checker-array-get-regression/src/Main.java +++ b/test/572-checker-array-get-regression/src/Main.java @@ -25,13 +25,11 @@ public class Main { /// CHECK-DAG: <<Const2P19:i\d+>> IntConstant 524288 /// CHECK-DAG: <<ConstM1:i\d+>> IntConstant -1 /// CHECK-DAG: <<Array:l\d+>> NewArray [<<Const2P19>>,<<Method>>] - /// CHECK-DAG: <<NullCheck1:l\d+>> NullCheck [<<Array>>] - /// CHECK-DAG: <<Length1:i\d+>> ArrayLength [<<NullCheck1>>] + /// CHECK-DAG: <<Length1:i\d+>> ArrayLength [<<Array>>] /// CHECK-DAG: <<Index:i\d+>> Add [<<Length1>>,<<ConstM1>>] - /// CHECK-DAG: <<NullCheck2:l\d+>> NullCheck [<<Array>>] - /// CHECK-DAG: <<Length2:i\d+>> ArrayLength [<<NullCheck2>>] + /// CHECK-DAG: <<Length2:i\d+>> ArrayLength [<<Array>>] /// CHECK-DAG: <<BoundsCheck:i\d+>> BoundsCheck [<<Index>>,<<Length2>>] - /// CHECK-DAG: <<LastElement:l\d+>> ArrayGet [<<NullCheck2>>,<<BoundsCheck>>] + /// CHECK-DAG: <<LastElement:l\d+>> ArrayGet [<<Array>>,<<BoundsCheck>>] /// CHECK-DAG: Return [<<LastElement>>] diff --git a/tools/ahat/README.txt b/tools/ahat/README.txt index d9b26bcf58..0cd77ab69d 100644 --- a/tools/ahat/README.txt +++ b/tools/ahat/README.txt @@ -77,7 +77,12 @@ Things to move to perflib: * Instance.isRoot and Instance.getRootTypes. Release History: - 0.4 Pending + 0.6 Pending + + 0.5 Apr 19, 2016 + Update perflib to perflib-25.0.0 to improve processing performance. + + 0.4 Feb 23, 2016 Annotate char[] objects with their string values. Show registered native allocations for heap dumps that support it. diff --git a/tools/ahat/src/AhatSnapshot.java b/tools/ahat/src/AhatSnapshot.java index 2adec6f17b..d088e8c43f 100644 --- a/tools/ahat/src/AhatSnapshot.java +++ b/tools/ahat/src/AhatSnapshot.java @@ -25,8 +25,8 @@ import com.android.tools.perflib.heap.Snapshot; import com.android.tools.perflib.heap.StackFrame; import com.android.tools.perflib.heap.StackTrace; import com.android.tools.perflib.captures.MemoryMappedFileBuffer; -import com.google.common.collect.Iterables; import com.google.common.collect.Lists; +import gnu.trove.TObjectProcedure; import java.io.File; import java.io.IOException; import java.util.ArrayList; @@ -85,49 +85,59 @@ class AhatSnapshot { ClassObj javaLangClass = mSnapshot.findClass("java.lang.Class"); for (Heap heap : mHeaps) { - long total = 0; - for (Instance inst : Iterables.concat(heap.getClasses(), heap.getInstances())) { - Instance dominator = inst.getImmediateDominator(); - if (dominator != null) { - total += inst.getSize(); - - if (dominator == Snapshot.SENTINEL_ROOT) { - mRooted.add(inst); - } + // Use a single element array for the total to act as a reference to a + // long. + final long[] total = new long[]{0}; + TObjectProcedure<Instance> processInstance = new TObjectProcedure<Instance>() { + @Override + public boolean execute(Instance inst) { + Instance dominator = inst.getImmediateDominator(); + if (dominator != null) { + total[0] += inst.getSize(); + + if (dominator == Snapshot.SENTINEL_ROOT) { + mRooted.add(inst); + } - // Properly label the class of a class object. - if (inst instanceof ClassObj && javaLangClass != null && inst.getClassObj() == null) { - inst.setClassId(javaLangClass.getId()); - } + // Properly label the class of a class object. + if (inst instanceof ClassObj && javaLangClass != null && inst.getClassObj() == null) { + inst.setClassId(javaLangClass.getId()); + } - // Update dominated instances. - List<Instance> instances = mDominated.get(dominator); - if (instances == null) { - instances = new ArrayList<Instance>(); - mDominated.put(dominator, instances); - } - instances.add(inst); - - // Update sites. - List<StackFrame> path = Collections.emptyList(); - StackTrace stack = getStack(inst); - int stackId = getStackTraceSerialNumber(stack); - if (stack != null) { - StackFrame[] frames = getStackFrames(stack); - if (frames != null && frames.length > 0) { - path = Lists.reverse(Arrays.asList(frames)); + // Update dominated instances. + List<Instance> instances = mDominated.get(dominator); + if (instances == null) { + instances = new ArrayList<Instance>(); + mDominated.put(dominator, instances); } - } - mRootSite.add(stackId, 0, path.iterator(), inst); + instances.add(inst); + + // Update sites. + List<StackFrame> path = Collections.emptyList(); + StackTrace stack = getStack(inst); + int stackId = getStackTraceSerialNumber(stack); + if (stack != null) { + StackFrame[] frames = getStackFrames(stack); + if (frames != null && frames.length > 0) { + path = Lists.reverse(Arrays.asList(frames)); + } + } + mRootSite.add(stackId, 0, path.iterator(), inst); - // Update native allocations. - InstanceUtils.NativeAllocation alloc = InstanceUtils.getNativeAllocation(inst); - if (alloc != null) { - mNativeAllocations.add(alloc); + // Update native allocations. + InstanceUtils.NativeAllocation alloc = InstanceUtils.getNativeAllocation(inst); + if (alloc != null) { + mNativeAllocations.add(alloc); + } } + return true; } + }; + for (Instance instance : heap.getClasses()) { + processInstance.execute(instance); } - mHeapSizes.put(heap, total); + heap.forEachInstance(processInstance); + mHeapSizes.put(heap, total[0]); } // Record the roots and their types. diff --git a/tools/ahat/src/InstanceUtils.java b/tools/ahat/src/InstanceUtils.java index d7b64e2afd..8defba2647 100644 --- a/tools/ahat/src/InstanceUtils.java +++ b/tools/ahat/src/InstanceUtils.java @@ -244,8 +244,8 @@ class InstanceUtils { if (inst instanceof ArrayInstance) { ArrayInstance array = (ArrayInstance)inst; - if (array.getArrayType() == Type.BYTE && inst.getHardReferences().size() == 1) { - Instance ref = inst.getHardReferences().get(0); + if (array.getArrayType() == Type.BYTE && inst.getHardReverseReferences().size() == 1) { + Instance ref = inst.getHardReverseReferences().get(0); ClassObj clsref = ref.getClassObj(); if (clsref != null && "android.graphics.Bitmap".equals(clsref.getClassName())) { return ref; @@ -344,7 +344,7 @@ class InstanceUtils { } Instance referent = null; - for (Instance ref : inst.getHardReferences()) { + for (Instance ref : inst.getHardReverseReferences()) { if (isInstanceOfClass(ref, "sun.misc.Cleaner")) { referent = InstanceUtils.getReferent(ref); if (referent != null) { diff --git a/tools/ahat/src/ObjectHandler.java b/tools/ahat/src/ObjectHandler.java index 06023dab7f..4df1be5ac2 100644 --- a/tools/ahat/src/ObjectHandler.java +++ b/tools/ahat/src/ObjectHandler.java @@ -160,11 +160,11 @@ class ObjectHandler implements AhatHandler { private static void printReferences( Doc doc, Query query, AhatSnapshot snapshot, Instance inst) { doc.section("Objects with References to this Object"); - if (inst.getHardReferences().isEmpty()) { + if (inst.getHardReverseReferences().isEmpty()) { doc.println(DocString.text("(none)")); } else { doc.table(new Column("Object")); - List<Instance> references = inst.getHardReferences(); + List<Instance> references = inst.getHardReverseReferences(); SubsetSelector<Instance> selector = new SubsetSelector(query, HARD_REFS_ID, references); for (Instance ref : selector.selected()) { doc.row(Value.render(snapshot, ref)); @@ -173,10 +173,10 @@ class ObjectHandler implements AhatHandler { selector.render(doc); } - if (inst.getSoftReferences() != null) { + if (inst.getSoftReverseReferences() != null) { doc.section("Objects with Soft References to this Object"); doc.table(new Column("Object")); - List<Instance> references = inst.getSoftReferences(); + List<Instance> references = inst.getSoftReverseReferences(); SubsetSelector<Instance> selector = new SubsetSelector(query, SOFT_REFS_ID, references); for (Instance ref : selector.selected()) { doc.row(Value.render(snapshot, ref)); |