00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 # include "incls/_precompiled.incl"
00025 # include "incls/_methodOop.cpp.incl"
00026 
00027 void methodOopDesc::decay_invocation_count(double decay_factor) {
00028   double new_count = (double) invocation_count() / decay_factor;
00029   set_invocation_count((int) new_count);
00030 
00031   
00032   CodeIterator c(this);
00033   do {
00034     switch(c.code()) {
00035       case Bytecodes::push_new_closure_tos_0:      
00036       case Bytecodes::push_new_closure_tos_1:      
00037       case Bytecodes::push_new_closure_tos_2:      
00038       case Bytecodes::push_new_closure_context_0:  
00039       case Bytecodes::push_new_closure_context_1:  
00040       case Bytecodes::push_new_closure_context_2: {
00041           methodOop block_method = methodOop(c.oop_at(1));
00042           assert(block_method->is_method(), "must be method");
00043           block_method->decay_invocation_count(decay_factor);
00044         }
00045         break;
00046       case Bytecodes::push_new_closure_tos_n:      
00047       case Bytecodes::push_new_closure_context_n: {
00048           methodOop block_method = methodOop(c.oop_at(2));
00049           assert(block_method->is_method(), "must be method");
00050           block_method->decay_invocation_count(decay_factor);
00051         }
00052         break;
00053     }
00054   } while (c.advance());
00055 }
00056 
00057 void methodOopDesc::inc_sharing_count() {
00058   if (sharing_count() < _sharing_count_max) {
00059     set_sharing_count(sharing_count()+1);
00060   }
00061 }
00062 
00063 void methodOopDesc::dec_sharing_count() {
00064   if (sharing_count() > 0) {
00065     set_sharing_count(sharing_count()-1);
00066   }
00067 }
00068 
00069 void methodOopDesc::bootstrap_object(bootstrap* st) {
00070   memOopDesc::bootstrap_header(st);
00071   st->read_oop((oop*)&addr()->_debugInfo);
00072   st->read_oop((oop*)&addr()->_selector_or_method);
00073   set_counters(0, 0);
00074   st->read_oop((oop*)&addr()->_size_and_flags);
00075 
00076   for(int index = 1; index <= size_of_codes() * 4; )
00077     if (st->is_byte()) {
00078       byte_at_put(index, st->read_byte());
00079       index++;
00080     } else {
00081       st->read_oop((oop*) codes(index));
00082       index += 4;
00083     }
00084 }
00085 
00086 int methodOopDesc::next_bci_from(u_char* hp) const {
00087   
00088   
00089   
00090 
00091   
00092   return (hp - (u_char*) addr()) - sizeof(methodOopDesc) + 1;
00093 }
00094 
00095 int methodOopDesc::bci_from(u_char* hp) const {
00096   
00097   return find_bci_from(next_bci_from(hp));
00098 }
00099 
00100 
00101 int methodOopDesc::number_of_arguments() const {
00102   assert(is_blockMethod() || selector()->number_of_arguments() == nofArgs(), "just checking");
00103   return nofArgs();
00104 }
00105 
00106 
00107 int methodOopDesc::number_of_stack_temporaries() const {
00108   int n = 1;            
00109   u_char b0 = *codes(1);
00110   switch (b0) {
00111     case Bytecodes::allocate_temp_1: n += 1; break;
00112     case Bytecodes::allocate_temp_2: n += 2; break;
00113     case Bytecodes::allocate_temp_3: n += 3; break;
00114     case Bytecodes::allocate_temp_n: {
00115         u_char b1 = *codes(2);
00116         n += ((b1 == 0) ? 256 : b1);
00117       }
00118       break;
00119     case Bytecodes::float_allocate: {
00120         
00121         
00122         u_char b1 = *codes(2);
00123         n += 1 + b1*2;
00124       }
00125       break;
00126   }
00127   return n;
00128 }
00129 
00130 int methodOopDesc::float_offset(int float_no) const {
00131   assert(0 <= float_no && float_no < number_of_float_temporaries(), "float_no out of range");
00132   return float_section_start_offset() - float_no*floatSize/oopSize - 1;
00133 }
00134 
00135 symbolOop methodOopDesc::enclosing_method_selector() const {
00136   assert(is_blockMethod(), "must be block method");
00137   methodOop m = parent();
00138   while (m->is_blockMethod()) m = m->parent();
00139   return m->selector();
00140 }
00141 
00142 void methodOopDesc::print_value_for(klassOop receiver_klass, outputStream* st) {
00143   outputStream* s = st ? st : std;
00144   if (is_blockMethod()) {
00145     st->print("[] in ");
00146     enclosing_method_selector()->print_symbol_on(st);
00147   } else {
00148     selector()->print_symbol_on(s);
00149   }
00150   klassOop holder = receiver_klass->klass_part()->lookup_method_holder_for(this);
00151   if (holder) {
00152     s->print(" in ");
00153     holder->klass_part()->print_name_on(s);
00154   }
00155 }
00156 
00157 void methodOopDesc::print_codes() {
00158   ResourceMark rm;
00159   selector()->print_symbol_on(std);
00160   std->cr();
00161   MethodIterator mi(this, &MethodPrinterClosure(std));
00162   std->cr();
00163 }
00164 
00165 
00166 void methodOopDesc::pretty_print() {
00167   ResourceMark rm;
00168   prettyPrinter::print(this);
00169 }
00170 
00171 
00172 symbolOop methodOopDesc::selector() const {
00173   if (selector_or_method()->is_symbol()) return symbolOop(selector_or_method());
00174   return vmSymbols::selector_for_blockMethod();
00175 }
00176 
00177 
00178 methodOop methodOopDesc::parent() const {
00179   oop t = selector_or_method();
00180   return t->is_method() ? methodOop(t) : NULL;
00181 }
00182 
00183 
00184 methodOop methodOopDesc::home() const {
00185   methodOop m = methodOop(this);
00186   while (m->is_blockMethod()) m = m->parent();
00187   return m;
00188 }
00189 
00190 
00191 byteArrayOop methodOopDesc::source() {
00192   return oopFactory::new_symbol("<no source>");
00193 }
00194 
00195 
00196 objArrayOop methodOopDesc::tempInfo() {
00197   return debugInfo();
00198 }
00199 
00200 class methodStream {
00201  public:
00202   GrowableArray<oop>* result;
00203 
00204   methodStream() {
00205     result = new GrowableArray<oop>(1000);
00206   }
00207 
00208   void put_byte(int byte) {
00209     result->append(trueObj);
00210     result->append(as_smiOop(byte));
00211   }
00212 
00213   void put_word(int word) {
00214     char* p = (char*) &word;
00215     put_byte(p[0]);
00216     put_byte(p[1]);
00217     put_byte(p[2]);
00218     put_byte(p[3]);
00219   }
00220 
00221   void put_oop(oop obj) {
00222     result->append(falseObj);
00223     result->append(obj);
00224   }
00225 
00226   void align(u_char* hp) {
00227     u_char* end = (u_char*) (((int) hp + 3) & (~3));
00228     while (hp < end) {
00229       put_byte(255);
00230       hp++;
00231     }
00232   }
00233 };
00234 
00235 objArrayOop methodOopDesc::fileout_body() {
00236   
00237   
00238   BlockScavenge bs;
00239   ResourceMark rm;
00240   methodStream out;
00241   
00242   CodeIterator c(this);
00243   do {
00244     if (Bytecodes::send_type(c.code()) != Bytecodes::no_send) {
00245       
00246       Bytecodes::Code original = Bytecodes::original_send_code_for(c.code());
00247       out.put_byte(original);
00248       if (Bytecodes::format(original) == Bytecodes::BBOO) {
00249         out.put_byte(c.byte_at(1));
00250         out.align(c.hp() + 2);
00251       } else {
00252         out.align(c.hp() + 1);
00253       }
00254       out.put_oop( c.ic()->selector());
00255       out.put_oop( smiOop_zero);
00256     } else if (c.is_primitive_call()) {
00257       
00258       Bytecodes::Code original = Bytecodes::original_primitive_call_code_for(c.code());
00259       out.put_byte(original);
00260       out.align(c.hp() + 1);
00261       if (   c.code() == Bytecodes::prim_call
00262           || c.code() == Bytecodes::prim_call_failure
00263           || c.code() == Bytecodes::prim_call_self
00264           || c.code() == Bytecodes::prim_call_self_failure) {
00265         primitive_desc* pdesc = primitives::lookup((fntype) c.word_at(1));
00266         out.put_oop(pdesc->selector());
00267       } else {
00268         out.put_oop(c.oop_at(1));
00269       }
00270       if (Bytecodes::format(original) == Bytecodes::BOL) {
00271        out.put_word(c.word_at(5));
00272       }
00273     } else if (c.is_dll_call()) {
00274       
00275       InterpretedDLL_Cache* ic = c.dll_cache();
00276       out.put_byte(c.code());
00277       out.align(c.hp() + 1);
00278       out.put_oop(ic->dll_name());
00279       out.put_oop(ic->funct_name());
00280       out.put_oop(smiOop_zero);
00281       out.put_byte(ic->number_of_arguments());
00282     } else {
00283       
00284       out.put_byte(c.code());
00285       switch(c.format()) {
00286         case Bytecodes::B:
00287           break;
00288         case Bytecodes::BB: 
00289           out.put_byte(c.byte_at(1));
00290           break;
00291         case Bytecodes::BBB:
00292           out.put_byte(c.byte_at(1));
00293           out.put_byte(c.byte_at(2));
00294           break;
00295         case Bytecodes::BBBB:
00296           out.put_byte(c.byte_at(1));
00297           out.put_byte(c.byte_at(2));
00298           out.put_byte(c.byte_at(3));
00299           break;
00300         case Bytecodes::BBO:
00301           out.put_byte(c.byte_at(1));
00302           out.align(c.hp() + 2);
00303           out.put_oop( c.oop_at(2));
00304           break;
00305         case Bytecodes::BBL:
00306           out.put_byte(c.byte_at(1));
00307           out.align(c.hp() + 2);
00308           out.put_word(c.word_at(2));
00309           break;
00310         case Bytecodes::BO:
00311           out.align(c.hp() + 1);
00312           out.put_oop( c.oop_at(1));
00313           break;
00314         case Bytecodes::BOL:
00315           out.put_oop( c.oop_at(1));
00316           out.align(c.hp() + 2);
00317           out.put_word(c.word_at(5));
00318           break;
00319         case Bytecodes::BLL:
00320           out.align(c.hp() + 1);
00321           out.put_word(c.word_at(1));
00322           out.put_word(c.word_at(5));
00323           break;
00324         case Bytecodes::BL:
00325           out.align(c.hp() + 1);
00326           out.put_word(c.word_at(1));
00327           break;
00328         case Bytecodes::BBS: {
00329             int length = c.byte_at(1) == 0 ? 256 : c.byte_at(1);
00330             out.put_byte(length);
00331             for(int index = 0; index < length; index++) {
00332               out.put_byte(c.byte_at(2 + index));
00333             }
00334             break;
00335         }
00336         default:
00337           std->print_cr("Format unknown %s", Bytecodes::format_as_string(c.format()));
00338           fatal("aborting");
00339       }
00340     }
00341   } while (c.advance());
00342   return oopFactory::new_objArray(out.result);
00343 }
00344 
00345 methodOopDesc::Method_Inlining_Info methodOopDesc::method_inlining_info() const {
00346   if (is_blockMethod()) return normal_inline;
00347   Method_Inlining_Info info = Method_Inlining_Info(get_unsigned_bitfield(flags(), methodInfoFlags, methodInfoSize));
00348   return info;
00349 }
00350 
00351 void methodOopDesc::set_method_inlining_info(Method_Inlining_Info info) {
00352   if (is_blockMethod()) return;
00353   set_flags(set_unsigned_bitfield(flags(), methodInfoFlags, methodInfoSize, info));
00354 }
00355 
00356 methodOopDesc::Block_Info methodOopDesc::block_info() const {
00357   assert(is_blockMethod(), "must be a block");
00358   return Block_Info(get_unsigned_bitfield(flags(), blockInfoFlags, blockInfoSize));
00359 }
00360 
00361 bool methodOopDesc::in_context_allocation(int bci) const {
00362   CodeIterator c(methodOop(this), bci);
00363   return c.code_type() == Bytecodes::new_context;
00364 }
00365 
00366 class BlockFinderClosure : public SpecializedMethodClosure {
00367 public:
00368   bool hasBlock;
00369   BlockFinderClosure() { hasBlock = false; }
00370   void allocate_closure(AllocationType type, int nofArgs, methodOop meth) { hasBlock = true; }
00371 };
00372 
00373 bool methodOopDesc::hasNestedBlocks() const {
00374   
00375   BlockFinderClosure cl;
00376   MethodIterator it(methodOop(this), &cl);
00377   return cl.hasBlock;
00378 }
00379 
00380 
00381 
00382 
00383 
00384 
00385 
00386 
00387 
00388 
00389 
00390 int methodOopDesc::lexicalDistance(int contextNo) {
00391   methodOop m = this;
00392   int c = -1;
00393   int d = -1;
00394   while (c < contextNo) {
00395     if (m->allocatesInterpretedContext()) c++;
00396     m = m->parent();
00397     d++;
00398   };
00399   return d;
00400 }
00401 
00402 
00403 int methodOopDesc::contextNo(int lexicalDistance) {
00404   methodOop m = this;
00405   int c = -1;
00406   int d = -1;
00407   while (d < lexicalDistance) {
00408     if (m->allocatesInterpretedContext()) c++;
00409     m = m->parent();
00410     d++;
00411   }
00412   return c;
00413 }
00414 
00415 int methodOopDesc::context_chain_length() const {
00416   int length = 0;
00417   for (methodOop method = methodOop(this); method; method = method->parent()) {
00418     if (method->allocatesInterpretedContext())
00419       length++;
00420   }
00421   return length;
00422 }
00423 
00424 void methodOopDesc::clear_inline_caches() {
00425   
00426   
00427   if (!is_customized()) return;
00428 
00429   CodeIterator c(this);
00430   do {
00431     InterpretedIC* ic = c.ic();
00432     if (ic) {
00433       ic->clear();
00434     } else {
00435       
00436       switch(c.code()) {
00437       case Bytecodes::push_new_closure_tos_0:      
00438       case Bytecodes::push_new_closure_tos_1:      
00439       case Bytecodes::push_new_closure_tos_2:      
00440       case Bytecodes::push_new_closure_context_0:  
00441       case Bytecodes::push_new_closure_context_1:  
00442       case Bytecodes::push_new_closure_context_2: {
00443           methodOop block_method = methodOop(c.oop_at(1));
00444           assert(block_method->is_method(), "must be method");
00445           block_method->clear_inline_caches();
00446         }
00447         break;
00448       case Bytecodes::push_new_closure_tos_n:      
00449       case Bytecodes::push_new_closure_context_n: {
00450           methodOop block_method = methodOop(c.oop_at(2));
00451           assert(block_method->is_method(), "must be method");
00452           block_method->clear_inline_caches();
00453         }
00454         break;
00455       }
00456     }
00457   } while (c.advance());
00458 }
00459 
00460 void methodOopDesc::cleanup_inline_caches() {
00461   
00462   
00463   if (!is_customized()) return;
00464 
00465   CodeIterator c(this);
00466   do {
00467     InterpretedIC* ic = c.ic();
00468     if (ic) {
00469       ic->cleanup();
00470     } else {
00471       methodOop bm = c.block_method();
00472       if (bm) {
00473         bm->cleanup_inline_caches();
00474       }
00475     }
00476   } while (c.advance());
00477 }
00478 
00479 
00480 bool methodOopDesc::was_never_executed() {
00481   
00482   if (!is_customized()) return true;
00483 
00484   
00485   if (invocation_count() != 0 || sharing_count() != 0) return false;
00486   CodeIterator c(this);
00487   do {
00488     InterpretedIC* ic = c.ic();
00489     if (ic && !ic->is_empty()) return false;
00490   } while (c.advance());
00491   return true;
00492 }
00493 
00494 int methodOopDesc::estimated_inline_cost(klassOop receiverKlass) {
00495   
00496   CodeIterator c(this);
00497   int cost = 0;
00498   do {
00499     cost += CostModel::cost_for(c.code());
00500     switch (c.code()) {
00501       case Bytecodes::push_new_closure_context_0:
00502       case Bytecodes::push_new_closure_context_1:
00503       case Bytecodes::push_new_closure_context_2:
00504       case Bytecodes::push_new_closure_tos_0:
00505       case Bytecodes::push_new_closure_tos_1:
00506       case Bytecodes::push_new_closure_tos_2: {
00507         methodOop m = methodOop(c.oop_at(1));
00508         assert(m->is_method(), "must be method");
00509         cost += m->estimated_inline_cost(receiverKlass);
00510         break;
00511       }
00512       case Bytecodes::push_new_closure_tos_n:
00513       case Bytecodes::push_new_closure_context_n: {
00514         methodOop m = methodOop(c.oop_at(2));
00515         assert(m->is_method(), "must be method");
00516         cost += m->estimated_inline_cost(receiverKlass);
00517         break;
00518       }
00519     }
00520     extern bool SuperSendsAreAlwaysInlined;
00521     if (Bytecodes::is_super_send(c.code()) && SuperSendsAreAlwaysInlined && receiverKlass) {
00522       klassOop mh = receiverKlass->klass_part()->lookup_method_holder_for(this);
00523       methodOop superMethod = mh ? lookupCache::compile_time_super_lookup(mh, selector()) : NULL;
00524       if (superMethod) cost += superMethod->estimated_inline_cost(receiverKlass);
00525     }
00526   } while (c.advance());
00527   return cost;
00528 }
00529 
00530 
00531 int methodOopDesc::find_bci_from(int nbci) const {
00532   CodeIterator c(methodOop(this));
00533   int prev_bci = 1;
00534   do {
00535     if (c.bci() == nbci) return prev_bci; 
00536     prev_bci = c.bci();
00537   } while (c.advance());
00538   return -1;
00539 }
00540 
00541 
00542 int methodOopDesc::next_bci(int bci) const {
00543   CodeIterator c(methodOop(this), bci);
00544   c.advance();
00545   return c.bci();
00546 }
00547 
00548 
00549 class ExpressionStackMapper : public MethodClosure {
00550  private:
00551    GrowableArray<int>* mapping;
00552    int target_bci;
00553 
00554    void map_push() { map_push(bci()); }
00555 
00556    void map_push(int b)  {
00557      
00558      if (b >= target_bci) {
00559        abort();
00560      } else {
00561        mapping->push(b);
00562      }
00563    }
00564 
00565    void map_pop() {
00566      if (bci() >= target_bci) {
00567        abort();
00568      } else {
00569        
00570        mapping->pop();
00571      }
00572    }
00573 
00574    void map_send(bool has_receiver, int number_of_arguments) {
00575      if (has_receiver) map_pop();
00576      for(int i = 0; i < number_of_arguments; i++) map_pop();
00577      map_push();
00578    }
00579 
00580  public:
00581   ExpressionStackMapper(GrowableArray<int>* mapping, int target_bci) {
00582     this->mapping    = mapping;
00583     this->target_bci = target_bci;
00584   }
00585 
00586   void push_self()                              { map_push(); }
00587   void push_tos()                               { map_push(); }  
00588   void push_literal(oop obj)                    { map_push(); }
00589   void push_argument(int no)                    { map_push(); }
00590   void push_temporary(int no)                   { map_push(); }
00591   void push_temporary(int no, int context)      { map_push(); }
00592   void push_instVar(int offset)                 { map_push(); }
00593   void push_instVar_name(symbolOop name)        { map_push(); }
00594   void push_classVar(associationOop assoc)      { map_push(); }
00595   void push_classVar_name(symbolOop name)       { map_push(); }
00596 
00597   void push_global(associationOop obj)          { map_push(); }
00598 
00599   void pop()                                    { map_pop(); }
00600 
00601   void normal_send(InterpretedIC* ic)           { map_send(true,  ic->selector()->number_of_arguments()); }
00602   void self_send(InterpretedIC* ic)             { map_send(false, ic->selector()->number_of_arguments()); }
00603   void super_send(InterpretedIC* ic)            { map_send(false, ic->selector()->number_of_arguments()); }
00604 
00605   void double_equal()                           { map_send(true, 1); }
00606   void double_not_equal()                       { map_send(true, 1); }
00607 
00608   void method_return(int nofArgs)               { map_pop(); }
00609   void nonlocal_return(int nofArgs)             { map_pop(); }
00610 
00611   void allocate_closure(AllocationType type, int nofArgs, methodOop meth) {
00612     if (type == tos_as_scope) map_pop(); 
00613     map_push();
00614   }
00615 
00616   
00617   void if_node(IfNode* node);
00618   void cond_node(CondNode* node);
00619   void while_node(WhileNode* node);
00620   void primitive_call_node(PrimitiveCallNode* node);
00621   void dll_call_node(DLLCallNode* node);
00622 
00623   
00624   void allocate_temporaries(int nofTemps)                          {}
00625   void store_temporary(int no)                                     {}
00626   void store_temporary(int no, int context)                        {}
00627   void store_instVar(int offset)                                   {}
00628   void store_instVar_name(symbolOop name)                          {}
00629   void store_classVar(associationOop assoc)                        {}
00630   void store_classVar_name(symbolOop name)                         {}
00631 
00632   void store_global(associationOop obj)                            {} 
00633   void allocate_context(int nofTemps, bool forMethod = false)      {}
00634   void set_self_via_context()                                      {}
00635   void copy_self_into_context()                                    {}
00636   void copy_argument_into_context(int argNo, int no)               {}
00637   void zap_scope()                                                 {}
00638   void predict_prim_call(primitive_desc* pdesc, int failure_start) {}
00639   void float_allocate(int nofFloatTemps, int nofFloatExprs)        {}
00640   void float_floatify(Floats::Function f, int tof)                 { map_pop(); }
00641   void float_move(int tof, int from)                               {}
00642   void float_set(int tof, doubleOop value)                         {}
00643   void float_nullary(Floats::Function f, int tof)                  {}
00644   void float_unary(Floats::Function f, int tof)                    {}
00645   void float_binary(Floats::Function f, int tof)                   {}
00646   void float_unaryToOop(Floats::Function f, int tof)               { map_push(); }
00647   void float_binaryToOop(Floats::Function f, int tof)              { map_push(); }
00648 };
00649 
00650 
00651 void ExpressionStackMapper::if_node(IfNode* node) {
00652   if (node->includes(target_bci)) {
00653     if (node->then_code()->includes(target_bci)) {
00654       map_pop();
00655       MethodIterator i(node->then_code(), this);
00656     } else if (node->else_code() && node->else_code()->includes(target_bci)) {
00657       map_pop();
00658       MethodIterator i(node->else_code(), this);
00659     }
00660     abort();
00661   } else {
00662     map_pop();
00663     if (node->produces_result())
00664       map_push(node->begin_bci());
00665   }
00666 }
00667 
00668 
00669 void ExpressionStackMapper::cond_node(CondNode* node) {
00670   if (node->includes(target_bci)) {
00671     if (node->expr_code()->includes(target_bci)) {
00672       map_pop();
00673       MethodIterator i(node->expr_code(), this);
00674     }
00675     abort();
00676   } else {
00677     map_pop();
00678     map_push(node->begin_bci());
00679   }
00680 }
00681 
00682 
00683 void ExpressionStackMapper::while_node(WhileNode* node) {
00684   if (node->includes(target_bci)) {
00685     if (node->expr_code()->includes(target_bci))
00686       MethodIterator i(node->expr_code(), this);
00687     else if (node->body_code() && node->body_code()->includes(target_bci))
00688       MethodIterator i(node->body_code(), this);
00689     abort();
00690   }
00691 }
00692 
00693 
00694 void ExpressionStackMapper::primitive_call_node(PrimitiveCallNode* node) {
00695   int nofArgsToPop = node->number_of_parameters();
00696   for(int i = 0; i < nofArgsToPop; i++) map_pop();
00697 
00698   map_push();
00699   if (node->failure_code() && node->failure_code()->includes(target_bci)) {
00700     MethodIterator i(node->failure_code(), this);
00701   }
00702 }
00703 
00704 
00705 void ExpressionStackMapper::dll_call_node(DLLCallNode* node) {
00706   int nargs = node->nofArgs();
00707   for (int index = 0; index < nargs; index++)
00708     map_pop();
00709 }
00710 
00711 
00712 GrowableArray<int>* methodOopDesc::expression_stack_mapping(int bci) {
00713   GrowableArray<int>* mapping = new GrowableArray<int>(10);
00714   ExpressionStackMapper blk(mapping, bci);
00715   MethodIterator i(this, &blk);
00716 
00717   
00718   
00719   
00720 
00721   GrowableArray<int>* result = new GrowableArray<int>(mapping->length());
00722   for (int index = mapping->length() - 1; index >= 0; index--) {
00723     result->push(mapping->at(index));
00724   }
00725   return result;
00726 }
00727 
00728 
00729 static void lookup_primitive_and_patch(u_char* p, u_char byte) {
00730   assert((int)p % 4 == 0, "first instruction supposed to be aligned");
00731   *p = byte;    
00732   p += 4;       
00733   
00734   *(int*)p = (int)primitives::lookup(*(symbolOop*)p)->fn();
00735 }
00736 
00737 bool methodOopDesc::is_primitiveMethod() const {
00738   char b = *codes();
00739   switch (*codes()) {
00740     case Bytecodes::predict_prim_call:
00741       return true;
00742     case Bytecodes::predict_prim_call_failure:
00743       return true;
00744     case Bytecodes::predict_prim_call_lookup:
00745       lookup_primitive_and_patch(codes(), Bytecodes::predict_prim_call);
00746       return true;
00747     case Bytecodes::predict_prim_call_failure_lookup:
00748       lookup_primitive_and_patch(codes(), Bytecodes::predict_prim_call_failure);
00749       return true;
00750     default:
00751       return false;
00752   }
00753 }
00754 
00755 
00756 Bytecodes::Code methodOopDesc::special_primitive_code() const {
00757   assert(is_special_primitiveMethod(), "should only be called for special primitive methods");
00758   Bytecodes::Code code = Bytecodes::Code(*codes(2));
00759   assert(Bytecodes::send_type(code) == Bytecodes::predicted_send, "code or bytecode table inconsistent");
00760   return code;
00761 }
00762 
00763 
00764 methodOop methodOopDesc::methodOop_from_hcode(u_char* hp) {
00765   methodOop method = methodOop(as_memOop(Universe::object_start((oop*) hp)));
00766   assert(method->is_method(), "must be method");
00767   assert(method->codes() <= hp && hp < method->codes() + method->size_of_codes() * sizeof(oop),
00768          "h-code pointer not contained in method");
00769   return method;
00770 }
00771 
00772 
00773 int methodOopDesc::end_bci() const {
00774   int last_entry = this->size_of_codes() * 4;
00775   for (int index = 0; index < 4; index++)
00776     if (byte_at(last_entry-index) != Bytecodes::halt) return last_entry+1-index;
00777   fatal("should never reach the point");
00778   return 0;
00779 }
00780 
00781 
00782 InterpretedIC* methodOopDesc::ic_at(int bci) const {
00783    CodeIterator iterator(methodOop(this), bci);
00784    return iterator.ic();
00785 }
00786 
00787 methodOop methodOopDesc::block_method_at(int bci) {
00788   CodeIterator c(methodOop(this), bci);
00789   switch(c.code()) {
00790     case Bytecodes::push_new_closure_tos_0:      
00791     case Bytecodes::push_new_closure_tos_1:      
00792     case Bytecodes::push_new_closure_tos_2:      
00793     case Bytecodes::push_new_closure_context_0:  
00794     case Bytecodes::push_new_closure_context_1:  
00795     case Bytecodes::push_new_closure_context_2: {
00796         methodOop block_method = methodOop(c.oop_at(1));
00797         assert(block_method->is_method(), "must be method");
00798         return block_method;
00799       }
00800       break;
00801     case Bytecodes::push_new_closure_tos_n:      
00802     case Bytecodes::push_new_closure_context_n: {
00803         methodOop block_method = methodOop(c.oop_at(2));
00804         assert(block_method->is_method(), "must be method");
00805         return block_method;
00806       }
00807       break;
00808    }
00809   return NULL;
00810 }
00811 
00812 int methodOopDesc::bci_for_block_method(methodOop inner) {
00813   CodeIterator c(this);
00814   do {
00815     if (inner == block_method_at(c.bci()))
00816       return c.bci();
00817   } while (c.advance());
00818   ShouldNotReachHere();
00819   return 0;
00820 }
00821 
00822 void methodOopDesc::print_inlining_database_on(outputStream* st) {
00823   if (is_blockMethod()) {
00824     methodOop o = parent();
00825     o->print_inlining_database_on(st);
00826     st->print(" %d", o->bci_for_block_method(this));
00827   } else {
00828     selector()->print_symbol_on(st);
00829   }
00830 }
00831 
00832 
00833 
00834 class ContextMethodIterator : public SpecializedMethodClosure {
00835  private:
00836   enum { sentinel = -1 };
00837   int  count;
00838   bool _self_in_context;
00839 
00840  public:
00841   ContextMethodIterator() {
00842     count = sentinel;
00843     _self_in_context = false;
00844   }
00845 
00846   bool self_in_context() { return _self_in_context; }
00847 
00848   int number_of_context_temporaries() {
00849     assert(count != sentinel, "number_of_context_temporaries not set");
00850     return count;
00851   }
00852 
00853   void allocate_context(int nofTemps, bool forMethod) {
00854     assert(count == sentinel, "make sure it is not called more than one");
00855     count = nofTemps;
00856   }
00857 
00858   void copy_self_into_context() {
00859     _self_in_context = true; 
00860   }
00861 };
00862 
00863 int methodOopDesc::number_of_context_temporaries(bool* self_in_context) {
00864   
00865   assert(allocatesInterpretedContext(), "can only be called if method allocates context");
00866   ContextMethodIterator blk;
00867   MethodIterator i(this, &blk);
00868   if (self_in_context) *self_in_context = blk.self_in_context();
00869   return blk.number_of_context_temporaries();
00870 }
00871 
00872 void methodOopDesc::customize_for(klassOop klass, mixinOop mixin) {
00873   assert(!is_customized() ||  klass != mixin->primary_invocation(), "should not recustomize to the same class"); 
00874   CodeIterator c(this);
00875   do {
00876     InterpretedIC* ic = c.ic();
00877     if (ic) ic->clear_without_deallocation_pic();
00878     switch(c.code()) {
00879 
00880       case Bytecodes::push_classVar_name:
00881       case Bytecodes::store_classVar_pop_name:
00882       case Bytecodes::store_classVar_name:
00883         c.customize_class_var_code(klass);
00884         break;
00885 
00886       case Bytecodes::push_classVar:
00887       case Bytecodes::store_classVar_pop:
00888       case Bytecodes::store_classVar:
00889         c.recustomize_class_var_code(mixin->primary_invocation(), klass);
00890         break;
00891 
00892       case Bytecodes::push_instVar_name:
00893       case Bytecodes::store_instVar_pop_name:
00894       case Bytecodes::store_instVar_name: 
00895       case Bytecodes::return_instVar_name:
00896         c.customize_inst_var_code(klass);
00897         break;
00898 
00899       case Bytecodes::push_instVar:
00900       case Bytecodes::store_instVar_pop:
00901       case Bytecodes::store_instVar: 
00902       case Bytecodes::return_instVar:
00903         c.recustomize_inst_var_code(mixin->primary_invocation(), klass);
00904         break;
00905 
00906       case Bytecodes::push_new_closure_tos_0:      
00907       case Bytecodes::push_new_closure_tos_1:      
00908       case Bytecodes::push_new_closure_tos_2:      
00909       case Bytecodes::push_new_closure_context_0:  
00910       case Bytecodes::push_new_closure_context_1:  
00911       case Bytecodes::push_new_closure_context_2: {
00912           methodOop block_method = methodOop(c.oop_at(1));
00913           assert(block_method->is_method(), "must be method");
00914           block_method->customize_for(klass, mixin);
00915         }
00916         break;
00917       case Bytecodes::push_new_closure_tos_n:      
00918       case Bytecodes::push_new_closure_context_n: {
00919           methodOop block_method = methodOop(c.oop_at(2));
00920           assert(block_method->is_method(), "must be method");
00921           block_method->customize_for(klass, mixin);
00922         }
00923         break;
00924     }
00925   } while (c.advance());
00926   
00927 
00928   int new_flags = addNth(flags(), isCustomizedFlag);
00929   set_size_and_flags(size_of_codes(), nofArgs(), new_flags);
00930 }
00931 
00932 void methodOopDesc::uncustomize_for(mixinOop mixin) {
00933   
00934   if (!is_customized()) return;
00935 
00936   klassOop klass = mixin->primary_invocation();
00937   assert(klass->is_klass(), "primary invocation muyst be present");
00938 
00939   CodeIterator c(this);
00940   do {
00941     InterpretedIC* ic = c.ic();
00942     if (ic) ic->clear_without_deallocation_pic();
00943     switch(c.code()) {
00944       case Bytecodes::push_classVar:
00945       case Bytecodes::store_classVar_pop:
00946       case Bytecodes::store_classVar:
00947         c.uncustomize_class_var_code(mixin->primary_invocation());
00948         break;
00949 
00950       case Bytecodes::push_instVar:
00951       case Bytecodes::store_instVar_pop:
00952       case Bytecodes::store_instVar: 
00953       case Bytecodes::return_instVar:
00954         c.uncustomize_inst_var_code(mixin->primary_invocation());
00955         break;
00956 
00957       case Bytecodes::push_new_closure_tos_0:      
00958       case Bytecodes::push_new_closure_tos_1:      
00959       case Bytecodes::push_new_closure_tos_2:      
00960       case Bytecodes::push_new_closure_context_0:  
00961       case Bytecodes::push_new_closure_context_1:  
00962       case Bytecodes::push_new_closure_context_2: {
00963           methodOop block_method = methodOop(c.oop_at(1));
00964           assert(block_method->is_method(), "must be method");
00965           block_method->uncustomize_for(mixin);
00966         }
00967         break;
00968       case Bytecodes::push_new_closure_tos_n:      
00969       case Bytecodes::push_new_closure_context_n: {
00970           methodOop block_method = methodOop(c.oop_at(2));
00971           assert(block_method->is_method(), "must be method");
00972           block_method->uncustomize_for(mixin);
00973         }
00974         break;
00975     }
00976   } while (c.advance());
00977   
00978   int new_flags = subNth(flags(), isCustomizedFlag);
00979   set_size_and_flags(size_of_codes(), nofArgs(), new_flags);
00980 }
00981 
00982 methodOop methodOopDesc::copy_for_customization() const {
00983   
00984   int  len   = size();
00985   oop* clone = Universe::allocate_tenured(len);
00986   oop* to    = clone;
00987   oop* from  = (oop*) addr();
00988   oop* end   = to + len;
00989   while (to < end) *to++ = *from++;
00990 
00991   
00992   methodOop new_method = methodOop(as_memOop(clone));
00993   CodeIterator c(new_method);
00994   do {
00995     switch(c.code()) {
00996       case Bytecodes::push_new_closure_tos_0:      
00997       case Bytecodes::push_new_closure_tos_1:      
00998       case Bytecodes::push_new_closure_tos_2:      
00999       case Bytecodes::push_new_closure_context_0:  
01000       case Bytecodes::push_new_closure_context_1:  
01001       case Bytecodes::push_new_closure_context_2: {
01002           methodOop block_method = methodOop(c.oop_at(1));
01003           assert(block_method->is_method(), "must be method");
01004           methodOop new_block_method = block_method->copy_for_customization();
01005           new_block_method->set_selector_or_method(new_method);
01006           Universe::store(c.aligned_oop(1), new_block_method);
01007         }
01008         break;
01009       case Bytecodes::push_new_closure_tos_n:      
01010       case Bytecodes::push_new_closure_context_n: {
01011           methodOop block_method = methodOop(c.oop_at(2));
01012           assert(block_method->is_method(), "must be method");
01013           methodOop new_block_method = block_method->copy_for_customization();
01014           new_block_method->set_selector_or_method(new_method);
01015           Universe::store(c.aligned_oop(2), new_block_method);
01016         }
01017         break;
01018     }
01019   } while (c.advance());
01020   return new_method;
01021 }
01022 
01023 void methodOopDesc::verify_context(contextOop con) {
01024   
01025   if (!activation_has_context()) {
01026     warning("Activation has no context (0x%lx).", con);
01027   }
01028   
01029   if (context_chain_length() != con->chain_length()) {
01030     warning("Wong context chain length (got %d expected %d)",
01031             con->chain_length(), context_chain_length());
01032   }
01033   
01034   if (con->unoptimized_context() != NULL) {
01035     warning("Context is optimized (0x%lx).", con);
01036   }
01037 }
01038 
01039 
01040 class TransitiveMethodClosure: public MethodClosure {
01041  public:
01042   void if_node(IfNode* node);
01043   void cond_node(CondNode* node);
01044   void while_node(WhileNode* node);
01045   void primitive_call_node(PrimitiveCallNode* node);
01046   void dll_call_node(DLLCallNode* node);
01047  
01048  public:
01049   virtual void inlined_send(symbolOop selector) {} 
01050 
01051  public:
01052   void allocate_temporaries(int nofTemps)                                       {}
01053   void push_self()                                                              {}
01054   void push_tos()                                                               {}
01055   void push_literal(oop obj)                                                    {}
01056   void push_argument(int no)                                                    {}
01057   void push_temporary(int no)                                                   {}
01058   void push_temporary(int no, int context)                                      {}
01059   void push_instVar(int offset)                                                 {}
01060   void push_instVar_name(symbolOop name)                                        {}
01061   void push_classVar(associationOop assoc)                                      {}
01062   void push_classVar_name(symbolOop name)                                       {}
01063   void push_global(associationOop obj)                                          {}
01064   void store_temporary(int no)                                                  {}
01065   void store_temporary(int no, int context)                                     {}
01066   void store_instVar(int offset)                                                {}
01067   void store_instVar_name(symbolOop name)                                       {}
01068   void store_classVar(associationOop assoc)                                     {}
01069   void store_classVar_name(symbolOop name)                                      {}
01070   void store_global(associationOop obj)                                         {}
01071   void pop()                                                                    {}
01072   void normal_send(InterpretedIC* ic)                                           {}
01073   void self_send  (InterpretedIC* ic)                                           {}
01074   void super_send (InterpretedIC* ic)                                           {}
01075   void double_equal()                                                           {}
01076   void double_not_equal()                                                       {}
01077   void method_return(int nofArgs)                                               {}
01078   void nonlocal_return(int nofArgs)                                             {}
01079   void allocate_closure(AllocationType type, int nofArgs, methodOop meth);
01080   void allocate_context(int nofTemps, bool forMethod)                           {}
01081   void set_self_via_context()                                                   {}
01082   void copy_self_into_context()                                                 {}
01083   void copy_argument_into_context(int argNo, int no)                            {}
01084   void zap_scope()                                                              {}
01085   void predict_prim_call(primitive_desc* pdesc, int failure_start)              {}
01086   void float_allocate(int nofFloatTemps, int nofFloatExprs)                     {}
01087   void float_floatify(Floats::Function f, int fno)                              {}
01088   void float_move(int fno, int from)                                            {}
01089   void float_set(int fno, doubleOop value)                                      {}
01090   void float_nullary(Floats::Function f, int fno)                               {}
01091   void float_unary(Floats::Function f, int fno)                                 {}
01092   void float_binary(Floats::Function f, int fno)                                {}
01093   void float_unaryToOop(Floats::Function f, int fno)                            {}
01094   void float_binaryToOop(Floats::Function f, int fno)                           {}
01095 };
01096 
01097 void TransitiveMethodClosure::allocate_closure(AllocationType type, int nofArgs, methodOop meth) {
01098   MethodIterator iter(meth, this);
01099 }
01100 
01101 void TransitiveMethodClosure::if_node(IfNode* node) {
01102   inlined_send(node->selector());
01103   MethodIterator iter(node->then_code(), this);
01104   if (node->else_code() != NULL) {
01105     MethodIterator iter(node->else_code(), this);
01106   }
01107 }
01108 
01109 void TransitiveMethodClosure::cond_node(CondNode* node) {
01110   inlined_send(node->selector());
01111   MethodIterator iter(node->expr_code(), this);
01112 }
01113 
01114 void TransitiveMethodClosure::while_node(WhileNode* node) {
01115   inlined_send(node->selector());
01116   MethodIterator iter(node->expr_code(), this);
01117   if (node->body_code() != NULL) {
01118     MethodIterator iter(node->body_code(), this);
01119   }
01120 }
01121 
01122 void TransitiveMethodClosure::primitive_call_node(PrimitiveCallNode* node) {
01123   inlined_send(node->name());
01124   if (node->failure_code() != NULL) {
01125     MethodIterator iter(node->failure_code(), this);
01126   }
01127 }
01128 
01129 void TransitiveMethodClosure::dll_call_node(DLLCallNode* node) {
01130   inlined_send(node->function_name());
01131   if (node->failure_code() != NULL) {
01132     MethodIterator iter(node->failure_code(), this);
01133   }
01134 }
01135 
01136 class ReferencedInstVarNamesClosure: public TransitiveMethodClosure {
01137  private:
01138   mixinOop mixin;
01139 
01140   void collect(int offset) {
01141     symbolOop name = mixin->primary_invocation()->klass_part()->inst_var_name_at(offset);
01142     if (name) result->append(name);
01143   }
01144 
01145   void collect(symbolOop name) {
01146     result->append(name);
01147   }
01148 
01149  public:
01150   void push_instVar(int offset)           { collect(offset); }
01151   void push_instVar_name(symbolOop name)  { collect(name);   }
01152   void store_instVar(int offset)          { collect(offset); }
01153   void store_instVar_name(symbolOop name) { collect(name);   }
01154  public:
01155   ReferencedInstVarNamesClosure(int size, mixinOop mixin) {
01156     this->result = new GrowableArray<oop>(size);
01157     this->mixin  = mixin;
01158   }
01159   GrowableArray<oop>* result; 
01160 };
01161 
01162 objArrayOop methodOopDesc::referenced_instance_variable_names(mixinOop mixin) const {
01163   ResourceMark rm;
01164   ReferencedInstVarNamesClosure blk(20, mixin);
01165   MethodIterator(methodOop(this), &blk);
01166   return oopFactory::new_objArray(blk.result);
01167 }
01168 
01169 class ReferencedClassVarNamesClosure: public TransitiveMethodClosure {
01170  private:
01171   void collect(symbolOop name) { result->append(name); }
01172  public:
01173   void push_classVar(associationOop assoc)  { collect(assoc->key()); }
01174   void push_classVar_name(symbolOop name)   { collect(name);         }
01175 
01176   void store_classVar(associationOop assoc) { collect(assoc->key()); }
01177   void store_classVar_name(symbolOop name)  { collect(name);         }
01178 
01179  public:
01180   ReferencedClassVarNamesClosure(int size) {
01181     result = new GrowableArray<oop>(size);
01182   }
01183   GrowableArray<oop>* result; 
01184 };
01185 
01186 objArrayOop methodOopDesc::referenced_class_variable_names() const {
01187   ResourceMark rm;
01188   ReferencedClassVarNamesClosure blk(20);
01189   MethodIterator(methodOop(this), &blk);
01190   return oopFactory::new_objArray(blk.result);
01191 }
01192 
01193 class ReferencedGlobalsClosure: public TransitiveMethodClosure {
01194  private:
01195   void collect(symbolOop selector) { result->append(selector); }
01196  public:
01197   void push_global(associationOop obj)  { collect(obj->key());}
01198   void store_global(associationOop obj) { collect(obj->key());}
01199 
01200  public:
01201   ReferencedGlobalsClosure(int size) {
01202     result = new GrowableArray<oop>(size);
01203   }
01204   GrowableArray<oop>* result; 
01205 };
01206 
01207 objArrayOop methodOopDesc::referenced_global_names() const {
01208   ResourceMark rm;
01209   ReferencedGlobalsClosure blk(20);
01210   MethodIterator(methodOop(this), &blk);
01211   return oopFactory::new_objArray(blk.result);
01212 }
01213 
01214 class SendersClosure: public TransitiveMethodClosure {
01215  private:
01216   void collect(symbolOop selector) { result->append(selector); }
01217 
01218   void float_op(Floats::Function f) {
01219     if (Floats::has_selector_for(f)) {
01220       collect(Floats::selector_for(f));
01221     }
01222   }
01223  public:
01224   void inlined_send(symbolOop selector) { collect(selector);       }
01225   void normal_send(InterpretedIC* ic)   { collect(ic->selector()); }
01226   void self_send  (InterpretedIC* ic)   { collect(ic->selector()); }
01227   void super_send (InterpretedIC* ic)   { collect(ic->selector()); }
01228   void double_equal()                   { collect(vmSymbols::double_equal());     }
01229   void double_not_equal()               { collect(vmSymbols::double_tilde());     }
01230 
01231   void float_floatify(Floats::Function f,    int fno) { float_op(f); }
01232   void float_nullary(Floats::Function f,     int fno) { float_op(f); }
01233   void float_unary(Floats::Function f,       int fno) { float_op(f); }
01234   void float_binary(Floats::Function f,      int fno) { float_op(f); }
01235   void float_unaryToOop(Floats::Function f,  int fno) { float_op(f); }
01236   void float_binaryToOop(Floats::Function f, int fno) { float_op(f); }
01237 
01238  public:
01239   SendersClosure(int size) {
01240     result = new GrowableArray<oop>(size);
01241   }
01242   GrowableArray<oop>* result; 
01243 };
01244 
01245 objArrayOop methodOopDesc::senders() const {
01246   ResourceMark rm;
01247   SendersClosure blk(20);
01248   MethodIterator(methodOop(this), &blk);
01249   return oopFactory::new_objArray(blk.result);
01250 }