idealGraphPrinter.cpp 21.0 KB
Newer Older
D
duke 已提交
1
/*
2
 * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
D
duke 已提交
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
19 20 21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
D
duke 已提交
22 23 24
 *
 */

25 26 27 28 29 30
#include "precompiled.hpp"
#include "opto/chaitin.hpp"
#include "opto/idealGraphPrinter.hpp"
#include "opto/machnode.hpp"
#include "opto/parse.hpp"
#include "runtime/threadCritical.hpp"
D
duke 已提交
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106

#ifndef PRODUCT

// Constants
// Keep consistent with Java constants
const char *IdealGraphPrinter::INDENT = "  ";
const char *IdealGraphPrinter::TOP_ELEMENT = "graphDocument";
const char *IdealGraphPrinter::GROUP_ELEMENT = "group";
const char *IdealGraphPrinter::GRAPH_ELEMENT = "graph";
const char *IdealGraphPrinter::PROPERTIES_ELEMENT = "properties";
const char *IdealGraphPrinter::EDGES_ELEMENT = "edges";
const char *IdealGraphPrinter::PROPERTY_ELEMENT = "p";
const char *IdealGraphPrinter::EDGE_ELEMENT = "edge";
const char *IdealGraphPrinter::NODE_ELEMENT = "node";
const char *IdealGraphPrinter::NODES_ELEMENT = "nodes";
const char *IdealGraphPrinter::REMOVE_EDGE_ELEMENT = "removeEdge";
const char *IdealGraphPrinter::REMOVE_NODE_ELEMENT = "removeNode";
const char *IdealGraphPrinter::METHOD_NAME_PROPERTY = "name";
const char *IdealGraphPrinter::METHOD_IS_PUBLIC_PROPERTY = "public";
const char *IdealGraphPrinter::METHOD_IS_STATIC_PROPERTY = "static";
const char *IdealGraphPrinter::TRUE_VALUE = "true";
const char *IdealGraphPrinter::NODE_NAME_PROPERTY = "name";
const char *IdealGraphPrinter::EDGE_NAME_PROPERTY = "name";
const char *IdealGraphPrinter::NODE_ID_PROPERTY = "id";
const char *IdealGraphPrinter::FROM_PROPERTY = "from";
const char *IdealGraphPrinter::TO_PROPERTY = "to";
const char *IdealGraphPrinter::PROPERTY_NAME_PROPERTY = "name";
const char *IdealGraphPrinter::GRAPH_NAME_PROPERTY = "name";
const char *IdealGraphPrinter::INDEX_PROPERTY = "index";
const char *IdealGraphPrinter::METHOD_ELEMENT = "method";
const char *IdealGraphPrinter::INLINE_ELEMENT = "inline";
const char *IdealGraphPrinter::BYTECODES_ELEMENT = "bytecodes";
const char *IdealGraphPrinter::METHOD_BCI_PROPERTY = "bci";
const char *IdealGraphPrinter::METHOD_SHORT_NAME_PROPERTY = "shortName";
const char *IdealGraphPrinter::CONTROL_FLOW_ELEMENT = "controlFlow";
const char *IdealGraphPrinter::BLOCK_NAME_PROPERTY = "name";
const char *IdealGraphPrinter::BLOCK_DOMINATOR_PROPERTY = "dom";
const char *IdealGraphPrinter::BLOCK_ELEMENT = "block";
const char *IdealGraphPrinter::SUCCESSORS_ELEMENT = "successors";
const char *IdealGraphPrinter::SUCCESSOR_ELEMENT = "successor";
const char *IdealGraphPrinter::ASSEMBLY_ELEMENT = "assembly";

int IdealGraphPrinter::_file_count = 0;

IdealGraphPrinter *IdealGraphPrinter::printer() {
  if (PrintIdealGraphLevel == 0) return NULL;

  JavaThread *thread = JavaThread::current();
  if (!thread->is_Compiler_thread()) return NULL;

  CompilerThread *compiler_thread = (CompilerThread *)thread;
  if (compiler_thread->ideal_graph_printer() == NULL) {
    IdealGraphPrinter *printer = new IdealGraphPrinter();
    compiler_thread->set_ideal_graph_printer(printer);
  }

  return compiler_thread->ideal_graph_printer();
}

void IdealGraphPrinter::clean_up() {
  JavaThread *p;
  for (p = Threads::first(); p; p = p->next()) {
    if (p->is_Compiler_thread()) {
      CompilerThread *c = (CompilerThread *)p;
      IdealGraphPrinter *printer = c->ideal_graph_printer();
      if (printer) {
        delete printer;
      }
      c->set_ideal_graph_printer(NULL);
    }
  }
}

// Constructor, either file or network output
IdealGraphPrinter::IdealGraphPrinter() {

107 108 109 110 111
  // By default dump both ins and outs since dead or unreachable code
  // needs to appear in the graph.  There are also some special cases
  // in the mach where kill projections have no users but should
  // appear in the dump.
  _traverse_outs = true;
D
duke 已提交
112 113 114 115 116 117
  _should_send_method = true;
  _output = NULL;
  buffer[0] = 0;
  _depth = 0;
  _current_method = NULL;
  assert(!_current_method, "current method must be initialized to NULL");
118
  _stream = NULL;
D
duke 已提交
119 120 121 122 123 124 125 126 127 128 129 130 131 132

  if (PrintIdealGraphFile != NULL) {
    ThreadCritical tc;
    // User wants all output to go to files
    if (_file_count != 0) {
      ResourceMark rm;
      stringStream st;
      const char* dot = strrchr(PrintIdealGraphFile, '.');
      if (dot) {
        st.write(PrintIdealGraphFile, dot - PrintIdealGraphFile);
        st.print("%d%s", _file_count, dot);
      } else {
        st.print("%s%d", PrintIdealGraphFile, _file_count);
      }
Z
zgu 已提交
133
      fileStream *stream = new (ResourceObj::C_HEAP, mtCompiler) fileStream(st.as_string());
134
      _output = stream;
D
duke 已提交
135
    } else {
Z
zgu 已提交
136
      fileStream *stream = new (ResourceObj::C_HEAP, mtCompiler) fileStream(PrintIdealGraphFile);
137
      _output = stream;
D
duke 已提交
138 139 140
    }
    _file_count++;
  } else {
Z
zgu 已提交
141
    _stream = new (ResourceObj::C_HEAP, mtCompiler) networkStream();
142

D
duke 已提交
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
    // Try to connect to visualizer
    if (_stream->connect(PrintIdealGraphAddress, PrintIdealGraphPort)) {
      char c = 0;
      _stream->read(&c, 1);
      if (c != 'y') {
        tty->print_cr("Client available, but does not want to receive data!");
        _stream->close();
        delete _stream;
        _stream = NULL;
        return;
      }
      _output = _stream;
    } else {
      // It would be nice if we could shut down cleanly but it should
      // be an error if we can't connect to the visualizer.
158 159
      fatal(err_msg_res("Couldn't connect to visualizer at %s:%d",
                        PrintIdealGraphAddress, PrintIdealGraphPort));
D
duke 已提交
160 161 162
    }
  }

Z
zgu 已提交
163
  _xml = new (ResourceObj::C_HEAP, mtCompiler) xmlStream(_output);
164 165

  head(TOP_ELEMENT);
D
duke 已提交
166 167 168 169 170
}

// Destructor, close file or network stream
IdealGraphPrinter::~IdealGraphPrinter() {

171 172 173 174 175 176 177 178 179 180
  tail(TOP_ELEMENT);

  // tty->print_cr("Walk time: %d", (int)_walk_time.milliseconds());
  // tty->print_cr("Output time: %d", (int)_output_time.milliseconds());
  // tty->print_cr("Build blocks time: %d", (int)_build_blocks_time.milliseconds());

  if(_xml) {
    delete _xml;
    _xml = NULL;
  }
D
duke 已提交
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196

  if (_stream) {
    delete _stream;
    if (_stream == _output) {
      _output = NULL;
    }
    _stream = NULL;
  }

  if (_output) {
    delete _output;
    _output = NULL;
  }
}


197 198 199
void IdealGraphPrinter::begin_elem(const char *s) {
  _xml->begin_elem(s);
}
D
duke 已提交
200

201 202 203
void IdealGraphPrinter::end_elem() {
  _xml->end_elem();
}
D
duke 已提交
204

205 206 207
void IdealGraphPrinter::begin_head(const char *s) {
  _xml->begin_head(s);
}
D
duke 已提交
208

209 210 211
void IdealGraphPrinter::end_head() {
  _xml->end_head();
}
D
duke 已提交
212

213 214 215 216 217
void IdealGraphPrinter::print_attr(const char *name, intptr_t val) {
  stringStream stream;
  stream.print(INTX_FORMAT, val);
  print_attr(name, stream.as_string());
}
D
duke 已提交
218

219 220 221 222 223
void IdealGraphPrinter::print_attr(const char *name, const char *val) {
  _xml->print(" %s='", name);
  text(val);
  _xml->print("'");
}
D
duke 已提交
224

225 226 227
void IdealGraphPrinter::head(const char *name) {
  _xml->head(name);
}
D
duke 已提交
228

229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249
void IdealGraphPrinter::tail(const char *name) {
  _xml->tail(name);
}

void IdealGraphPrinter::text(const char *s) {
  _xml->text(s);
}

void IdealGraphPrinter::print_prop(const char *name, int val) {

  stringStream stream;
  stream.print("%d", val);
  print_prop(name, stream.as_string());
}

void IdealGraphPrinter::print_prop(const char *name, const char *val) {
  begin_head(PROPERTY_ELEMENT);
  print_attr(PROPERTY_NAME_PROPERTY, name);
  end_head();
  text(val);
  tail(PROPERTY_ELEMENT);
D
duke 已提交
250 251 252
}

void IdealGraphPrinter::print_method(ciMethod *method, int bci, InlineTree *tree) {
253
  begin_head(METHOD_ELEMENT);
D
duke 已提交
254 255 256 257 258 259 260

  stringStream str;
  method->print_name(&str);

  stringStream shortStr;
  method->print_short_name(&shortStr);

261 262 263
  print_attr(METHOD_NAME_PROPERTY, str.as_string());
  print_attr(METHOD_SHORT_NAME_PROPERTY, shortStr.as_string());
  print_attr(METHOD_BCI_PROPERTY, bci);
D
duke 已提交
264

265
  end_head();
D
duke 已提交
266

267
  head(BYTECODES_ELEMENT);
D
duke 已提交
268 269 270
  output()->print_cr("<![CDATA[");
  method->print_codes_on(output());
  output()->print_cr("]]>");
271
  tail(BYTECODES_ELEMENT);
D
duke 已提交
272

273
  head(INLINE_ELEMENT);
D
duke 已提交
274 275 276 277 278 279
  if (tree != NULL) {
    GrowableArray<InlineTree *> subtrees = tree->subtrees();
    for (int i = 0; i < subtrees.length(); i++) {
      print_inline_tree(subtrees.at(i));
    }
  }
280
  tail(INLINE_ELEMENT);
D
duke 已提交
281

282
  tail(METHOD_ELEMENT);
D
duke 已提交
283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315
  output()->flush();
}

void IdealGraphPrinter::print_inline_tree(InlineTree *tree) {

  if (tree == NULL) return;

  ciMethod *method = tree->method();
  print_method(tree->method(), tree->caller_bci(), tree);

}

void IdealGraphPrinter::print_inlining(Compile* compile) {

  // Print inline tree
  if (_should_send_method) {
    InlineTree *inlineTree = compile->ilt();
    if (inlineTree != NULL) {
      print_inline_tree(inlineTree);
    } else {
      // print this method only
    }
  }
}

// Has to be called whenever a method is compiled
void IdealGraphPrinter::begin_method(Compile* compile) {

  ciMethod *method = compile->method();
  assert(_output, "output stream must exist!");
  assert(method, "null methods are not allowed!");
  assert(!_current_method, "current method must be null!");

316
  head(GROUP_ELEMENT);
D
duke 已提交
317

318
  head(PROPERTIES_ELEMENT);
D
duke 已提交
319 320 321 322 323

  // Print properties
  // Add method name
  stringStream strStream;
  method->print_name(&strStream);
324
  print_prop(METHOD_NAME_PROPERTY, strStream.as_string());
D
duke 已提交
325 326

  if (method->flags().is_public()) {
327
    print_prop(METHOD_IS_PUBLIC_PROPERTY, TRUE_VALUE);
D
duke 已提交
328 329 330
  }

  if (method->flags().is_static()) {
331
    print_prop(METHOD_IS_STATIC_PROPERTY, TRUE_VALUE);
D
duke 已提交
332 333
  }

334
  tail(PROPERTIES_ELEMENT);
D
duke 已提交
335 336 337

  if (_stream) {
    char answer = 0;
338
    _xml->flush();
D
duke 已提交
339 340 341 342 343 344
    int result = _stream->read(&answer, 1);
    _should_send_method = (answer == 'y');
  }

  this->_current_method = method;

345
  _xml->flush();
D
duke 已提交
346 347 348 349 350 351 352
}

// Has to be called whenever a method has finished compilation
void IdealGraphPrinter::end_method() {

  nmethod* method = (nmethod*)this->_current_method->code();

353
  tail(GROUP_ELEMENT);
D
duke 已提交
354
  _current_method = NULL;
355
  _xml->flush();
D
duke 已提交
356 357 358 359
}

// Print indent
void IdealGraphPrinter::print_indent() {
360
  tty->print_cr("printing ident %d", _depth);
D
duke 已提交
361
  for (int i = 0; i < _depth; i++) {
362
    _xml->print(INDENT);
D
duke 已提交
363 364 365 366 367 368 369 370 371 372 373
  }
}

bool IdealGraphPrinter::traverse_outs() {
  return _traverse_outs;
}

void IdealGraphPrinter::set_traverse_outs(bool b) {
  _traverse_outs = b;
}

374 375 376
intptr_t IdealGraphPrinter::get_node_id(Node *n) {
  return (intptr_t)(n);
}
D
duke 已提交
377

378
void IdealGraphPrinter::visit_node(Node *n, bool edges, VectorSet* temp_set) {
D
duke 已提交
379

380
  if (edges) {
D
duke 已提交
381

382 383
    // Output edge
    intptr_t dest_id = get_node_id(n);
D
duke 已提交
384 385
    for ( uint i = 0; i < n->len(); i++ ) {
      if ( n->in(i) ) {
386 387 388 389 390 391 392
        Node *source = n->in(i);
        begin_elem(EDGE_ELEMENT);
        intptr_t source_id = get_node_id(source);
        print_attr(FROM_PROPERTY, source_id);
        print_attr(TO_PROPERTY, dest_id);
        print_attr(INDEX_PROPERTY, i);
        end_elem();
D
duke 已提交
393 394 395 396 397
      }
    }

  } else {

398 399 400 401
    // Output node
    begin_head(NODE_ELEMENT);
    print_attr(NODE_ID_PROPERTY, get_node_id(n));
    end_head();
D
duke 已提交
402

403
    head(PROPERTIES_ELEMENT);
D
duke 已提交
404

405 406 407 408 409
    Node *node = n;
#ifndef PRODUCT
    node->_in_dump_cnt++;
    print_prop(NODE_NAME_PROPERTY, (const char *)node->Name());
    const Type *t = node->bottom_type();
410
    print_prop("type", t->msg());
411 412 413 414
    print_prop("idx", node->_idx);
#ifdef ASSERT
    print_prop("debug_idx", node->_debug_idx);
#endif
D
duke 已提交
415

416 417 418 419 420 421
    if(C->cfg() != NULL) {
      Block *block = C->cfg()->_bbs[node->_idx];
      if(block == NULL) {
        print_prop("block", C->cfg()->_blocks[0]->_pre_order);
      } else {
        print_prop("block", block->_pre_order);
D
duke 已提交
422 423 424
      }
    }

425 426 427
    const jushort flags = node->flags();
    if (flags & Node::Flag_is_Copy) {
      print_prop("is_copy", "true");
D
duke 已提交
428
    }
429 430
    if (flags & Node::Flag_rematerialize) {
      print_prop("rematerialize", "true");
D
duke 已提交
431
    }
432 433
    if (flags & Node::Flag_needs_anti_dependence_check) {
      print_prop("needs_anti_dependence_check", "true");
D
duke 已提交
434
    }
435 436
    if (flags & Node::Flag_is_macro) {
      print_prop("is_macro", "true");
D
duke 已提交
437
    }
438 439
    if (flags & Node::Flag_is_Con) {
      print_prop("is_con", "true");
D
duke 已提交
440
    }
441 442
    if (flags & Node::Flag_is_cisc_alternate) {
      print_prop("is_cisc_alternate", "true");
D
duke 已提交
443
    }
444 445
    if (flags & Node::Flag_is_dead_loop_safe) {
      print_prop("is_dead_loop_safe", "true");
D
duke 已提交
446
    }
447 448
    if (flags & Node::Flag_may_be_short_branch) {
      print_prop("may_be_short_branch", "true");
D
duke 已提交
449
    }
450 451 452
    if (flags & Node::Flag_has_call) {
      print_prop("has_call", "true");
    }
D
duke 已提交
453

454 455 456 457 458 459 460 461 462 463 464
    if (C->matcher() != NULL) {
      if (C->matcher()->is_shared(node)) {
        print_prop("is_shared", "true");
      } else {
        print_prop("is_shared", "false");
      }
      if (C->matcher()->is_dontcare(node)) {
        print_prop("is_dontcare", "true");
      } else {
        print_prop("is_dontcare", "false");
      }
D
duke 已提交
465

466
#ifdef ASSERT
467 468 469
      Node* old = C->matcher()->find_old_node(node);
      if (old != NULL) {
        print_prop("old_node_idx", old->_idx);
D
duke 已提交
470
      }
471
#endif
D
duke 已提交
472 473
    }

474 475
    if (node->is_Proj()) {
      print_prop("con", (int)node->as_Proj()->_con);
D
duke 已提交
476 477
    }

478 479
    if (node->is_Mach()) {
      print_prop("idealOpcode", (const char *)NodeClassNames[node->as_Mach()->ideal_Opcode()]);
D
duke 已提交
480 481
    }

482 483
    buffer[0] = 0;
    stringStream s2(buffer, sizeof(buffer) - 1);
D
duke 已提交
484

485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501
    node->dump_spec(&s2);
    if (t != NULL && (t->isa_instptr() || t->isa_klassptr())) {
      const TypeInstPtr  *toop = t->isa_instptr();
      const TypeKlassPtr *tkls = t->isa_klassptr();
      ciKlass*           klass = toop ? toop->klass() : (tkls ? tkls->klass() : NULL );
      if( klass && klass->is_loaded() && klass->is_interface() ) {
        s2.print("  Interface:");
      } else if( toop ) {
        s2.print("  Oop:");
      } else if( tkls ) {
        s2.print("  Klass:");
      }
      t->dump_on(&s2);
    } else if( t == Type::MEMORY ) {
      s2.print("  Memory:");
      MemNode::dump_adr_type(node, node->adr_type(), &s2);
    }
D
duke 已提交
502

503 504
    assert(s2.size() < sizeof(buffer), "size in range");
    print_prop("dump_spec", buffer);
D
duke 已提交
505

506 507 508
    if (node->is_block_proj()) {
      print_prop("is_block_proj", "true");
    }
D
duke 已提交
509

510 511 512
    if (node->is_block_start()) {
      print_prop("is_block_start", "true");
    }
D
duke 已提交
513

514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537
    const char *short_name = "short_name";
    if (strcmp(node->Name(), "Parm") == 0 && node->as_Proj()->_con >= TypeFunc::Parms) {
      int index = node->as_Proj()->_con - TypeFunc::Parms;
      if (index >= 10) {
        print_prop(short_name, "PA");
      } else {
        sprintf(buffer, "P%d", index);
        print_prop(short_name, buffer);
      }
    } else if (strcmp(node->Name(), "IfTrue") == 0) {
      print_prop(short_name, "T");
    } else if (strcmp(node->Name(), "IfFalse") == 0) {
      print_prop(short_name, "F");
    } else if ((node->is_Con() && node->is_Type()) || node->is_Proj()) {

      if (t->base() == Type::Int && t->is_int()->is_con()) {
        const TypeInt *typeInt = t->is_int();
        assert(typeInt->is_con(), "must be constant");
        jint value = typeInt->get_con();

        // max. 2 chars allowed
        if (value >= -9 && value <= 99) {
          sprintf(buffer, "%d", value);
          print_prop(short_name, buffer);
D
duke 已提交
538
        } else {
539
          print_prop(short_name, "I");
D
duke 已提交
540
        }
541 542 543 544 545 546 547 548 549
      } else if (t == Type::TOP) {
        print_prop(short_name, "^");
      } else if (t->base() == Type::Long && t->is_long()->is_con()) {
        const TypeLong *typeLong = t->is_long();
        assert(typeLong->is_con(), "must be constant");
        jlong value = typeLong->get_con();

        // max. 2 chars allowed
        if (value >= -9 && value <= 99) {
550
          sprintf(buffer, INT64_FORMAT, value);
551 552 553
          print_prop(short_name, buffer);
        } else {
          print_prop(short_name, "L");
D
duke 已提交
554
        }
555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581
      } else if (t->base() == Type::KlassPtr) {
        const TypeKlassPtr *typeKlass = t->is_klassptr();
        print_prop(short_name, "CP");
      } else if (t->base() == Type::Control) {
        print_prop(short_name, "C");
      } else if (t->base() == Type::Memory) {
        print_prop(short_name, "M");
      } else if (t->base() == Type::Abio) {
        print_prop(short_name, "IO");
      } else if (t->base() == Type::Return_Address) {
        print_prop(short_name, "RA");
      } else if (t->base() == Type::AnyPtr) {
        print_prop(short_name, "P");
      } else if (t->base() == Type::RawPtr) {
        print_prop(short_name, "RP");
      } else if (t->base() == Type::AryPtr) {
        print_prop(short_name, "AP");
      }
    }

    JVMState* caller = NULL;
    if (node->is_SafePoint()) {
      caller = node->as_SafePoint()->jvms();
    } else {
      Node_Notes* notes = C->node_notes_at(node->_idx);
      if (notes != NULL) {
        caller = notes->jvms();
D
duke 已提交
582
      }
583
    }
D
duke 已提交
584

585 586
    if (caller != NULL) {
      stringStream bciStream;
587 588
      ciMethod* last = NULL;
      int last_bci;
589
      while(caller) {
590 591 592 593
        if (caller->has_method()) {
          last = caller->method();
          last_bci = caller->bci();
        }
594 595
        bciStream.print("%d ", caller->bci());
        caller = caller->caller();
D
duke 已提交
596
      }
597
      print_prop("bci", bciStream.as_string());
598 599 600 601 602
      if (last != NULL && last->has_linenumber_table() && last_bci >= 0) {
        print_prop("line", last->line_number_from_bci(last_bci));
      }
    }

603
#ifdef ASSERT
604
    if (node->debug_orig() != NULL) {
605
      temp_set->Clear();
606 607
      stringStream dorigStream;
      Node* dorig = node->debug_orig();
608
      while (dorig && temp_set->test_set(dorig->_idx)) {
609 610 611
        dorigStream.print("%d ", dorig->_idx);
      }
      print_prop("debug_orig", dorigStream.as_string());
D
duke 已提交
612
    }
613
#endif
D
duke 已提交
614

615 616 617 618 619
    if (_chaitin && _chaitin != (PhaseChaitin *)0xdeadbeef) {
      buffer[0] = 0;
      _chaitin->dump_register(node, buffer);
      print_prop("reg", buffer);
      print_prop("lrg", _chaitin->n2lidx(node));
D
duke 已提交
620 621
    }

622 623 624 625 626
    node->_in_dump_cnt--;
#endif

    tail(PROPERTIES_ELEMENT);
    tail(NODE_ELEMENT);
D
duke 已提交
627
  }
628
}
D
duke 已提交
629

630
void IdealGraphPrinter::walk_nodes(Node *start, bool edges, VectorSet* temp_set) {
D
duke 已提交
631 632


633 634 635 636
  VectorSet visited(Thread::current()->resource_area());
  GrowableArray<Node *> nodeStack(Thread::current()->resource_area(), 0, 0, NULL);
  nodeStack.push(start);
  visited.test_set(start->_idx);
637 638 639 640 641 642 643 644 645 646 647
  if (C->cfg() != NULL) {
    // once we have a CFG there are some nodes that aren't really
    // reachable but are in the CFG so add them here.
    for (uint i = 0; i < C->cfg()->_blocks.size(); i++) {
      Block *b = C->cfg()->_blocks[i];
      for (uint s = 0; s < b->_nodes.size(); s++) {
        nodeStack.push(b->_nodes[s]);
      }
    }
  }

648
  while(nodeStack.length() > 0) {
D
duke 已提交
649

650
    Node *n = nodeStack.pop();
651
    visit_node(n, edges, temp_set);
D
duke 已提交
652

653 654 655 656 657
    if (_traverse_outs) {
      for (DUIterator i = n->outs(); n->has_out(i); i++) {
        Node* p = n->out(i);
        if (!visited.test_set(p->_idx)) {
          nodeStack.push(p);
D
duke 已提交
658 659 660 661
        }
      }
    }

662 663 664 665 666 667
    for ( uint i = 0; i < n->len(); i++ ) {
      if ( n->in(i) ) {
        if (!visited.test_set(n->in(i)->_idx)) {
          nodeStack.push(n->in(i));
        }
      }
D
duke 已提交
668 669 670 671 672 673 674 675 676 677 678 679 680
    }
  }
}

void IdealGraphPrinter::print_method(Compile* compile, const char *name, int level, bool clear_nodes) {
  print(compile, name, (Node *)compile->root(), level, clear_nodes);
}

// Print current ideal graph
void IdealGraphPrinter::print(Compile* compile, const char *name, Node *node, int level, bool clear_nodes) {

  if (!_current_method || !_should_send_method || level > PrintIdealGraphLevel) return;

681
  this->C = compile;
D
duke 已提交
682

683 684
  // Warning, unsafe cast?
  _chaitin = (PhaseChaitin *)C->regalloc();
D
duke 已提交
685

686 687 688
  begin_head(GRAPH_ELEMENT);
  print_attr(GRAPH_NAME_PROPERTY, (const char *)name);
  end_head();
D
duke 已提交
689

690 691
  VectorSet temp_set(Thread::current()->resource_area());

692
  head(NODES_ELEMENT);
693
  walk_nodes(node, false, &temp_set);
694
  tail(NODES_ELEMENT);
D
duke 已提交
695

696
  head(EDGES_ELEMENT);
697
  walk_nodes(node, true, &temp_set);
698 699 700 701 702 703 704 705 706 707
  tail(EDGES_ELEMENT);
  if (C->cfg() != NULL) {
    head(CONTROL_FLOW_ELEMENT);
    for (uint i = 0; i < C->cfg()->_blocks.size(); i++) {
      Block *b = C->cfg()->_blocks[i];
      begin_head(BLOCK_ELEMENT);
      print_attr(BLOCK_NAME_PROPERTY, b->_pre_order);
      end_head();

      head(SUCCESSORS_ELEMENT);
708
      for (uint s = 0; s < b->_num_succs; s++) {
709 710 711 712 713
        begin_elem(SUCCESSOR_ELEMENT);
        print_attr(BLOCK_NAME_PROPERTY, b->_succs[s]->_pre_order);
        end_elem();
      }
      tail(SUCCESSORS_ELEMENT);
D
duke 已提交
714

715 716 717 718 719 720 721 722
      head(NODES_ELEMENT);
      for (uint s = 0; s < b->_nodes.size(); s++) {
        begin_elem(NODE_ELEMENT);
        print_attr(NODE_ID_PROPERTY, get_node_id(b->_nodes[s]));
        end_elem();
      }
      tail(NODES_ELEMENT);

723
      tail(BLOCK_ELEMENT);
D
duke 已提交
724
    }
725
    tail(CONTROL_FLOW_ELEMENT);
D
duke 已提交
726
  }
727 728
  tail(GRAPH_ELEMENT);
  output()->flush();
D
duke 已提交
729 730 731 732 733
}

extern const char *NodeClassNames[];

outputStream *IdealGraphPrinter::output() {
734
  return _xml;
D
duke 已提交
735 736 737
}

#endif