uncommonBranch.cpp

Go to the documentation of this file.
00001 /* Copyright 1994, 1995 LongView Technologies L.L.C. $Revision: 1.24 $ */
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 
00027 #ifdef DELTA_COMPILER
00028 # include "incls/_uncommonBranch.cpp.incl"
00029 
00030 // Tells whether the call has been executed before
00031 // %note:
00032 //    This function is highly INTEL specific.
00033 
00034 bool patch_uncommon_call(frame* f) {
00035   // patch the call site:
00036   //  from: call _unused_uncommon_trap
00037   //  to:   call _used_uncommon_trap
00038 
00039   int* next_inst = (int*) f->pc();
00040   int* dest_addr = next_inst-1;
00041   int  dest      = *dest_addr + (int) next_inst;
00042 
00043   // return true if the call has been executed before
00044   if (dest == (int)StubRoutines::used_uncommon_trap_entry())
00045     return true;
00046 
00047   assert(dest == (int)StubRoutines::unused_uncommon_trap_entry(), "Make sure we are patching the right call");
00048 
00049   // patch with used_uncommon_trap
00050   *dest_addr = ((int)StubRoutines::used_uncommon_trap_entry()) - ((int) next_inst);
00051 
00052   assert(*dest_addr + (int) next_inst == (int)StubRoutines::used_uncommon_trap_entry(), "Check the patch");
00053 
00054   // return false since the call is patched
00055   return false;
00056 }
00057 
00058 
00059 // Tells whether the frame is a candidate for deoptimization by
00060 // checking if the frame uses contextOops with forward pointers.
00061 static bool has_invalid_context(frame* f) {
00062   // Return false if we're not in compiled code
00063   if (!f->is_compiled_frame()) return false;
00064 
00065   // Iterate over the vframes and check the compiled_context
00066   compiledVFrame* vf = (compiledVFrame*) vframe::new_vframe(f);
00067   assert(vf->is_compiled_frame(), "should be compiled vframe");
00068   while (true) {
00069     contextOop con = vf->compiled_context();
00070 
00071     // std->print_cr("checking context fp = 0x%lx, pc = 0x%lx", f->fp(), f->pc());
00072     if (con) con->print();
00073 
00074     if (con && con->unoptimized_context()) return true;
00075     if (vf->is_top()) break;
00076     vf = (compiledVFrame*) vf->sender();
00077     assert(vf->is_compiled_frame(), "should be compiled vframe");
00078   }
00079   return false;
00080 }
00081 
00082 
00083 class FrameAndContextElement : public ResourceObj {
00084  public:
00085   frame      fr;
00086   contextOop con;
00087 
00088   FrameAndContextElement(frame* f, contextOop c) {
00089     fr  = *f;
00090     con = c;
00091   }
00092 };
00093 
00094 
00095 void collect_compiled_contexts_for(frame* f, GrowableArray<FrameAndContextElement*>* elements) {
00096   // Return false if we're not in compiled code
00097   if (!f->is_compiled_frame()) return;
00098 
00099   // Iterate over the vframes and check the compiled_context
00100   compiledVFrame* vf = (compiledVFrame*) vframe::new_vframe(f);
00101   assert(vf->is_compiled_frame(), "should be compiled vframe");
00102   while (true) {
00103     contextOop con = vf->compiled_context();
00104     if (con) {
00105       elements->append(new FrameAndContextElement(f, con));
00106     }
00107     if (vf->is_top()) break;
00108     vf = (compiledVFrame*) vf->sender();
00109     assert(vf->is_compiled_frame(), "should be compiled vframe");
00110   }
00111 }
00112 
00113 
00114 class EnableDeoptimization: StackObj {
00115  public:
00116   EnableDeoptimization()  { StackChunkBuilder::begin_deoptimization(); }
00117   ~EnableDeoptimization() { StackChunkBuilder::end_deoptimization();   }
00118 };
00119 
00120 
00121 void uncommon_trap() {
00122   /*
00123   if (UseNewBackend) {
00124     warning("uncommon traps not supported yet for new backend");
00125     Unimplemented();
00126   }
00127   */
00128 
00129   ResourceMark rm;
00130   // Find the frame that caused the uncommon trap
00131   DeltaProcess* process = DeltaProcess::active();
00132 
00133 #ifdef ASSERT
00134   process->verify();
00135 #endif
00136 
00137   FlagSetting fl(processSemaphore, true);
00138 
00139   process->enter_uncommon();
00140   frame f = process->last_frame();
00141 
00142   // Patch the call destination if necessary
00143   bool used = patch_uncommon_call(&f);
00144 
00145   // Find the nmethod containing the uncommon trap
00146   compiledVFrame* vf = (compiledVFrame*) vframe::new_vframe(&f);
00147   assert(vf->is_compiled_frame(), "must be compiled frame");
00148   nmethod* nm = vf->code();
00149 
00150   nm->inc_uncommon_trap_counter();
00151 
00152   LOG_EVENT3("Uncommon trap in 0x%lx@%d #%d", nm, vf->scope()->offset(), nm->uncommon_trap_counter());
00153 
00154   /* For Debugging inserted by Lars Bak 5-13-96
00155   if (nm->is_block()) { 
00156     PrintUncommonBranches = true;
00157     TraceDeoptimization = true;
00158   } else {
00159     PrintUncommonBranches = false;
00160     TraceDeoptimization = false;
00161   }
00162   */
00163 
00164   if (PrintUncommonBranches)  {
00165     std->print("%s trap in ", used ? "Uncommon" : "New uncommon");
00166     nm->print_value_on(std);
00167     std->print(" #%d", nm->uncommon_trap_counter());
00168     if (WizardMode) std->print(" @%d called from %#x", vf->scope()->offset(), f.pc() - Assembler::sizeOfCall);
00169     std->cr();
00170     if (TraceDeoptimization) vf->print_activation(0);
00171     process->trace_top(0, 3);
00172   }
00173 
00174   // if counter is high enough, recompile the nmethod
00175   if (RecompilationPolicy::shouldRecompileAfterUncommonTrap(nm)) {
00176     if (!nm->isZombie()) nm->makeZombie(false);
00177     Recompilation recomp(vf->receiver(), nm, true);
00178     VMProcess::execute(&recomp);
00179   }
00180 
00181 
00182   {
00183   FinalResourceMark rm;
00184   EnableDeoptimization ed; // Wrapper that enables canonicalization when deoptimization.
00185 
00186   DeltaProcess::deoptimize_redo_last_send();
00187   process->deoptimize_stretch(&f, &f);
00188   if (!nm->is_method()) {
00189     // This is a top level block nmethod so we have to make sure all frames on the stack
00190     // referring the context chain are deoptimized.
00191     // Frames on other stacks might be candidates for deoptimization but are ignored for now.  fix this later
00192     //
00193     // Recipe:
00194     //   walk the stack and collect a work list of {frame, compiled_context} pairs.
00195     //   iterate over the work list until no deoptimized contextOops are present.
00196     GrowableArray<FrameAndContextElement*>* elements  = new GrowableArray<FrameAndContextElement*>(10);
00197     for (frame current_frame = f.sender(); !current_frame.is_first_frame(); current_frame = current_frame.sender()) {
00198       collect_compiled_contexts_for(&current_frame, elements);
00199     }
00200     
00201     bool done = false;
00202 
00203     while (!done) {
00204       done = true;      
00205       for (int index = 0; index < elements->length() && done; index++) {
00206         FrameAndContextElement* e = elements->at(index);
00207         if (e && e->con->unoptimized_context()) {
00208           process->deoptimize_stretch(&e->fr, &e->fr);
00209 
00210           for (int j = 0; j < elements->length(); j++) {
00211             if (elements->at(j) && elements->at(j)->fr.fp() == e->fr.fp())
00212               elements->at_put(j, NULL);
00213           }
00214           done = false;
00215         }
00216       } 
00217     }
00218   }
00219   }
00220   process->exit_uncommon();
00221 }
00222 
00223 #endif

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