prettyPrinter.cpp

Go to the documentation of this file.
00001 /* Copyright 1994, LongView Technologies L.L.C. $Revision: 1.73 $ */
00002 /* Copyright (c) 2006, Sun Microsystems, Inc.
00003 All rights reserved.
00004 
00005 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the 
00006 following conditions are met:
00007 
00008     * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
00009     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following 
00010           disclaimer in the documentation and/or other materials provided with the distribution.
00011     * Neither the name of Sun Microsystems nor the names of its contributors may be used to endorse or promote products derived 
00012           from this software without specific prior written permission.
00013 
00014 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 
00015 NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
00016 THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
00017 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
00018 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
00019 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
00020 
00021 
00022 */
00023 
00024 # include "incls/_precompiled.incl"
00025 # include "incls/_prettyPrinter.cpp.incl"
00026 
00027 // ToDo list for pretty printer
00028 // - convert the stream stuff to ostream.
00029 // - improve the namedesc printout for temps etc.
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     // binary send
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);    // print method header first (in case something crashes later)
00433 
00434     if (ActivationShowBCI) {
00435       // Print current bci
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       // expression stack:
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       // Print the context if present
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 // Forward declaration
01292 astNode* generateForBlock(methodOop method, klassOop klass, int bci, int numOfArgs);
01293 
01294 class MethodPrettyPrinter : public MethodClosure {
01295  private:
01296   GrowableArray<astNode*>* _stack; // expression stack
01297   scopeNode*               _scope; // debugging scope
01298 
01299   // the receiver is on the stack
01300   void normal_send(symbolOop selector, bool is_prim = false);
01301   // the receiver is provided 
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   // Constructor
01315   MethodPrettyPrinter(scopeNode* scope);
01316 
01317   // node call backs
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   // complicated call backs
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   // sends
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   // simple call backs
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   // call backs to ignore
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   // This has to be on a statement boundary.
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     // This must be a cascade send
01465     //    - exp
01466     //    - receiver for the cascade send
01467       
01468     // Replace the receiver with a cascade code
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   // This has to be on a statement boundary.
01482   if (_size() == 1) {
01483     // Make the last statement in the method a nlr.
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   // This has to be on a statement boundary.
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(); // discard the result value
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 }

Generated on Mon Oct 9 13:37:23 2006 for Strongtalk VM by  doxygen 1.4.7