codeIterator.cpp

Go to the documentation of this file.
00001 /* Copyright 1994 - 1996 LongView Technologies L.L.C. $Revision: 1.42 $ */
00002 /* Copyright (c) 2006, Sun Microsystems, Inc.
00003 All rights reserved.
00004 
00005 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the 
00006 following conditions are met:
00007 
00008     * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
00009     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following 
00010           disclaimer in the documentation and/or other materials provided with the distribution.
00011     * Neither the name of Sun Microsystems nor the names of its contributors may be used to endorse or promote products derived 
00012           from this software without specific prior written permission.
00013 
00014 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 
00015 NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
00016 THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
00017 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
00018 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
00019 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
00020 
00021 
00022 */
00023 
00024 # include "incls/_precompiled.incl"
00025 # include "incls/_codeIterator.cpp.incl"
00026 
00027 
00028 bool InterpretedDLL_Cache::async() const {
00029   u_char* p = (u_char*)this;                            // p point to first oop in DLL call
00030   while (Bytecodes::Code(*--p) == Bytecodes::halt) ;    // search back for DLL call bytecode
00031   Bytecodes::Code code = Bytecodes::Code(*p);
00032   assert(code == Bytecodes::dll_call_sync || code == Bytecodes::dll_call_async, "not a dll call");
00033   return code == Bytecodes::dll_call_async;
00034 }
00035 
00036 
00037 inline void CodeIterator::align() {
00038   current = align(current);
00039 }
00040 
00041 
00042 CodeIterator::CodeIterator(methodOop method, int startBCI) {
00043   assert(PrologueBCI <= startBCI && startBCI <= method->size_of_codes() * oopSize, "startBCI out of range");
00044   this->method = method;
00045   set_bci(startBCI);
00046   end = method->codes_end();
00047 }
00048 
00049 
00050 CodeIterator::CodeIterator(u_char* hp) {
00051   method  = methodOopDesc::methodOop_from_hcode(hp);
00052   current = hp;
00053   end     = method->codes_end();
00054 }
00055 
00056 
00057 void CodeIterator::set_bci(int bci) {
00058   current = method->codes(bci);
00059 }
00060 
00061 
00062 int CodeIterator::bci() const {
00063   return (current - method->codes()) + 1;
00064 }
00065 
00066 
00067 int CodeIterator::next_bci() const {
00068   return (next_hp() - method->codes()) + 1;
00069 }
00070 
00071 
00072 u_char* CodeIterator::next_hp() const {
00073   if (current >= end) return 0;
00074   switch(format()) {
00075    case Bytecodes::B:     return current+1;
00076    case Bytecodes::BB:    return current+2;
00077    case Bytecodes::BBB:   return current+3;
00078    case Bytecodes::BBBB:  return current+4;
00079    case Bytecodes::BBO:   // fall through
00080    case Bytecodes::BBL:   return align(current+2) + oopSize;
00081    case Bytecodes::BO:    // fall through
00082    case Bytecodes::BL:    return align(current+1) + oopSize;
00083    case Bytecodes::BLB:   return align(current+1) + oopSize + 1;
00084    case Bytecodes::BOO:   // fall through
00085    case Bytecodes::BLO:   // fall through
00086    case Bytecodes::BOL:   // fall through
00087    case Bytecodes::BLL:   return align(current+1) + oopSize + oopSize;
00088    case Bytecodes::BBOO:  // fall through
00089    case Bytecodes::BBLO:  return align(current+2) + oopSize + oopSize;
00090    case Bytecodes::BOOLB: return align(current+1) + oopSize + oopSize + oopSize + 1;
00091    case Bytecodes::BBS:   return current + 2 + (current[1] == 0 ? 256 : current[1]);
00092   }
00093   ShouldNotReachHere();
00094   return 0;
00095 }
00096 
00097 
00098 InterpretedIC* CodeIterator::ic() { 
00099   switch (format()) {
00100    case Bytecodes::BOO:   // fall through
00101    case Bytecodes::BLO:   return (InterpretedIC*) align(current+1);
00102    case Bytecodes::BBOO:  // fall through
00103    case Bytecodes::BBLO:  return (InterpretedIC*) align(current+2);    
00104   }
00105   return NULL;
00106 }
00107 
00108 
00109 InterpretedDLL_Cache* CodeIterator::dll_cache() {
00110   return (InterpretedDLL_Cache*) align(current+1);
00111 }
00112 
00113 InterpretedPrim_Cache* CodeIterator::prim_cache() {
00114   return (InterpretedPrim_Cache*) current;
00115 }
00116 
00117 extern "C" void deoptimized_return_from_send_without_receiver();
00118 extern "C" void deoptimized_return_from_send_without_receiver_restore();
00119 
00120 extern "C" void deoptimized_return_from_send_without_receiver_pop();
00121 extern "C" void deoptimized_return_from_send_without_receiver_pop_restore();
00122 
00123 extern "C" void deoptimized_return_from_send_with_receiver();
00124 extern "C" void deoptimized_return_from_send_with_receiver_restore();
00125 
00126 extern "C" void deoptimized_return_from_send_with_receiver_pop();
00127 extern "C" void deoptimized_return_from_send_with_receiver_pop_restore();
00128 
00129 extern "C" void deoptimized_return_from_primitive_call_without_failure_block();
00130 extern "C" void deoptimized_return_from_primitive_call_without_failure_block_restore();
00131 
00132 extern "C" void deoptimized_return_from_primitive_call_with_failure_block();
00133 extern "C" void deoptimized_return_from_primitive_call_with_failure_block_restore();
00134 
00135 extern "C" void deoptimized_return_from_dll_call();
00136 extern "C" void deoptimized_return_from_dll_call_restore();
00137 
00138 char* CodeIterator::interpreter_return_point(bool restore_value) const {
00139   // The return is only valid if we are in a send/primtive call/dll call.
00140 
00141   if (is_message_send()) {
00142     switch(argumentsType()) {
00143       case Bytecodes::recv_0_args:
00144       case Bytecodes::recv_1_args:
00145       case Bytecodes::recv_2_args:
00146       case Bytecodes::recv_n_args:
00147         return pop_result()
00148              ? (restore_value
00149                 ? (char*) deoptimized_return_from_send_with_receiver_pop_restore
00150                 : (char*) deoptimized_return_from_send_with_receiver_pop)
00151              : (restore_value
00152                 ? (char*) deoptimized_return_from_send_with_receiver_restore
00153                 : (char*) deoptimized_return_from_send_with_receiver);
00154       case Bytecodes::args_only:
00155         return pop_result()
00156              ? (restore_value
00157                 ? (char*) deoptimized_return_from_send_without_receiver_pop_restore
00158                 : (char*) deoptimized_return_from_send_without_receiver_pop)
00159              : (restore_value
00160                 ? (char*) deoptimized_return_from_send_without_receiver_restore
00161                 : (char*) deoptimized_return_from_send_without_receiver);
00162       default: ShouldNotReachHere();
00163     }
00164   }
00165   
00166   if (is_primitive_call()) {
00167     switch (code()) {
00168       case Bytecodes::prim_call:
00169       case Bytecodes::prim_call_lookup:
00170       case Bytecodes::prim_call_self:
00171       case Bytecodes::prim_call_self_lookup:
00172         return restore_value
00173              ? (char*) deoptimized_return_from_primitive_call_without_failure_block_restore
00174              : (char*) deoptimized_return_from_primitive_call_without_failure_block;
00175       case Bytecodes::prim_call_failure:
00176       case Bytecodes::prim_call_failure_lookup:
00177       case Bytecodes::prim_call_self_failure:
00178       case Bytecodes::prim_call_self_failure_lookup:
00179         return  restore_value
00180              ? (char*) deoptimized_return_from_primitive_call_with_failure_block_restore
00181              : (char*) deoptimized_return_from_primitive_call_with_failure_block;
00182       default: ShouldNotReachHere();
00183     }
00184   }
00185 
00186   if (is_dll_call()) {
00187     return restore_value
00188          ? (char*) deoptimized_return_from_dll_call_restore
00189          : (char*) deoptimized_return_from_dll_call;
00190   }
00191 
00192   ShouldNotReachHere();
00193   return NULL;
00194 }
00195 
00196 oop* CodeIterator::block_method_addr() {
00197   switch(code()) {
00198     case Bytecodes::push_new_closure_tos_0:      // fall through
00199     case Bytecodes::push_new_closure_tos_1:      // fall through
00200     case Bytecodes::push_new_closure_tos_2:      // fall through
00201     case Bytecodes::push_new_closure_context_0:  // fall through
00202     case Bytecodes::push_new_closure_context_1:  // fall through
00203     case Bytecodes::push_new_closure_context_2:
00204       return aligned_oop(1);
00205     case Bytecodes::push_new_closure_tos_n:      // fall through
00206     case Bytecodes::push_new_closure_context_n:
00207       return aligned_oop(2);
00208   }
00209   return NULL;
00210 }
00211 
00212 methodOop CodeIterator::block_method() {
00213   switch(code()) {
00214     case Bytecodes::push_new_closure_tos_0:      // fall through
00215     case Bytecodes::push_new_closure_tos_1:      // fall through
00216     case Bytecodes::push_new_closure_tos_2:      // fall through
00217     case Bytecodes::push_new_closure_context_0:  // fall through
00218     case Bytecodes::push_new_closure_context_1:  // fall through
00219     case Bytecodes::push_new_closure_context_2:
00220         return methodOop(oop_at(1));
00221     case Bytecodes::push_new_closure_tos_n:      // fall through
00222     case Bytecodes::push_new_closure_context_n:
00223         return methodOop(oop_at(2));
00224   }
00225   return NULL;
00226 }
00227 
00228 void CodeIterator::customize_class_var_code(klassOop to_klass) {
00229   assert(   code() == Bytecodes::push_classVar_name
00230          || code() == Bytecodes::store_classVar_pop_name
00231          || code() == Bytecodes::store_classVar_name, "must be class variable byte code");
00232 
00233   oop* p = aligned_oop(1);
00234   symbolOop name = symbolOop(*p);
00235   assert(name->is_symbol(), "name must be symbol");
00236   associationOop assoc = to_klass->klass_part()->lookup_class_var(name);
00237   if (assoc) {
00238     assert(assoc->is_old(), "must be tenured");
00239          if (code() == Bytecodes::push_classVar_name)      set_code(Bytecodes::push_classVar);
00240     else if (code() == Bytecodes::store_classVar_pop_name) set_code(Bytecodes::store_classVar_pop);
00241     else                                                   set_code(Bytecodes::store_classVar);
00242     Universe::store(p, assoc, false);
00243   }
00244 }
00245 
00246 void CodeIterator::uncustomize_class_var_code(klassOop from_klass) {
00247   assert(   code() == Bytecodes::push_classVar
00248          || code() == Bytecodes::store_classVar_pop
00249          || code() == Bytecodes::store_classVar, "must be class variable byte code");
00250 
00251   oop* p = aligned_oop(1);
00252   associationOop old_assoc = associationOop(*p);
00253   assert(old_assoc->is_association(), "must be association");
00254        if (code() == Bytecodes::push_classVar)      set_code(Bytecodes::push_classVar_name);
00255   else if (code() == Bytecodes::store_classVar_pop) set_code(Bytecodes::store_classVar_pop_name);
00256   else                                              set_code(Bytecodes::store_classVar_name);
00257   Universe::store(p, old_assoc->key(), false);
00258 }
00259 
00260 void CodeIterator::recustomize_class_var_code(klassOop from_klass, klassOop to_klass) {
00261   assert(   code() == Bytecodes::push_classVar
00262          || code() == Bytecodes::store_classVar_pop
00263          || code() == Bytecodes::store_classVar, "must be class variable byte code");
00264 
00265   oop* p = aligned_oop(1);
00266   associationOop old_assoc = associationOop(*p);
00267   assert(old_assoc->is_association(), "must be association");
00268   associationOop new_assoc = to_klass->klass_part()->lookup_class_var(old_assoc->key());
00269   if (new_assoc) {
00270     Universe::store(p, new_assoc, false);
00271   } else {
00272          if (code() == Bytecodes::push_classVar)      set_code(Bytecodes::push_classVar_name);
00273     else if (code() == Bytecodes::store_classVar_pop) set_code(Bytecodes::store_classVar_pop_name);
00274     else                                              set_code(Bytecodes::store_classVar_name);
00275     Universe::store(p, old_assoc->key(), false);
00276   }
00277 }
00278 
00279 void CodeIterator::customize_inst_var_code(klassOop to_klass) {
00280   assert(   code() == Bytecodes::push_instVar_name
00281          || code() == Bytecodes::store_instVar_pop_name
00282          || code() == Bytecodes::store_instVar_name
00283          || code() == Bytecodes::return_instVar_name, "must be instance variable byte code");
00284 
00285   oop* p = aligned_oop(1);
00286   symbolOop name = symbolOop(*p);
00287   assert(name->is_symbol(), "name must be symbol");
00288   int offset = to_klass->klass_part()->lookup_inst_var(name);
00289   if (offset >= 0) {
00290          if (code() == Bytecodes::push_instVar_name)      set_code(Bytecodes::push_instVar);
00291     else if (code() == Bytecodes::store_instVar_pop_name) set_code(Bytecodes::store_instVar_pop);
00292     else if (code() == Bytecodes::store_instVar_name)     set_code(Bytecodes::store_instVar);
00293     else                                                  set_code(Bytecodes::return_instVar);
00294     Universe::store(p, as_smiOop(offset));
00295   }
00296 }
00297 
00298 void CodeIterator::uncustomize_inst_var_code(klassOop from_klass) {
00299   assert(   code() == Bytecodes::push_instVar
00300          || code() == Bytecodes::store_instVar_pop
00301          || code() == Bytecodes::store_instVar
00302          || code() == Bytecodes::return_instVar, "must be instance variable byte code");
00303 
00304   oop* p = aligned_oop(1);
00305   assert((*p)->is_smi(), "must be smi");
00306   int old_offset = smiOop(*p)->value();
00307   symbolOop name = from_klass->klass_part()->inst_var_name_at(old_offset);
00308   if (!name) {
00309     fatal("instance variable not found");
00310   }
00311        if (code() == Bytecodes::push_instVar)      set_code(Bytecodes::push_instVar_name);
00312   else if (code() == Bytecodes::store_instVar_pop) set_code(Bytecodes::store_instVar_pop_name);
00313   else if (code() == Bytecodes::store_instVar)     set_code(Bytecodes::store_instVar_name);
00314   else                                             set_code(Bytecodes::return_instVar_name);
00315   Universe::store(p, name, false);
00316 }
00317 
00318 void CodeIterator::recustomize_inst_var_code(klassOop from_klass, klassOop to_klass) {
00319   assert(   code() == Bytecodes::push_instVar
00320          || code() == Bytecodes::store_instVar_pop
00321          || code() == Bytecodes::store_instVar
00322          || code() == Bytecodes::return_instVar, "must be instance variable byte code");
00323 
00324   oop* p = aligned_oop(1);
00325   assert((*p)->is_smi(), "must be smi");
00326   int old_offset = smiOop(*p)->value();
00327   symbolOop name = from_klass->klass_part()->inst_var_name_at(old_offset);
00328   if (!name) {
00329     fatal("instance variable not found");
00330   }
00331   int new_offset = to_klass->klass_part()->lookup_inst_var(name);
00332   if (new_offset >= 0) {
00333     Universe::store(p, as_smiOop(new_offset));
00334   } else {
00335          if (code() == Bytecodes::push_instVar)      set_code(Bytecodes::push_instVar_name);
00336     else if (code() == Bytecodes::store_instVar_pop) set_code(Bytecodes::store_instVar_pop_name);
00337     else if (code() == Bytecodes::store_instVar)     set_code(Bytecodes::store_instVar_name);
00338     else                                             set_code(Bytecodes::return_instVar_name);
00339     Universe::store(p, name, false);
00340   }
00341 }
00342 

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