idealGraphPrinter.cpp 20.0 KB
Newer Older
D
duke 已提交
1
/*
X
xdono 已提交
2
 * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
D
duke 已提交
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 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
 * 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.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 *
 */

#include "incls/_precompiled.incl"
#include "incls/_idealGraphPrinter.cpp.incl"

#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() {

103 104 105 106 107
  // 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 已提交
108 109 110 111 112 113
  _should_send_method = true;
  _output = NULL;
  buffer[0] = 0;
  _depth = 0;
  _current_method = NULL;
  assert(!_current_method, "current method must be initialized to NULL");
114
  _stream = NULL;
D
duke 已提交
115 116 117 118 119 120 121 122 123 124 125 126 127 128

  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);
      }
129 130
      fileStream *stream = new (ResourceObj::C_HEAP) fileStream(st.as_string());
      _output = stream;
D
duke 已提交
131
    } else {
132 133
      fileStream *stream = new (ResourceObj::C_HEAP) fileStream(PrintIdealGraphFile);
      _output = stream;
D
duke 已提交
134 135 136
    }
    _file_count++;
  } else {
137 138
    _stream = new (ResourceObj::C_HEAP) networkStream();

D
duke 已提交
139 140 141 142 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.
      fatal2("Couldn't connect to visualizer at %s:%d", PrintIdealGraphAddress, PrintIdealGraphPort);
    }
  }

158 159 160
  _xml = new (ResourceObj::C_HEAP) xmlStream(_output);

  head(TOP_ELEMENT);
D
duke 已提交
161 162 163 164 165
}

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

166 167 168 169 170 171 172 173 174 175
  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 已提交
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191

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

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


192 193 194
void IdealGraphPrinter::begin_elem(const char *s) {
  _xml->begin_elem(s);
}
D
duke 已提交
195

196 197 198
void IdealGraphPrinter::end_elem() {
  _xml->end_elem();
}
D
duke 已提交
199

200 201 202
void IdealGraphPrinter::begin_head(const char *s) {
  _xml->begin_head(s);
}
D
duke 已提交
203

204 205 206
void IdealGraphPrinter::end_head() {
  _xml->end_head();
}
D
duke 已提交
207

208 209 210 211 212
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 已提交
213

214 215 216 217 218
void IdealGraphPrinter::print_attr(const char *name, const char *val) {
  _xml->print(" %s='", name);
  text(val);
  _xml->print("'");
}
D
duke 已提交
219

220 221 222
void IdealGraphPrinter::head(const char *name) {
  _xml->head(name);
}
D
duke 已提交
223

224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244
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 已提交
245 246 247
}

void IdealGraphPrinter::print_method(ciMethod *method, int bci, InlineTree *tree) {
248
  begin_head(METHOD_ELEMENT);
D
duke 已提交
249 250 251 252 253 254 255

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

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

256 257 258
  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 已提交
259

260
  end_head();
D
duke 已提交
261

262
  head(BYTECODES_ELEMENT);
D
duke 已提交
263 264 265
  output()->print_cr("<![CDATA[");
  method->print_codes_on(output());
  output()->print_cr("]]>");
266
  tail(BYTECODES_ELEMENT);
D
duke 已提交
267

268
  head(INLINE_ELEMENT);
D
duke 已提交
269 270 271 272 273 274
  if (tree != NULL) {
    GrowableArray<InlineTree *> subtrees = tree->subtrees();
    for (int i = 0; i < subtrees.length(); i++) {
      print_inline_tree(subtrees.at(i));
    }
  }
275
  tail(INLINE_ELEMENT);
D
duke 已提交
276

277
  tail(METHOD_ELEMENT);
D
duke 已提交
278 279 280 281 282 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
  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!");

311
  head(GROUP_ELEMENT);
D
duke 已提交
312

313
  head(PROPERTIES_ELEMENT);
D
duke 已提交
314 315 316 317 318

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

  if (method->flags().is_public()) {
322
    print_prop(METHOD_IS_PUBLIC_PROPERTY, TRUE_VALUE);
D
duke 已提交
323 324 325
  }

  if (method->flags().is_static()) {
326
    print_prop(METHOD_IS_STATIC_PROPERTY, TRUE_VALUE);
D
duke 已提交
327 328
  }

329
  tail(PROPERTIES_ELEMENT);
D
duke 已提交
330 331 332

  if (_stream) {
    char answer = 0;
333
    _xml->flush();
D
duke 已提交
334 335 336 337 338 339
    int result = _stream->read(&answer, 1);
    _should_send_method = (answer == 'y');
  }

  this->_current_method = method;

340
  _xml->flush();
D
duke 已提交
341 342 343 344 345 346 347
}

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

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

348
  tail(GROUP_ELEMENT);
D
duke 已提交
349
  _current_method = NULL;
350
  _xml->flush();
D
duke 已提交
351 352 353 354
}

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

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

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

369 370 371
intptr_t IdealGraphPrinter::get_node_id(Node *n) {
  return (intptr_t)(n);
}
D
duke 已提交
372

373
void IdealGraphPrinter::visit_node(Node *n, void *param) {
D
duke 已提交
374

375
  if(param) {
D
duke 已提交
376

377 378
    // Output edge
    intptr_t dest_id = get_node_id(n);
D
duke 已提交
379 380
    for ( uint i = 0; i < n->len(); i++ ) {
      if ( n->in(i) ) {
381 382 383 384 385 386 387
        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 已提交
388 389 390 391 392
      }
    }

  } else {

393 394 395 396
    // Output node
    begin_head(NODE_ELEMENT);
    print_attr(NODE_ID_PROPERTY, get_node_id(n));
    end_head();
D
duke 已提交
397

398
    head(PROPERTIES_ELEMENT);
D
duke 已提交
399

400 401 402 403 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();
    print_prop("type", (const char *)Type::msg[t->base()]);
    print_prop("idx", node->_idx);
#ifdef ASSERT
    print_prop("debug_idx", node->_debug_idx);
#endif
D
duke 已提交
410

411 412 413 414 415 416
    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 已提交
417 418 419
      }
    }

420 421 422
    const jushort flags = node->flags();
    if (flags & Node::Flag_is_Copy) {
      print_prop("is_copy", "true");
D
duke 已提交
423
    }
424 425
    if (flags & Node::Flag_is_Call) {
      print_prop("is_call", "true");
D
duke 已提交
426
    }
427 428
    if (flags & Node::Flag_rematerialize) {
      print_prop("rematerialize", "true");
D
duke 已提交
429
    }
430 431
    if (flags & Node::Flag_needs_anti_dependence_check) {
      print_prop("needs_anti_dependence_check", "true");
D
duke 已提交
432
    }
433 434
    if (flags & Node::Flag_is_macro) {
      print_prop("is_macro", "true");
D
duke 已提交
435
    }
436 437
    if (flags & Node::Flag_is_Con) {
      print_prop("is_con", "true");
D
duke 已提交
438
    }
439 440
    if (flags & Node::Flag_is_cisc_alternate) {
      print_prop("is_cisc_alternate", "true");
D
duke 已提交
441
    }
442 443
    if (flags & Node::Flag_is_Branch) {
      print_prop("is_branch", "true");
D
duke 已提交
444
    }
445 446
    if (flags & Node::Flag_is_block_start) {
      print_prop("is_block_start", "true");
D
duke 已提交
447
    }
448 449
    if (flags & Node::Flag_is_Goto) {
      print_prop("is_goto", "true");
D
duke 已提交
450
    }
451 452
    if (flags & Node::Flag_is_dead_loop_safe) {
      print_prop("is_dead_loop_safe", "true");
D
duke 已提交
453
    }
454 455
    if (flags & Node::Flag_may_be_short_branch) {
      print_prop("may_be_short_branch", "true");
D
duke 已提交
456
    }
457 458
    if (flags & Node::Flag_is_safepoint_node) {
      print_prop("is_safepoint_node", "true");
D
duke 已提交
459
    }
460 461
    if (flags & Node::Flag_is_pc_relative) {
      print_prop("is_pc_relative", "true");
D
duke 已提交
462 463
    }

464 465 466 467 468 469 470 471 472 473 474
    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 已提交
475

476
#ifdef ASSERT
477 478 479
      Node* old = C->matcher()->find_old_node(node);
      if (old != NULL) {
        print_prop("old_node_idx", old->_idx);
D
duke 已提交
480
      }
481
#endif
D
duke 已提交
482 483
    }

484 485
    if (node->is_Proj()) {
      print_prop("con", (int)node->as_Proj()->_con);
D
duke 已提交
486 487
    }

488 489
    if (node->is_Mach()) {
      print_prop("idealOpcode", (const char *)NodeClassNames[node->as_Mach()->ideal_Opcode()]);
D
duke 已提交
490 491
    }

492 493
    buffer[0] = 0;
    stringStream s2(buffer, sizeof(buffer) - 1);
D
duke 已提交
494

495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511
    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 已提交
512

513 514
    assert(s2.size() < sizeof(buffer), "size in range");
    print_prop("dump_spec", buffer);
D
duke 已提交
515

516 517 518
    if (node->is_block_proj()) {
      print_prop("is_block_proj", "true");
    }
D
duke 已提交
519

520 521 522
    if (node->is_block_start()) {
      print_prop("is_block_start", "true");
    }
D
duke 已提交
523

524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547
    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 已提交
548
        } else {
549
          print_prop(short_name, "I");
D
duke 已提交
550
        }
551 552 553 554 555 556 557 558 559
      } 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) {
560
          sprintf(buffer, INT64_FORMAT, value);
561 562 563
          print_prop(short_name, buffer);
        } else {
          print_prop(short_name, "L");
D
duke 已提交
564
        }
565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591
      } 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 已提交
592
      }
593
    }
D
duke 已提交
594

595 596 597 598 599
    if (caller != NULL) {
      stringStream bciStream;
      while(caller) {
        bciStream.print("%d ", caller->bci());
        caller = caller->caller();
D
duke 已提交
600
      }
601
      print_prop("bci", bciStream.as_string());
D
duke 已提交
602 603
    }

604 605 606 607 608
    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 已提交
609 610
    }

611 612 613 614 615
    node->_in_dump_cnt--;
#endif

    tail(PROPERTIES_ELEMENT);
    tail(NODE_ELEMENT);
D
duke 已提交
616
  }
617
}
D
duke 已提交
618

619
void IdealGraphPrinter::walk_nodes(Node *start, void *param) {
D
duke 已提交
620 621


622 623 624 625 626
  VectorSet visited(Thread::current()->resource_area());
  GrowableArray<Node *> nodeStack(Thread::current()->resource_area(), 0, 0, NULL);
  nodeStack.push(start);
  visited.test_set(start->_idx);
  while(nodeStack.length() > 0) {
D
duke 已提交
627

628 629
    Node *n = nodeStack.pop();
    visit_node(n, param);
D
duke 已提交
630

631 632 633 634 635
    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 已提交
636 637 638 639
        }
      }
    }

640 641 642 643 644 645
    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 已提交
646 647 648 649 650 651 652 653 654 655 656 657 658
    }
  }
}

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;

659
  this->C = compile;
D
duke 已提交
660

661 662
  // Warning, unsafe cast?
  _chaitin = (PhaseChaitin *)C->regalloc();
D
duke 已提交
663

664 665 666
  begin_head(GRAPH_ELEMENT);
  print_attr(GRAPH_NAME_PROPERTY, (const char *)name);
  end_head();
D
duke 已提交
667

668 669 670
  head(NODES_ELEMENT);
  walk_nodes(node, NULL);
  tail(NODES_ELEMENT);
D
duke 已提交
671

672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689
  head(EDGES_ELEMENT);
  walk_nodes(node, (void *)1);
  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);
      for (uint s = 0; s < C->cfg()->_blocks[i]->_num_succs; s++) {
        begin_elem(SUCCESSOR_ELEMENT);
        print_attr(BLOCK_NAME_PROPERTY, b->_succs[s]->_pre_order);
        end_elem();
      }
      tail(SUCCESSORS_ELEMENT);
D
duke 已提交
690

691
      tail(BLOCK_ELEMENT);
D
duke 已提交
692 693
    }

694
    tail(CONTROL_FLOW_ELEMENT);
D
duke 已提交
695
  }
696 697
  tail(GRAPH_ELEMENT);
  output()->flush();
D
duke 已提交
698 699 700 701 702
}

extern const char *NodeClassNames[];

outputStream *IdealGraphPrinter::output() {
703
  return _xml;
D
duke 已提交
704 705 706
}

#endif