interpretedIC.cpp

Go to the documentation of this file.
00001 /* Copyright 1994 - 1996, LongView Technologies, L.L.C. $Revision: 1.34 $ */
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 
00025 # include "incls/_precompiled.incl"
00026 # include "incls/_interpretedIC.cpp.incl"
00027 
00028 
00029 // Implementation of Interpreter_PICs
00030 //
00031 // A simple free list manager for interpreted PICs.
00032 
00033 class Interpreter_PICs : AllStatic {
00034  public:
00035   static objArrayOop free_list() { return Universe::pic_free_list(); }
00036 
00037   static objArrayOop allocate(int size) {
00038     oop first = free_list()->obj_at(size - 1);
00039     if (first == nilObj) {
00040       return objArrayKlass::allocate_tenured_pic(size*2);
00041     }
00042     free_list()->obj_at_put(size - 1, objArrayOop(first)->obj_at(1));
00043 
00044     objArrayOop result = objArrayOop(first);
00045     assert(result->is_objArray(),        "must be object array");
00046     assert(result->is_old(),             "must be tenures");
00047     assert(result->length() == size * 2, "checking size");
00048     return result;
00049   }
00050 
00051   static objArrayOop extend(objArrayOop old_pic) {
00052     int old_size = old_pic->length()/2;
00053     if (old_size >= size_of_largest_interpreterPIC) return NULL;
00054     objArrayOop result = allocate(old_size + 1);
00055     for (int index = 1; index <= old_size*2; index++) {
00056       result->obj_at_put(index, old_pic->obj_at(index));
00057     }
00058     return result;
00059   }
00060 
00061   static void deallocate(objArrayOop pic) {
00062     int entry = (pic->length()/2) - 1;
00063     oop first = free_list()->obj_at(entry);
00064     pic->obj_at_put(1, first);
00065     free_list()->obj_at_put(entry, pic);
00066   }
00067 
00068   static void set_first(objArrayOop pic, oop first, oop second) {
00069      pic->obj_at_put(1, first);
00070      pic->obj_at_put(2, second);
00071   }
00072 
00073   static void set_second(objArrayOop pic, oop first, oop second) {
00074      pic->obj_at_put(3, first);
00075      pic->obj_at_put(4, second);
00076   }
00077 
00078   static void set_last(objArrayOop pic, oop first, oop second) {
00079      int size = pic->length();
00080      pic->obj_at_put(size--, second);
00081      pic->obj_at_put(size,   first);
00082   }
00083 };
00084 
00085 
00086 // Implementation of InterpretedIC
00087 
00088 void InterpretedIC::set(Bytecodes::Code send_code, oop first_word, oop second_word) {
00089   // Remember pics are allocated in new space and
00090   // require a store check when saved in the InlineCache
00091   // Note: If the second_word is a PIC, it has to be deallocated
00092   //       before using set!
00093   *send_code_addr() = send_code;
00094   Universe::store(first_word_addr(), first_word, first_word->is_new());
00095   Universe::store(second_word_addr(), second_word, second_word->is_new());
00096 }
00097 
00098 
00099 u_char* InterpretedIC::findStartOfSend(u_char* sel_addr) {
00100   u_char* p = sel_addr;                 // start of inline cache
00101   while (*--p == Bytecodes::halt) ;     // skip alignment bytes if there - this works only if the nofArgs byte != halt ! FIX THIS!
00102   if (*p < 128) --p;                    // skip nofArgs byte if there - this works only for sends with less than 128 args
00103                                         // and assumes that no send bytecodes is smaller than 128. FIX THIS!!!
00104   if (!Bytecodes::is_send_code(Bytecodes::Code(*p))) {
00105     return NULL;   // not a send
00106   }
00107   return p;
00108   // Clean solution:
00109   //
00110   // make all send bytecodes holding the no. of arguments,
00111   // use special filler value (e.g. restrict no of. args to 254).
00112   // not urgent (gri 1/29/96)
00113 }
00114 
00115 
00116 int InterpretedIC::findStartOfSend(methodOop m, int bci) {
00117   u_char* p = findStartOfSend(m->codes(bci));
00118   return (p == NULL) ? IllegalBCI : p - m->codes() + 1;
00119 }
00120 
00121 
00122 symbolOop InterpretedIC::selector() const {
00123   oop fw = first_word();
00124   if (fw->is_symbol()) {
00125     return symbolOop(fw);
00126   } else if (fw->is_method()) {
00127     return methodOop(fw)->selector();
00128   } else {
00129     jumpTableEntry* e = jump_table_entry();
00130     nmethod* nm = e->method();
00131     assert(nm != NULL, "must have an nmethod");
00132     return nm->key.selector();
00133   }
00134 }
00135 
00136 
00137 jumpTableEntry* InterpretedIC::jump_table_entry() const {
00138   assert(send_type() == Bytecodes::compiled_send ||
00139          send_type() == Bytecodes::megamorphic_send, "must be a compiled call");
00140   assert(first_word()->is_smi(), "must be smi");
00141   return (jumpTableEntry*) first_word();
00142 }
00143 
00144 
00145 int InterpretedIC::nof_arguments() const {
00146   u_char* p = send_code_addr();
00147   switch (Bytecodes::argument_spec(Bytecodes::Code(*p))) {
00148     case Bytecodes::recv_0_args: return 0;
00149     case Bytecodes::recv_1_args: return 1;
00150     case Bytecodes::recv_2_args: return 2;
00151     case Bytecodes::recv_n_args: {
00152       int n = selector()->number_of_arguments();
00153       assert(n = int(*(p+1)), "just checkin'..."); // send_code_addr()+1 must hold the number of arguments
00154       return n;
00155     }
00156     case Bytecodes::args_only: return selector()->number_of_arguments();
00157   }
00158   ShouldNotReachHere();
00159   return 0;
00160 }
00161 
00162 
00163 Bytecodes::SendType InterpretedIC::send_type() const {
00164   return Bytecodes::send_type(send_code());
00165 }
00166 
00167 
00168 Bytecodes::ArgumentSpec InterpretedIC::argument_spec() const {
00169   return Bytecodes::argument_spec(send_code());
00170 }
00171 
00172 
00173 void InterpretedIC::clear() {
00174   if (is_empty()) return;
00175   if (send_type() == Bytecodes::polymorphic_send) {
00176     // recycle PIC
00177     assert(second_word()->is_objArray(), "must be a pic");
00178     Interpreter_PICs::deallocate(objArrayOop(second_word()));
00179   }
00180   set(Bytecodes::original_send_code_for(send_code()), oop(selector()), smiOop_zero);
00181 }
00182 
00183 
00184 void InterpretedIC::replace(LookupResult result, klassOop receiver_klass) {
00185   // IC entries before modification - used for loging only
00186   Bytecodes::Code code_before  = send_code();
00187   oop             word1_before = first_word();
00188   oop             word2_before = second_word();
00189   int             transition   = 0;
00190   // modify IC
00191   guarantee(word2_before == receiver_klass, "klass should be the same");
00192   if (result.is_empty()) {
00193     clear();
00194     transition = 1;
00195   } else if (result.is_method()) {
00196     if (send_type() == Bytecodes::megamorphic_send) {
00197       set(send_code(), result.method(), receiver_klass);
00198       transition = 2;
00199     } else {
00200       // Please Fix this Robert
00201       // implement set_monomorphic(klass, method)
00202       clear();
00203       transition = 3;
00204     }
00205   } else {
00206     if (send_type() == Bytecodes::megamorphic_send) {
00207       set(send_code(), oop(result.entry()), receiver_klass);
00208       transition = 4;
00209     } else {
00210       assert(result.is_entry(), "must be jump table entry");
00211       // a jump table entry of a nmethod is found so let's update the current send
00212       set(Bytecodes::compiled_send_code_for(send_code()), oop(result.entry()), receiver_klass);
00213       transition = 5;
00214     }
00215   }
00216   // IC entries after modification - used for loging only
00217   Bytecodes::Code code_after  = send_code();
00218   oop             word1_after = first_word();
00219   oop             word2_after = second_word();
00220   // log modification
00221   LOG_EVENT3("InterpretedIC::replace: IC at 0x%x: entry for klass 0x%x replaced (transition %d)", this, receiver_klass, transition);
00222   LOG_EVENT3("  from (%s, 0x%x, 0x%x)", Bytecodes::name(code_before), word1_before, word2_before);
00223   LOG_EVENT3("  to   (%s, 0x%x, 0x%x)", Bytecodes::name(code_after ), word1_after , word2_after );
00224 }
00225 
00226 
00227 void InterpretedIC::cleanup() {
00228   if (is_empty()) return; // Nothing to cleanup
00229 
00230   switch (send_type()) {
00231     case Bytecodes::accessor_send:    // fall through
00232     case Bytecodes::primitive_send:   // fall through
00233     case Bytecodes::predicted_send:   // fall through
00234     case Bytecodes::interpreted_send:
00235       { // check if the interpreted send should be replaced by a compiled send   
00236         klassOop receiver_klass = klassOop(second_word());
00237         assert(receiver_klass->is_klass(), "receiver klass must be a klass");
00238         methodOop method = methodOop(first_word());
00239         assert(method->is_method(), "first word in interpreter IC must be method");
00240         if (!Bytecodes::is_super_send(send_code())) {
00241           // super sends cannot be handled since the sending method holder is unknown at this point.
00242           LookupKey key(receiver_klass, selector());
00243           LookupResult result = lookupCache::lookup(&key);
00244           if (!result.matches(method)) {
00245             replace(result, receiver_klass);
00246           }
00247         }
00248       }
00249       break;
00250     case Bytecodes::compiled_send:
00251       { // check if the current compiled send is valid
00252         klassOop receiver_klass = klassOop(second_word());
00253         assert(receiver_klass->is_klass(), "receiver klass must be a klass");
00254         jumpTableEntry* entry = (jumpTableEntry*) first_word();
00255         nmethod* nm = entry->method();
00256         LookupResult result = lookupCache::lookup(&nm->key);
00257         if (!result.matches(nm)) {
00258           replace(result, receiver_klass);
00259         }
00260       }
00261       break;
00262     case Bytecodes::megamorphic_send:
00263       // Note that with the current definition of is_empty()
00264       // this will not be called for normal megamorphic sends
00265       // since they store only the selector.
00266       { klassOop receiver_klass = klassOop(second_word());
00267         if (first_word()->is_smi()) {
00268           jumpTableEntry* entry = (jumpTableEntry*) first_word();
00269           nmethod* nm = entry->method();
00270           LookupResult result = lookupCache::lookup(&nm->key);
00271           if (!result.matches(nm)) {
00272             replace(result, receiver_klass);
00273           }
00274         } else {
00275           methodOop method = methodOop(first_word());
00276           assert(method->is_method(), "first word in interpreter IC must be method");
00277           if (!Bytecodes::is_super_send(send_code())) {
00278             // super sends cannot be handled since the sending method holder is unknown at this point.
00279             LookupKey key(receiver_klass, selector());
00280             LookupResult result = lookupCache::lookup(&key);
00281             if (!result.matches(method)) {
00282               replace(result, receiver_klass);
00283             }
00284           }
00285         }
00286       }
00287       break;
00288     case Bytecodes::polymorphic_send:
00289       {
00290         // %implementation note:
00291         //   when cleaning up we can always preserve the old pic since the
00292         //   the only transitions are:
00293         //     (compiled    -> compiled)
00294         //     (compiled    -> interpreted)
00295         //     (interpreted -> compiled)
00296         //   in case of a super send we do not have to cleanup because
00297         //   no nmethods are compiled for super sends. 
00298         if (!Bytecodes::is_super_send(send_code())) {
00299           objArrayOop pic = pic_array();
00300           for (int index = pic->length(); index > 0; index -= 2) {
00301             klassOop klass = klassOop(pic->obj_at(index));
00302             assert(klass->is_klass(), "receiver klass must be klass");
00303             oop first = pic->obj_at(index-1);
00304             if (first->is_smi()) {
00305               jumpTableEntry* entry = (jumpTableEntry*) first;
00306               nmethod* nm = entry->method();
00307               LookupResult result = lookupCache::lookup(&nm->key);
00308               if (!result.matches(nm)) {
00309                 pic->obj_at_put(index-1, result.value());
00310               }
00311             } else {
00312               methodOop method = methodOop(first);
00313               assert(method->is_method(), "first word in interpreter IC must be method");
00314               LookupKey key(klass, selector());
00315               LookupResult result = lookupCache::lookup(&key);
00316               if (!result.matches(method)) {
00317                 pic->obj_at_put(index-1, result.value());
00318               }
00319             }
00320           }
00321         }
00322       }
00323    }
00324 }
00325 
00326 void InterpretedIC::clear_without_deallocation_pic() {
00327   if (is_empty()) return;
00328   set(Bytecodes::original_send_code_for(send_code()), oop(selector()), smiOop_zero);
00329 }
00330 
00331 
00332 void InterpretedIC::replace(nmethod* nm) {
00333   // replace entry with nm's klass by nm (if entry exists)
00334   smiOop entry_point = smiOop(nm->jump_table_entry()->entry_point());
00335   assert(selector() == nm->key.selector(), "mismatched selector");
00336   if (is_empty()) return;
00337 
00338   switch (send_type()) {
00339     case Bytecodes::accessor_send:    // fall through
00340     case Bytecodes::primitive_send:   // fall through
00341     case Bytecodes::predicted_send:   // fall through
00342     case Bytecodes::interpreted_send:
00343       { // replace the monomorphic interpreted send with compiled send
00344         klassOop receiver_klass = klassOop(second_word());
00345         assert(receiver_klass->is_klass(), "receiver klass must be a klass");
00346         if (receiver_klass == nm->key.klass()) {
00347           set(Bytecodes::compiled_send_code_for(send_code()), entry_point, nm->key.klass());
00348         }
00349       }
00350       break;
00351     case Bytecodes::compiled_send:   // fall through
00352     case Bytecodes::megamorphic_send:
00353       // replace the monomorphic compiled send with compiled send
00354       set(send_code(), entry_point, nm->key.klass());
00355       break;
00356     case Bytecodes::polymorphic_send:
00357       { objArrayOop pic = pic_array();
00358         for (int index = pic->length(); index > 0; index -= 2) {
00359           klassOop receiver_klass = klassOop(pic->obj_at(index));
00360           assert(receiver_klass->is_klass(), "receiver klass must be klass");
00361           if (receiver_klass == nm->key.klass()) {
00362             pic->obj_at_put(index-1, entry_point);
00363             return;
00364           } 
00365         }
00366       }
00367       // did not find klass
00368       break;
00369     default: fatal("unknown send type");
00370   }
00371   LOG_EVENT3("interpreted IC at 0x%x: new nmethod 0x%x for klass 0x%x replaces old entry", this, nm, nm->key.klass());
00372 }
00373 
00374 
00375 void InterpretedIC::print() {
00376   std->print("Inline cache (");
00377   if (is_empty()) {
00378     std->print("empty");
00379   } else {
00380     std->print(Bytecodes::send_type_as_string(send_type()));
00381   }
00382   std->print(") ");
00383   selector()->print_value();
00384   std->cr();
00385   InterpretedIC_Iterator it(this);
00386   while (!it.at_end()) {
00387     std->print("\t- klass: ");
00388     it.klass()->print_value();
00389     if (it.is_interpreted()) {
00390       std->print(";\tmethod  %#x\n", it.interpreted_method());
00391     } else {
00392       std->print(";\tnmethod %#x\n", it.compiled_method());
00393     }
00394     it.advance();
00395   }
00396 }
00397 
00398 objArrayOop InterpretedIC::pic_array() {
00399   assert(send_type() == Bytecodes::polymorphic_send, "Must be a polymorphic send site");
00400   objArrayOop result = objArrayOop(second_word());  
00401   assert(result->is_objArray(), "interpreter pic must be object array");
00402   assert(result->length() >= 4, "pic should contain at least two entries");
00403   return result;
00404 }
00405 
00406 void InterpretedIC::update_inline_cache(InterpretedIC* ic, frame* f, Bytecodes::Code send_code, klassOop klass, LookupResult result) {
00407     // update inline cache
00408     if (ic->is_empty() && ic->send_type() != Bytecodes::megamorphic_send) {
00409       // fill ic for the first time
00410       Bytecodes::Code new_send_code = Bytecodes::halt;
00411       if (result.is_entry()) {
00412 
00413         methodOop method = result.method();
00414         if (UseAccessMethods && Bytecodes::has_access_send_code(send_code) && method->is_accessMethod()) {
00415           // access method found ==> switch to access send
00416           new_send_code = Bytecodes::access_send_code_for(send_code);
00417           ic->set(new_send_code, method, klass);
00418 
00419         } else if (UsePredictedMethods && Bytecodes::has_predicted_send_code(send_code) && method->is_special_primitiveMethod()) {
00420           // predictable method found ==> switch to predicted send
00421           // NB: ic of predicted send should be empty so that the compiler knows whether another type occurred or not
00422           // i.e., {predicted + empty} --> 1 class, {predicted + nonempty} --> 2 klasses (polymorphic)
00423           // but: this actually doesn't work (yet?) since the interpreter fills the ic on any failure (e.g. overflow)
00424           new_send_code = method->special_primitive_code();
00425           method = methodOop(ic->selector()); // ic must stay empty
00426           klass  = NULL;                     // ic must stay empty
00427           ic->set(new_send_code, method, klass);
00428 
00429         } else {
00430           // jump table entry found ==> switch to compiled send
00431           new_send_code = Bytecodes::compiled_send_code_for(send_code);
00432           ic->set(new_send_code, oop(result.entry()->entry_point()), klass);
00433         }
00434       } else {
00435         // methodOop found
00436         methodOop method = result.method();
00437 
00438         if (UseAccessMethods && Bytecodes::has_access_send_code(send_code) && method->is_accessMethod()) {
00439           // access method found ==> switch to access send
00440           new_send_code = Bytecodes::access_send_code_for(send_code);
00441 
00442         } else if (UsePredictedMethods && Bytecodes::has_predicted_send_code(send_code) && method->is_special_primitiveMethod()) {
00443           // predictable method found ==> switch to predicted send
00444           // NB: ic of predicted send should be empty so that the compiler knows whether another type occurred or not
00445           // i.e., {predicted + empty} --> 1 class, {predicted + nonempty} --> 2 klasses (polymorphic)
00446           // but: this actually doesn't work (yet?) since the interpreter fills the ic on any failure (e.g. overflow)
00447           new_send_code = method->special_primitive_code();
00448           method = methodOop(ic->selector()); // ic must stay empty
00449           klass  = NULL;                     // ic must stay empty
00450 
00451         } else if (UsePrimitiveMethods && method->is_primitiveMethod()) {
00452           // primitive method found ==> switch to primitive send
00453           new_send_code = Bytecodes::primitive_send_code_for(send_code);
00454           Unimplemented(); // take this out when all primitive send bytecodes implemented
00455         
00456         } else {
00457           // normal interpreted send ==> do not change
00458           new_send_code = send_code;
00459           assert(new_send_code == Bytecodes::original_send_code_for(send_code), "bytecode should not change");
00460         }
00461         assert(new_send_code != Bytecodes::halt, "new_send_code not set");
00462         ic->set(new_send_code, method, klass);
00463       }
00464     } else {
00465       // ic not empty
00466       switch (ic->send_type()) {
00467         // monomorphic send
00468         case Bytecodes::accessor_send   : // fall through
00469         case Bytecodes::predicted_send  : // fall through
00470         case Bytecodes::compiled_send   : // fall through
00471         case Bytecodes::interpreted_send: {
00472           // switch to polymorphic send with 2 entries
00473           objArrayOop pic = Interpreter_PICs::allocate(2);
00474           Interpreter_PICs::set_first(pic, ic->first_word(), ic->second_word());
00475           Interpreter_PICs::set_second(pic, result.value(), klass);
00476           ic->set(Bytecodes::polymorphic_send_code_for(send_code), ic->selector(), pic);
00477           break;
00478         }
00479 
00480         // polymorphic send
00481         case Bytecodes::polymorphic_send: {
00482 
00483           objArrayOop old_pic = ic->pic_array();
00484           objArrayOop new_pic = Interpreter_PICs::extend(old_pic); // add an entry to the PIC if appropriate
00485           if (new_pic == NULL) {
00486             // switch to megamorphic send
00487             if (Bytecodes::is_super_send(send_code)) {
00488               ic->set(Bytecodes::megamorphic_send_code_for(send_code), result.value(), klass);
00489             } else {
00490               ic->set(Bytecodes::megamorphic_send_code_for(send_code), ic->selector(), NULL);
00491             }
00492           } else {
00493             // still a polymorphic send, add entry and set ic to new_pic
00494             Interpreter_PICs::set_last(new_pic, result.value(), klass);
00495             ic->set(send_code, ic->selector(), new_pic);
00496           }
00497           // recycle old pic
00498           Interpreter_PICs::deallocate(old_pic);
00499           break;
00500         }
00501 
00502         // megamorphic send
00503         case Bytecodes::megamorphic_send: {
00504           if (Bytecodes::is_super_send(send_code)) {
00505             ic->set(send_code, result.value(), klass);
00506           }
00507           break;
00508         }
00509 
00510         default: ShouldNotReachHere();
00511       }
00512     }
00513 
00514     // redo send (reset instruction pointer)
00515     f->set_hp(ic->send_code_addr());
00516 }
00517 
00518 
00519 extern "C" bool have_nlr_through_C;
00520 
00521 void InterpretedIC::does_not_understand(oop receiver, InterpretedIC* ic, frame* f) {
00522   // message not understood...
00523   BlockScavenge bs; // make sure that no scavenge happens
00524   klassOop msgKlass = klassOop(Universe::find_global("Message"));
00525   oop obj = msgKlass->klass_part()->allocateObject();
00526   assert(obj->is_mem(), "just checkin'...");
00527   memOop msg = memOop(obj);
00528   int nofArgs = ic->selector()->number_of_arguments();
00529   objArrayOop args = oopFactory::new_objArray(nofArgs);
00530   for (int i = 1; i <= nofArgs; i++) {
00531     args->obj_at_put(i, f->expr(nofArgs - i));
00532   }
00533   // for now: assume instance variables are there...
00534   // later: should check this or use a VM interface:
00535   // msg->set_receiver(recv);
00536   // msg->set_selector(ic->selector());
00537   // msg->set_arguments(args);
00538   msg->raw_at_put(2, receiver);
00539   msg->raw_at_put(3, ic->selector());
00540   msg->raw_at_put(4, args);
00541   symbolOop sel = oopFactory::new_symbol("doesNotUnderstand:");
00542   if (interpreter_normal_lookup(receiver->klass(), sel).is_empty()) {
00543     // doesNotUnderstand: not found ==> process error
00544     { ResourceMark rm;
00545       std->print("LOOKUP ERROR\n");
00546       sel->print_value(); std->print(" not found\n");
00547     }
00548     if (DeltaProcess::active()->is_scheduler()) {
00549       DeltaProcess::active()->trace_stack();
00550       fatal("lookup error in scheduler");
00551     } else {
00552       DeltaProcess::active()->suspend(::lookup_error);
00553     }
00554     ShouldNotReachHere();
00555   }
00556   // return marked result of doesNotUnderstand: message
00557   oop result = Delta::call(receiver, sel, msg);
00558 
00559   // Solution: use an nmethod-like stub-routine called from
00560   // within a (possibly one-element) PIC (in order to keep
00561   // the method selector in the IC. That stub does the
00562   // Delta:call and pops the right number of arguments
00563   // taken from the selector (the no. of arguments from
00564   // the selector can be optimized).
00565 }
00566 
00567 
00568 void InterpretedIC::trace_inline_cache_miss(InterpretedIC* ic, klassOop klass, LookupResult result) {
00569   std->print("InterpretedIC lookup (");
00570   klass->print_value();
00571   std->print(", ");
00572   ic->selector()->print_value();
00573   std->print(") --> ");
00574   result.print_short_on(std);
00575   std->cr();
00576 }
00577 
00578 
00579 // The following routine handles all inline cache misses in the interpreter
00580 // by looking at the ic state and the send byte code issuing the send. The
00581 // inline cache is updated and the send bytecode might be backpatched such
00582 // that it corresponds to the inline cache contents.
00583 
00584 void InterpretedIC::inline_cache_miss() {
00585   NoGCVerifier noGC;  
00586 
00587   // get ic info
00588   frame           f         = DeltaProcess::active()->last_frame();
00589   InterpretedIC*  ic        = f.current_interpretedIC();
00590   Bytecodes::Code send_code = ic->send_code();
00591 
00592   oop receiver = ic->argument_spec() == Bytecodes::args_only // Are we at a self or super send?
00593                ? f.receiver()                                //  yes: take receiver of frame
00594                : f.expr(ic->nof_arguments());                //  no:  take receiver pushed before the arguments
00595 
00596   // do the lookup
00597   klassOop klass = receiver->klass();
00598   LookupResult result = Bytecodes::is_super_send(send_code)
00599                       ? interpreter_super_lookup(ic->selector())
00600                       : interpreter_normal_lookup(klass, ic->selector());
00601 
00602   // tracing
00603   if (TraceMessageSend) std->print_cr("inline cache miss");
00604   if (TraceLookup)      trace_inline_cache_miss(ic, klass, result);
00605 
00606   // handle the lookup result
00607   if (!result.is_empty()) 
00608     update_inline_cache(ic, &f, send_code, klass, result);
00609   else {
00610     does_not_understand(receiver, ic, &f);
00611     // If the program continues we'll redo the inline_cache_miss
00612     if (!have_nlr_through_C) inline_cache_miss();
00613   }
00614 }
00615 
00616 
00617 // Implementation of InterpretedIC_Iterator
00618 
00619 InterpretedIC_Iterator::InterpretedIC_Iterator(InterpretedIC* ic) {
00620   _ic = ic;
00621   init_iteration();
00622 }
00623 
00624 
00625 void InterpretedIC_Iterator::set_klass(oop k) {
00626   assert(k->is_klass(), "not a klass");
00627   _klass = klassOop(k);
00628 }
00629 
00630 
00631 void InterpretedIC_Iterator::set_method(oop m) {
00632   if (m->is_mem()) {
00633     assert(m->is_method(), "must be a method");
00634     _method = (methodOop)m;
00635     _nm = NULL;
00636   } else {
00637     jumpTableEntry* e = (jumpTableEntry*)m;
00638     _nm = e->method();
00639     _method = _nm->method();
00640   }
00641 }
00642 
00643 
00644 void InterpretedIC_Iterator::init_iteration() {
00645   _pic = NULL;
00646   _index = 0;
00647   // determine initial state
00648   switch (_ic->send_type()) {
00649     case Bytecodes::interpreted_send:
00650       if (_ic->is_empty()) {
00651         // anamorphic call site (has never been executed => no type information)
00652         _number_of_targets = 0;
00653         _info = anamorphic;
00654       } else {
00655         // monomorphic call site
00656         _number_of_targets = 1;
00657         _info = monomorphic;
00658         set_klass(_ic->second_word());
00659         set_method(_ic->first_word());
00660       }
00661       break;
00662     case Bytecodes::compiled_send   : 
00663       _number_of_targets = 1;
00664       _info = monomorphic;
00665       set_klass(_ic->second_word());
00666       assert(_ic->first_word()->is_smi(), "must have jumpTableEntry");
00667       set_method(_ic->first_word());
00668       assert(is_compiled(), "bad type");
00669       break;
00670     case Bytecodes::accessor_send   : // fall through
00671     case Bytecodes::primitive_send  :
00672       _number_of_targets = 1;
00673       _info = monomorphic;
00674       set_klass(_ic->second_word());
00675       set_method(_ic->first_word());
00676       assert(is_interpreted(), "bad type");
00677       break;
00678     case Bytecodes::megamorphic_send:
00679       // no type information stored
00680       _number_of_targets = 0;
00681       _info = megamorphic;
00682       break;
00683     case Bytecodes::polymorphic_send:
00684       // information on many types
00685       _pic = objArrayOop(_ic->second_word());
00686       _number_of_targets = _pic->length() / 2;
00687       _info = polymorphic;
00688       set_klass(_pic->obj_at(2));
00689       set_method(_pic->obj_at(1));
00690       break;
00691     case Bytecodes::predicted_send:
00692       if (_ic->is_empty() || _ic->second_word() == smiKlassObj) {
00693         _number_of_targets = 1;
00694         _info = monomorphic;
00695       } else {
00696         _number_of_targets = 2;
00697         _info = polymorphic;
00698       }
00699       set_klass(smiKlassObj);
00700       set_method(interpreter_normal_lookup(smiKlassObj, selector()).value());
00701       assert(_method != NULL && _method->is_mem(), "this method must be there");
00702       break;
00703     default: ShouldNotReachHere();
00704   }
00705   assert((number_of_targets() > 1) == (_info == polymorphic), "inconsistency");
00706 }
00707 
00708 
00709 void InterpretedIC_Iterator::advance() {
00710   assert(!at_end(), "iterated over the end");
00711   _index++;
00712   if (! at_end()) {
00713     if (_pic != NULL) {
00714       // polymorphic inline cache 
00715       int index = _index + 1;   // array is 1-origin
00716       set_klass (_pic->obj_at(2 * index));
00717       set_method(_pic->obj_at(2 * index - 1));
00718     } else {
00719       // predicted send with non_empty inline cache
00720       assert(_index < 2, "illegal index");
00721       set_klass(_ic->second_word());
00722       set_method(_ic->first_word());
00723     }
00724   }
00725 }
00726 
00727 
00728 methodOop InterpretedIC_Iterator::interpreted_method() const { 
00729   if (is_interpreted()) {
00730     methodOop m = (methodOop)_method;
00731 #ifdef ASSERT
00732     assert(m->is_old(), "methods must be old");
00733     m->verify();
00734 #endif
00735     return m; 
00736   } else {
00737     return compiled_method()->method();
00738   }
00739 }
00740 
00741 
00742 nmethod* InterpretedIC_Iterator::compiled_method() const { 
00743   if (!is_compiled()) return NULL;  
00744 #ifdef ASSERT 
00745   if (!_nm->isNMethod()) fatal("not an nmethod"); // cheap test
00746   // _nm->verify();     // very slow
00747 #endif
00748   return _nm; 
00749 }
00750 
00751 
00752 bool InterpretedIC_Iterator::is_super_send() const {
00753   return Bytecodes::is_super_send(_ic->send_code());
00754 }
00755 
00756 
00757 void InterpretedIC_Iterator::print() {
00758   std->print_cr("InterpretedIC_Iterator %#x for ic %#x (%s)", this, _ic, selector()->as_string());
00759 }
00760 
00761   InterpretedIC* as_InterpretedIC(char* address_of_next_instr) {
00762     return (InterpretedIC*)(address_of_next_instr - InterpretedIC::size);
00763   }
00764 

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