scopeDescRecorder.cpp

Go to the documentation of this file.
00001 /* Copyright 1994 - 1996, LongView Technologies L.L.C. $Revision: 1.53 $ */
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 
00026 #ifdef DELTA_COMPILER
00027 
00028 # include "incls/_scopeDescRecorder.cpp.incl"
00029 
00030 // Todo list 
00031 // - Insert Logical addresses
00032 //   If there is only on physical address they should be stored a today.
00033 
00034 # define INITIAL_ARG_SIZE                5
00035 # define INITIAL_TEMP_SIZE               5
00036 # define INITIAL_CONTEXT_TEMP_SIZE       5
00037 # define INITIAL_EXPR_STACK_SIZE        10
00038 
00039 # define INITIAL_OOPS_SIZE                100
00040 # define INITIAL_VALUES_SIZE              100
00041 # define INITIAL_DEPENDANTS_SIZE           20
00042 # define INITIAL_CONTEXT_SCOPE_ARRAY_SIZE  10
00043 
00044 const u_char nameDescHeaderByte::code_width        = 2;
00045 const u_char nameDescHeaderByte::index_width       = 5;
00046 const u_char nameDescHeaderByte::is_last_bit_num   = code_width+index_width;
00047 const u_char nameDescHeaderByte::max_code          = nthMask(code_width);
00048 
00049 const u_char nameDescHeaderByte::max_index         = nthMask(index_width) - 3;
00050 const u_char nameDescHeaderByte::no_index          = nthMask(index_width) - 2;
00051 const u_char nameDescHeaderByte::termination_index = nthMask(index_width) - 1;
00052 const u_char nameDescHeaderByte::illegal_index     = nthMask(index_width) - 0;
00053 
00054 // 2 bits: scopeDesc type
00055 // 1 bit:  is lite scope desc
00056 // 1 bit:  has arguments
00057 // 1 bit:  has temporaries
00058 // 1 bit:  has expression stack
00059 // 1 bit:  has context temporaries
00060 // 1 bit:  has context
00061 const u_char scopeDescHeaderByte::code_width            = 2;
00062 const u_char scopeDescHeaderByte::max_code              = nthMask(code_width);
00063 const u_char scopeDescHeaderByte::lite_bit_num          = code_width;
00064 const u_char scopeDescHeaderByte::args_bit_num          = code_width+1;
00065 const u_char scopeDescHeaderByte::temps_bit_num         = code_width+2;
00066 const u_char scopeDescHeaderByte::context_temps_bit_num = code_width+3;
00067 const u_char scopeDescHeaderByte::expr_stack_bit_num    = code_width+4;
00068 const u_char scopeDescHeaderByte::context_bit_num       = code_width+5;
00069 
00070 
00071 // A LogicalAddress describes a source level location.
00072 // Since backend optimizations reshuffles code a source level location
00073 // may change its physical location.
00074 class LogicalAddress : public ResourceObj {
00075  private:
00076   NameNode*       _physical_address;
00077   int             _pc_offset;
00078   LogicalAddress* _next;
00079   int             _offset;
00080 
00081   NameNode*       physical_address() const { return _physical_address; }
00082   int             pc_offset()        const { return _pc_offset;        }
00083   LogicalAddress* next()             const { return _next;             }
00084  public:
00085   LogicalAddress(NameNode* physical_address, int pc_offset = 0);
00086 
00087   void append(NameNode* physical_address, int pc_offset);
00088   NameNode* physical_address_at(int pc_offset);
00089   void generate(ScopeDescRecorder* rec);
00090 
00091   int length(); 
00092 };
00093 
00094 
00095 LogicalAddress::LogicalAddress(NameNode* physical_address, int pc_offset) {
00096   _physical_address = physical_address;
00097   _pc_offset        = pc_offset;
00098   _next             = NULL;
00099   _offset           = -1; // Illegal value
00100 }
00101 
00102 void LogicalAddress::append(NameNode* physical_address, int pc_offset) {
00103   if (next()) {
00104     // hopefully these lists are not getting too long...
00105     next()->append(physical_address, pc_offset);
00106   } else {
00107     assert(_pc_offset <= pc_offset, "checking progress");
00108    _next = new LogicalAddress(physical_address, pc_offset);
00109   }
00110 }
00111 
00112 NameNode* LogicalAddress::physical_address_at(int pc_offset) {
00113   LogicalAddress* current = this;
00114   while (current->next() && current->next()->pc_offset() > pc_offset) {
00115     current = current->next();
00116   }
00117   return current->physical_address();
00118 }
00119 
00120 int LogicalAddress::length() {
00121   LogicalAddress* current = this;
00122   int result = 1;
00123   while (current->next()) {
00124     current = current->next();
00125     result++;
00126   }
00127   return result;
00128 }
00129 
00130 void LogicalAddress::generate(ScopeDescRecorder* rec) {
00131   // emit: 
00132   //  [first ]
00133   //  [next  ], offset
00134   // where last element has the is_last bit set.
00135   LogicalAddress* n = next();
00136   physical_address()->generate(rec, n == NULL);
00137 
00138   int last_pc_offset = 0;
00139   while (n != NULL) {
00140     LogicalAddress* current = n;
00141     n = n->next();
00142     current->physical_address()->generate(rec, n == NULL);
00143     assert(last_pc_offset <= current->pc_offset(), "checking progress");
00144     rec->genValue(current->pc_offset() - last_pc_offset);
00145     last_pc_offset = current->pc_offset();
00146   }
00147 }
00148 
00149 class Array: public ResourceObj {
00150  private:
00151   int index;
00152   int size;
00153 
00154   int offset;
00155 
00156   int* values;
00157  public:
00158   Array(int size);
00159 
00160   int length() { return index; }
00161   void extend(int newSize);
00162   int insertIfAbsent(int value);  // returns index for value
00163   void copy_to(int*& addr);
00164 };
00165 
00166 class ByteArray : public ResourceObj {
00167 private:
00168   u_char* array;
00169   int  top;
00170   int  max;
00171 
00172   void extend();
00173 
00174  public:
00175   int size()      { return top; }
00176   u_char* start() { return array; }
00177 
00178   ByteArray(int size);
00179 
00180   void appendByte(u_char p) {
00181     if (top + (int) sizeof(u_char) > max) extend();
00182     array[top++] = p;
00183   }
00184 
00185   void appendHalf(int16 p);
00186 #ifdef UNUSED
00187   void appendWord(int p);
00188 #endif
00189 
00190   void putByteAt(u_char p, int offset) {
00191     assert( offset < max, "index out of bound");
00192     array[offset] = p;
00193   }
00194 
00195  void putHalfAt(int16 p, int offset);
00196 
00197   // Cut off some of the generated code.
00198   void setTop(int offset) {
00199     assert( this->top >= offset, "A smaller top is expected");
00200     this->top = offset;
00201   }
00202 
00203   void alignToWord();
00204   void copy_to(int*& addr);
00205 };
00206 
00207 NameNode* newValueName(oop value) {
00208   if (value->is_block()) {
00209     fatal("should never be a block");
00210     return NULL;
00211   } else {
00212     return new ValueName(value);
00213   }
00214 }
00215 
00216 bool NameNode::genHeaderByte(ScopeDescRecorder* rec, u_char code, bool is_last, int index) {
00217   // Since id is most likely to be 0, the info part of the header byte
00218   // indicates if is is non zero.
00219   // Experiments show id is zero in at least 90% of the generated nameDescs.
00220   // returns true if index could be inlined in headerByte.
00221   nameDescHeaderByte b;
00222   bool   can_inline  = index <= b.max_index;
00223   u_char coded_index = can_inline ? index : b.no_index;
00224   b.pack(code, is_last, coded_index);
00225   rec->codes->appendByte( b.value());
00226   return can_inline;
00227 } 
00228 
00229 inline int ScopeDescRecorder::getValueIndex(int v) {
00230   // if v fits into 7 bits inline the value instead of creating index
00231   if ( 0 <= v && v <= MAX_INLINE_VALUE) return v;
00232   return MAX_INLINE_VALUE + 1 + values->insertIfAbsent(v);
00233 }
00234 
00235 inline int ScopeDescRecorder::getOopIndex(oop o) {
00236   return o == 0 ? 0 : oops->insertIfAbsent((int)o) + 1;
00237 }
00238 
00239 void ScopeDescRecorder::emit_illegal_node(bool is_last) {
00240   nameDescHeaderByte b;
00241   b.pack_illegal(is_last);
00242   codes->appendByte(b.value());
00243 }
00244 
00245 void ScopeDescRecorder::emit_termination_node() {
00246   nameDescHeaderByte b;
00247   b.pack_termination(true);
00248   codes->appendByte(b.value());
00249 }
00250 
00251 void IllegalName::generate(ScopeDescRecorder* rec, bool is_last) {
00252   rec->emit_illegal_node(is_last);
00253 }
00254 
00255 // Please encapsulate iterator.
00256 static ScopeDesc*     _sd;
00257 static nmethodScopes* _scopes;
00258 static ScopeDesc*     _getNextScopeDesc() {
00259   _sd = _scopes->getNext(_sd);
00260   if (!_sd) fatal("out of scopeDescs");
00261   return _sd;
00262 }
00263 
00264 Array::Array(int sz) {
00265   size   = sz;
00266   index  = 0;
00267   values = NEW_RESOURCE_ARRAY(int, sz);
00268 }
00269 
00270 int Array::insertIfAbsent(int value){
00271   for (int i = 0; i < index; i ++)
00272     if (values[i] == value)
00273       return i;
00274   if (index == size)
00275     extend(size*2);
00276   values[index] = value;
00277   return index++;
00278 }
00279 
00280 void Array::extend(int newSize) {
00281   int* newValues = NEW_RESOURCE_ARRAY(int, newSize);
00282   for(int i=0;i < index; i++)
00283     newValues[i] = values[i];
00284   values = newValues;
00285   size   = newSize;
00286 }
00287 
00288 void Array::copy_to(int*& addr) {
00289   for(int i=0;i < length(); i++) {
00290     *addr++ = values[i];
00291   }
00292 }
00293 
00294 ByteArray::ByteArray(int size) {
00295   array = NEW_RESOURCE_ARRAY(u_char, size); 
00296   max   = size;
00297   top   = 0;
00298 }
00299 
00300 void ByteArray::extend() {
00301   int  newMax = max*2;
00302   u_char* newArray = NEW_RESOURCE_ARRAY(u_char, newMax);
00303   for(int i=0;i < top; i++)
00304     newArray[i] = array[i];
00305   array = newArray;
00306   max  = newMax;
00307 }
00308 
00309 void ByteArray::appendHalf(int16 p) {
00310   if (top + (int) sizeof(int16) > max) extend();
00311   // Saving the half as two bytes to avoid alignment problem.
00312   array[top++] = p >> BYTE_WIDTH;
00313   array[top++] = (u_char)lowerBits(p, 8);
00314 }
00315 
00316 void ByteArray::putHalfAt(int16 p, int offset) {
00317   // Saving the half as two bytes to avoid alignment problem.
00318   array[offset  ] = p >> BYTE_WIDTH;
00319   array[offset+1] = (u_char)lowerBits(p, 8);
00320 }
00321 
00322 #ifdef UNUSED
00323 void ByteArray::appendWord(int p) {
00324   if (top+sizeof(int) > max) extend();
00325   assert( size() % sizeof(int) == 0, "Not word aligned");
00326   int* s = (int*) &array[top];
00327   *s = p;
00328   top += sizeof(int);
00329 }
00330 #endif
00331 
00332 void ByteArray::alignToWord() {
00333   int fill_size = (sizeof(int) - (size()%sizeof(int))) % sizeof(int);
00334   for(int i = 0; i < fill_size; i++)
00335     appendByte(0); 
00336 }
00337 
00338 void ByteArray::copy_to(int*& addr) {
00339   int* fromAddr = (int*) start();
00340   int len = size()/sizeof(int);
00341   for(int i=0;i < len; i++) {
00342     *addr++ = *fromAddr++;
00343   }
00344 }
00345 
00346 // Class hierarchy for nodes generating scopeDescs.
00347 // ScopeDescNode
00348 //  - MethodScopeNode
00349 //  - TopLevelBlockScopeNode
00350 //  - BlockScopeNode
00351 
00352 # define INVALID_OFFSET -1
00353 
00354 class ScopeDescNode: public ResourceObj {
00355  public:
00356   methodOop       method;
00357   bool            allocates_compiled_context;
00358   int             scopeID;
00359   bool            lite;
00360   int             senderBCI;
00361   bool            visible;
00362 
00363   GrowableArray<LogicalAddress*>* arg_list;
00364   GrowableArray<LogicalAddress*>* temp_list;
00365   GrowableArray<LogicalAddress*>* context_temp_list;
00366   GrowableArray<LogicalAddress*>* expr_stack_list;
00367 
00368   int offset; // byte offset to the encoded scopeDesc
00369               // Initial value is  INVALID_OFFSET
00370   
00371   bool usedInPcs;
00372   
00373  public:
00374   bool has_args()          const { return !lite && !arg_list->isEmpty();          }
00375   bool has_temps()         const { return !lite && !temp_list->isEmpty();         }
00376   bool has_context_temps() const { return !lite && !context_temp_list->isEmpty(); }
00377   bool has_expr_stack()    const { return !lite && !expr_stack_list->isEmpty();   }
00378   bool has_context()       const { return allocates_compiled_context; }
00379 
00380   bool has_nameDescs()     const { return has_args()
00381                                        || has_temps()
00382                                        || has_context_temps()
00383                                        || has_expr_stack(); }
00384 
00385   ScopeInfo scopesHead;
00386   ScopeInfo scopesTail;
00387   ScopeInfo next;
00388 
00389   ScopeDescNode(methodOop method, bool allocates_compiled_context, int scopeID, bool lite, int senderBCI, bool visible);
00390 
00391   void addNested(ScopeInfo scope);
00392 
00393   virtual u_char code() = 0;
00394 
00395   virtual void generate(ScopeDescRecorder* rec, int senderScopeOffset, bool bigHeader);
00396   void generateBody(ScopeDescRecorder* rec, int senderScopeOffset);
00397   void generateNameDescs(ScopeDescRecorder* rec);
00398 
00399   void generate_solid(GrowableArray<LogicalAddress*>* list, ScopeDescRecorder* rec);
00400   void generate_sparse(GrowableArray<LogicalAddress*>* list, ScopeDescRecorder* rec);
00401 
00402   bool computeVisibility();
00403 
00404   ScopeInfo find_scope(int scope_id);
00405 
00406   virtual void verify(ScopeDesc* sd);
00407   void verifyBody();
00408 };
00409 
00410 ScopeInfo ScopeDescNode::find_scope(int scope_id) {
00411   if (scopeID == scope_id) return this;
00412   for(ScopeInfo p = scopesHead; p  != NULL; p = p->next) {
00413     ScopeInfo result = p->find_scope(scope_id);
00414     if (result) return result;
00415   }
00416   return NULL;
00417 }
00418 
00419 void ScopeDescNode::generate_solid(GrowableArray<LogicalAddress*>* list, ScopeDescRecorder* rec) {
00420   // Dump all the elements
00421   for(int i = 0; i < list->length(); i++) {
00422     assert(list->at(i), "must be a solid array"); 
00423     list->at(i)->generate(rec);
00424   }
00425   // Terminate the list
00426   rec->emit_termination_node();
00427 }
00428 
00429 void ScopeDescNode::generate_sparse(GrowableArray<LogicalAddress*>* list, ScopeDescRecorder* rec) {
00430   // Dump all the elements
00431   for(int i = 0; i < list->length(); i++) {
00432     if (list->at(i)) {
00433       list->at(i)->generate(rec);
00434       rec->genValue(i);
00435     }
00436   }
00437   // Terminate the list
00438   rec->emit_termination_node();
00439 }
00440 
00441 struct PcDescNode: public ResourceObj {
00442   int     pcOffset;
00443   ScopeInfo scope;
00444   int     bci;
00445 };
00446 
00447 class PcDescInfoClass : public ResourceObj {
00448  protected:
00449   PcDescNode*   nodes;
00450   int          end;
00451   int          size;
00452  public:
00453   PcDescInfoClass(int size);
00454   int length() { return end; }
00455   void extend(int newSize);
00456   void add(int pcOffset, ScopeInfo scope, int bci);
00457   void mark_scopes();
00458   void copy_to(int*& addr);
00459 };
00460 
00461 ScopeDescNode::ScopeDescNode(methodOop method, bool allocates_compiled_context, int scopeID, bool lite, int senderBCI, bool visible) {
00462   this->scopeID                    = scopeID;
00463   this->method                     = method;
00464   this->lite                       = lite;
00465   this->senderBCI                  = senderBCI;
00466   this->visible                    = visible;
00467   this->allocates_compiled_context = allocates_compiled_context;
00468 
00469   arg_list          = new GrowableArray<LogicalAddress*>(INITIAL_ARG_SIZE);
00470   temp_list         = new GrowableArray<LogicalAddress*>(INITIAL_TEMP_SIZE);
00471   context_temp_list = new GrowableArray<LogicalAddress*>(INITIAL_CONTEXT_TEMP_SIZE);
00472   expr_stack_list   = new GrowableArray<LogicalAddress*>(INITIAL_EXPR_STACK_SIZE);
00473 
00474   offset     = INVALID_OFFSET;
00475   scopesHead = NULL;
00476   scopesTail = NULL;
00477   usedInPcs  = false;
00478 }
00479 
00480 void ScopeDescNode::addNested(ScopeInfo scope) {
00481   scope->next = NULL;
00482   if (scopesHead == NULL) {
00483     scopesHead = scopesTail = scope; 
00484   } else {
00485     scopesTail->next = scope;
00486     scopesTail = scope;
00487   }
00488 }
00489 
00490 void ScopeDescNode::generate(ScopeDescRecorder* rec, int senderScopeOffset, bool bigHeader) {
00491   offset = rec->codes->size();
00492 
00493   rec->genScopeDescHeader(code(), lite, has_args(), has_temps(), has_context_temps(), has_expr_stack(), has_context(), bigHeader);
00494   if (offset != 0) {
00495     // Save the sender
00496     rec->genValue(offset - senderScopeOffset);
00497     rec->genValue(senderBCI);
00498   }
00499   rec->genOop(method);
00500   rec->genValue(scopeID);
00501 }
00502 
00503 void ScopeDescNode::generateNameDescs(ScopeDescRecorder* rec) {
00504   assert(has_nameDescs(), "must have nameDescs");
00505   if (has_args())          generate_solid(arg_list, rec);
00506   if (has_temps())         generate_solid(temp_list, rec);
00507   if (has_context_temps()) generate_solid(context_temp_list, rec);
00508   if (has_expr_stack())    generate_sparse(expr_stack_list, rec);
00509 }
00510 
00511 void ScopeDescNode::generateBody(ScopeDescRecorder* rec, int senderScopeOffset) {
00512   if (has_nameDescs()) {
00513     generateNameDescs(rec);
00514     if (!rec->updateScopeDescHeader(offset, rec->codes->size())) {
00515       // the offsets in the encoded scopeDesc header could not be
00516       // written in the pre-allocated two bytes.
00517       // Make the header large enough for extended index.
00518       rec->codes->setTop(offset);
00519       generate(rec, senderScopeOffset, true);
00520       generateNameDescs(rec);
00521       rec->updateExtScopeDescHeader(offset, rec->codes->size());
00522    }
00523   }
00524   
00525   for(ScopeInfo p = scopesHead; p  != NULL; p = p->next) {
00526     if (p->visible) {
00527       p->generate(rec, offset, false);
00528       p->generateBody(rec, offset);
00529     }
00530   }
00531 }
00532 
00533 void ScopeDescNode::verify(ScopeDesc* sd) {
00534   if (senderBCI != IllegalBCI && senderBCI != sd->senderBCI()) fatal("senderBCI is wrong");
00535 }
00536 
00537 void ScopeDescNode::verifyBody() {
00538   for(ScopeInfo p = scopesHead; p  != NULL; p = p->next) {
00539     if (p->visible) {
00540       p->verify(_getNextScopeDesc());
00541       p->verifyBody();
00542     }
00543   }
00544 }
00545 
00546 bool ScopeDescNode::computeVisibility() {
00547   visible = false;
00548   for(ScopeInfo p = scopesHead; p  != NULL; p = p->next) {
00549     visible = p->computeVisibility() || visible;
00550   }
00551   visible = visible || (usedInPcs && GenerateLiteScopeDescs) || !lite;
00552   return visible;
00553 }
00554 
00555 
00556 class MethodScopeNode: public ScopeDescNode {
00557  public:
00558   LookupKey*      key;
00559   LogicalAddress* receiver_location;
00560 
00561   u_char code() { return METHOD_CODE; }
00562 
00563   MethodScopeNode(LookupKey*      key, 
00564                   methodOop       method, 
00565                   LogicalAddress* receiver_location,
00566                   bool            allocates_compiled_context,
00567                   bool            lite,
00568                   int             scopeID,
00569                   int             senderBCI,
00570                   bool            visible)
00571     : ScopeDescNode(method, allocates_compiled_context, scopeID, lite, senderBCI, visible) {
00572       this->key               = key;
00573       this->receiver_location = receiver_location;
00574   }
00575 
00576   void generate(ScopeDescRecorder* rec, int senderScopeOffset, bool bigHeader);
00577 
00578   void verify(ScopeDesc* sd);
00579 };
00580 
00581 
00582 void MethodScopeNode::generate(ScopeDescRecorder* rec,
00583                                int senderScopeOffset, bool bigHeader) {
00584   ScopeDescNode::generate(rec,senderScopeOffset, bigHeader);
00585   rec->genOop(key->klass());
00586   rec->genOop(key->selector_or_method());
00587   receiver_location->generate(rec);
00588 }
00589 
00590 void MethodScopeNode::verify(ScopeDesc* sd) {
00591   ScopeDescNode::verify(sd);
00592   if (!sd->isMethodScope()) fatal("MethodScope expected");
00593 }
00594 
00595 class TopLevelBlockScopeNode: public ScopeDescNode {
00596  public:
00597   LogicalAddress* receiver_location;
00598   klassOop        receiver_klass;
00599 
00600   u_char code() { return TOPLEVELBLOCK_CODE; }
00601 
00602   TopLevelBlockScopeNode(methodOop  method, LogicalAddress* receiver_location, klassOop receiver_klass, bool allocates_compiled_context)
00603   : ScopeDescNode(method, allocates_compiled_context, false, 0, NULL, true) {
00604     this->receiver_location = receiver_location;
00605     this->receiver_klass    = receiver_klass;
00606   }
00607 
00608   void generate(ScopeDescRecorder* rec, int senderScopeOffset, bool bigHeader) {
00609     ScopeDescNode::generate(rec, senderScopeOffset, bigHeader);
00610     receiver_location->generate(rec);
00611     rec->genOop(receiver_klass);
00612   }
00613 
00614   void verify(ScopeDesc* sd) {
00615     ScopeDescNode::verify(sd);
00616     if (!sd->isTopLevelBlockScope()) fatal("TopLevelBlockScope expected");
00617   }  
00618 };
00619 
00620 class BlockScopeNode: public ScopeDescNode {
00621  public:
00622   ScopeInfo parent;
00623 
00624   BlockScopeNode(methodOop method,
00625                  ScopeInfo parent,
00626                  bool      allocates_compiled_context,
00627                  bool      lite,
00628                  int       scopeID,
00629                  int       senderBCI, 
00630                  bool      visible) 
00631     : ScopeDescNode(method, allocates_compiled_context, scopeID, lite, senderBCI, visible) {
00632     this->parent = parent;
00633   }
00634 
00635   u_char code() { return BLOCK_CODE; }
00636 
00637   void generate(ScopeDescRecorder* rec, int senderScopeOffset, bool bigHeader);
00638 
00639   void verify(ScopeDesc* sd);
00640 };
00641 
00642 void BlockScopeNode::generate(ScopeDescRecorder* rec, int senderScopeOffset, bool bigHeader) {
00643   ScopeDescNode::generate(rec, senderScopeOffset, bigHeader);
00644   rec->genValue(offset - parent->offset);
00645 }
00646 
00647 void BlockScopeNode::verify(ScopeDesc* sd) {
00648   ScopeDescNode::verify(sd);
00649 } 
00650 
00651 class NonInlinedBlockScopeNode: public ResourceObj {
00652  public:
00653   int                       offset;
00654   NonInlinedBlockScopeNode* next;
00655   methodOop                 method;
00656   ScopeInfo                 parent;
00657 
00658   NonInlinedBlockScopeNode(methodOop method, ScopeInfo parent)  {
00659     this->method = method;
00660     this->parent = parent;
00661     this->offset = INVALID_OFFSET;
00662     this->next   = NULL;
00663   }
00664   u_char code() { return NONINLINED_BLOCK_CODE; }
00665   void generate(ScopeDescRecorder* rec);
00666 };
00667 
00668 void NonInlinedBlockScopeNode::generate(ScopeDescRecorder* rec) {
00669   offset = rec->codes->size();
00670   rec->genScopeDescHeader(code(), false, false, false, false, false, false, false);
00671   rec->genOop(method);
00672   rec->genValue(offset - parent->offset);
00673 //  if (WizardMode) lprintf("generating NonInlinedBlockScopeNode at %d\n", offset);
00674 }
00675 
00676 void ScopeDescRecorder::generate() {
00677   assert(root, "root scope must be present");
00678   // Generate the bytecodes for the ScopeDescs and their NameDescs.
00679 
00680   generateDependencies();
00681 
00682   pcs->mark_scopes();
00683   (void) root->computeVisibility();
00684   root->generate(this, 0, false);
00685   root->generateBody(this, 0);
00686   
00687   for(NonInlinedBlockScopeNode* p = nonInlinedBlockScopesHead; p != NULL; p = p->next) {
00688     p->generate(this);
00689   }
00690 
00691   codes->alignToWord();
00692   _hasCodeBeenGenerated = true;
00693 }
00694 
00695 void ScopeDescRecorder::generateDependencies() {
00696   int end_marker = 0;
00697   for (int index = 0; index < dependants->length(); index++) {
00698     int i = oops->insertIfAbsent((int)dependants->at(index));
00699     if (i > end_marker)  end_marker = i;
00700   }
00701   dependants_end = end_marker;
00702 }
00703 
00704 ScopeInfo ScopeDescRecorder::addScope(ScopeInfo scope, ScopeInfo senderScope){
00705   if (root == NULL) {
00706     assert( senderScope == NULL, "Root scope must be the first");
00707     root = scope;
00708   } else {
00709     assert( senderScope != NULL, "Sender scope must be present"); 
00710     senderScope->addNested(scope);
00711   }
00712   return scope;
00713 }
00714 
00715 NonInlinedBlockScopeNode* ScopeDescRecorder::addNonInlinedBlockScope(NonInlinedBlockScopeNode* scope) {
00716   scope->next = NULL;
00717   if (nonInlinedBlockScopesHead == NULL) {
00718     nonInlinedBlockScopesHead = nonInlinedBlockScopesTail = scope; 
00719   } else {
00720     nonInlinedBlockScopesTail->next = scope;
00721     nonInlinedBlockScopesTail = scope;
00722   }
00723   return scope;
00724 }
00725 
00726 int ScopeDescRecorder::offset(ScopeInfo scope) {
00727   assert(scope->offset != INVALID_OFFSET, "uninitialized offset");
00728   return scope->offset;
00729 }
00730 
00731 int ScopeDescRecorder::offset_for_noninlined_scope_node(NonInlinedBlockScopeNode* scope) {
00732   assert(scope->offset != INVALID_OFFSET, "uninitialized offset");
00733   return scope->offset;
00734 }
00735 
00736 ScopeInfo ScopeDescRecorder::addMethodScope(LookupKey*      key, 
00737                                             methodOop       method,
00738                                             LogicalAddress* receiver_location,
00739                                             bool            allocates_compiled_context,
00740                                             bool            lite,
00741                                             int             scopeID,
00742                                             ScopeInfo       senderScope, 
00743                                             int             senderBCI,
00744                                             bool            visible) {
00745   return addScope(
00746     new MethodScopeNode(key, method, receiver_location, allocates_compiled_context, lite, scopeID, senderBCI, visible),               
00747     senderScope);
00748 }
00749 
00750 
00751 ScopeInfo ScopeDescRecorder::addBlockScope(methodOop       method,
00752                                            ScopeInfo       parent,
00753                                            bool            allocates_compiled_context,
00754                                            bool            lite,
00755                                            int             scopeID,
00756                                            ScopeInfo       senderScope, 
00757                                            int             senderBCI,
00758                                            bool            visible) {
00759   return addScope(
00760     new BlockScopeNode(method, parent, allocates_compiled_context, lite, scopeID, senderBCI, visible),
00761     senderScope);
00762 }
00763 
00764 ScopeInfo ScopeDescRecorder::addTopLevelBlockScope(methodOop       method, 
00765                                                    LogicalAddress* receiver_location,
00766                                                    klassOop        receiver_klass,
00767                                                    bool            allocates_compiled_context) {
00768   return addScope(new TopLevelBlockScopeNode(method, receiver_location, receiver_klass, allocates_compiled_context), NULL);
00769 }
00770 
00771 NonInlinedBlockScopeNode* ScopeDescRecorder::addNonInlinedBlockScope(methodOop method, ScopeInfo parent) {
00772   
00773   return addNonInlinedBlockScope(new NonInlinedBlockScopeNode(method, parent));
00774 }
00775 
00776 
00777 void ScopeDescRecorder::addArgument(ScopeInfo scope, int index, LogicalAddress* location){
00778   assert(!scope->lite, "cannot add slot to lite scopeDesc");
00779   scope->arg_list->at_put_grow(index, location);
00780 }
00781 
00782 void ScopeDescRecorder::addTemporary(ScopeInfo scope, int index, LogicalAddress* location){
00783   assert(!scope->lite, "cannot add slot to lite scopeDesc");
00784   scope->temp_list->at_put_grow(index, location);
00785 }
00786 
00787 void ScopeDescRecorder::addExprStack(ScopeInfo scope, int index, LogicalAddress* location) {
00788   assert(!scope->lite, "cannot add expression to lite scopeDesc");
00789   scope->expr_stack_list->at_put_grow(index, location);
00790 }
00791 
00792 void ScopeDescRecorder::addContextTemporary(ScopeInfo scope, int index, LogicalAddress* location) {
00793   assert(!scope->lite, "cannot add expression to lite scopeDesc");
00794   scope->context_temp_list->at_put_grow(index, location);
00795 }
00796 
00797 LogicalAddress* ScopeDescRecorder::createLogicalAddress(NameNode* initial_value) {
00798   return new LogicalAddress(initial_value);
00799 }
00800 
00801 void ScopeDescRecorder::changeLogicalAddress(LogicalAddress* location, NameNode* new_value, int pc_offset) {
00802   location->append(new_value, pc_offset);
00803 }
00804 
00805 void ScopeDescRecorder::genScopeDescHeader(u_char code, 
00806                                            bool lite,
00807                                            bool args,
00808                                            bool temps,
00809                                            bool context_temps,
00810                                            bool expr_stack,
00811                                            bool has_context,
00812                                            bool bigHeader) {
00813   scopeDescHeaderByte b;
00814   b.pack(code, lite, args, temps, context_temps, expr_stack, has_context);
00815   codes->appendByte(b.value());
00816   if (b.has_nameDescs()) {
00817     codes->appendByte(0); // placeholder for next offset
00818     if (bigHeader) {
00819       codes->appendHalf(0);
00820     }
00821   }
00822 }
00823 
00824 int ScopeDescRecorder::updateScopeDescHeader(int offset, int next) {
00825   int nextIndex = getValueIndex(next - offset);
00826   if (nextIndex < EXTENDED_INDEX) {
00827     codes->putByteAt(nextIndex, offset+1);
00828     return true;
00829   } else {
00830     return false;
00831   }
00832 }
00833 
00834 void ScopeDescRecorder::updateExtScopeDescHeader(int offset, int next) {
00835   int nextIndex = getValueIndex(next - offset);
00836   codes->putByteAt(EXTENDED_INDEX, offset+1);
00837   codes->putHalfAt(nextIndex,      offset+2);
00838 }
00839 
00840 inline void ScopeDescRecorder::genIndex(int index) {
00841   if (index < EXTENDED_INDEX) {
00842     // generate 1 byte indexing the oop.
00843     codes->appendByte(index);
00844   } else {
00845     codes->appendByte(EXTENDED_INDEX);
00846     codes->appendHalf(index);
00847   }
00848 }
00849 
00850 void ScopeDescRecorder::genValue(int v) {
00851   genIndex(getValueIndex(v));
00852 }
00853 
00854 void ScopeDescRecorder::genOop(oop o) {
00855   genIndex(getOopIndex(o));
00856 }
00857 
00858 PcDescInfoClass::PcDescInfoClass(int sz) {
00859   nodes = NEW_RESOURCE_ARRAY(PcDescNode, sz); 
00860   end   = 0;
00861   size  = sz;
00862 }
00863 
00864 void PcDescInfoClass::extend(int newSize) {
00865   PcDescNode* newNodes = NEW_RESOURCE_ARRAY(PcDescNode, newSize);
00866   for(int i=0;i < end; i++)
00867     newNodes[i] = nodes[i];
00868   nodes = newNodes;
00869   size  = newSize;
00870 }
00871 
00872 void PcDescInfoClass::add(int pcOffset, ScopeInfo scope, int bci) {
00873   if (scope->lite && !GenerateLiteScopeDescs) return;
00874   if (end == size) extend(size*2);
00875 
00876   // After Robert's jmp elimination, instructions can be eliminated
00877   // We can therefore remove pc descs describing the eliminated code.
00878   while (end > 0 && pcOffset < nodes[end-1].pcOffset) {
00879     end--;
00880   }
00881 
00882   if (CompressPcDescs && end > 0) {
00883     // skip if the previous had the same scope and bci.
00884     if (scope == nodes[end-1].scope && bci == nodes[end-1].bci) return;
00885     // overwrite if the previous had the same pcOffset.
00886     if (pcOffset == nodes[end-1].pcOffset) {
00887       end--;
00888     }
00889   }
00890 
00891   nodes[end].pcOffset = pcOffset;
00892   nodes[end].scope    = scope;
00893   nodes[end].bci      = bci;
00894   end++;
00895 }
00896 
00897 void PcDescInfoClass::mark_scopes() {
00898   for(int i=0;i < end; i++) {
00899     if (nodes[i].scope) nodes[i].scope->usedInPcs = true;
00900   }
00901 }
00902 
00903 void PcDescInfoClass::copy_to(int*& addr) {
00904   for(int i = 0; i < end; i++) {
00905     PcDesc* pc = (PcDesc*) addr;
00906     pc->pc       = nodes[i].pcOffset;
00907     pc->scope    = nodes[i].scope ? nodes[i].scope->offset : IllegalBCI;
00908     pc->byteCode = nodes[i].bci;
00909     addr += sizeof(PcDesc)/sizeof(int);
00910   }
00911 }
00912 
00913 void LocationName::generate(ScopeDescRecorder* rec, bool is_last) {
00914   Location converted_location = rec->convert_location(l);
00915   int index = rec->getValueIndex(converted_location._loc);
00916   if (!genHeaderByte(rec, LOCATION_CODE, is_last, index)) rec->genIndex(index);
00917 }
00918 
00919 void ValueName::generate(ScopeDescRecorder* rec, bool is_last) {
00920   int index = rec->getOopIndex(value);
00921   if (!genHeaderByte(rec, VALUE_CODE, is_last, index)) rec->genIndex(index);
00922 }
00923 
00924 void MemoizedName::generate(ScopeDescRecorder* rec, bool is_last) {
00925   Location converted_location  = rec->convert_location(loc);
00926   int index = rec->getValueIndex(converted_location._loc);
00927   if (!genHeaderByte(rec, MEMOIZEDBLOCK_CODE, is_last, index)) rec->genIndex(index);
00928   rec->genOop(oop(block_method));
00929   rec->genValue(parent_scope == NULL ? 0 : parent_scope->offset); // Lars, please check this (gri 2/2/96)
00930 }
00931 
00932 void BlockValueName::generate(ScopeDescRecorder* rec, bool is_last) {
00933   int index = rec->getOopIndex(oop(block_method));
00934   if (!genHeaderByte(rec, BLOCKVALUE_CODE, is_last, index)) rec->genIndex(index);
00935   rec->genValue(parent_scope == NULL ? 0 : parent_scope->offset); // Lars, please check this (gri 2/2/96)
00936 }
00937 
00938 Location ScopeDescRecorder::convert_location(Location loc) {
00939   if (!loc.isContextLocation()) return loc;
00940   int scope_id = loc.scopeID();
00941 
00942   // Find the ScopeInfo with the right scope_id
00943   ScopeInfo scope = theCompiler->scopes->at(scope_id)->scopeInfo();
00944   assert(scope, "scope must exist");
00945   if (scope->offset == INVALID_OFFSET) {
00946     std->print_cr(loc.name());
00947     theCompiler->print_code(false);
00948     fatal("compiler error: context location appears outside its scope");    // Urs 5/96
00949   }
00950   return Location::runtimeContextLocation(loc.contextNo(), loc.tempNo(), scope->offset);
00951 }
00952 
00953 
00954 int ScopeDescRecorder::size() {
00955   return   sizeof(nmethodScopes)
00956          + codes->size()
00957          + oops->length()   * sizeof(oop)
00958          + values->length() * sizeof(int)
00959          + pcs->length()    * sizeof(PcDesc);
00960 }
00961 
00962 ScopeDescRecorder::ScopeDescRecorder(int byte_size, int pcDesc_size) {
00963   // size is the initial size of the byte array.
00964   root   = NULL;
00965   oops   = new Array(INITIAL_OOPS_SIZE);
00966   values = new Array(INITIAL_VALUES_SIZE);
00967   codes  = new ByteArray(byte_size);
00968   pcs    = new PcDescInfoClass(pcDesc_size);
00969 
00970   dependants = new GrowableArray<klassOop>(INITIAL_DEPENDANTS_SIZE);
00971 
00972   _hasCodeBeenGenerated = false;
00973 
00974   nonInlinedBlockScopesHead = NULL;
00975   nonInlinedBlockScopesTail = NULL;
00976 }
00977 
00978 void ScopeDescRecorder::copyTo(nmethod* nm) {
00979   { nmethodScopes* d = (nmethodScopes*) nm->scopes();
00980     bool update = false;
00981 
00982     // Copy the body part of the nmethodScopes
00983     int* start = (int*)(d+1);
00984     int* p     = start;
00985 
00986     d->set_nmethod_offset((char*) d - (char*) nm);
00987 
00988     codes->copy_to( p);
00989 
00990     d->set_oops_offset((char*) p - (char*) start);
00991     oops->copy_to( p);
00992 
00993     d->set_value_offset((char*) p - (char*) start);
00994     values->copy_to( p);
00995 
00996     d->set_pcs_offset((char*) p - (char*) start);
00997     pcs->copy_to( p);
00998 
00999     d->set_length((char*) p - (char*) start);
01000 
01001     d->set_dependants_end(dependants_end);
01002 
01003     assert( (char*) d + size() == (char*) p, "wrong size of nmethodScopes");
01004   }
01005 }
01006 
01007 void ScopeDescRecorder::addPcDesc(int pcOffset, ScopeInfo scope, int bci) {
01008   assert( scope, "scope must be specified in addPcDesc");
01009   assert( root, "root must be present");
01010   pcs->add(pcOffset, scope, bci);
01011 }
01012 
01013 void ScopeDescRecorder::add_dependant(LookupKey* key) {
01014   // make this nmethod dependent on the receiver klass of the lookup key.
01015   dependants->append(key->klass());
01016 }
01017 
01018 
01019 void ScopeDescRecorder::verify(nmethodScopes* scopes) {
01020   // Initialize iterator
01021   _scopes = scopes;
01022   _sd     = NULL;
01023 
01024   assert( root, "root must be present to verify");
01025   root->verify(_getNextScopeDesc());
01026   root->verifyBody();
01027 }
01028 
01029 #endif

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