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/_codeIterator.cpp.incl"
00026
00027
00028 bool InterpretedDLL_Cache::async() const {
00029 u_char* p = (u_char*)this;
00030 while (Bytecodes::Code(*--p) == Bytecodes::halt) ;
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:
00080 case Bytecodes::BBL: return align(current+2) + oopSize;
00081 case Bytecodes::BO:
00082 case Bytecodes::BL: return align(current+1) + oopSize;
00083 case Bytecodes::BLB: return align(current+1) + oopSize + 1;
00084 case Bytecodes::BOO:
00085 case Bytecodes::BLO:
00086 case Bytecodes::BOL:
00087 case Bytecodes::BLL: return align(current+1) + oopSize + oopSize;
00088 case Bytecodes::BBOO:
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:
00101 case Bytecodes::BLO: return (InterpretedIC*) align(current+1);
00102 case Bytecodes::BBOO:
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
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:
00199 case Bytecodes::push_new_closure_tos_1:
00200 case Bytecodes::push_new_closure_tos_2:
00201 case Bytecodes::push_new_closure_context_0:
00202 case Bytecodes::push_new_closure_context_1:
00203 case Bytecodes::push_new_closure_context_2:
00204 return aligned_oop(1);
00205 case Bytecodes::push_new_closure_tos_n:
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:
00215 case Bytecodes::push_new_closure_tos_1:
00216 case Bytecodes::push_new_closure_tos_2:
00217 case Bytecodes::push_new_closure_context_0:
00218 case Bytecodes::push_new_closure_context_1:
00219 case Bytecodes::push_new_closure_context_2:
00220 return methodOop(oop_at(1));
00221 case Bytecodes::push_new_closure_tos_n:
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