idealGraphPrinter.cpp 20.9 KB
Newer Older
D
duke 已提交
1
/*
2
 * Copyright (c) 2007, 2011, 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);
      }
133 134
      fileStream *stream = new (ResourceObj::C_HEAP) fileStream(st.as_string());
      _output = stream;
D
duke 已提交
135
    } else {
136 137
      fileStream *stream = new (ResourceObj::C_HEAP) fileStream(PrintIdealGraphFile);
      _output = stream;
D
duke 已提交
138 139 140
    }
    _file_count++;
  } else {
141 142
    _stream = new (ResourceObj::C_HEAP) networkStream();

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("Couldn't connect to visualizer at %s:%d",
                    PrintIdealGraphAddress, PrintIdealGraphPort));
D
duke 已提交
160 161 162
    }
  }

163 164 165
  _xml = new (ResourceObj::C_HEAP) xmlStream(_output);

  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 410 411 412 413 414
    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 已提交
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 453 454 455 456 457 458 459 460 461
    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 已提交
462

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

471 472
    if (node->is_Proj()) {
      print_prop("con", (int)node->as_Proj()->_con);
D
duke 已提交
473 474
    }

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

479 480
    buffer[0] = 0;
    stringStream s2(buffer, sizeof(buffer) - 1);
D
duke 已提交
481

482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498
    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 已提交
499

500 501
    assert(s2.size() < sizeof(buffer), "size in range");
    print_prop("dump_spec", buffer);
D
duke 已提交
502

503 504 505
    if (node->is_block_proj()) {
      print_prop("is_block_proj", "true");
    }
D
duke 已提交
506

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

511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534
    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 已提交
535
        } else {
536
          print_prop(short_name, "I");
D
duke 已提交
537
        }
538 539 540 541 542 543 544 545 546
      } 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) {
547
          sprintf(buffer, INT64_FORMAT, value);
548 549 550
          print_prop(short_name, buffer);
        } else {
          print_prop(short_name, "L");
D
duke 已提交
551
        }
552 553 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
      } 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 已提交
579
      }
580
    }
D
duke 已提交
581

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

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

612 613 614 615 616
    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 已提交
617 618
    }

619 620 621 622 623
    node->_in_dump_cnt--;
#endif

    tail(PROPERTIES_ELEMENT);
    tail(NODE_ELEMENT);
D
duke 已提交
624
  }
625
}
D
duke 已提交
626

627
void IdealGraphPrinter::walk_nodes(Node *start, bool edges, VectorSet* temp_set) {
D
duke 已提交
628 629


630 631 632 633
  VectorSet visited(Thread::current()->resource_area());
  GrowableArray<Node *> nodeStack(Thread::current()->resource_area(), 0, 0, NULL);
  nodeStack.push(start);
  visited.test_set(start->_idx);
634 635 636 637 638 639 640 641 642 643 644
  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]);
      }
    }
  }

645
  while(nodeStack.length() > 0) {
D
duke 已提交
646

647
    Node *n = nodeStack.pop();
648
    visit_node(n, edges, temp_set);
D
duke 已提交
649

650 651 652 653 654
    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 已提交
655 656 657 658
        }
      }
    }

659 660 661 662 663 664
    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 已提交
665 666 667 668 669 670 671 672 673 674 675 676 677
    }
  }
}

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;

678
  this->C = compile;
D
duke 已提交
679

680 681
  // Warning, unsafe cast?
  _chaitin = (PhaseChaitin *)C->regalloc();
D
duke 已提交
682

683 684 685
  begin_head(GRAPH_ELEMENT);
  print_attr(GRAPH_NAME_PROPERTY, (const char *)name);
  end_head();
D
duke 已提交
686

687 688
  VectorSet temp_set(Thread::current()->resource_area());

689
  head(NODES_ELEMENT);
690
  walk_nodes(node, false, &temp_set);
691
  tail(NODES_ELEMENT);
D
duke 已提交
692

693
  head(EDGES_ELEMENT);
694
  walk_nodes(node, true, &temp_set);
695 696 697 698 699 700 701 702 703 704
  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);
705
      for (uint s = 0; s < b->_num_succs; s++) {
706 707 708 709 710
        begin_elem(SUCCESSOR_ELEMENT);
        print_attr(BLOCK_NAME_PROPERTY, b->_succs[s]->_pre_order);
        end_elem();
      }
      tail(SUCCESSORS_ELEMENT);
D
duke 已提交
711

712 713 714 715 716 717 718 719
      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);

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

extern const char *NodeClassNames[];

outputStream *IdealGraphPrinter::output() {
731
  return _xml;
D
duke 已提交
732 733 734
}

#endif