summaryrefslogtreecommitdiff
path: root/compiler/optimizing/graph_visualizer.cc
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/optimizing/graph_visualizer.cc')
-rw-r--r--compiler/optimizing/graph_visualizer.cc159
1 files changed, 101 insertions, 58 deletions
diff --git a/compiler/optimizing/graph_visualizer.cc b/compiler/optimizing/graph_visualizer.cc
index 5ff31cead5..2a7bbcb72f 100644
--- a/compiler/optimizing/graph_visualizer.cc
+++ b/compiler/optimizing/graph_visualizer.cc
@@ -106,8 +106,7 @@ std::ostream& operator<<(std::ostream& os, const StringList& list) {
}
}
-typedef Disassembler* create_disasm_prototype(InstructionSet instruction_set,
- DisassemblerOptions* options);
+using create_disasm_prototype = Disassembler*(InstructionSet, DisassemblerOptions*);
class HGraphVisualizerDisassembler {
public:
HGraphVisualizerDisassembler(InstructionSet instruction_set,
@@ -131,10 +130,10 @@ class HGraphVisualizerDisassembler {
// been generated, so we can read data in literal pools.
disassembler_ = std::unique_ptr<Disassembler>((*create_disassembler)(
instruction_set,
- new DisassemblerOptions(/* absolute_addresses */ false,
+ new DisassemblerOptions(/* absolute_addresses= */ false,
base_address,
end_address,
- /* can_read_literals */ true,
+ /* can_read_literals= */ true,
Is64BitInstructionSet(instruction_set)
? &Thread::DumpThreadOffset<PointerSize::k64>
: &Thread::DumpThreadOffset<PointerSize::k32>)));
@@ -333,7 +332,7 @@ class HGraphVisualizerPrinter : public HGraphDelegateVisitor {
return output_;
}
- void VisitParallelMove(HParallelMove* instruction) OVERRIDE {
+ void VisitParallelMove(HParallelMove* instruction) override {
StartAttributeStream("liveness") << instruction->GetLifetimePosition();
StringList moves;
for (size_t i = 0, e = instruction->NumMoves(); i < e; ++i) {
@@ -346,36 +345,36 @@ class HGraphVisualizerPrinter : public HGraphDelegateVisitor {
StartAttributeStream("moves") << moves;
}
- void VisitIntConstant(HIntConstant* instruction) OVERRIDE {
+ void VisitIntConstant(HIntConstant* instruction) override {
StartAttributeStream() << instruction->GetValue();
}
- void VisitLongConstant(HLongConstant* instruction) OVERRIDE {
+ void VisitLongConstant(HLongConstant* instruction) override {
StartAttributeStream() << instruction->GetValue();
}
- void VisitFloatConstant(HFloatConstant* instruction) OVERRIDE {
+ void VisitFloatConstant(HFloatConstant* instruction) override {
StartAttributeStream() << instruction->GetValue();
}
- void VisitDoubleConstant(HDoubleConstant* instruction) OVERRIDE {
+ void VisitDoubleConstant(HDoubleConstant* instruction) override {
StartAttributeStream() << instruction->GetValue();
}
- void VisitPhi(HPhi* phi) OVERRIDE {
+ void VisitPhi(HPhi* phi) override {
StartAttributeStream("reg") << phi->GetRegNumber();
StartAttributeStream("is_catch_phi") << std::boolalpha << phi->IsCatchPhi() << std::noboolalpha;
}
- void VisitMemoryBarrier(HMemoryBarrier* barrier) OVERRIDE {
+ void VisitMemoryBarrier(HMemoryBarrier* barrier) override {
StartAttributeStream("kind") << barrier->GetBarrierKind();
}
- void VisitMonitorOperation(HMonitorOperation* monitor) OVERRIDE {
+ void VisitMonitorOperation(HMonitorOperation* monitor) override {
StartAttributeStream("kind") << (monitor->IsEnter() ? "enter" : "exit");
}
- void VisitLoadClass(HLoadClass* load_class) OVERRIDE {
+ void VisitLoadClass(HLoadClass* load_class) override {
StartAttributeStream("load_kind") << load_class->GetLoadKind();
const char* descriptor = load_class->GetDexFile().GetTypeDescriptor(
load_class->GetDexFile().GetTypeId(load_class->GetTypeIndex()));
@@ -386,23 +385,42 @@ class HGraphVisualizerPrinter : public HGraphDelegateVisitor {
<< load_class->NeedsAccessCheck() << std::noboolalpha;
}
- void VisitLoadString(HLoadString* load_string) OVERRIDE {
+ void VisitLoadMethodHandle(HLoadMethodHandle* load_method_handle) override {
+ StartAttributeStream("load_kind") << "RuntimeCall";
+ StartAttributeStream("method_handle_index") << load_method_handle->GetMethodHandleIndex();
+ }
+
+ void VisitLoadMethodType(HLoadMethodType* load_method_type) override {
+ StartAttributeStream("load_kind") << "RuntimeCall";
+ const DexFile& dex_file = load_method_type->GetDexFile();
+ const dex::ProtoId& proto_id = dex_file.GetProtoId(load_method_type->GetProtoIndex());
+ StartAttributeStream("method_type") << dex_file.GetProtoSignature(proto_id);
+ }
+
+ void VisitLoadString(HLoadString* load_string) override {
StartAttributeStream("load_kind") << load_string->GetLoadKind();
}
- void VisitCheckCast(HCheckCast* check_cast) OVERRIDE {
- StartAttributeStream("check_kind") << check_cast->GetTypeCheckKind();
+ void HandleTypeCheckInstruction(HTypeCheckInstruction* check) {
+ StartAttributeStream("check_kind") << check->GetTypeCheckKind();
StartAttributeStream("must_do_null_check") << std::boolalpha
- << check_cast->MustDoNullCheck() << std::noboolalpha;
+ << check->MustDoNullCheck() << std::noboolalpha;
+ if (check->GetTypeCheckKind() == TypeCheckKind::kBitstringCheck) {
+ StartAttributeStream("path_to_root") << std::hex
+ << "0x" << check->GetBitstringPathToRoot() << std::dec;
+ StartAttributeStream("mask") << std::hex << "0x" << check->GetBitstringMask() << std::dec;
+ }
}
- void VisitInstanceOf(HInstanceOf* instance_of) OVERRIDE {
- StartAttributeStream("check_kind") << instance_of->GetTypeCheckKind();
- StartAttributeStream("must_do_null_check") << std::boolalpha
- << instance_of->MustDoNullCheck() << std::noboolalpha;
+ void VisitCheckCast(HCheckCast* check_cast) override {
+ HandleTypeCheckInstruction(check_cast);
+ }
+
+ void VisitInstanceOf(HInstanceOf* instance_of) override {
+ HandleTypeCheckInstruction(instance_of);
}
- void VisitArrayLength(HArrayLength* array_length) OVERRIDE {
+ void VisitArrayLength(HArrayLength* array_length) override {
StartAttributeStream("is_string_length") << std::boolalpha
<< array_length->IsStringLength() << std::noboolalpha;
if (array_length->IsEmittedAtUseSite()) {
@@ -410,31 +428,31 @@ class HGraphVisualizerPrinter : public HGraphDelegateVisitor {
}
}
- void VisitBoundsCheck(HBoundsCheck* bounds_check) OVERRIDE {
+ void VisitBoundsCheck(HBoundsCheck* bounds_check) override {
StartAttributeStream("is_string_char_at") << std::boolalpha
<< bounds_check->IsStringCharAt() << std::noboolalpha;
}
- void VisitArrayGet(HArrayGet* array_get) OVERRIDE {
+ void VisitArrayGet(HArrayGet* array_get) override {
StartAttributeStream("is_string_char_at") << std::boolalpha
<< array_get->IsStringCharAt() << std::noboolalpha;
}
- void VisitArraySet(HArraySet* array_set) OVERRIDE {
+ void VisitArraySet(HArraySet* array_set) override {
StartAttributeStream("value_can_be_null") << std::boolalpha
<< array_set->GetValueCanBeNull() << std::noboolalpha;
StartAttributeStream("needs_type_check") << std::boolalpha
<< array_set->NeedsTypeCheck() << std::noboolalpha;
}
- void VisitCompare(HCompare* compare) OVERRIDE {
+ void VisitCompare(HCompare* compare) override {
ComparisonBias bias = compare->GetBias();
StartAttributeStream("bias") << (bias == ComparisonBias::kGtBias
? "gt"
: (bias == ComparisonBias::kLtBias ? "lt" : "none"));
}
- void VisitInvoke(HInvoke* invoke) OVERRIDE {
+ void VisitInvoke(HInvoke* invoke) override {
StartAttributeStream("dex_file_index") << invoke->GetDexMethodIndex();
ArtMethod* method = invoke->GetResolvedMethod();
// We don't print signatures, which conflict with c1visualizer format.
@@ -451,12 +469,12 @@ class HGraphVisualizerPrinter : public HGraphDelegateVisitor {
<< std::noboolalpha;
}
- void VisitInvokeUnresolved(HInvokeUnresolved* invoke) OVERRIDE {
+ void VisitInvokeUnresolved(HInvokeUnresolved* invoke) override {
VisitInvoke(invoke);
StartAttributeStream("invoke_type") << invoke->GetInvokeType();
}
- void VisitInvokeStaticOrDirect(HInvokeStaticOrDirect* invoke) OVERRIDE {
+ void VisitInvokeStaticOrDirect(HInvokeStaticOrDirect* invoke) override {
VisitInvoke(invoke);
StartAttributeStream("method_load_kind") << invoke->GetMethodLoadKind();
StartAttributeStream("intrinsic") << invoke->GetIntrinsic();
@@ -465,96 +483,104 @@ class HGraphVisualizerPrinter : public HGraphDelegateVisitor {
}
}
- void VisitInvokeVirtual(HInvokeVirtual* invoke) OVERRIDE {
+ void VisitInvokeVirtual(HInvokeVirtual* invoke) override {
VisitInvoke(invoke);
StartAttributeStream("intrinsic") << invoke->GetIntrinsic();
}
- void VisitInvokePolymorphic(HInvokePolymorphic* invoke) OVERRIDE {
+ void VisitInvokePolymorphic(HInvokePolymorphic* invoke) override {
VisitInvoke(invoke);
StartAttributeStream("invoke_type") << "InvokePolymorphic";
}
- void VisitInstanceFieldGet(HInstanceFieldGet* iget) OVERRIDE {
+ void VisitInstanceFieldGet(HInstanceFieldGet* iget) override {
StartAttributeStream("field_name") <<
iget->GetFieldInfo().GetDexFile().PrettyField(iget->GetFieldInfo().GetFieldIndex(),
/* with type */ false);
StartAttributeStream("field_type") << iget->GetFieldType();
}
- void VisitInstanceFieldSet(HInstanceFieldSet* iset) OVERRIDE {
+ void VisitInstanceFieldSet(HInstanceFieldSet* iset) override {
StartAttributeStream("field_name") <<
iset->GetFieldInfo().GetDexFile().PrettyField(iset->GetFieldInfo().GetFieldIndex(),
/* with type */ false);
StartAttributeStream("field_type") << iset->GetFieldType();
}
- void VisitStaticFieldGet(HStaticFieldGet* sget) OVERRIDE {
+ void VisitStaticFieldGet(HStaticFieldGet* sget) override {
StartAttributeStream("field_name") <<
sget->GetFieldInfo().GetDexFile().PrettyField(sget->GetFieldInfo().GetFieldIndex(),
/* with type */ false);
StartAttributeStream("field_type") << sget->GetFieldType();
}
- void VisitStaticFieldSet(HStaticFieldSet* sset) OVERRIDE {
+ void VisitStaticFieldSet(HStaticFieldSet* sset) override {
StartAttributeStream("field_name") <<
sset->GetFieldInfo().GetDexFile().PrettyField(sset->GetFieldInfo().GetFieldIndex(),
/* with type */ false);
StartAttributeStream("field_type") << sset->GetFieldType();
}
- void VisitUnresolvedInstanceFieldGet(HUnresolvedInstanceFieldGet* field_access) OVERRIDE {
+ void VisitUnresolvedInstanceFieldGet(HUnresolvedInstanceFieldGet* field_access) override {
StartAttributeStream("field_type") << field_access->GetFieldType();
}
- void VisitUnresolvedInstanceFieldSet(HUnresolvedInstanceFieldSet* field_access) OVERRIDE {
+ void VisitUnresolvedInstanceFieldSet(HUnresolvedInstanceFieldSet* field_access) override {
StartAttributeStream("field_type") << field_access->GetFieldType();
}
- void VisitUnresolvedStaticFieldGet(HUnresolvedStaticFieldGet* field_access) OVERRIDE {
+ void VisitUnresolvedStaticFieldGet(HUnresolvedStaticFieldGet* field_access) override {
StartAttributeStream("field_type") << field_access->GetFieldType();
}
- void VisitUnresolvedStaticFieldSet(HUnresolvedStaticFieldSet* field_access) OVERRIDE {
+ void VisitUnresolvedStaticFieldSet(HUnresolvedStaticFieldSet* field_access) override {
StartAttributeStream("field_type") << field_access->GetFieldType();
}
- void VisitTryBoundary(HTryBoundary* try_boundary) OVERRIDE {
+ void VisitTryBoundary(HTryBoundary* try_boundary) override {
StartAttributeStream("kind") << (try_boundary->IsEntry() ? "entry" : "exit");
}
- void VisitDeoptimize(HDeoptimize* deoptimize) OVERRIDE {
+ void VisitDeoptimize(HDeoptimize* deoptimize) override {
StartAttributeStream("kind") << deoptimize->GetKind();
}
- void VisitVecOperation(HVecOperation* vec_operation) OVERRIDE {
+ void VisitVecOperation(HVecOperation* vec_operation) override {
StartAttributeStream("packed_type") << vec_operation->GetPackedType();
}
- void VisitVecMemoryOperation(HVecMemoryOperation* vec_mem_operation) OVERRIDE {
+ void VisitVecMemoryOperation(HVecMemoryOperation* vec_mem_operation) override {
StartAttributeStream("alignment") << vec_mem_operation->GetAlignment().ToString();
}
- void VisitVecHalvingAdd(HVecHalvingAdd* hadd) OVERRIDE {
+ void VisitVecHalvingAdd(HVecHalvingAdd* hadd) override {
VisitVecBinaryOperation(hadd);
StartAttributeStream("rounded") << std::boolalpha << hadd->IsRounded() << std::noboolalpha;
}
- void VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instruction) OVERRIDE {
+ void VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instruction) override {
VisitVecOperation(instruction);
StartAttributeStream("kind") << instruction->GetOpKind();
}
+ void VisitVecDotProd(HVecDotProd* instruction) override {
+ VisitVecOperation(instruction);
+ DataType::Type arg_type = instruction->InputAt(1)->AsVecOperation()->GetPackedType();
+ StartAttributeStream("type") << (instruction->IsZeroExtending() ?
+ DataType::ToUnsigned(arg_type) :
+ DataType::ToSigned(arg_type));
+ }
+
#if defined(ART_ENABLE_CODEGEN_arm) || defined(ART_ENABLE_CODEGEN_arm64)
- void VisitMultiplyAccumulate(HMultiplyAccumulate* instruction) OVERRIDE {
+ void VisitMultiplyAccumulate(HMultiplyAccumulate* instruction) override {
StartAttributeStream("kind") << instruction->GetOpKind();
}
- void VisitBitwiseNegatedRight(HBitwiseNegatedRight* instruction) OVERRIDE {
+ void VisitBitwiseNegatedRight(HBitwiseNegatedRight* instruction) override {
StartAttributeStream("kind") << instruction->GetOpKind();
}
- void VisitDataProcWithShifterOp(HDataProcWithShifterOp* instruction) OVERRIDE {
+ void VisitDataProcWithShifterOp(HDataProcWithShifterOp* instruction) override {
StartAttributeStream("kind") << instruction->GetInstrKind() << "+" << instruction->GetOpKind();
if (HDataProcWithShifterOp::IsShiftOp(instruction->GetOpKind())) {
StartAttributeStream("shift") << instruction->GetShiftAmount();
@@ -576,6 +602,11 @@ class HGraphVisualizerPrinter : public HGraphDelegateVisitor {
}
StartAttributeStream() << input_list;
}
+ if (instruction->GetDexPc() != kNoDexPc) {
+ StartAttributeStream("dex_pc") << instruction->GetDexPc();
+ } else {
+ StartAttributeStream("dex_pc") << "n/a";
+ }
instruction->Accept(this);
if (instruction->HasEnvironment()) {
StringList envs;
@@ -641,20 +672,32 @@ class HGraphVisualizerPrinter : public HGraphDelegateVisitor {
<< std::boolalpha << loop_info->IsIrreducible() << std::noboolalpha;
}
+ // For the builder and the inliner, we want to add extra information on HInstructions
+ // that have reference types, and also HInstanceOf/HCheckcast.
if ((IsPass(HGraphBuilder::kBuilderPassName)
|| IsPass(HInliner::kInlinerPassName))
- && (instruction->GetType() == DataType::Type::kReference)) {
- ReferenceTypeInfo info = instruction->IsLoadClass()
- ? instruction->AsLoadClass()->GetLoadedClassRTI()
- : instruction->GetReferenceTypeInfo();
+ && (instruction->GetType() == DataType::Type::kReference ||
+ instruction->IsInstanceOf() ||
+ instruction->IsCheckCast())) {
+ ReferenceTypeInfo info = (instruction->GetType() == DataType::Type::kReference)
+ ? instruction->IsLoadClass()
+ ? instruction->AsLoadClass()->GetLoadedClassRTI()
+ : instruction->GetReferenceTypeInfo()
+ : instruction->IsInstanceOf()
+ ? instruction->AsInstanceOf()->GetTargetClassRTI()
+ : instruction->AsCheckCast()->GetTargetClassRTI();
ScopedObjectAccess soa(Thread::Current());
if (info.IsValid()) {
StartAttributeStream("klass")
<< mirror::Class::PrettyDescriptor(info.GetTypeHandle().Get());
- StartAttributeStream("can_be_null")
- << std::boolalpha << instruction->CanBeNull() << std::noboolalpha;
+ if (instruction->GetType() == DataType::Type::kReference) {
+ StartAttributeStream("can_be_null")
+ << std::boolalpha << instruction->CanBeNull() << std::noboolalpha;
+ }
StartAttributeStream("exact") << std::boolalpha << info.IsExact() << std::noboolalpha;
- } else if (instruction->IsLoadClass()) {
+ } else if (instruction->IsLoadClass() ||
+ instruction->IsInstanceOf() ||
+ instruction->IsCheckCast()) {
StartAttributeStream("klass") << "unresolved";
} else {
// The NullConstant may be added to the graph during other passes that happen between
@@ -778,7 +821,7 @@ class HGraphVisualizerPrinter : public HGraphDelegateVisitor {
Flush();
}
- void VisitBasicBlock(HBasicBlock* block) OVERRIDE {
+ void VisitBasicBlock(HBasicBlock* block) override {
StartTag("block");
PrintProperty("name", "B", block->GetBlockId());
if (block->GetLifetimeStart() != kNoLifetime) {
@@ -881,8 +924,8 @@ void HGraphVisualizer::DumpGraphWithDisassembly() const {
HGraphVisualizerPrinter printer(graph_,
*output_,
"disassembly",
- /* is_after_pass */ true,
- /* graph_in_bad_state */ false,
+ /* is_after_pass= */ true,
+ /* graph_in_bad_state= */ false,
codegen_,
codegen_.GetDisassemblyInformation());
printer.Run();