aoqi@0: /* aoqi@0: * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. aoqi@0: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. aoqi@0: * aoqi@0: * This code is free software; you can redistribute it and/or modify it aoqi@0: * under the terms of the GNU General Public License version 2 only, as aoqi@0: * published by the Free Software Foundation. aoqi@0: * aoqi@0: * This code is distributed in the hope that it will be useful, but WITHOUT aoqi@0: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or aoqi@0: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License aoqi@0: * version 2 for more details (a copy is included in the LICENSE file that aoqi@0: * accompanied this code). aoqi@0: * aoqi@0: * You should have received a copy of the GNU General Public License version aoqi@0: * 2 along with this work; if not, write to the Free Software Foundation, aoqi@0: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. aoqi@0: * aoqi@0: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA aoqi@0: * or visit www.oracle.com if you need additional information or have any aoqi@0: * questions. aoqi@0: * aoqi@0: */ aoqi@0: aoqi@0: #include "precompiled.hpp" aoqi@0: #include "c1/c1_InstructionPrinter.hpp" aoqi@0: #include "c1/c1_ValueStack.hpp" aoqi@0: #include "ci/ciArray.hpp" aoqi@0: #include "ci/ciInstance.hpp" aoqi@0: #include "ci/ciObject.hpp" aoqi@0: aoqi@0: aoqi@0: #ifndef PRODUCT aoqi@0: aoqi@0: const char* InstructionPrinter::basic_type_name(BasicType type) { aoqi@0: switch (type) { aoqi@0: case T_BOOLEAN: return "boolean"; aoqi@0: case T_BYTE : return "byte"; aoqi@0: case T_CHAR : return "char"; aoqi@0: case T_SHORT : return "short"; aoqi@0: case T_INT : return "int"; aoqi@0: case T_LONG : return "long"; aoqi@0: case T_FLOAT : return "float"; aoqi@0: case T_DOUBLE : return "double"; aoqi@0: case T_ARRAY : return "array"; aoqi@0: case T_OBJECT : return "object"; aoqi@0: default : return "???"; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: aoqi@0: const char* InstructionPrinter::cond_name(If::Condition cond) { aoqi@0: switch (cond) { aoqi@0: case If::eql: return "=="; aoqi@0: case If::neq: return "!="; aoqi@0: case If::lss: return "<"; aoqi@0: case If::leq: return "<="; aoqi@0: case If::gtr: return ">"; aoqi@0: case If::geq: return ">="; aoqi@0: case If::aeq: return "|>=|"; aoqi@0: case If::beq: return "|<=|"; aoqi@0: } aoqi@0: ShouldNotReachHere(); aoqi@0: return NULL; aoqi@0: } aoqi@0: aoqi@0: aoqi@0: const char* InstructionPrinter::op_name(Bytecodes::Code op) { aoqi@0: switch (op) { aoqi@0: // arithmetic ops aoqi@0: case Bytecodes::_iadd : // fall through aoqi@0: case Bytecodes::_ladd : // fall through aoqi@0: case Bytecodes::_fadd : // fall through aoqi@0: case Bytecodes::_dadd : return "+"; aoqi@0: case Bytecodes::_isub : // fall through aoqi@0: case Bytecodes::_lsub : // fall through aoqi@0: case Bytecodes::_fsub : // fall through aoqi@0: case Bytecodes::_dsub : return "-"; aoqi@0: case Bytecodes::_imul : // fall through aoqi@0: case Bytecodes::_lmul : // fall through aoqi@0: case Bytecodes::_fmul : // fall through aoqi@0: case Bytecodes::_dmul : return "*"; aoqi@0: case Bytecodes::_idiv : // fall through aoqi@0: case Bytecodes::_ldiv : // fall through aoqi@0: case Bytecodes::_fdiv : // fall through aoqi@0: case Bytecodes::_ddiv : return "/"; aoqi@0: case Bytecodes::_irem : // fall through aoqi@0: case Bytecodes::_lrem : // fall through aoqi@0: case Bytecodes::_frem : // fall through aoqi@0: case Bytecodes::_drem : return "%"; aoqi@0: // shift ops aoqi@0: case Bytecodes::_ishl : // fall through aoqi@0: case Bytecodes::_lshl : return "<<"; aoqi@0: case Bytecodes::_ishr : // fall through aoqi@0: case Bytecodes::_lshr : return ">>"; aoqi@0: case Bytecodes::_iushr: // fall through aoqi@0: case Bytecodes::_lushr: return ">>>"; aoqi@0: // logic ops aoqi@0: case Bytecodes::_iand : // fall through aoqi@0: case Bytecodes::_land : return "&"; aoqi@0: case Bytecodes::_ior : // fall through aoqi@0: case Bytecodes::_lor : return "|"; aoqi@0: case Bytecodes::_ixor : // fall through aoqi@0: case Bytecodes::_lxor : return "^"; aoqi@0: } aoqi@0: return Bytecodes::name(op); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: bool InstructionPrinter::is_illegal_phi(Value v) { aoqi@0: Phi* phi = v ? v->as_Phi() : NULL; aoqi@0: if (phi && phi->is_illegal()) { aoqi@0: return true; aoqi@0: } aoqi@0: return false; aoqi@0: } aoqi@0: aoqi@0: aoqi@0: bool InstructionPrinter::is_phi_of_block(Value v, BlockBegin* b) { aoqi@0: Phi* phi = v ? v->as_Phi() : NULL; aoqi@0: return phi && phi->block() == b; aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::print_klass(ciKlass* klass) { aoqi@0: klass->name()->print_symbol_on(output()); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::print_object(Value obj) { aoqi@0: ValueType* type = obj->type(); aoqi@0: if (type->as_ObjectConstant() != NULL) { aoqi@0: ciObject* value = type->as_ObjectConstant()->value(); aoqi@0: if (value->is_null_object()) { aoqi@0: output()->print("null"); aoqi@0: } else if (!value->is_loaded()) { aoqi@0: output()->print("", p2i(value)); aoqi@0: } else { aoqi@0: output()->print(""); aoqi@0: } aoqi@0: } else if (type->as_InstanceConstant() != NULL) { aoqi@0: ciInstance* value = type->as_InstanceConstant()->value(); aoqi@0: if (value->is_loaded()) { aoqi@0: output()->print(""); aoqi@0: } else { aoqi@0: output()->print("", p2i(value)); aoqi@0: } aoqi@0: } else if (type->as_ArrayConstant() != NULL) { aoqi@0: output()->print("", p2i(type->as_ArrayConstant()->value()->constant_encoding())); aoqi@0: } else if (type->as_ClassConstant() != NULL) { aoqi@0: ciInstanceKlass* klass = type->as_ClassConstant()->value(); aoqi@0: if (!klass->is_loaded()) { aoqi@0: output()->print(" "); aoqi@0: } aoqi@0: output()->print("class "); aoqi@0: print_klass(klass); aoqi@0: } else if (type->as_MethodConstant() != NULL) { aoqi@0: ciMethod* m = type->as_MethodConstant()->value(); aoqi@0: output()->print("", m->holder()->name()->as_utf8(), m->name()->as_utf8()); aoqi@0: } else { aoqi@0: output()->print("???"); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::print_temp(Value value) { aoqi@0: output()->print("%c%d", value->type()->tchar(), value->id()); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::print_field(AccessField* field) { aoqi@0: print_value(field->obj()); aoqi@0: output()->print("._%d", field->offset()); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::print_indexed(AccessIndexed* indexed) { aoqi@0: print_value(indexed->array()); aoqi@0: output()->put('['); aoqi@0: print_value(indexed->index()); aoqi@0: output()->put(']'); aoqi@0: if (indexed->length() != NULL) { aoqi@0: output()->put('('); aoqi@0: print_value(indexed->length()); aoqi@0: output()->put(')'); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::print_monitor(AccessMonitor* monitor) { aoqi@0: output()->print("monitor[%d](", monitor->monitor_no()); aoqi@0: print_value(monitor->obj()); aoqi@0: output()->put(')'); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::print_op2(Op2* instr) { aoqi@0: print_value(instr->x()); aoqi@0: output()->print(" %s ", op_name(instr->op())); aoqi@0: print_value(instr->y()); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::print_value(Value value) { aoqi@0: if (value == NULL) { aoqi@0: output()->print("NULL"); aoqi@0: } else { aoqi@0: print_temp(value); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::print_instr(Instruction* instr) { aoqi@0: instr->visit(this); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::print_stack(ValueStack* stack) { aoqi@0: int start_position = output()->position(); aoqi@0: if (stack->stack_is_empty()) { aoqi@0: output()->print("empty stack"); aoqi@0: } else { aoqi@0: output()->print("stack ["); aoqi@0: for (int i = 0; i < stack->stack_size();) { aoqi@0: if (i > 0) output()->print(", "); aoqi@0: output()->print("%d:", i); aoqi@0: Value value = stack->stack_at_inc(i); aoqi@0: print_value(value); aoqi@0: Phi* phi = value->as_Phi(); aoqi@0: if (phi != NULL) { aoqi@0: if (phi->operand()->is_valid()) { aoqi@0: output()->print(" "); aoqi@0: phi->operand()->print(output()); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: output()->put(']'); aoqi@0: } aoqi@0: if (!stack->no_active_locks()) { aoqi@0: // print out the lines on the line below this aoqi@0: // one at the same indentation level. aoqi@0: output()->cr(); aoqi@0: fill_to(start_position, ' '); aoqi@0: output()->print("locks ["); aoqi@0: for (int i = i = 0; i < stack->locks_size(); i++) { aoqi@0: Value t = stack->lock_at(i); aoqi@0: if (i > 0) output()->print(", "); aoqi@0: output()->print("%d:", i); aoqi@0: if (t == NULL) { aoqi@0: // synchronized methods push null on the lock stack aoqi@0: output()->print("this"); aoqi@0: } else { aoqi@0: print_value(t); aoqi@0: } aoqi@0: } aoqi@0: output()->print("]"); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::print_inline_level(BlockBegin* block) { aoqi@0: output()->print_cr("inlining depth %d", block->scope()->level()); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::print_unsafe_op(UnsafeOp* op, const char* name) { aoqi@0: output()->print("%s", name); aoqi@0: output()->print(".("); aoqi@0: } aoqi@0: aoqi@0: void InstructionPrinter::print_unsafe_raw_op(UnsafeRawOp* op, const char* name) { aoqi@0: print_unsafe_op(op, name); aoqi@0: output()->print("base "); aoqi@0: print_value(op->base()); aoqi@0: if (op->has_index()) { aoqi@0: output()->print(", index "); print_value(op->index()); aoqi@0: output()->print(", log2_scale %d", op->log2_scale()); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::print_unsafe_object_op(UnsafeObjectOp* op, const char* name) { aoqi@0: print_unsafe_op(op, name); aoqi@0: print_value(op->object()); aoqi@0: output()->print(", "); aoqi@0: print_value(op->offset()); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::print_phi(int i, Value v, BlockBegin* b) { aoqi@0: Phi* phi = v->as_Phi(); aoqi@0: output()->print("%2d ", i); aoqi@0: print_value(v); aoqi@0: // print phi operands aoqi@0: if (phi && phi->block() == b) { aoqi@0: output()->print(" ["); aoqi@0: for (int j = 0; j < phi->operand_count(); j ++) { aoqi@0: output()->print(" "); aoqi@0: Value opd = phi->operand_at(j); aoqi@0: if (opd) print_value(opd); aoqi@0: else output()->print("NULL"); aoqi@0: } aoqi@0: output()->print("] "); aoqi@0: } aoqi@0: print_alias(v); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::print_alias(Value v) { aoqi@0: if (v != v->subst()) { aoqi@0: output()->print("alias "); print_value(v->subst()); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::fill_to(int pos, char filler) { aoqi@0: while (output()->position() < pos) output()->put(filler); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::print_head() { aoqi@0: const char filler = '_'; aoqi@0: fill_to(bci_pos , filler); output()->print("bci" ); aoqi@0: fill_to(use_pos , filler); output()->print("use" ); aoqi@0: fill_to(temp_pos , filler); output()->print("tid" ); aoqi@0: fill_to(instr_pos, filler); output()->print("instr"); aoqi@0: fill_to(end_pos , filler); aoqi@0: output()->cr(); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::print_line(Instruction* instr) { aoqi@0: // print instruction data on one line aoqi@0: if (instr->is_pinned()) output()->put('.'); aoqi@0: fill_to(bci_pos ); output()->print("%d", instr->printable_bci()); aoqi@0: fill_to(use_pos ); output()->print("%d", instr->use_count()); aoqi@0: fill_to(temp_pos ); print_temp(instr); aoqi@0: fill_to(instr_pos); print_instr(instr); aoqi@0: output()->cr(); aoqi@0: // add a line for StateSplit instructions w/ non-empty stacks aoqi@0: // (make it robust so we can print incomplete instructions) aoqi@0: StateSplit* split = instr->as_StateSplit(); aoqi@0: if (split != NULL && split->state() != NULL && !split->state()->stack_is_empty()) { aoqi@0: fill_to(instr_pos); print_stack(split->state()); aoqi@0: output()->cr(); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::do_Phi(Phi* x) { aoqi@0: output()->print("phi function"); // make that more detailed later aoqi@0: if (x->is_illegal()) aoqi@0: output()->print(" (illegal)"); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::do_Local(Local* x) { aoqi@0: output()->print("local[index %d]", x->java_index()); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::do_Constant(Constant* x) { aoqi@0: ValueType* t = x->type(); aoqi@0: switch (t->tag()) { aoqi@0: case intTag : output()->print("%d" , t->as_IntConstant ()->value()); break; aoqi@0: case longTag : output()->print(JLONG_FORMAT, t->as_LongConstant()->value()); output()->print("L"); break; aoqi@0: case floatTag : output()->print("%g" , t->as_FloatConstant ()->value()); break; aoqi@0: case doubleTag : output()->print("%gD" , t->as_DoubleConstant()->value()); break; aoqi@0: case objectTag : print_object(x); break; aoqi@0: case addressTag: output()->print("bci:%d", t->as_AddressConstant()->value()); break; aoqi@0: default : output()->print("???"); break; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::do_LoadField(LoadField* x) { aoqi@0: print_field(x); aoqi@0: output()->print(" (%c)", type2char(x->field()->type()->basic_type())); aoqi@0: output()->print(" %s", x->field()->name()->as_utf8()); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::do_StoreField(StoreField* x) { aoqi@0: print_field(x); aoqi@0: output()->print(" := "); aoqi@0: print_value(x->value()); aoqi@0: output()->print(" (%c)", type2char(x->field()->type()->basic_type())); aoqi@0: output()->print(" %s", x->field()->name()->as_utf8()); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::do_ArrayLength(ArrayLength* x) { aoqi@0: print_value(x->array()); aoqi@0: output()->print(".length"); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::do_LoadIndexed(LoadIndexed* x) { aoqi@0: print_indexed(x); aoqi@0: output()->print(" (%c)", type2char(x->elt_type())); aoqi@0: if (x->check_flag(Instruction::NeedsRangeCheckFlag)) { aoqi@0: output()->print(" [rc]"); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::do_StoreIndexed(StoreIndexed* x) { aoqi@0: print_indexed(x); aoqi@0: output()->print(" := "); aoqi@0: print_value(x->value()); aoqi@0: output()->print(" (%c)", type2char(x->elt_type())); aoqi@0: if (x->check_flag(Instruction::NeedsRangeCheckFlag)) { aoqi@0: output()->print(" [rc]"); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: void InstructionPrinter::do_NegateOp(NegateOp* x) { aoqi@0: output()->put('-'); aoqi@0: print_value(x->x()); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::do_ArithmeticOp(ArithmeticOp* x) { aoqi@0: print_op2(x); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::do_ShiftOp(ShiftOp* x) { aoqi@0: print_op2(x); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::do_LogicOp(LogicOp* x) { aoqi@0: print_op2(x); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::do_CompareOp(CompareOp* x) { aoqi@0: print_op2(x); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::do_IfOp(IfOp* x) { aoqi@0: print_value(x->x()); aoqi@0: output()->print(" %s ", cond_name(x->cond())); aoqi@0: print_value(x->y()); aoqi@0: output()->print(" ? "); aoqi@0: print_value(x->tval()); aoqi@0: output()->print(" : "); aoqi@0: print_value(x->fval()); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::do_Convert(Convert* x) { aoqi@0: output()->print("%s(", Bytecodes::name(x->op())); aoqi@0: print_value(x->value()); aoqi@0: output()->put(')'); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::do_NullCheck(NullCheck* x) { aoqi@0: output()->print("null_check("); aoqi@0: print_value(x->obj()); aoqi@0: output()->put(')'); aoqi@0: if (!x->can_trap()) { aoqi@0: output()->print(" (eliminated)"); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::do_TypeCast(TypeCast* x) { aoqi@0: output()->print("type_cast("); aoqi@0: print_value(x->obj()); aoqi@0: output()->print(") "); aoqi@0: if (x->declared_type()->is_klass()) aoqi@0: print_klass(x->declared_type()->as_klass()); aoqi@0: else aoqi@0: output()->print("%s", type2name(x->declared_type()->basic_type())); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::do_Invoke(Invoke* x) { aoqi@0: if (x->receiver() != NULL) { aoqi@0: print_value(x->receiver()); aoqi@0: output()->print("."); aoqi@0: } aoqi@0: aoqi@0: output()->print("%s(", Bytecodes::name(x->code())); aoqi@0: for (int i = 0; i < x->number_of_arguments(); i++) { aoqi@0: if (i > 0) output()->print(", "); aoqi@0: print_value(x->argument_at(i)); aoqi@0: } aoqi@0: output()->print_cr(")"); aoqi@0: fill_to(instr_pos); aoqi@0: output()->print("%s.%s%s", aoqi@0: x->target()->holder()->name()->as_utf8(), aoqi@0: x->target()->name()->as_utf8(), aoqi@0: x->target()->signature()->as_symbol()->as_utf8()); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::do_NewInstance(NewInstance* x) { aoqi@0: output()->print("new instance "); aoqi@0: print_klass(x->klass()); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::do_NewTypeArray(NewTypeArray* x) { aoqi@0: output()->print("new %s array [", basic_type_name(x->elt_type())); aoqi@0: print_value(x->length()); aoqi@0: output()->put(']'); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::do_NewObjectArray(NewObjectArray* x) { aoqi@0: output()->print("new object array ["); aoqi@0: print_value(x->length()); aoqi@0: output()->print("] "); aoqi@0: print_klass(x->klass()); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::do_NewMultiArray(NewMultiArray* x) { aoqi@0: output()->print("new multi array ["); aoqi@0: Values* dims = x->dims(); aoqi@0: for (int i = 0; i < dims->length(); i++) { aoqi@0: if (i > 0) output()->print(", "); aoqi@0: print_value(dims->at(i)); aoqi@0: } aoqi@0: output()->print("] "); aoqi@0: print_klass(x->klass()); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::do_MonitorEnter(MonitorEnter* x) { aoqi@0: output()->print("enter "); aoqi@0: print_monitor(x); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::do_MonitorExit(MonitorExit* x) { aoqi@0: output()->print("exit "); aoqi@0: print_monitor(x); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::do_Intrinsic(Intrinsic* x) { aoqi@0: const char* name = vmIntrinsics::name_at(x->id()); aoqi@0: if (name[0] == '_') name++; // strip leading bug from _hashCode, etc. aoqi@0: const char* kname = vmSymbols::name_for(vmIntrinsics::class_for(x->id())); aoqi@0: if (strchr(name, '_') == NULL) { aoqi@0: kname = NULL; aoqi@0: } else { aoqi@0: const char* kptr = strrchr(kname, '/'); aoqi@0: if (kptr != NULL) kname = kptr + 1; aoqi@0: } aoqi@0: if (kname == NULL) aoqi@0: output()->print("%s(", name); aoqi@0: else aoqi@0: output()->print("%s.%s(", kname, name); aoqi@0: for (int i = 0; i < x->number_of_arguments(); i++) { aoqi@0: if (i > 0) output()->print(", "); aoqi@0: print_value(x->argument_at(i)); aoqi@0: } aoqi@0: output()->put(')'); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::do_BlockBegin(BlockBegin* x) { aoqi@0: // print block id aoqi@0: BlockEnd* end = x->end(); aoqi@0: output()->print("B%d ", x->block_id()); aoqi@0: aoqi@0: // print flags aoqi@0: bool printed_flag = false; aoqi@0: if (x->is_set(BlockBegin::std_entry_flag)) { aoqi@0: if (!printed_flag) output()->print("("); aoqi@0: output()->print("S"); printed_flag = true; aoqi@0: } aoqi@0: if (x->is_set(BlockBegin::osr_entry_flag)) { aoqi@0: if (!printed_flag) output()->print("("); aoqi@0: output()->print("O"); printed_flag = true; aoqi@0: } aoqi@0: if (x->is_set(BlockBegin::exception_entry_flag)) { aoqi@0: if (!printed_flag) output()->print("("); aoqi@0: output()->print("E"); printed_flag = true; aoqi@0: } aoqi@0: if (x->is_set(BlockBegin::subroutine_entry_flag)) { aoqi@0: if (!printed_flag) output()->print("("); aoqi@0: output()->print("s"); printed_flag = true; aoqi@0: } aoqi@0: if (x->is_set(BlockBegin::parser_loop_header_flag)) { aoqi@0: if (!printed_flag) output()->print("("); aoqi@0: output()->print("LH"); printed_flag = true; aoqi@0: } aoqi@0: if (x->is_set(BlockBegin::backward_branch_target_flag)) { aoqi@0: if (!printed_flag) output()->print("("); aoqi@0: output()->print("b"); printed_flag = true; aoqi@0: } aoqi@0: if (x->is_set(BlockBegin::was_visited_flag)) { aoqi@0: if (!printed_flag) output()->print("("); aoqi@0: output()->print("V"); printed_flag = true; aoqi@0: } aoqi@0: if (printed_flag) output()->print(") "); aoqi@0: aoqi@0: // print block bci range aoqi@0: output()->print("[%d, %d]", x->bci(), (end == NULL ? -1 : end->printable_bci())); aoqi@0: aoqi@0: // print block successors aoqi@0: if (end != NULL && end->number_of_sux() > 0) { aoqi@0: output()->print(" ->"); aoqi@0: for (int i = 0; i < end->number_of_sux(); i++) { aoqi@0: output()->print(" B%d", end->sux_at(i)->block_id()); aoqi@0: } aoqi@0: } aoqi@0: // print exception handlers aoqi@0: if (x->number_of_exception_handlers() > 0) { aoqi@0: output()->print(" (xhandlers "); aoqi@0: for (int i = 0; i < x->number_of_exception_handlers(); i++) { aoqi@0: if (i > 0) output()->print(" "); aoqi@0: output()->print("B%d", x->exception_handler_at(i)->block_id()); aoqi@0: } aoqi@0: output()->put(')'); aoqi@0: } aoqi@0: aoqi@0: // print dominator block aoqi@0: if (x->dominator() != NULL) { aoqi@0: output()->print(" dom B%d", x->dominator()->block_id()); aoqi@0: } aoqi@0: aoqi@0: // print predecessors and successors aoqi@0: if (x->successors()->length() > 0) { aoqi@0: output()->print(" sux:"); aoqi@0: for (int i = 0; i < x->successors()->length(); i ++) { aoqi@0: output()->print(" B%d", x->successors()->at(i)->block_id()); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: if (x->number_of_preds() > 0) { aoqi@0: output()->print(" pred:"); aoqi@0: for (int i = 0; i < x->number_of_preds(); i ++) { aoqi@0: output()->print(" B%d", x->pred_at(i)->block_id()); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: if (!_print_phis) { aoqi@0: return; aoqi@0: } aoqi@0: aoqi@0: // print phi functions aoqi@0: bool has_phis_in_locals = false; aoqi@0: bool has_phis_on_stack = false; aoqi@0: aoqi@0: if (x->end() && x->end()->state()) { aoqi@0: ValueStack* state = x->state(); aoqi@0: aoqi@0: int i = 0; aoqi@0: while (!has_phis_on_stack && i < state->stack_size()) { aoqi@0: Value v = state->stack_at_inc(i); aoqi@0: has_phis_on_stack = is_phi_of_block(v, x); aoqi@0: } aoqi@0: aoqi@0: do { aoqi@0: for (i = 0; !has_phis_in_locals && i < state->locals_size();) { aoqi@0: Value v = state->local_at(i); aoqi@0: has_phis_in_locals = is_phi_of_block(v, x); aoqi@0: // also ignore illegal HiWords aoqi@0: if (v && !v->type()->is_illegal()) i += v->type()->size(); else i ++; aoqi@0: } aoqi@0: state = state->caller_state(); aoqi@0: } while (state != NULL); aoqi@0: aoqi@0: } aoqi@0: aoqi@0: // print values in locals aoqi@0: if (has_phis_in_locals) { aoqi@0: output()->cr(); output()->print_cr("Locals:"); aoqi@0: aoqi@0: ValueStack* state = x->state(); aoqi@0: do { aoqi@0: for (int i = 0; i < state->locals_size();) { aoqi@0: Value v = state->local_at(i); aoqi@0: if (v) { aoqi@0: print_phi(i, v, x); output()->cr(); aoqi@0: // also ignore illegal HiWords aoqi@0: i += (v->type()->is_illegal() ? 1 : v->type()->size()); aoqi@0: } else { aoqi@0: i ++; aoqi@0: } aoqi@0: } aoqi@0: output()->cr(); aoqi@0: state = state->caller_state(); aoqi@0: } while (state != NULL); aoqi@0: } aoqi@0: aoqi@0: // print values on stack aoqi@0: if (has_phis_on_stack) { aoqi@0: output()->print_cr("Stack:"); aoqi@0: int i = 0; aoqi@0: while (i < x->state()->stack_size()) { aoqi@0: int o = i; aoqi@0: Value v = x->state()->stack_at_inc(i); aoqi@0: if (v) { aoqi@0: print_phi(o, v, x); output()->cr(); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::do_CheckCast(CheckCast* x) { aoqi@0: output()->print("checkcast("); aoqi@0: print_value(x->obj()); aoqi@0: output()->print(") "); aoqi@0: print_klass(x->klass()); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::do_InstanceOf(InstanceOf* x) { aoqi@0: output()->print("instanceof("); aoqi@0: print_value(x->obj()); aoqi@0: output()->print(") "); aoqi@0: print_klass(x->klass()); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::do_Goto(Goto* x) { aoqi@0: output()->print("goto B%d", x->default_sux()->block_id()); aoqi@0: if (x->is_safepoint()) output()->print(" (safepoint)"); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::do_If(If* x) { aoqi@0: output()->print("if "); aoqi@0: print_value(x->x()); aoqi@0: output()->print(" %s ", cond_name(x->cond())); aoqi@0: print_value(x->y()); aoqi@0: output()->print(" then B%d else B%d", x->sux_at(0)->block_id(), x->sux_at(1)->block_id()); aoqi@0: if (x->is_safepoint()) output()->print(" (safepoint)"); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::do_IfInstanceOf(IfInstanceOf* x) { aoqi@0: output()->print(""); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::do_TableSwitch(TableSwitch* x) { aoqi@0: output()->print("tableswitch "); aoqi@0: if (x->is_safepoint()) output()->print("(safepoint) "); aoqi@0: print_value(x->tag()); aoqi@0: output()->cr(); aoqi@0: int l = x->length(); aoqi@0: for (int i = 0; i < l; i++) { aoqi@0: fill_to(instr_pos); aoqi@0: output()->print_cr("case %5d: B%d", x->lo_key() + i, x->sux_at(i)->block_id()); aoqi@0: } aoqi@0: fill_to(instr_pos); aoqi@0: output()->print("default : B%d", x->default_sux()->block_id()); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::do_LookupSwitch(LookupSwitch* x) { aoqi@0: output()->print("lookupswitch "); aoqi@0: if (x->is_safepoint()) output()->print("(safepoint) "); aoqi@0: print_value(x->tag()); aoqi@0: output()->cr(); aoqi@0: int l = x->length(); aoqi@0: for (int i = 0; i < l; i++) { aoqi@0: fill_to(instr_pos); aoqi@0: output()->print_cr("case %5d: B%d", x->key_at(i), x->sux_at(i)->block_id()); aoqi@0: } aoqi@0: fill_to(instr_pos); aoqi@0: output()->print("default : B%d", x->default_sux()->block_id()); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::do_Return(Return* x) { aoqi@0: if (x->result() == NULL) { aoqi@0: output()->print("return"); aoqi@0: } else { aoqi@0: output()->print("%creturn ", x->type()->tchar()); aoqi@0: print_value(x->result()); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::do_Throw(Throw* x) { aoqi@0: output()->print("throw "); aoqi@0: print_value(x->exception()); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::do_Base(Base* x) { aoqi@0: output()->print("std entry B%d", x->std_entry()->block_id()); aoqi@0: if (x->number_of_sux() > 1) { aoqi@0: output()->print(" osr entry B%d", x->osr_entry()->block_id()); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::do_OsrEntry(OsrEntry* x) { aoqi@0: output()->print("osr entry"); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::do_ExceptionObject(ExceptionObject* x) { aoqi@0: output()->print("incoming exception"); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::do_RoundFP(RoundFP* x) { aoqi@0: output()->print("round_fp "); aoqi@0: print_value(x->input()); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::do_UnsafeGetRaw(UnsafeGetRaw* x) { aoqi@0: print_unsafe_raw_op(x, "UnsafeGetRaw"); aoqi@0: output()->put(')'); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::do_UnsafePutRaw(UnsafePutRaw* x) { aoqi@0: print_unsafe_raw_op(x, "UnsafePutRaw"); aoqi@0: output()->print(", value "); aoqi@0: print_value(x->value()); aoqi@0: output()->put(')'); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::do_UnsafeGetObject(UnsafeGetObject* x) { aoqi@0: print_unsafe_object_op(x, "UnsafeGetObject"); aoqi@0: output()->put(')'); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void InstructionPrinter::do_UnsafePutObject(UnsafePutObject* x) { aoqi@0: print_unsafe_object_op(x, "UnsafePutObject"); aoqi@0: output()->print(", value "); aoqi@0: print_value(x->value()); aoqi@0: output()->put(')'); aoqi@0: } aoqi@0: aoqi@0: void InstructionPrinter::do_UnsafeGetAndSetObject(UnsafeGetAndSetObject* x) { aoqi@0: print_unsafe_object_op(x, x->is_add()?"UnsafeGetAndSetObject (add)":"UnsafeGetAndSetObject"); aoqi@0: output()->print(", value "); aoqi@0: print_value(x->value()); aoqi@0: output()->put(')'); aoqi@0: } aoqi@0: aoqi@0: void InstructionPrinter::do_UnsafePrefetchRead(UnsafePrefetchRead* x) { aoqi@0: print_unsafe_object_op(x, "UnsafePrefetchRead"); aoqi@0: output()->put(')'); aoqi@0: } aoqi@0: aoqi@0: void InstructionPrinter::do_RangeCheckPredicate(RangeCheckPredicate* x) { aoqi@0: aoqi@0: if (x->x() != NULL && x->y() != NULL) { aoqi@0: output()->print("if "); aoqi@0: print_value(x->x()); aoqi@0: output()->print(" %s ", cond_name(x->cond())); aoqi@0: print_value(x->y()); aoqi@0: output()->print(" then deoptimize!"); aoqi@0: } else { aoqi@0: output()->print("always deoptimize!"); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: #ifdef ASSERT aoqi@0: void InstructionPrinter::do_Assert(Assert* x) { aoqi@0: output()->print("assert "); aoqi@0: print_value(x->x()); aoqi@0: output()->print(" %s ", cond_name(x->cond())); aoqi@0: print_value(x->y()); aoqi@0: } aoqi@0: #endif aoqi@0: aoqi@0: void InstructionPrinter::do_UnsafePrefetchWrite(UnsafePrefetchWrite* x) { aoqi@0: print_unsafe_object_op(x, "UnsafePrefetchWrite"); aoqi@0: output()->put(')'); aoqi@0: } aoqi@0: aoqi@0: void InstructionPrinter::do_ProfileCall(ProfileCall* x) { aoqi@0: output()->print("profile "); aoqi@0: print_value(x->recv()); aoqi@0: output()->print(" %s.%s", x->method()->holder()->name()->as_utf8(), x->method()->name()->as_utf8()); aoqi@0: if (x->known_holder() != NULL) { aoqi@0: output()->print(", "); aoqi@0: print_klass(x->known_holder()); aoqi@0: output()->print(" "); aoqi@0: } aoqi@0: for (int i = 0; i < x->nb_profiled_args(); i++) { aoqi@0: if (i > 0) output()->print(", "); aoqi@0: print_value(x->profiled_arg_at(i)); aoqi@0: if (x->arg_needs_null_check(i)) { aoqi@0: output()->print(" [NC]"); aoqi@0: } aoqi@0: } aoqi@0: output()->put(')'); aoqi@0: } aoqi@0: aoqi@0: void InstructionPrinter::do_ProfileReturnType(ProfileReturnType* x) { aoqi@0: output()->print("profile ret type "); aoqi@0: print_value(x->ret()); aoqi@0: output()->print(" %s.%s", x->method()->holder()->name()->as_utf8(), x->method()->name()->as_utf8()); aoqi@0: output()->put(')'); aoqi@0: } aoqi@0: void InstructionPrinter::do_ProfileInvoke(ProfileInvoke* x) { aoqi@0: output()->print("profile_invoke "); aoqi@0: output()->print(" %s.%s", x->inlinee()->holder()->name()->as_utf8(), x->inlinee()->name()->as_utf8()); aoqi@0: output()->put(')'); aoqi@0: aoqi@0: } aoqi@0: aoqi@0: void InstructionPrinter::do_RuntimeCall(RuntimeCall* x) { aoqi@0: output()->print("call_rt %s(", x->entry_name()); aoqi@0: for (int i = 0; i < x->number_of_arguments(); i++) { aoqi@0: if (i > 0) output()->print(", "); aoqi@0: print_value(x->argument_at(i)); aoqi@0: } aoqi@0: output()->put(')'); aoqi@0: } aoqi@0: aoqi@0: void InstructionPrinter::do_MemBar(MemBar* x) { aoqi@0: if (os::is_MP()) { aoqi@0: LIR_Code code = x->code(); aoqi@0: switch (code) { aoqi@0: case lir_membar_acquire : output()->print("membar_acquire"); break; aoqi@0: case lir_membar_release : output()->print("membar_release"); break; aoqi@0: case lir_membar : output()->print("membar"); break; aoqi@0: case lir_membar_loadload : output()->print("membar_loadload"); break; aoqi@0: case lir_membar_storestore: output()->print("membar_storestore"); break; aoqi@0: case lir_membar_loadstore : output()->print("membar_loadstore"); break; aoqi@0: case lir_membar_storeload : output()->print("membar_storeload"); break; aoqi@0: default : ShouldNotReachHere(); break; aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: #endif // PRODUCT