00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 # include "incls/_precompiled.incl"
00025 # include "incls/_prettyPrinter.cpp.incl"
00026
00027
00028
00029
00030
00031 class cascadeSendNode;
00032 class statement;
00033 class codeNode;
00034
00035 class astNode : public ResourceObj {
00036 protected:
00037 int bci;
00038 scopeNode* scope;
00039 public:
00040 astNode(int bci, scopeNode* scope) {
00041 this->bci = bci;
00042 this->scope = scope;
00043 }
00044 int this_bci() { return bci; }
00045 scopeNode* this_scope() { return scope; }
00046
00047 virtual bool is_message() { return false; }
00048 virtual bool is_statement() { return false; }
00049 virtual bool is_code() { return false; }
00050 virtual bool is_cascade() { return false; }
00051
00052 virtual void add(astNode* statement) {
00053 fatal("subclass should implement add");
00054 }
00055
00056 void top_level_print(prettyPrintStream* output);
00057
00058 virtual bool print(prettyPrintStream* output);
00059 virtual int width(prettyPrintStream* output) { return output->infinity(); }
00060
00061 virtual symbolOop selector() { return NULL; }
00062 virtual bool should_wrap_argument(astNode* argument) { return false; };
00063 virtual astNode* argument_at(int i) { return NULL; }
00064 };
00065
00066
00067 class PrintWrapper {
00068 private:
00069 astNode* t;
00070 bool hit;
00071 prettyPrintStream* output;
00072 public:
00073 PrintWrapper(astNode* t, prettyPrintStream* output);
00074 ~PrintWrapper();
00075 };
00076
00077
00078 # define HIGHLIGHT PrintWrapper pw(this, output);
00079
00080 # include <ctype.h>
00081
00082 bool should_wrap(int type, astNode* arg);
00083
00084
00085 static bool print_selector_with_arguments(prettyPrintStream* output,
00086 symbolOop selector,
00087 GrowableArray<astNode*>* arguments,
00088 bool split) {
00089 if (ispunct(selector->byte_at(1))) {
00090
00091 output->print(selector->as_string());
00092 output->space();
00093 astNode* arg = arguments->at(0);
00094 bool wrap = should_wrap(1, arg);
00095 if (wrap) output->print("(");
00096 bool result = arg->print(output);
00097 if (wrap) output->print(")");
00098 return result;
00099 }
00100
00101 int arg = arguments->length();
00102
00103 if (arg == 0) {
00104 output->print(selector->as_string());
00105 return false;
00106 }
00107
00108 for (int index = 1; index <= selector->length(); index++) {
00109 int c = selector->byte_at(index);
00110 output->print_char(c);
00111 if (c == ':') {
00112 output->space();
00113 astNode* a = arguments->at(--arg);
00114 bool wrap = should_wrap(2, a);
00115 if (wrap) output->print("(");
00116 a->print(output);
00117 if (wrap) output->print(")");
00118
00119 if (index < selector->length()) {
00120 if (split) output->newline();
00121 else output->space();
00122 }
00123 }
00124 }
00125 return split;
00126 }
00127
00128
00129 static astNode* get_literal_node(oop obj, int bci, scopeNode* scope);
00130
00131 class PrintTemps : public TempDecoder {
00132 public:
00133 GrowableArray<astNode*>* elements;
00134 scopeNode* scope;
00135 void decode(methodOop method, scopeNode *scope) {
00136 this->scope = scope;
00137 elements = new GrowableArray<astNode*>(10);
00138 TempDecoder::decode(method);
00139 }
00140 void stack_temp(byteArrayOop name, int offset);
00141 void heap_temp(byteArrayOop name, int offset);
00142 };
00143
00144
00145 class PrintParams : public TempDecoder {
00146 scopeNode* scope;
00147 public:
00148 GrowableArray<astNode*>* elements;
00149 void decode(methodOop method, scopeNode* scope) {
00150 this->scope = scope;
00151 elements = new GrowableArray<astNode*>(10);
00152 TempDecoder::decode(method);
00153 }
00154 void PrintParams::parameter(byteArrayOop name, int index);
00155 };
00156
00157
00158 class leafNode : public astNode {
00159 public:
00160 leafNode(int bci, scopeNode* scope) : astNode(bci, scope) {}
00161 bool print(prettyPrintStream* output) {
00162 HIGHLIGHT
00163 astNode::print(output);
00164 output->print(string());
00165 return false;
00166 }
00167 int width(prettyPrintStream* output) { return output->width_of_string(string()); }
00168 virtual char* string() = 0;
00169 };
00170
00171
00172 class paramNode : public leafNode {
00173 private:
00174 int no;
00175 char* str;
00176 public:
00177 paramNode(int bci, scopeNode* scope, int no);
00178 char* string() { return str; }
00179 bool is_param() { return true; }
00180 };
00181
00182
00183 class nameValueNode : public astNode {
00184 char* name;
00185 char* value;
00186 public:
00187 nameValueNode(char* name, char* value) : astNode(0, 0) {
00188 this->name = name;
00189 this->value = value;
00190 }
00191 bool print(prettyPrintStream* output) {
00192 output->print(name);
00193 output->print(" \"");
00194 output->print(value);
00195 output->print("\"");
00196 return false;
00197 }
00198 int width(prettyPrintStream* output) {
00199 return output->width_of_string(name) + 3 + output->width_of_string(value);
00200 }
00201 };
00202
00203
00204 class nameNode : public leafNode {
00205 private:
00206 char* str;
00207 public:
00208 nameNode(char* str) : leafNode(0,0) {
00209 this->str = str;
00210 }
00211 char* string() { return str; }
00212 };
00213
00214
00215 class listNode : public astNode {
00216 protected:
00217 GrowableArray<astNode*>* elements;
00218 char* begin_sym;
00219 char* end_sym;
00220 public:
00221 listNode(char* begin_sym, char* end_sym) : astNode(0,0) {
00222 this->begin_sym = begin_sym;
00223 this->end_sym = end_sym;
00224 elements = new GrowableArray<astNode*>(10);
00225 }
00226
00227 void add(astNode* element) {
00228 elements->push(element);
00229 }
00230
00231 bool print(prettyPrintStream* output) {
00232 if (begin_sym) {
00233 output->print(begin_sym);
00234 output->space();
00235 }
00236
00237 for (int index = 0; index < elements->length(); index++) {
00238 elements->at(index)->print(output);
00239 output->space();
00240 }
00241
00242 if (end_sym)
00243 output->print(end_sym);
00244 return false;
00245 }
00246
00247 int width(prettyPrintStream* output) {
00248 int w = 0;
00249 if (begin_sym)
00250 w += output->width_of_string(begin_sym) + output->width_of_space();
00251
00252 for (int index = 0; index < elements->length(); index++) {
00253 w += elements->at(index)->width(output) + output->width_of_space();
00254 }
00255
00256 if (end_sym)
00257 w += output->width_of_string(end_sym);
00258 return w;
00259 }
00260
00261 };
00262
00263
00264 class scopeNode : public astNode {
00265 protected:
00266 methodOop _method;
00267 klassOop klass;
00268 int in;
00269 int _hot_bci;
00270 int frame_index;
00271 deltaVFrame* _fr;
00272 ScopeDesc* _sd;
00273 public:
00274 scopeNode(deltaVFrame* fr, int index)
00275 : astNode(0, NULL) {
00276 frame_index = index;
00277 _method = fr->method();
00278 klass = fr->receiver()->klass();
00279 _hot_bci = fr->bci();
00280 _fr = fr;
00281 in = 0;
00282 _sd = _fr->is_compiled_frame()
00283 ? ((compiledVFrame*) _fr)->scope()
00284 : NULL;
00285 }
00286
00287 scopeNode(methodOop method, klassOop klass, int hot_bci)
00288 : astNode(0, NULL) {
00289 _method = method;
00290 this->klass = klass;
00291 this->_hot_bci = hot_bci;
00292 _fr = NULL;
00293 in = 0;
00294 _sd = NULL;
00295 }
00296
00297 deltaVFrame* fr() { return _fr; }
00298 ScopeDesc* sd() const { return _sd; }
00299
00300 methodOop method() { return _method; }
00301
00302 int hot_bci() { return _hot_bci; }
00303
00304 klassOop get_klass() { return klass; }
00305
00306 bool is_block_method() { return method()->is_blockMethod(); }
00307
00308 void context_allocated() { assert(is_context_allocated(), "just checking"); }
00309 bool is_context_allocated() { return method()->allocatesInterpretedContext(); }
00310
00311 char* param_string(int index, bool in_block = false) {
00312 byteArrayOop res = find_parameter_name(method(), index);
00313 if (in_block) {
00314 if (!res) return create_name(":p", index);
00315 char* buffer = NEW_RESOURCE_ARRAY(char, res->length() + 2);
00316 buffer[0] = ':';
00317 res->copy_null_terminated(&buffer[1], res->length());
00318 return buffer;
00319 } else {
00320 return res ? res->as_string() : create_name("p", index);
00321 }
00322 }
00323
00324 char* stack_temp_string(int bci, int no) {
00325 byteArrayOop res = find_stack_temp(method(), bci, no);
00326 return res ? res->as_string() : create_name("t", no);
00327 }
00328
00329 char* stack_float_temp_string(int bci, int fno) {
00330 byteArrayOop res = find_stack_float_temp(method(), bci, fno);
00331 return res ? res->as_string() : create_name("f", fno);
00332 }
00333
00334 char* create_name(char* prefix, int no) {
00335 char* str = NEW_RESOURCE_ARRAY(char, 7);
00336 sprintf(str, "%s_%d", prefix, no);
00337 return str;
00338 }
00339
00340 char* heap_temp_string(int bci, int no, int context_level) {
00341 if (is_block_method()) {
00342 int level = context_level;
00343 if (is_context_allocated()) {
00344 level--;
00345 if (context_level == 0) {
00346 byteArrayOop res = find_heap_temp(method(), bci, no);
00347 return res ? res->as_string() : create_name("ht", no);
00348 }
00349 }
00350 scopeNode* n = new scopeNode(method()->parent(), klass, 0);
00351 return n->heap_temp_string(bci, no, level);
00352 } else {
00353 byteArrayOop res = find_heap_temp(method(), bci, no);
00354 return res ? res->as_string() : create_name("ht", no);
00355 }
00356 }
00357
00358 char* inst_var_string(int offset) {
00359 if (klass) {
00360 symbolOop name = klass->klass_part()->inst_var_name_at(offset);
00361 if (name) return name->as_string();
00362 }
00363 char* str = NEW_RESOURCE_ARRAY(char, 15);
00364 sprintf(str, "i_%d", offset);
00365 return str;
00366 }
00367
00368 astNode* temps() {
00369 PrintTemps p;
00370 p.decode(method(), this);
00371 if (p.elements->length() == 0) return NULL;
00372 listNode* l = new listNode("|", "|");
00373 for(int index = 0; index < p.elements->length(); index++)
00374 l->add(p.elements->at(index));
00375 return l;
00376 }
00377
00378 astNode* params() {
00379 PrintParams p;
00380 p.decode(method(), this);
00381 if (p.elements->length() == 0) return NULL;
00382
00383 listNode* l = new listNode(NULL, "|");
00384 for(int index = 0; index < p.elements->length(); index++) {
00385 l->add(p.elements->at(index));
00386 }
00387 return l;
00388 }
00389
00390 astNode* heap_temp_at(int no) {
00391 char* name = heap_temp_string(0, no, 0);
00392 if (!fr()) return new nameNode(name);
00393 char* value = fr()->context_temp_at(no)->print_value_string();
00394 return new nameValueNode(name, value);
00395 }
00396
00397 astNode* stack_temp_at(int no) {
00398 byteArrayOop res = find_stack_temp(method(), 0, no);
00399 char* name = res ? res->as_string() : create_name("t", no);
00400 if (!fr()) return new nameNode(name);
00401 char* value = fr()->temp_at(no)->print_value_string();
00402 return new nameValueNode(name, value);
00403 }
00404
00405 astNode* parameter_at(int index, bool in_block = false) {
00406 char* name = param_string(index, in_block);
00407 if (!fr()) return new nameNode(name);
00408 char* value = fr()->argument_at(index)->print_value_string();
00409 return new nameValueNode(name, value);
00410 }
00411
00412 void print_frame_header(prettyPrintStream* output) {
00413 char num[10];
00414 output->newline();
00415 output->print("#");
00416 sprintf(num, "%d", frame_index);
00417 output->print(num);
00418 output->print(", receiver \"");
00419 output->print(fr()->receiver()->print_value_string());
00420 output->print("\"");
00421
00422 if (!method()->is_blockMethod()) {
00423 klassOop method_holder = fr()->receiver()->klass()->klass_part()->lookup_method_holder_for(method());
00424 if (method_holder && (method_holder != fr()->receiver()->klass())) {
00425 output->print(", method holder \"");
00426 output->print(method_holder->print_value_string());
00427 output->print("\"");
00428 }
00429 }
00430 output->newline();
00431
00432 print_method_header(output);
00433
00434 if (ActivationShowBCI) {
00435
00436 output->print(" [bci = ");
00437 sprintf(num, "%d", _hot_bci);
00438 output->print(num);
00439 output->print("]");
00440 output->newline();
00441 }
00442
00443 if (ActivationShowExpressionStack) {
00444
00445 GrowableArray<oop>* stack = fr()->expression_stack();
00446 if (stack->length() > 0) {
00447 output->print(" [expression stack:");
00448 output->newline();
00449 GrowableArray<oop>* stack = fr()->expression_stack();
00450 for (int index = 0; index < stack->length(); index++) {
00451 output->print(" - ");
00452 stack->at(index)->print_value();
00453 output->newline();
00454 }
00455 output->print(" ]");
00456 output->newline();
00457 }
00458 }
00459
00460 if (ActivationShowContext) {
00461
00462 contextOop con = NULL;
00463 if (fr()->is_interpreted_frame()) {
00464 con = ((interpretedVFrame*) fr())->interpreter_context();
00465 } else if (fr()->is_deoptimized_frame()) {
00466 con = ((deoptimizedVFrame*) fr())->deoptimized_context();
00467 } else if (fr()->is_compiled_frame()) {
00468 con = ((compiledVFrame*) fr())->compiled_context();
00469 }
00470 if (con) con->print();
00471 }
00472 }
00473
00474 void print_header(prettyPrintStream* output) {
00475 if (fr()) {
00476 print_frame_header(output);
00477 } else {
00478 print_method_header(output);
00479 }
00480 }
00481
00482 void print_method_header(prettyPrintStream* output) {
00483 GrowableArray<astNode*>* arguments = new GrowableArray<astNode*>(10);
00484 for (int i = method()->number_of_arguments()-1; i >= 0; i--) {
00485 arguments->push(parameter_at(i));
00486 }
00487 print_selector_with_arguments(output, method()->selector(), arguments, false);
00488 }
00489 };
00490
00491
00492 paramNode::paramNode(int bci, scopeNode* scope, int no) : leafNode(bci, scope) {
00493 this->no = no;
00494 this->str = scope->param_string(no);
00495 }
00496
00497
00498 PrintWrapper::PrintWrapper(astNode* t, prettyPrintStream* output) {
00499 this->t = t;
00500 this->output = output;
00501 this->hit = false;
00502 if(!t->this_scope()) return;
00503 if (t->this_bci() == t->this_scope()->hot_bci() && !output->in_highlight()) {
00504 output->begin_highlight();
00505 hit = true;
00506 }
00507 }
00508
00509
00510 PrintWrapper::~PrintWrapper() {
00511 if (hit) output->end_highlight();
00512 }
00513
00514
00515 bool astNode::print(prettyPrintStream* output) {
00516 if (ActivationShowNameDescs) {
00517 if (scope && scope->sd()) {
00518 NameDesc* nd = scope->sd()->exprStackElem(bci);
00519 if (nd) nd->print();
00520 }
00521 }
00522 return false;
00523 }
00524
00525
00526 void astNode::top_level_print(prettyPrintStream* output) {
00527 scope->print_header(output);
00528 print(output);
00529 }
00530
00531
00532 class codeNode : public astNode {
00533 protected:
00534 GrowableArray<astNode*>* statements;
00535 public:
00536 codeNode(int bci, scopeNode* scope) : astNode(bci, scope) {
00537 statements = new GrowableArray<astNode*>(10);
00538 }
00539
00540 void add(astNode* statement) {
00541 statements->push(statement);
00542 }
00543
00544 bool print(prettyPrintStream* output);
00545 bool is_code() { return true; }
00546
00547 statement* last_statement() {
00548 if (statements->length() > 0) {
00549 assert(statements->at(statements->length() - 1)->is_statement(), "must be statement");
00550 return (statement*) statements->at(statements->length() - 1);
00551 }
00552 return NULL;
00553 }
00554
00555 int width(prettyPrintStream* output) {
00556 int len = statements->length();
00557 if (len == 0) return 0;
00558 if (len == 1) return statements->at(0)->width(output);
00559 return output->infinity();
00560 }
00561 };
00562
00563
00564 class inlinedBlockNode : public codeNode {
00565 public:
00566 inlinedBlockNode(int bci, scopeNode* scope) : codeNode(bci, scope) {}
00567
00568 void add(astNode* statement) {
00569 statements->push(statement);
00570 }
00571
00572 bool print(prettyPrintStream* output) {
00573 bool split = output->remaining() < width(output);
00574 output->print("[");
00575 if (split) output->inc_newline();
00576 codeNode::print(output);
00577 if (split) output->dec_indent();
00578 output->print("]");
00579 return split;
00580 }
00581
00582 int width(prettyPrintStream* output) {
00583 return output->width_of_string("[")
00584 + codeNode::width(output)
00585 + output->width_of_string("]");
00586 }
00587 };
00588
00589
00590 class statement : public astNode {
00591 private:
00592 bool has_return;
00593 astNode* stat;
00594 char* hat() { return "^"; }
00595 public:
00596
00597 bool is_statement() { return true; }
00598
00599 statement(int bci, scopeNode* scope, astNode* stat, bool has_return) : astNode(bci, scope) {
00600 this->stat = stat;
00601 this->has_return = has_return;
00602 }
00603
00604 void set_return() { has_return = true; }
00605 bool has_hat() { return has_return; }
00606
00607 bool print(prettyPrintStream* output) {
00608 HIGHLIGHT
00609 if (has_return) output->print(hat());
00610 return stat->print(output);
00611 }
00612 int width(prettyPrintStream* output) {
00613 return (has_return ? output->width_of_string(hat()) : 0)
00614 + stat->width(output);
00615 }
00616 };
00617
00618
00619 bool codeNode::print(prettyPrintStream* output) {
00620 bool first = true;
00621 for (int index = 0; index < statements->length(); index++) {
00622 astNode* s = statements->at(index);
00623 if (!first) {
00624 output->print(".");
00625 output->newline();
00626 }
00627 s->print(output);
00628 if (s->is_statement() && ((statement*)s)->has_hat()) break;
00629 first = false;
00630 }
00631 return true;
00632 }
00633
00634
00635 class methodNode : public codeNode {
00636 public:
00637 methodNode(int bci, scopeNode* scope) : codeNode(bci, scope) {}
00638
00639 bool print(prettyPrintStream* output) {
00640 output->inc_indent();
00641 output->indent();
00642
00643 astNode* l = scope->temps();
00644 if (l) {
00645 l->print(output);
00646 output->newline();
00647 }
00648 codeNode::print(output);
00649 output->dec_newline();
00650 return true;
00651 }
00652 };
00653
00654
00655 class blockNode : public codeNode {
00656 private:
00657 int numOfArgs;
00658 public:
00659 blockNode(int bci, scopeNode* scope, int numOfArgs)
00660 : codeNode(bci, scope) {
00661 this->numOfArgs = numOfArgs;
00662 }
00663
00664 bool print(prettyPrintStream* output) {
00665 HIGHLIGHT
00666 bool split = false;
00667 output->print("[");
00668 astNode* p = scope->params();
00669 if (p) {
00670 if (split = output->remaining() < p->width(output) + output->width_of_space()) {
00671 output->inc_newline();
00672 p->print(output);
00673 output->newline();
00674 }
00675 if (!split) {
00676 output->space();
00677 p->print(output);
00678 }
00679 }
00680
00681 astNode* l = scope->temps();
00682 if (l) {
00683 if (!split) {
00684 if(output->remaining() >= l->width(output) + output->width_of_space()) {
00685 output->space();
00686 l->print(output);
00687 } else {
00688 output->inc_newline();
00689 split = true;
00690 }
00691 }
00692 if (split) {
00693 l->print(output);
00694 output->newline();
00695 }
00696 }
00697
00698 if (!split) {
00699 if(output->remaining() >= codeNode::width(output)) {
00700 if (l || p) output->space();
00701 codeNode::print(output);
00702 } else {
00703 output->inc_newline();
00704 split = true;
00705 }
00706 }
00707 if (split) {
00708 codeNode::print(output);
00709 }
00710 output->print("]");
00711 if (split) output->dec_indent();
00712 return split;
00713 }
00714
00715 int width(prettyPrintStream* output) {
00716 int w = output->width_of_string("[") + output->width_of_string("]");
00717 astNode* p = scope->params();
00718 if (p) w += p->width(output) + 2 * output->width_of_space();
00719 astNode* t = scope->temps();
00720 if (t) w += t->width(output) + output->width_of_space();
00721 w += codeNode::width(output);
00722 return w;
00723 }
00724
00725 };
00726
00727
00728 class assignment : public astNode {
00729 private:
00730 astNode* variable;
00731 astNode* e;
00732 char* sym() { return ":="; }
00733 public:
00734 assignment(int bci, scopeNode* scope, astNode* variable, astNode* e) : astNode(bci, scope) {
00735 this->variable = variable;
00736 this->e = e;
00737 }
00738 bool print(prettyPrintStream* output) {
00739 HIGHLIGHT
00740 bool split = output->remaining() < width(output);
00741 variable->print(output);
00742 output->space(); output->print(sym());
00743 astNode::print(output);
00744 if (split) output->inc_newline();
00745 else output->space();
00746 e->print(output);
00747 if (split) output->dec_indent();
00748 return split;
00749 }
00750 int width(prettyPrintStream* output) {
00751 return variable->width(output)
00752 + 2 * output->width_of_space()
00753 + output->width_of_string(sym());
00754 }
00755 };
00756
00757
00758 class messageNode : public astNode {
00759 private:
00760 astNode* _receiver;
00761 symbolOop selector;
00762 GrowableArray<astNode*>* arguments;
00763 bool _is_prim;
00764 public:
00765 messageNode(int bci, scopeNode* scope, symbolOop selector, bool is_prim = false) : astNode(bci, scope) {
00766 this->selector = selector;
00767 arguments = new GrowableArray<astNode*>(10);
00768 _receiver = NULL;
00769 _is_prim = is_prim;
00770 }
00771
00772 bool is_unary() { return selector->is_unary(); }
00773 bool is_binary() { return selector->is_binary(); }
00774 bool is_keyword() { return selector->is_keyword(); }
00775
00776 bool should_wrap_receiver() {
00777 if (receiver() && receiver()->is_message()) {
00778 if (((messageNode*)_receiver)->is_keyword()) return true;
00779 if (((messageNode*)_receiver)->is_binary() && is_binary()) return true;
00780 }
00781 return false;
00782 }
00783
00784 bool should_wrap_argument(astNode* arg) {
00785 if (arg->is_message()) {
00786 if (((messageNode*)arg)->is_keyword()) return true;
00787 if (((messageNode*)arg)->is_binary() && is_binary()) return true;
00788 }
00789 return false;
00790 }
00791
00792 bool print_receiver(prettyPrintStream* output) {
00793 bool wrap = should_wrap_receiver();
00794 if (wrap) output->print("(");
00795 _receiver->print(output);
00796 if (wrap) output->print(")");
00797 output->print(" ");
00798 return false;
00799 }
00800
00801 bool real_print(prettyPrintStream* output) {
00802 HIGHLIGHT
00803 bool split;
00804 if (_is_prim) output->print("{{");
00805 if (valid_receiver()) print_receiver(output);
00806 if (output->remaining() < width_send(output)) {
00807 output->inc_newline();
00808 astNode::print(output);
00809 split = print_selector_with_arguments(output, selector, arguments, true);
00810 if (_is_prim) output->print("}}");
00811 output->dec_indent();
00812 return split;
00813 }
00814 split = print_selector_with_arguments(output, selector, arguments, false);
00815 if (_is_prim) output->print("}}");
00816 return split;
00817 }
00818
00819 bool print(prettyPrintStream* output) {
00820 if(receiver() && receiver()->is_cascade()) return receiver()->print(output);
00821 return real_print(output);
00822 }
00823
00824 int width_receiver(prettyPrintStream* output) {
00825 int w = receiver() ? receiver()->width(output) + output->width_of_space() : 0;
00826 if (should_wrap_receiver()) {
00827 w += output->width_of_string("(") + output->width_of_string(")");
00828 }
00829 return w;
00830 }
00831
00832 int width_send(prettyPrintStream* output) {
00833 int arg = selector->number_of_arguments();
00834 int w = output->width_of_string(selector->as_string())
00835 + arg * output->width_of_space();
00836 for (int index = 0; index < arguments->length(); index++)
00837 w += arguments->at(index)->width(output);
00838 return w;
00839 }
00840
00841 int real_width(prettyPrintStream* output) {
00842 return (receiver() ? width_receiver(output) + output->width_of_space() : 0)
00843 + width_send(output);
00844 }
00845
00846 int width(prettyPrintStream* output) {
00847 if(receiver() && receiver()->is_cascade()) return receiver()->width(output);
00848 return real_width(output);
00849 }
00850
00851 void add_param(astNode* p) { arguments->push(p); }
00852 void set_receiver(astNode* p);
00853
00854 astNode* receiver() { return _receiver; }
00855
00856 bool valid_receiver() {
00857 return receiver() ? !receiver()->is_cascade() : false;
00858 }
00859
00860 bool is_message() { return true; }
00861 };
00862
00863
00864 class selfNode : public leafNode {
00865 public:
00866 selfNode(int bci, scopeNode* scope) : leafNode(bci, scope) {}
00867 char* string() { return "self"; }
00868 };
00869
00870
00871 class ignoreReceiver : public leafNode {
00872 public:
00873 ignoreReceiver(int bci, scopeNode* scope) : leafNode(bci, scope) {}
00874 char* string() { return ""; }
00875 };
00876
00877
00878 class superNode : public leafNode {
00879 public:
00880 superNode(int bci, scopeNode* scope) : leafNode(bci, scope) {}
00881 char* string() { return "super"; }
00882 };
00883
00884
00885 class literalNode : public leafNode {
00886 private:
00887 char* str;
00888 public:
00889 literalNode(int bci, scopeNode* scope, char* str) : leafNode(bci, scope) {
00890 this->str = str;
00891 }
00892 char* string() { return str; }
00893 };
00894
00895
00896 class symbolNode : public astNode {
00897 private:
00898 symbolOop value;
00899 bool is_outer;
00900 char* str;
00901 public:
00902 symbolNode(int bci, scopeNode* scope, symbolOop value, bool is_outer = true)
00903 : astNode(bci, scope) {
00904 this->value = value;
00905 this->is_outer = is_outer;
00906 this->str = value->as_string();
00907 }
00908 bool print(prettyPrintStream* output) {
00909 astNode::print(output);
00910 if (is_outer) output->print("#");
00911 output->print(str);
00912 return false;
00913 }
00914 int width(prettyPrintStream* output) {
00915 return (is_outer ? output->width_of_string("#") : 0)
00916 + output->width_of_string(str);
00917 }
00918 };
00919
00920
00921 class doubleByteArrayNode : public astNode {
00922 private:
00923 doubleByteArrayOop value;
00924 char* str;
00925 public:
00926 doubleByteArrayNode(int bci, scopeNode* scope, doubleByteArrayOop value)
00927 : astNode(bci, scope) {
00928 this->value = value;
00929 this->str = value->as_string();
00930 }
00931 bool print(prettyPrintStream* output) {
00932 astNode::print(output);
00933 output->print("'");
00934 output->print(str);
00935 output->print("'");
00936 return false;
00937 }
00938 int width(prettyPrintStream* output) {
00939 return 2 * output->width_of_string("'")
00940 + output->width_of_string(str);
00941 }
00942 };
00943
00944
00945 class byteArrayNode : public astNode {
00946 private:
00947 byteArrayOop value;
00948 char* str;
00949 public:
00950 byteArrayNode(int bci, scopeNode* scope, byteArrayOop value)
00951 : astNode(bci, scope) {
00952 this->value = value;
00953 this->str = value->as_string();
00954 }
00955 bool print(prettyPrintStream* output) {
00956 HIGHLIGHT
00957 astNode::print(output);
00958 output->print("'");
00959 output->print(str);
00960 output->print("'");
00961 return false;
00962 }
00963 int width(prettyPrintStream* output) {
00964 return 2 * output->width_of_string("'")
00965 + output->width_of_string(str);
00966 }
00967 };
00968
00969
00970 class smiNode : public leafNode {
00971 private:
00972 int value;
00973 char* str;
00974 public:
00975 smiNode(int bci, scopeNode* scope, int value)
00976 : leafNode(bci, scope) {
00977 this->value = value;
00978 this->str = NEW_RESOURCE_ARRAY(char, 10);
00979 sprintf(this->str, "%d", value);
00980 }
00981 char* string() { return str; }
00982 };
00983
00984 class doubleNode : public leafNode {
00985 private:
00986 double value;
00987 char* str;
00988 public:
00989 doubleNode(int bci, scopeNode* scope, double value)
00990 : leafNode(bci, scope) {
00991 this->value = value;
00992 this->str = NEW_RESOURCE_ARRAY(char, 30);
00993 sprintf(this->str, "%1.10gd", value);
00994 }
00995 char* string() { return str; }
00996 };
00997
00998
00999 class characterNode : public leafNode {
01000 private:
01001 oop value;
01002 char* str;
01003 public:
01004 characterNode(int bci, scopeNode* scope, oop value)
01005 : leafNode(bci, scope) {
01006 this->value = value;
01007 this->str = NEW_RESOURCE_ARRAY(char, 3);
01008 if (value->is_mem()) {
01009 oop ch = memOop(value)->instVarAt(2);
01010 if(ch->is_smi()) {
01011 sprintf(this->str, "$%c", smiOop(ch)->value());
01012 return;
01013 }
01014 }
01015 this->str = "$%c";
01016 }
01017 char* string() { return str; }
01018 };
01019
01020
01021 class objArrayNode : public astNode {
01022 private:
01023 objArrayOop value;
01024 bool is_outer;
01025 GrowableArray<astNode*>* elements;
01026 public:
01027 objArrayNode(int bci, scopeNode* scope, objArrayOop value, bool is_outer = true)
01028 : astNode(bci, scope) {
01029 this->value = value;
01030 this->is_outer = is_outer;
01031 this->elements = new GrowableArray<astNode*>(10);
01032 for (int index = 1; index <= value->length(); index++)
01033 elements->push(get_literal_node(value->obj_at(index), bci, scope));
01034 }
01035 bool print(prettyPrintStream* output) {
01036 HIGHLIGHT
01037 astNode::print(output);
01038 output->print("#(");
01039 for (int index = 0; index < elements->length(); index++) {
01040 elements->at(index)->print(output);
01041 if (index < elements->length() -1) output->space();
01042 }
01043 output->print(")");
01044 return false;
01045 }
01046 int width(prettyPrintStream* output) {
01047 int w = output->width_of_string("#(") + output->width_of_string(")");
01048 for (int index = 0; index < elements->length(); index++) {
01049 w += elements->at(index)->width(output);
01050 if (index < elements->length() -1)
01051 w += output->width_of_space();
01052 }
01053 return 0;
01054 }
01055 };
01056
01057
01058 class dllNode : public astNode {
01059 private:
01060 astNode* dll_name;
01061 astNode* func_name;
01062 GrowableArray<astNode*>* arguments;
01063 astNode* proxy;
01064 public:
01065 dllNode(int bci, scopeNode* scope, symbolOop dll_name, symbolOop func_name)
01066 : astNode(bci, scope) {
01067 this->dll_name = new symbolNode(bci,scope,dll_name,false);
01068 this->func_name = new symbolNode(bci,scope,func_name,false);
01069 arguments = new GrowableArray<astNode*>(10);
01070 proxy = NULL;
01071 }
01072
01073 void add_param(astNode* param) { arguments->push(param); }
01074
01075 void set_proxy(astNode* p) { proxy = p; }
01076
01077 bool print(prettyPrintStream* output) {
01078 HIGHLIGHT
01079 astNode::print(output);
01080 output->print("{{<");
01081 dll_name->print(output);
01082 output->space();
01083 proxy->print(output);
01084 output->space();
01085 func_name->print(output);
01086 output->print(">");
01087 for (int index = arguments->length() - 1; index >= 0 ; index--) {
01088 arguments->at(index)->print(output);
01089 if (index < arguments->length() -1) output->print(", ");
01090 }
01091 output->print("}}");
01092 return false;
01093 }
01094
01095 int width(prettyPrintStream* output) {
01096 return output->width_of_string("<")
01097 + output->width_of_string("Printing dll call")
01098 + output->width_of_string(">");
01099 }
01100 };
01101
01102
01103 class stackTempNode : public leafNode {
01104 private:
01105 int offset;
01106 char* str;
01107 public:
01108 stackTempNode(int bci, scopeNode* scope, int offset) : leafNode(bci, scope) {
01109 this->offset = offset;
01110 this->str = scope->stack_temp_string(this_bci(), offset);
01111 }
01112 char* string() { return str; }
01113 };
01114
01115
01116 class heapTempNode : public leafNode {
01117 private:
01118 int offset;
01119 int context_level;
01120 char* str;
01121 public:
01122 heapTempNode(int bci, scopeNode* scope, int offset, int context_level) : leafNode(bci, scope) {
01123 this->offset = offset;
01124 this->context_level = context_level;
01125 this->str = scope->heap_temp_string(this_bci(), offset, context_level);
01126 }
01127 char* string() { return str; }
01128 };
01129
01130 class floatNode : public leafNode {
01131 private:
01132 char* str;
01133 public:
01134 floatNode(int no, int bci, scopeNode* scope)
01135 : leafNode(bci, scope) {
01136 this->str = scope->stack_temp_string(this_bci(), no);
01137 }
01138 char* string() { return str; }
01139 };
01140
01141
01142 class instVarNode : public leafNode {
01143 private:
01144 oop obj;
01145 char* str;
01146 public:
01147 instVarNode(int bci, scopeNode* scope, oop obj) : leafNode(bci, scope) {
01148 this->obj = obj;
01149 if (obj->is_smi()) {
01150 str = scope->inst_var_string(smiOop(obj)->value());
01151 } else {
01152 str = symbolOop(obj)->as_string();
01153 }
01154 }
01155 char* string() { return str; }
01156 };
01157
01158
01159 class classVarNode : public leafNode {
01160 private:
01161 oop obj;
01162 char* str;
01163 public:
01164 classVarNode(int bci, scopeNode* scope, oop obj) : leafNode(bci, scope) {
01165 this->obj = obj;
01166 if (obj->is_association()) {
01167 str = associationOop(obj)->key()->as_string();
01168 } else {
01169 str = symbolOop(obj)->as_string();
01170 }
01171 }
01172 char* string() { return str; }
01173 };
01174
01175
01176 class primitiveResultNode : public leafNode {
01177 public:
01178 bool is_primitive_result() { return true; }
01179 primitiveResultNode(int bci, scopeNode* scope)
01180 : leafNode(bci, scope) { }
01181 char* string() { return "`primitive result`"; }
01182 };
01183
01184
01185 class assocNode : public leafNode {
01186 private:
01187 associationOop assoc;
01188 char* str;
01189 public:
01190 assocNode(int bci, scopeNode* scope, associationOop assoc)
01191 : leafNode(bci, scope) {
01192 this->assoc = assoc;
01193 this->str = assoc->key()->as_string();
01194 }
01195 char* string() { return str; }
01196 };
01197
01198
01199 class cascadeSendNode : public astNode {
01200 private:
01201 GrowableArray<messageNode*>* messages;
01202 astNode* receiver;
01203 public:
01204 cascadeSendNode(int bci, scopeNode* scope, messageNode* first) : astNode(bci, scope) {
01205 messages = new GrowableArray<messageNode*>(10);
01206 receiver = first->receiver();
01207 first->set_receiver(this);
01208 }
01209
01210 bool is_cascade() { return true; }
01211
01212 void add_message(messageNode* m) {
01213 messages->push(m);
01214 }
01215
01216 bool print(prettyPrintStream* output) {
01217 receiver->print(output);
01218 output->inc_newline();
01219 for (int i = 0; i < messages->length(); i++) {
01220 if (i == 0) output->print(" ");
01221 else output->print("; ");
01222 messages->at(i)->real_print(output);
01223 if (i != messages->length() - 1) output->newline();
01224 }
01225 output->dec_indent();
01226 return true;
01227 }
01228 int width(prettyPrintStream* output) {
01229 return 0;
01230 }
01231 };
01232
01233
01234 void messageNode::set_receiver(astNode* p) {
01235 if (p->is_cascade()) {
01236 ((cascadeSendNode*)p)->add_message(this);
01237 }
01238 _receiver = p;
01239 }
01240
01241
01242 static astNode* get_literal_node(oop obj, int bci, scopeNode* scope) {
01243 if (obj == trueObj) return new literalNode(bci, scope, "true");
01244 if (obj == falseObj) return new literalNode(bci, scope, "false");
01245 if (obj == nilObj) return new literalNode(bci, scope, "nil");
01246 if (obj->is_doubleByteArray()) return new doubleByteArrayNode(bci, scope, doubleByteArrayOop(obj));
01247 if (obj->is_symbol()) return new symbolNode(bci, scope, symbolOop(obj));
01248 if (obj->is_byteArray()) return new byteArrayNode(bci, scope, byteArrayOop(obj));
01249 if (obj->is_smi()) return new smiNode(bci, scope, smiOop(obj)->value());
01250 if (obj->is_double()) return new doubleNode(bci, scope, doubleOop(obj)->value());
01251 if (obj->is_objArray()) return new objArrayNode(bci, scope, objArrayOop(obj));
01252 return new characterNode(bci, scope, obj);
01253 }
01254
01255 void prettyPrintStream::print() { std->print("pretty-printer stream"); }
01256
01257 void defaultPrettyPrintStream::indent() {
01258 for (int i = 0; i < indentation; i++) {
01259 space(); space();
01260 }
01261 }
01262 void defaultPrettyPrintStream::print(char* str) {
01263 for (int i = 0; str[i]; i++)
01264 print_char(str[i]);
01265 }
01266 void defaultPrettyPrintStream::print_char(char c) {
01267 std->print("%c", c);
01268 pos += width_of_char(c);
01269 }
01270 int defaultPrettyPrintStream::width_of_string(char* str) {
01271 int w = 0;
01272 for (int i = 0; str[i]; i++)
01273 w += width_of_char(str[i]);
01274 return w;
01275 }
01276 void defaultPrettyPrintStream::space() { print_char(' '); }
01277 void defaultPrettyPrintStream::newline() {
01278 print_char('\n');
01279 pos = 0;
01280 indent();
01281 }
01282 void defaultPrettyPrintStream::begin_highlight() { set_highlight(true); print("{"); }
01283 void defaultPrettyPrintStream::end_highlight() { set_highlight(false); print("}"); }
01284
01285 void byteArrayPrettyPrintStream::newline() {
01286 print_char('\r');
01287 pos = 0;
01288 indent();
01289 }
01290
01291
01292 astNode* generateForBlock(methodOop method, klassOop klass, int bci, int numOfArgs);
01293
01294 class MethodPrettyPrinter : public MethodClosure {
01295 private:
01296 GrowableArray<astNode*>* _stack;
01297 scopeNode* _scope;
01298
01299
01300 void normal_send(symbolOop selector, bool is_prim = false);
01301
01302 void special_send(astNode* receiver, symbolOop selector, bool is_prim = false);
01303
01304 astNode* generateInlineBlock(MethodInterval* interval, bool produces_result, astNode* push_elem = NULL);
01305 void store(astNode* node) { _push(new assignment(bci(), scope(), node, _pop())); }
01306
01307 public:
01308 void _push(astNode* node) { _stack->push(node); }
01309 astNode* _pop() { return _stack->pop(); }
01310 astNode* _top() { return _stack->top(); }
01311 int _size() const { return _stack->length(); }
01312 scopeNode* scope() const { return _scope; }
01313
01314
01315 MethodPrettyPrinter(scopeNode* scope);
01316
01317
01318 void if_node(IfNode* node);
01319 void cond_node(CondNode* node);
01320 void while_node(WhileNode* node);
01321 void primitive_call_node(PrimitiveCallNode* node);
01322 void dll_call_node(DLLCallNode* node);
01323
01324
01325 void pop();
01326 void method_return(int nofArgs);
01327 void nonlocal_return(int nofArgs);
01328
01329 void allocate_closure(AllocationType type, int nofArgs, methodOop meth) {
01330 if (type == tos_as_scope) _pop();
01331 _push(generateForBlock(meth, scope()->get_klass(), -1, nofArgs));
01332 }
01333 void allocate_context(int nofTemps, bool forMethod) {
01334 scope()->context_allocated();
01335 }
01336
01337
01338 void normal_send(InterpretedIC* ic) { normal_send(ic->selector()); }
01339 void self_send(InterpretedIC* ic) { special_send(new selfNode(bci(), scope()), ic->selector()); }
01340 void super_send(InterpretedIC* ic) { special_send(new superNode(bci(), scope()), ic->selector()); }
01341 void double_equal() { normal_send(vmSymbols::double_equal()); }
01342 void double_not_equal() { normal_send(vmSymbols::double_tilde()); }
01343
01344
01345 void push_self() { _push(new selfNode(bci(), scope())); }
01346 void push_tos() { _push(_top()); }
01347 void push_literal(oop obj) { _push(get_literal_node(obj, bci(), scope())); }
01348 void push_argument(int no) { _push(new paramNode(bci(), scope(), no)); }
01349 void push_temporary(int no) { _push(new stackTempNode(bci(), scope(), no)); }
01350 void push_temporary(int no, int context) { _push(new heapTempNode(bci(), scope(), no, context)); }
01351 void push_instVar(int offset) { _push(new instVarNode(bci(), scope(), as_smiOop(offset))); }
01352 void push_instVar_name(symbolOop name) { _push(new instVarNode(bci(), scope(), name)); }
01353 void push_classVar(associationOop assoc) { _push(new classVarNode(bci(), scope(), assoc)); }
01354 void push_classVar_name(symbolOop name) { _push(new classVarNode(bci(), scope(), name)); }
01355 void push_global(associationOop obj) { _push(new assocNode(bci(), scope(), obj)); }
01356 void store_temporary(int no) { store(new stackTempNode(bci(), scope(), no)); }
01357 void store_temporary(int no, int context) { store(new heapTempNode(bci(), scope(), no, context)); }
01358 void store_instVar(int offset) { store(new instVarNode(bci(), scope(), as_smiOop(offset))); }
01359 void store_instVar_name(symbolOop name) { store(new instVarNode(bci(), scope(), name)); }
01360 void store_classVar(associationOop assoc) { store(new classVarNode(bci(), scope(), assoc)); }
01361 void store_classVar_name(symbolOop name) { store(new classVarNode(bci(), scope(), name)); }
01362 void store_global(associationOop obj) { store(new assocNode(bci(), scope(), obj)); }
01363
01364
01365 void allocate_temporaries(int nofTemps) {}
01366 void set_self_via_context() {}
01367 void copy_self_into_context() {}
01368 void copy_argument_into_context(int argNo, int no) {}
01369 void zap_scope() {}
01370 void predict_prim_call(primitive_desc* pdesc, int failure_start) {}
01371
01372 void float_allocate(int nofFloatTemps, int nofFloatExprs) {}
01373 void float_floatify(Floats::Function f, int tof) {
01374 normal_send(Floats::selector_for(f));
01375 pop();
01376 }
01377 void float_move(int tof, int from) {
01378 _push(new floatNode(from, bci(), scope()));
01379 store(new floatNode(tof, bci(), scope()));
01380 pop();
01381 }
01382 void float_set(int tof, doubleOop value) {}
01383 void float_nullary(Floats::Function f, int tof) {}
01384 void float_unary(Floats::Function f, int tof) {
01385 _push(new floatNode(tof, bci(), scope()));
01386 normal_send(Floats::selector_for(f));
01387 pop();
01388 }
01389 void float_binary(Floats::Function f, int tof) {
01390 _push(new floatNode(tof-1, bci(), scope()));
01391 _push(new floatNode(tof, bci(), scope()));
01392 normal_send(Floats::selector_for(f));
01393 pop();
01394 }
01395
01396 void float_unaryToOop(Floats::Function f, int tof) {
01397 _push(new floatNode(tof, bci(), scope()));
01398 normal_send(Floats::selector_for(f));
01399 }
01400
01401 void float_binaryToOop(Floats::Function f, int tof) {
01402 _push(new floatNode(tof, bci(), scope()));
01403 _push(new floatNode(tof-1, bci(), scope()));
01404 normal_send(Floats::selector_for(f));
01405 }
01406 };
01407
01408
01409 MethodPrettyPrinter::MethodPrettyPrinter(scopeNode* scope) {
01410 _stack = new GrowableArray<astNode*>(10);
01411 _scope = scope;
01412 if (scope->method()->is_blockMethod())
01413 _push(new blockNode(1, scope, scope->method()->number_of_arguments()));
01414 else
01415 _push(new methodNode(1, scope));
01416 }
01417
01418
01419 void MethodPrettyPrinter::normal_send(symbolOop selector, bool is_prim) {
01420 int nargs = selector->number_of_arguments();
01421 messageNode* msg = new messageNode(bci(), scope(), selector, is_prim);
01422
01423 GrowableArray<astNode*>* arguments = new GrowableArray<astNode*>(10);
01424 for (int index = 0; index < nargs; index++)
01425 arguments->push(_pop());
01426
01427 for (index = 0; index < nargs; index++)
01428 msg->add_param(arguments->at(index));
01429
01430 msg->set_receiver(_pop());
01431
01432 _push(msg);
01433 }
01434
01435
01436 void MethodPrettyPrinter::special_send(astNode* receiver, symbolOop selector, bool is_prim) {
01437 int nargs = selector->number_of_arguments();
01438 messageNode* msg = new messageNode(bci(), scope(), selector, is_prim);
01439
01440 GrowableArray<astNode*>* arguments = new GrowableArray<astNode*>(10);
01441 for (int index = 0; index < nargs; index++)
01442 arguments->push(_pop());
01443
01444 for (index = 0; index < nargs; index++)
01445 msg->add_param(arguments->at(index));
01446
01447 msg->set_receiver(receiver);
01448
01449 _push(msg);
01450 }
01451
01452
01453 void MethodPrettyPrinter::pop() {
01454
01455 astNode* expr = _pop();
01456 astNode* code = _top();
01457
01458 if (code->is_code()) {
01459 code->add(new statement(bci(), scope(), expr, false));
01460 return;
01461 }
01462
01463 if (expr->is_message()) {
01464
01465
01466
01467
01468
01469 if (!_top()->is_cascade()) {
01470 _pop();
01471 _push(new cascadeSendNode(bci(), scope(), (messageNode*) expr));
01472 }
01473 } else {
01474 _pop();
01475 _push(expr);
01476 }
01477 }
01478
01479
01480 void MethodPrettyPrinter::method_return(int nofArgs) {
01481
01482 if (_size() == 1) {
01483
01484 astNode* code = _top();
01485 ((codeNode*) code)->last_statement()->set_return();
01486 } else {
01487 astNode* expr = _pop();
01488 astNode* code = _top();
01489 if (code->is_code()) {
01490 code->add(new statement(bci(), scope(), expr, !scope()->is_block_method()));
01491 } else {
01492 fatal1("Stack size = %d", _size());
01493 }
01494 }
01495 }
01496
01497
01498 void MethodPrettyPrinter::nonlocal_return(int nofArgs) {
01499
01500 astNode* expr = _pop();
01501 astNode* code = _top();
01502 if (code->is_code()) {
01503 ((codeNode*) code)->add(new statement(bci(), scope(), expr, true));
01504 } else {
01505 fatal1("Stack size = %d", _size());
01506 }
01507 }
01508
01509
01510 class StackChecker {
01511 public:
01512 MethodPrettyPrinter* pp;
01513 int size;
01514 char* name;
01515 int offset;
01516
01517 StackChecker(char* name, MethodPrettyPrinter* pp, int offset = 0) {
01518 this->pp = pp;
01519 this->size = pp->_size();
01520 this->name = name;
01521 this->offset = offset;
01522 }
01523
01524 ~StackChecker() {
01525 if (pp->_size() != size + offset) {
01526 std->print_cr("StackTracer found misaligned stack");
01527 std->print_cr("Expecting %d but found %d", size + offset, pp->_size());
01528 fatal("aborting");
01529 }
01530 }
01531 };
01532
01533
01534 astNode* MethodPrettyPrinter::generateInlineBlock(MethodInterval* interval, bool produces_result, astNode* push_elem) {
01535 inlinedBlockNode* block = new inlinedBlockNode(bci(), scope());
01536 _push(block);
01537 if (push_elem) _push(push_elem);
01538 MethodIterator mi(interval, this);
01539 if (produces_result) pop();
01540 return _pop();
01541 }
01542
01543
01544 void MethodPrettyPrinter::if_node(IfNode* node) {
01545 _push(generateInlineBlock(node->then_code(), node->produces_result()));
01546 if (node->else_code()) {
01547 _push(generateInlineBlock(node->else_code(), node->produces_result()));
01548 }
01549 normal_send(node->selector());
01550 if (!node->produces_result()) pop();
01551 }
01552
01553
01554 void MethodPrettyPrinter::cond_node(CondNode* node) {
01555 _push(generateInlineBlock(node->expr_code(), true));
01556 normal_send(node->selector());
01557 }
01558
01559
01560 void MethodPrettyPrinter::while_node(WhileNode* node) {
01561 _push(generateInlineBlock(node->expr_code(), true));
01562 if (node->body_code())
01563 _push(generateInlineBlock(node->body_code(), false));
01564 normal_send(node->selector());
01565 pop();
01566 }
01567
01568
01569 void MethodPrettyPrinter::primitive_call_node(PrimitiveCallNode* node) {
01570 if (node->failure_code())
01571 _push(generateInlineBlock(node->failure_code(), true, new primitiveResultNode(bci(), scope())));
01572 if (node->has_receiver())
01573 normal_send(node->name(), true);
01574 else
01575 special_send(new ignoreReceiver(bci(), scope()), node->name(), true);
01576 }
01577
01578
01579 void MethodPrettyPrinter::dll_call_node(DLLCallNode* node) {
01580 dllNode* msg = new dllNode(bci(), scope(), node->dll_name(), node->function_name());
01581
01582 int nargs = node->nofArgs();
01583
01584 GrowableArray<astNode*>* arguments = new GrowableArray<astNode*>(10);
01585 for (int index = 0; index < nargs; index++)
01586 arguments->push(_pop());
01587
01588 for (index = 0; index < nargs; index++)
01589 msg->add_param(arguments->at(index));
01590
01591 msg->set_proxy(_pop());
01592
01593 _push(msg);
01594 }
01595
01596
01597 astNode* generate(scopeNode* scope) {
01598 MethodPrettyPrinter blk(scope);
01599 MethodIterator mi(scope->method(), &blk);
01600 assert(blk._size() == 1, "just checking");
01601 return blk._top();
01602 }
01603
01604
01605 astNode* generateForActivation(deltaVFrame* fr, int index) {
01606 return generate(new scopeNode(fr, index));
01607 }
01608
01609
01610 astNode* generateForMethod(methodOop method, klassOop klass, int bci) {
01611 return generate(new scopeNode(method, klass, bci));
01612 }
01613
01614
01615 astNode* generateForBlock(methodOop method, klassOop klass, int bci, int numOfArgs) {
01616 return generate(new scopeNode(method, klass, bci));
01617 }
01618
01619
01620 void prettyPrinter::print(methodOop method, klassOop klass, int bci, prettyPrintStream* output) {
01621 ResourceMark rm;
01622 if (!output) output = new defaultPrettyPrintStream;
01623 astNode* root = generateForMethod(method, klass, bci);
01624 root->top_level_print(output);
01625 output->newline();
01626 }
01627
01628 void prettyPrinter::print(int index, deltaVFrame* fr, prettyPrintStream* output) {
01629 ResourceMark rm;
01630 if (!output) output = new defaultPrettyPrintStream;
01631
01632 if (ActivationShowCode) {
01633 astNode* root = generateForActivation(fr, index);
01634 root->top_level_print(output);
01635 } else {
01636 scopeNode* scope = new scopeNode(fr, index);
01637 scope->print_header(output);
01638 }
01639 output->newline();
01640 }
01641
01642 void prettyPrinter::print_body(deltaVFrame* fr, prettyPrintStream* output) {
01643 ResourceMark rm;
01644 if (!output) output = new defaultPrettyPrintStream;
01645
01646 astNode* root = generateForActivation(fr, 0);
01647 root->print(output);
01648 }
01649
01650 byteArrayPrettyPrintStream::byteArrayPrettyPrintStream() : defaultPrettyPrintStream() {
01651 _buffer = new GrowableArray<int>(200);
01652 }
01653
01654 void byteArrayPrettyPrintStream::print_char(char c) {
01655 _buffer->append((int)c);
01656 pos += width_of_char(c);
01657 }
01658
01659 byteArrayOop byteArrayPrettyPrintStream::asByteArray() {
01660 int l = _buffer->length();
01661 byteArrayOop a = oopFactory::new_byteArray(l);
01662 for (int i = 0; i < l; i++) {
01663 a->byte_at_put(i+1, (char)_buffer->at(i));
01664 }
01665 return a;
01666 }
01667
01668 byteArrayOop prettyPrinter::print_in_byteArray(methodOop method, klassOop klass, int bci) {
01669 ResourceMark rm;
01670 byteArrayPrettyPrintStream* stream = new byteArrayPrettyPrintStream;
01671 prettyPrinter::print(method, klass, bci, stream);
01672 return stream->asByteArray();
01673 }
01674
01675
01676 bool should_wrap(int type, astNode* arg) {
01677 if (!arg->is_message()) return false;
01678 messageNode* msg = (messageNode*) arg;
01679 switch (type) {
01680 case 0: return false;
01681 case 1: return !msg->is_unary();
01682 case 2: return msg->is_keyword();
01683 }
01684 return false;
01685 }
01686
01687
01688 void PrintParams::parameter(byteArrayOop name, int index) {
01689 elements->push(scope->parameter_at(index, true));
01690 }
01691
01692
01693 void PrintTemps::stack_temp(byteArrayOop name, int offset) {
01694 elements->push(scope->stack_temp_at(offset));
01695 }
01696
01697
01698 void PrintTemps::heap_temp(byteArrayOop name, int offset) {
01699 elements->push(scope->heap_temp_at(offset));
01700 }