frame.cpp

Go to the documentation of this file.
00001 /* Copyright 1994 - 1996 LongView Technologies L.L.C. $Revision: 1.73 $ */
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/_frame.cpp.incl"
00026 
00027 u_char* frame::hp() const { 
00028   // Lars, please check -- assertion fails
00029   //assert(is_interpreted_frame(), "must be interpreted");
00030   return *hp_addr(); 
00031 }
00032 
00033 void  frame::set_hp(u_char* hp) { 
00034   //assert(is_interpreted_frame(), "must be interpreted");
00035   *hp_addr() = hp; 
00036 }
00037 
00038 void frame::patch_pc(char* pc) {
00039   char** pc_addr = (char**) sp() - 1;
00040   *pc_addr = pc;
00041 }
00042 
00043 objArrayOop* frame::frame_array_addr() const {
00044   assert(frame_size() >= minimum_size_for_deoptimized_frame, "Compiler frame is too small for deoptimization");
00045   //assert(is_deoptimized_frame(), "must be deoptimized frame");
00046   return (objArrayOop*) addr_at(frame_frame_array_offset);
00047 }
00048 
00049 objArrayOop frame::frame_array() const {
00050   objArrayOop result = *frame_array_addr();
00051   assert(result->is_objArray(), "must be objArray");
00052   return result;
00053 }
00054 
00055 oop** frame::real_sender_sp_addr() const {
00056   //assert(is_deoptimized_frame(), "must be deoptimized frame");
00057   return (oop**) addr_at(frame_real_sender_sp_offset);
00058 }
00059 
00060 void frame::patch_fp(int* fp) {
00061   frame previous(NULL, ((int*) sp()) - frame_sender_sp_offset, NULL);
00062   previous.set_link(fp);
00063 }
00064 
00065 methodOop frame::method() const {
00066   assert(is_interpreted_frame(), "must be interpreter frame");
00067   // First we will check the interpreter frame is valid by checking the frame size.
00068   // The interpreter guarantees hp is valid if the frame is at least 4 in size. 
00069   // (return address, link, receiver, hcode pointer)
00070   if (frame_size() < minimum_size_for_deoptimized_frame) return NULL;
00071 
00072   u_char* h = hp();
00073   if (!Universe::old_gen.contains(h)) return NULL; 
00074   memOop obj = as_memOop(Universe::object_start((oop*) h));  
00075   return obj->is_method() ? methodOop(obj) : NULL;
00076 }
00077 
00078 nmethod* frame::code() const {
00079   assert(is_compiled_frame(), "no code");
00080   return findNMethod(pc());
00081 }
00082 
00083 bool frame::is_interpreted_frame() const  {
00084   return Interpreter::contains(pc());
00085 }
00086 
00087 bool frame::is_compiled_frame() const {
00088 #ifdef DELTA_COMPILER
00089   return Universe::code->contains(pc());
00090 #else
00091   return false;
00092 #endif
00093 }
00094 
00095 extern "C" void unpack_unoptimized_frames();
00096 
00097 bool frame::is_deoptimized_frame()  const {
00098   return pc() == (char*) &unpack_unoptimized_frames;
00099 }
00100 
00101 IC_Iterator* frame::sender_ic_iterator() const {
00102   return is_entry_frame() ?  NULL : sender().current_ic_iterator();
00103 }
00104 
00105 IC_Iterator* frame::current_ic_iterator() const {
00106 
00107   if (is_interpreted_frame()) {
00108     InterpretedIC* ic = current_interpretedIC();
00109     if (ic && !Bytecodes::is_send_code(ic->send_code())) return NULL;
00110     return ic ? new InterpretedIC_Iterator(ic) : NULL;
00111   }
00112 
00113   if (is_compiled_frame()) {
00114     CompiledIC* ic = current_compiledIC();
00115     return  ic->inlineCache() 
00116           ? new CompiledIC_Iterator(ic)
00117           : NULL; // a perform, not a send
00118   }
00119 
00120   // entry or deoptimized frame
00121   return NULL;
00122 }
00123 
00124 InterpretedIC* frame::current_interpretedIC() const {
00125 
00126   if (is_interpreted_frame()) {
00127     methodOop m = method();
00128     int bci = m->bci_from(hp());
00129     u_char* codeptr = m->codes(bci);
00130     if (Bytecodes::is_send_code(Bytecodes::Code(*codeptr))) {
00131       InterpretedIC* ic = as_InterpretedIC((char*)hp());
00132       assert(ic->send_code_addr() == codeptr, "found wrong ic");
00133       return ic;
00134     } else {
00135       return NULL;        // perform, dll call, etc.
00136     }
00137   }
00138 
00139   return NULL;    // doesn't have InterpretedIC
00140 }
00141 
00142 CompiledIC* frame::current_compiledIC() const {
00143   return is_compiled_frame()
00144        ? CompiledIC_from_return_addr(pc())  // may fail if current frame isn't at a send -- caller must know
00145        : NULL;
00146 }
00147 
00148 extern "C" void return_from_Delta();
00149 
00150 bool frame::is_entry_frame() const {
00151   return pc() == (char*) &return_from_Delta;
00152 }
00153 
00154 bool frame::has_next_Delta_fp() const {
00155   return at(frame_next_Delta_fp_offset) != NULL;
00156 }
00157 
00158 int* frame::next_Delta_fp() const       {
00159   return (int*) at(frame_next_Delta_fp_offset);
00160 }
00161 
00162 oop* frame::next_Delta_sp() const       {
00163   return (oop*) at(frame_next_Delta_sp_offset);
00164 }
00165 
00166 bool frame::is_first_frame() const {
00167   return is_entry_frame() && !has_next_Delta_fp();
00168 }
00169 
00170 bool frame::is_first_delta_frame() const {
00171   // last Delta frame isn't necessarily is_first_frame(), so check is a bit more complicated
00172   // [I don't understand why, but the first Delta frame of a process isn't an entry frame  -Urs 2/96]
00173   frame s;
00174   for (s = sender(); !(s.is_delta_frame() || s.is_first_frame()); s = s.sender()) ;
00175   return s.is_first_frame();
00176 }
00177 
00178 char* frame::print_name() const {
00179   if (is_interpreted_frame()) return "interpreted";
00180   if (is_compiled_frame())    return "compiled";
00181   if (is_deoptimized_frame()) return "deoptimized";
00182   return "C";
00183 }
00184 
00185 void frame::print() const {
00186   std->print("[%s frame: fp = %#lx, sp = %#lx, pc = %#lx", print_name(), fp(), sp(), pc());
00187   if (is_compiled_frame()) {
00188     std->print(", nm = %#x", findNMethod(pc()));
00189   } else if (is_interpreted_frame()) {
00190     std->print(", hp = %#x, method = %#x", hp(), method());
00191   }
00192   std->print_cr("]");
00193 
00194   if (PrintLongFrames) {
00195     for (oop* p = sp(); p < (oop*)fp(); p++)
00196       std->print_cr("  - 0x%lx: 0x%lx", p, *p);
00197   }
00198 }
00199 
00200 
00201 static void print_context_chain(contextOop con, outputStream* st) {
00202   if (con) {
00203     // Print out the contexts chain
00204     st->print("    context ");
00205     con->print_value_on(st);
00206     while (con->has_outer_context()) {
00207       con = con->outer_context();
00208       st->print(" -> ");
00209       con->print_value_on(st);
00210     }
00211     st->cr();
00212   }
00213 }
00214 
00215 void frame::print_for_deoptimization(outputStream* st) {
00216  ResourceMark rm;
00217  st->print(" - ");
00218  if (is_interpreted_frame()) {
00219    st->print("I ");
00220    interpretedVFrame* vf = (interpretedVFrame*) vframe::new_vframe(this);
00221    vf->method()->print_value_on(st);
00222    if (ActivationShowBCI) {
00223      st->print(" bci=%d ", vf->bci());
00224    }
00225    std->print_cr(" @ 0x%lx", fp());
00226    print_context_chain(vf->interpreter_context(), st);
00227    if (ActivationShowExpressionStack) {
00228      GrowableArray<oop>* stack = vf->expression_stack();
00229      for (int index = 0; index < stack->length(); index++) {
00230        st->print("    %3d: ", index);
00231        stack->at(index)->print_value_on(st);
00232        st->cr();
00233      }
00234    }
00235    return;
00236  } 
00237 
00238  if (is_compiled_frame()) {
00239    st->print("C ");
00240    compiledVFrame* vf = (compiledVFrame*) vframe::new_vframe(this);
00241    assert(vf->is_compiled_frame(), "should be compiled vframe");
00242    vf->code()->print_value_on(st);
00243    std->print_cr(" @ 0x%lx", fp());
00244 
00245    while (true) {
00246      st->print("    ");
00247      vf->method()->print_value_on(st);
00248      std->print_cr(" @ %d", vf->scope()->offset());
00249      print_context_chain(vf->compiled_context(), st);
00250      if (vf->is_top()) break;
00251      vf = (compiledVFrame*) vf->sender();
00252      assert(vf->is_compiled_frame(), "should be compiled vframe");
00253    }
00254    return;
00255  }
00256 
00257  if (is_deoptimized_frame()) {
00258    st->print("D "); 
00259    frame_array()->print_value();
00260    std->print_cr(" @ 0x%lx", fp());
00261 
00262    deoptimizedVFrame* vf = (deoptimizedVFrame*) vframe::new_vframe(this);
00263    assert(vf->is_deoptimized_frame(), "should be deoptimized vframe");
00264    while (true) {
00265      st->print("    ");
00266      vf->method()->print_value_on(st);
00267      std->cr();
00268      print_context_chain(vf->deoptimized_context(), st);
00269      if (vf->is_top()) break;
00270      vf = (deoptimizedVFrame*) vf->sender();
00271      assert(vf->is_deoptimized_frame(), "should be deoptimized vframe");
00272    }
00273    return;
00274  }
00275 
00276  st->print("E foreign frame @ 0x%lx", fp());
00277 }
00278 
00279 void frame::layout_iterate(FrameLayoutClosure* blk) {
00280   if (is_interpreted_frame()){ 
00281     oop* eos = temp_addr(0);
00282     for (oop* p = sp(); p <= eos; p++) 
00283       blk->do_stack(eos-p, p);
00284     blk->do_hp(hp_addr());
00285     blk->do_receiver(receiver_addr());
00286     blk->do_link(link_addr());
00287     blk->do_return_addr(return_addr_addr());
00288   }
00289 }
00290 
00291 bool frame::has_interpreted_float_marker() const {
00292   return oop(at(interpreted_frame_float_magic_offset)) == Floats::magic_value();
00293 }
00294 
00295 bool frame::has_compiled_float_marker() const {
00296   return oop(at(compiled_frame_magic_oop_offset)) == Floats::magic_value();
00297 }
00298 
00299 bool frame::oop_iterate_interpreted_float_frame(OopClosure* blk) {
00300   methodOop m =  methodOopDesc::methodOop_from_hcode(hp());
00301   // Return if this activation has no floats (the marker is conservative)
00302   if (!m->has_float_temporaries()) return false;
00303         
00304   // Iterator from stack pointer to end of float section
00305   oop* end = (oop*) addr_at(m->float_section_start_offset() - m->float_section_size());
00306   for (oop* p = sp(); p <= end; p++) {
00307     blk->do_oop(p);
00308   }
00309 
00310   // Skip the float section and magic_value
00311 
00312   // Iterate from just before the float section to the first temp
00313   for (oop* q = (oop*) addr_at(m->float_section_start_offset() + 2); q <= temp_addr(0); q++) {
00314     blk->do_oop(q);
00315   }
00316 
00317   // The receiver
00318   blk->do_oop(receiver_addr());
00319 
00320   return true;
00321 }
00322 
00323 bool frame::oop_iterate_compiled_float_frame(OopClosure* blk) {
00324   warning("oop_iterate_compiled_float_frame not implemented");
00325   return false;
00326 }
00327 
00328 void frame::oop_iterate(OopClosure* blk) {
00329   if (is_interpreted_frame()) {
00330     if (has_interpreted_float_marker() && oop_iterate_interpreted_float_frame(blk)) return;
00331  
00332     // lprintf("Frame: fp = %#lx, sp = %#lx]\n", fp(), sp());
00333     for (oop* p = sp(); p <= temp_addr(0); p++) {
00334       // lprintf("\t[%#lx]: ", p);
00335       // (*p)->short_print();
00336       // lprintf("\n");
00337       blk->do_oop(p);
00338     }
00339     // lprintf("\t{%#lx}: ", receiver_addr());
00340     // (*receiver_addr())->short_print();
00341     // lprintf("\n");
00342     blk->do_oop(receiver_addr());
00343     return;
00344   }
00345   
00346   if (is_compiled_frame()) {
00347     if (has_compiled_float_marker() && oop_iterate_compiled_float_frame(blk)) return;
00348 
00349      // All oops are [sp..fp[
00350     for (oop* p = sp(); p < (oop*)fp(); p++) {
00351       blk->do_oop(p);
00352     }
00353     return;
00354   }
00355 
00356   if (is_entry_frame()) {
00357     // All oops are [sp..fp[
00358     for (oop* p = sp(); p < (oop*)fp(); p++) {
00359       blk->do_oop(p);
00360     }
00361     return;
00362   }
00363   
00364   if (is_deoptimized_frame()) {
00365     // Expression stack
00366     oop* end = (oop*)fp() + frame_real_sender_sp_offset;
00367     // All oops are [sp..end[
00368     for (oop* p = sp(); p < end; p++) {
00369       blk->do_oop(p);
00370     }
00371     blk->do_oop((oop*)frame_array_addr());
00372     return;
00373   }
00374 }
00375 
00376 bool frame::follow_roots_interpreted_float_frame() {
00377   methodOop m = methodOop(hp());
00378   assert(m->is_method(), "must be method");
00379   // Return if this activation has no floats (the marker is conservative)
00380   if (!m->has_float_temporaries()) return false;
00381 
00382   // Iterator from stack pointer to end of float section
00383   oop* end = (oop*) addr_at(m->float_section_start_offset() - m->float_section_size());
00384   for (oop* p = sp(); p <= end; p++) {
00385     MarkSweep::follow_root(p);
00386   }
00387 
00388   // Skip the float section and magic_value
00389 
00390   // Iterate from just before the float section to the first temp
00391   for (oop* q = (oop*) addr_at(m->float_section_start_offset() + 2); q <= temp_addr(0); q++) {
00392     MarkSweep::follow_root(q);
00393   }
00394 
00395   // The receiver
00396   MarkSweep::follow_root(receiver_addr());
00397 
00398   return true;
00399 }
00400 
00401 bool frame::follow_roots_compiled_float_frame() {
00402   warning("follow_roots_compiled_float_frame not implemented");
00403   return true;
00404 }
00405 
00406 void frame::follow_roots() {
00407   if (is_interpreted_frame()) {
00408     if (has_interpreted_float_marker() && follow_roots_interpreted_float_frame()) return;
00409 
00410     // Follow the roots of the frame
00411     for (oop* p = sp(); p <= temp_addr(0); p++) {
00412       MarkSweep::follow_root(p);
00413     }
00414     MarkSweep::follow_root((oop*)hp_addr());
00415     MarkSweep::follow_root(receiver_addr());
00416     return;
00417   } 
00418   
00419   if (is_compiled_frame()) {
00420     if (has_compiled_float_marker() && follow_roots_compiled_float_frame()) return;
00421 
00422     for (oop* p = sp(); p < (oop*)fp(); p++) MarkSweep::follow_root(p);
00423     return;
00424   }
00425     
00426   if (is_entry_frame()) {
00427     for (oop* p = sp(); p < (oop*)fp(); p++) MarkSweep::follow_root(p);
00428     return;
00429   }
00430 
00431   if (is_deoptimized_frame()) {
00432     // Expression stack
00433     oop* end = (oop*)fp() + frame_real_sender_sp_offset;
00434     for (oop* p = sp(); p < end; p++) MarkSweep::follow_root(p);
00435     MarkSweep::follow_root((oop*)frame_array_addr());
00436     return;
00437   }
00438 }
00439 
00440 void frame::convert_hcode_pointer() {
00441   if (!is_interpreted_frame()) return;
00442   // Adjust hcode pointer to object start
00443   u_char* h   = hp();
00444   u_char* obj = (u_char*) as_memOop(Universe::object_start((oop*) h));
00445   set_hp(obj);
00446   // Save the offset
00447   MarkSweep::add_hcode_offset(h - obj);
00448   // if (WizardMode) lprintf("[0x%lx+%d]\n", obj, h - obj);
00449 }
00450 
00451 void frame::restore_hcode_pointer() {
00452   if (!is_interpreted_frame()) return;
00453   // Readjust hcode pointer
00454   u_char* obj  = hp();
00455   int   offset = MarkSweep::next_hcode_offset();
00456   // if (WizardMode) lprintf("[0x%lx+%d]\n", obj, offset);
00457   set_hp(obj + offset);
00458 }
00459 
00460 class VerifyOopClosure : public OopClosure {
00461  public:
00462   frame* fr;
00463   void do_oop(oop* o) {
00464     oop obj = *o;
00465     if (!obj->verify()) {
00466       lprintf("Verify failed in frame:\n");
00467       fr->print();
00468     }
00469   }
00470 };
00471 
00472 void frame::verify() const {
00473   if (fp() == NULL) fatal("fp cannot be NULL");
00474   if (sp() == NULL) fatal("fp cannot be NULL");
00475   VerifyOopClosure blk;
00476   blk.fr = (frame*) this;
00477   ((frame*) this)->oop_iterate(&blk);
00478 }
00479 
00480 frame frame::sender() const {
00481   frame result;
00482   if (is_entry_frame()) {
00483     // Delta frame called from C; skip all C frames and return top C
00484     // frame of that chunk as the sender
00485     assert(has_next_Delta_fp(), "next Delta fp must be non zero");
00486     assert(next_Delta_fp() > _fp, "must be above this frame on stack");
00487     result = frame(next_Delta_sp(), next_Delta_fp());
00488   } else if (is_deoptimized_frame()) {
00489      result = frame(real_sender_sp(), link(), return_addr());
00490   } else {
00491     result = frame(sender_sp(), link(), return_addr());
00492   }
00493   return result;
00494 }
00495 
00496 frame frame::delta_sender() const {
00497   for (frame s = sender(); !s.is_delta_frame(); s = s.sender()) ;
00498   return s;
00499 }
00500 
00501 bool frame::should_be_deoptimized() const {
00502   if (!is_compiled_frame()) return false;
00503   nmethod* nm = code();
00504   if (TraceApplyChange) {
00505     std->print("checking (%s) ", nm->is_marked_for_deoptimization() ? "true" : "false"); 
00506     nm->print_value_on(std);
00507     std->cr();
00508   }
00509   return nm->is_marked_for_deoptimization();
00510 }

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