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 }