process.cpp

Go to the documentation of this file.
00001 /* Copyright 1994, 1995 LongView Technologies L.L.C. $Revision: 1.119 $ */
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/_process.cpp.incl"
00026 
00027 // The tricky part is to restore the original return address of the primitive before
00028 // the delta call. This is necessary for a consistent stack during the delta call.
00029 extern "C" char*  C_frame_return_addr;
00030 extern "C" bool have_nlr_through_C;
00031 extern "C" int  nlr_home;
00032 extern "C" int  nlr_home_id;
00033 extern "C" oop  nlr_result;
00034 
00035 unwindInfo::unwindInfo() {
00036    assert(have_nlr_through_C, "you must have have_nlr_through_C before using unwindInfo");
00037 
00038    // Save NLR state 
00039    _nlr_home    = ::nlr_home;
00040    _nlr_home_id = ::nlr_home_id;
00041    _nlr_result  = ::nlr_result;
00042 
00043    // Save patch information
00044    assert(last_Delta_fp, "last_Delta_fp must be set");
00045    saved_C_frame_return_addr          = C_frame_return_addr;
00046    saved_C_frame_return_addr_location = (char**) (last_Delta_sp - 1);
00047    saved_patch_return_address         = *saved_C_frame_return_addr_location;
00048 
00049    // Restore original return address
00050    *saved_C_frame_return_addr_location = saved_C_frame_return_addr;
00051 
00052    _is_compiled = _nlr_home_id >= 0;
00053    DeltaProcess::active()->push_unwind(this);
00054 }
00055 
00056 unwindInfo::~unwindInfo() {
00057   // If we get an aborting NLR in the protect part we should continue the aborting NLR
00058   // and not the original NLR.
00059   if (::nlr_home != 0) {
00060     // Restore NLR state
00061     ::nlr_home    = _nlr_home;
00062     ::nlr_home_id = _nlr_home_id;
00063     ::nlr_result  = _nlr_result;
00064   }
00065   // Restore patch information
00066   *saved_C_frame_return_addr_location = saved_patch_return_address;
00067   C_frame_return_addr                 = saved_C_frame_return_addr;
00068 
00069   DeltaProcess::active()->pop_unwind();
00070 }
00071 
00072 void unwindInfo::update_nlr_targets(compiledVFrame* f, contextOop con) {
00073   // Convert the nlr information if:
00074   //    nlr_home     is the frame pointer of f
00075   // && nlr_home_id  is the offset of f's scope
00076   if (f->fr().fp() == (int*) nlr_home() && f->scope()->offset() == nlr_home_id()) {
00077     _nlr_home_context = con;
00078   }
00079 }
00080 
00081 bool processSemaphore = false;
00082 
00083 // For current Delta process, the last FP/Sp is stored in these global vars, not
00084 // the instance vars of the process
00085 int* last_Delta_fp = NULL;
00086 oop* last_Delta_sp = NULL;
00087 
00088 // last_Delta_fp
00089 int* DeltaProcess::last_Delta_fp() const { 
00090   return this == _active_delta_process ? ::last_Delta_fp : _last_Delta_fp; 
00091 }
00092 
00093 void DeltaProcess::set_last_Delta_fp(int* fp) { 
00094   if (this == _active_delta_process) {
00095     ::last_Delta_fp = fp;
00096   } else {
00097     _last_Delta_fp = fp;   
00098   }
00099 }
00100 
00101 // last_Delta_sp
00102 oop* DeltaProcess::last_Delta_sp() const { 
00103   return this == _active_delta_process ? ::last_Delta_sp : _last_Delta_sp; 
00104 }
00105 
00106 void DeltaProcess::set_last_Delta_sp(oop* sp) { 
00107   if (this == _active_delta_process) {
00108     ::last_Delta_sp = sp;
00109   } else {
00110     _last_Delta_sp = sp;   
00111   }
00112 }
00113 
00114 // last_Delta_pc
00115 char* DeltaProcess::last_Delta_pc() const { 
00116   return _last_Delta_pc; 
00117 }
00118 
00119 void DeltaProcess::set_last_Delta_pc(char* pc) { 
00120   _last_Delta_pc = pc;   
00121 }
00122 
00123 int CurrentHash = 23;
00124 
00125 bool Process::external_suspend_current() {
00126   if (current() == NULL) return false;
00127   os::suspend_thread(current()->_thread);
00128   return true;
00129 }
00130 
00131 void Process::external_resume_current() {
00132   os::resume_thread(current()->_thread);
00133 }
00134 
00135 void Process::basic_transfer(Process* target) {
00136   if (TraceProcessEvents) {
00137     std->print("Process: "); print();
00138     std->print(" -> "); target->print();
00139     std->cr();
00140   }
00141   os::transfer(_thread, _event, target->_thread, target->_event);
00142 }
00143 
00144 // ======= VMProcess ========
00145 
00146 VMProcess::VMProcess() {
00147   assert(vm_process() == NULL, "we can only allocate one VMProcess");
00148 
00149   _vm_process   = this;
00150   _vm_operation = NULL;
00151 
00152   _thread    = os::starting_thread(&_thread_id);
00153   _event     = os::create_event(true);
00154 }
00155 
00156 void VMProcess::transfer_to(DeltaProcess* target) {
00157   {
00158     ThreadCritical tc;
00159 
00160     // restore state
00161     ::last_Delta_fp = target->_last_Delta_fp;   // *don't* use accessors! 
00162     ::last_Delta_sp = target->_last_Delta_sp;
00163     DeltaProcess::set_active(target);
00164     DeltaProcess::set_current(target);
00165   }
00166   basic_transfer(target);
00167 }
00168 
00169 
00170 void VMProcess::terminate(DeltaProcess* proc) {
00171   assert(Process::current()->is_vmProcess(), "can only be called from vm process");
00172   assert(proc->is_deltaProcess(),            "must be deltaProcess");
00173   assert(proc->_thread,                      "thread must be present");
00174   assert(proc->_event,                       "event must be present");
00175 
00176   os::terminate_thread(proc->_thread);
00177   proc->_thread = NULL;
00178   os::delete_event(proc->_event);
00179   proc->_event  = NULL;
00180 
00181   DeltaProcess::set_terminating_process(proc->state());
00182 }
00183 
00184 void VMProcess::activate_system() {
00185   // Find the Delta level 'Processor'
00186   processOop proc = processOop(Universe::find_global("Processor"));
00187   if (!proc->is_process()) {
00188     klassOop scheduler_klass = klassOop(Universe::find_global("ProcessorScheduler"));
00189     proc = processOop(scheduler_klass->klass_part()->allocateObject());
00190     associationOop assoc = Universe::find_global_association("Processor");
00191     assoc->set_value(proc);
00192   }
00193 
00194   DeltaProcess::initialize_async_dll_event();
00195 
00196   // Create the initial process
00197   DeltaProcess::set_scheduler(new DeltaProcess(proc, oopFactory::new_symbol("start")));
00198 
00199   // Bind the scheduler to Processor
00200   proc->set_process(DeltaProcess::scheduler());
00201   DeltaProcess::scheduler()->set_processObj(proc);
00202 
00203   // Transfer control to the scheduler
00204   transfer_to(DeltaProcess::scheduler());
00205 
00206   // Call the ever running loop handling vm operations
00207   loop();
00208 }
00209 
00210 void VMProcess::loop() {
00211   while (true) {
00212     assert(vm_operation(), "A VM_Operation should be present");
00213     vm_operation()->evaluate();
00214     DeltaProcess* p = vm_operation()->calling_process();
00215     _vm_operation = NULL;
00216     if (p) {
00217       transfer_to(p);
00218     } else {
00219       transfer_to(DeltaProcess::scheduler());
00220     }
00221   }
00222 }
00223 
00224 void VMProcess::print() {
00225   std->print_cr("VMProcess");
00226 }
00227 
00228 void VMProcess::execute(VM_Operation* op) {
00229 
00230   if (Sweeper::is_running()) {
00231     // We cannot perform a vm operations when running the sweeper since
00232     // the sweeper run  outside the active process.
00233     fatal("VMProcess is called during sweeper run");
00234   }
00235 
00236   if (DeltaProcess::active()->in_vm_operation()) {
00237     // already running in VM process, no need to switch
00238     op->evaluate();
00239   } else {
00240     op->set_calling_process(DeltaProcess::active());
00241     _vm_operation = op;
00242     // Suspend currentProcess and resume vmProcess
00243     DeltaProcess::active()->transfer_to_vm();
00244   }
00245 }
00246 
00247 VMProcess*    VMProcess::_vm_process   = NULL;
00248 VM_Operation* VMProcess::_vm_operation = NULL;
00249 
00250 // ======= DeltaProcess ========
00251 
00252 Process*      DeltaProcess::_current_process             = NULL;
00253 DeltaProcess* DeltaProcess::_active_delta_process        = NULL;
00254 DeltaProcess* DeltaProcess::_scheduler_process           = NULL;
00255 bool          DeltaProcess::_is_idle                     = false;
00256 
00257 bool          DeltaProcess::_process_has_terminated      = false;
00258 ProcessState  DeltaProcess::_state_of_terminated_process = initialized;
00259 
00260 Event*        DeltaProcess::_async_dll_completion_event  = NULL;
00261 
00262 void DeltaProcess::transfer(ProcessState reason, DeltaProcess* target) {
00263   // change time_stamp for targer
00264   target->inc_time_stamp();
00265 
00266   {
00267     ThreadCritical tc;
00268 
00269     assert(this == active(), "receiver must be the active process");
00270 
00271     // save state
00272     _last_Delta_fp = ::last_Delta_fp;   // *don't* use accessors! (check their implementation to see why)
00273     _last_Delta_sp = ::last_Delta_sp;
00274     set_state(reason);
00275 
00276     // restore state
00277     ::last_Delta_fp = target->_last_Delta_fp;   // *don't* use accessors! 
00278     ::last_Delta_sp = target->_last_Delta_sp;
00279     set_current(target);
00280     set_active(target);
00281   }
00282 
00283   // transfer
00284   basic_transfer(target);
00285 }
00286 
00287 void DeltaProcess::suspend(ProcessState reason) {
00288   assert(!is_scheduler(), "active must be other than scheduler");
00289   assert(!in_vm_operation(), "must not be in VM operation");
00290 
00291   transfer(reason, scheduler());
00292   if (is_terminating()) 
00293     ErrorHandler::abort_current_process();
00294 }
00295 
00296 ProcessState DeltaProcess::transfer_to(DeltaProcess* destination) {
00297   assert(is_scheduler(), "active must be scheduler");
00298   assert(!in_vm_operation(), "must not be in VM operation");
00299   // Do not transfer if destination process is execution DLL.
00300   if (destination->state() == in_async_dll)
00301     return destination->state();
00302 
00303   transfer(yielded, destination);
00304   if (process_has_terminated()) {
00305     return state_of_terminated_process();
00306   }
00307   return destination->state();
00308 }
00309 
00310 void DeltaProcess::transfer_to_vm() {
00311   {
00312     ThreadCritical tc;
00313 
00314     assert(this == active(), "receiver must be the active process");
00315 
00316     // save state
00317     _last_Delta_fp = ::last_Delta_fp;   // *don't* use accessors! (check their implementation to see why)
00318     _last_Delta_sp = ::last_Delta_sp;
00319     set_current(VMProcess::vm_process());
00320   }
00321   basic_transfer(VMProcess::vm_process());
00322 }
00323 
00324 void DeltaProcess::suspend_at_creation() {
00325   // This is called as soon a DeltaProcess is created
00326   // Let's wait until we're given the torch.
00327   os::wait_for_event(_event);
00328 }
00329 
00330 void DeltaProcess::transfer_and_continue() {
00331   {
00332     ThreadCritical tc;
00333 
00334     assert(!is_scheduler(), "active must be other than scheduler");
00335     assert(!in_vm_operation(), "must not be in VM operation");
00336     assert(this == active(), "receiver must be the active process");
00337 
00338 
00339     // save state
00340     _last_Delta_fp = ::last_Delta_fp;   // *don't* use accessors! (check their implementation to see why)
00341     _last_Delta_sp = ::last_Delta_sp;
00342     set_state(in_async_dll);
00343 
00344 
00345     // restore state
00346     ::last_Delta_fp = scheduler()->_last_Delta_fp;      // *don't* use accessors! 
00347     ::last_Delta_sp = scheduler()->_last_Delta_sp;
00348     set_current(scheduler());
00349     set_active(scheduler());
00350 
00351     if (TraceProcessEvents) {
00352       std->print("Async call: "); print();
00353       std->print("        to: "); scheduler()->print();
00354       std->cr();
00355     }
00356   }
00357   os::transfer_and_continue(_thread, _event, scheduler()->_thread, scheduler()->_event);
00358 }
00359 
00360 bool DeltaProcess::wait_for_async_dll(int timeout_in_ms) {
00361   os::reset_event(_async_dll_completion_event);
00362   if (Processes::has_completed_async_call()) return true;
00363 
00364   if (TraceProcessEvents) {
00365     std->print("Waiting for async %d ms", timeout_in_ms);
00366   }
00367 
00368   _is_idle = true;
00369   bool result = os::wait_for_event_or_timer(_async_dll_completion_event, timeout_in_ms);
00370   _is_idle = false;
00371 
00372 
00373   if (TraceProcessEvents) {
00374     std->print_cr(result ? " {timeout}" : " {async}");
00375   }
00376 
00377   return result;
00378 }
00379 
00380 void DeltaProcess::initialize_async_dll_event() {
00381   _async_dll_completion_event = os::create_event(false);
00382 }
00383 
00384 void DeltaProcess::async_dll_call_completed() {
00385   os::signal_event(_async_dll_completion_event);
00386 }
00387 
00388 void DeltaProcess::wait_for_control() {
00389   if (TraceProcessEvents) {
00390     std->print("*");
00391   }
00392 
00393   set_state(yielded_after_async_dll);
00394   async_dll_call_completed();
00395   os::wait_for_event(_event);
00396   if (is_terminating()) 
00397     ErrorHandler::abort_current_process();
00398 }
00399 
00400 extern "C" bool have_nlr_through_C;
00401 
00402 // Code entry point for at Delta process
00403 int DeltaProcess::launch_delta(DeltaProcess* process) {
00404   // Wait until we get the torch
00405   process->suspend_at_creation();
00406 
00407   // We have the torch
00408   assert(process == DeltaProcess::active(),  "process consistency check");
00409   assert(process->is_deltaProcess(), "this should be a deltaProcess");
00410 
00411   DeltaProcess* p = (DeltaProcess*) process;
00412   oop result = Delta::call(p->receiver(), p->selector());
00413 
00414   if (have_nlr_through_C) {
00415     if (nlr_home_id == ErrorHandler::aborting_nlr_home_id()) {
00416       p->set_state(aborted);
00417     } else {
00418       p->set_state(NLR_error);
00419     }
00420   } else {
00421     p->set_state(completed);
00422   }
00423   assert(process == DeltaProcess::active(),  "process consistency check");
00424 
00425   VM_TerminateProcess op(process);
00426   VMProcess::execute(&op);
00427   return 0;
00428 }
00429 
00430 DeltaProcess::DeltaProcess(oop receiver, symbolOop selector) {
00431   _receiver    = receiver;
00432   _selector    = selector;
00433 
00434   _state       = initialized;
00435 
00436   _is_terminating = false;
00437 
00438   _event       = os::create_event(false);
00439   _thread      = os::create_thread((int (*)(void*)) &launch_delta, (void*) this, &_thread_id);
00440 
00441   _unwind_head = NULL;
00442 
00443   _time_stamp  = 0;
00444 
00445   LOG_EVENT1("creating process %#lx", this);
00446 
00447   set_last_Delta_fp(NULL);
00448   set_last_Delta_sp(NULL);
00449   set_last_Delta_pc(NULL);
00450   Processes::add(this);
00451 }
00452 
00453 frame DeltaProcess::profile_top_frame() {
00454   int*  sp;
00455   int*  fp;
00456   char* pc;
00457   os::fetch_top_frame(_thread, &sp, &fp, &pc);
00458   frame result((oop*)sp, fp, pc);
00459   return result;
00460 }
00461 
00462 
00463 DeltaProcess::~DeltaProcess() {
00464   processObj()->set_process(NULL);
00465   if (Processes::includes(this)) {
00466     Processes::remove(this);
00467   }
00468 }
00469 
00470 void DeltaProcess::print() {
00471   processObj()->print_value();
00472   std->print(" ");
00473   switch (state()) {
00474     case initialized:             std->print_cr("initialized");            break;
00475     case running:                 std->print_cr("running");                break;
00476     case yielded:                 std->print_cr("yielded");                break;
00477     case in_async_dll:            std->print_cr("in asynchronous dll all");break;
00478     case yielded_after_async_dll: std->print_cr("yielded after asynchronous dll"); break;
00479     case preempted:               std->print_cr("preempted");              break;
00480     case completed:               std->print_cr("completed");              break;
00481     case boolean_error:           std->print_cr("boolean error");          break;
00482     case lookup_error:            std->print_cr("lookup error");           break;
00483     case primitive_lookup_error:  std->print_cr("primitive lookup error"); break;
00484     case DLL_lookup_error:        std->print_cr("DLL lookup error");       break;
00485     case NLR_error:               std->print_cr("NLR error");              break;
00486     case stack_overflow:          std->print_cr("stack overflow");         break;
00487   }
00488 }
00489 
00490 void DeltaProcess::frame_iterate(FrameClosure* blk) {
00491   blk->begin_process(this);
00492   
00493   if (has_stack()) {
00494     frame v = last_frame();
00495     do {
00496       blk->do_frame(&v);
00497       v = v.sender();
00498     } while (!v.is_first_frame());
00499   }
00500 
00501   blk->end_process(this);
00502 }
00503 
00504 void DeltaProcess::oop_iterate(OopClosure* blk) {
00505   blk->do_oop((oop*) &_receiver);
00506   blk->do_oop((oop*) &_selector);
00507   blk->do_oop((oop*) &_processObj);
00508 
00509   for (unwindInfo* p = _unwind_head; p; p = p->next())
00510     blk->do_oop((oop*) &p->_nlr_result);
00511 
00512   if (has_stack()) {
00513     frame v = last_frame();
00514     do {
00515       v.oop_iterate(blk);
00516       v = v.sender();
00517     } while (!v.is_first_frame());
00518   }
00519 }
00520 
00521 symbolOop DeltaProcess::symbol_from_state(ProcessState state) {
00522   switch(state) {
00523     case initialized:             return vmSymbols::initialized();
00524     case yielded:                 return vmSymbols::yielded();
00525     case running:                 return vmSymbols::running();
00526     case stopped:                 return vmSymbols::stopped();
00527     case preempted:               return vmSymbols::preempted();
00528     case aborted:                 return vmSymbols::aborted();
00529     case in_async_dll:            return vmSymbols::in_async_dll();
00530     case yielded_after_async_dll: return vmSymbols::yielded();
00531     case completed:               return vmSymbols::completed();
00532     case boolean_error:           return vmSymbols::boolean_error();
00533     case lookup_error:            return vmSymbols::lookup_error();
00534     case primitive_lookup_error:  return vmSymbols::primitive_lookup_error();
00535     case DLL_lookup_error:        return vmSymbols::DLL_lookup_error();
00536     case float_error:             return vmSymbols::float_error();
00537     case NLR_error:               return vmSymbols::NLR_error();
00538     case stack_overflow:          return vmSymbols::stack_overflow();
00539   }
00540   return vmSymbols::not_found();
00541 }
00542 
00543 bool DeltaProcess::has_stack() const {
00544   if (state() == initialized) return false;
00545   if (state() == completed)   return false;
00546   return true;
00547 }
00548 
00549 
00550 void DeltaProcess::follow_roots() {
00551   MarkSweep::follow_root((oop*) &_receiver);
00552   MarkSweep::follow_root((oop*) &_selector);
00553   MarkSweep::follow_root((oop*) &_processObj);
00554 
00555   if (has_stack()) {
00556     frame v = last_frame();
00557     do {
00558       v.follow_roots();
00559       v = v.sender();
00560     } while (!v.is_first_frame());
00561   }
00562 }
00563 
00564 void DeltaProcess::verify() {
00565   ResourceMark rm;
00566   BlockScavenge bs;
00567 
00568   vframe* f = last_delta_vframe();
00569   if (f == NULL) return;
00570 
00571   // Do not verify the first vframe
00572   // It will fail if scavenging in allocateContext (Lars)
00573   for (f = f->sender(); f; f = f->sender()) {
00574     f->verify();
00575   }
00576 }
00577 
00578 
00579 void DeltaProcess::enter_uncommon() {
00580   assert(_state == running, "must be running");
00581   _state = uncommon;
00582 }
00583 
00584 void DeltaProcess::exit_uncommon() {
00585   assert(_state == uncommon, "must be uncommon");
00586   _state = running;
00587 }
00588 
00589 //  [-1            ] <-- link to next frame
00590 //  [-1            ] <-- return address
00591 //
00592 //
00593 //
00594 //  [              ] <-- old_sp
00595 //  ...
00596 //  [              ] <--   old_fp
00597 
00598 static oop*        old_sp;
00599 static oop*        new_sp;
00600 static int*        old_fp;
00601 static int*        cur_fp;
00602 static objArrayOop frame_array;
00603 
00604 extern "C" oop* setup_deoptimization_and_return_new_sp(oop* old_sp, int* old_fp, objArrayOop frame_array, int* current_frame) {
00605   ResourceMark rm;
00606 
00607   // Save all parameters for later use (check unpack_frame_array)
00608   ::old_sp      = old_sp;
00609   ::old_fp      = old_fp;
00610   ::frame_array = frame_array;
00611   ::cur_fp      = current_frame;
00612 
00613   smiOop number_of_vframes = smiOop(frame_array->obj_at(StackChunkBuilder::number_of_vframes_index));
00614   smiOop number_of_locals  = smiOop(frame_array->obj_at(StackChunkBuilder::number_of_locals_index));
00615 
00616   assert(number_of_vframes->is_smi(), "must be smi");
00617   assert(number_of_locals->is_smi(), "must be smi");
00618 
00619   new_sp = old_sp - frame::interpreter_stack_size(number_of_vframes->value(),
00620                                                   number_of_locals->value());
00621   return new_sp;
00622 }
00623 
00624 
00625 // Used to transfer information from deoptimize_stretch to unpack_frame_array.
00626 static bool redo_the_send;
00627 
00628 extern "C" int redo_send_offset = 0;
00629 
00630 void DeltaProcess::deoptimize_redo_last_send() {
00631   redo_the_send = true;
00632 }
00633 
00634 // Interpreter entry point for redoing a send.
00635 extern "C" void redo_bytecode_after_deoptimization();
00636 
00637 extern "C" bool       nlr_through_unpacking = false;
00638 extern "C" oop        result_through_unpacking = NULL;
00639 extern "C" int        number_of_arguments_through_unpacking = 0;
00640 extern "C" char*      C_frame_return_addr = NULL;
00641 extern "C" contextOop nlr_home_context;
00642 
00643 // Called from assembler in unpack_unoptimized_frames.
00644 // Based on the statics (old_sp, old_fp, and frame_array) this function unpacks
00645 // the array into interpreter frames.
00646 // Returning from this function should activate the most recent deoptimized frame.
00647 extern "C" void unpack_frame_array() {
00648   BlockScavenge bs;
00649   ResourceMark rm;
00650 
00651   int* pc_addr = (int*) new_sp - 1;
00652   assert(*pc_addr = -1, "just checking");
00653 
00654   if (TraceDeoptimization) {
00655     std->print("[Unpacking]");
00656     if (nlr_through_unpacking) {
00657       std->print(" NLR %s", (nlr_home == (int) cur_fp) ? "inside" : "outside");
00658     }
00659     std->cr();
00660     std->print(" - array ");
00661     frame_array->print_value();
00662     std->print_cr(" @ 0x%lx", old_fp);
00663   }
00664 
00665   bool must_find_nlr_target = nlr_through_unpacking && nlr_home == (int) cur_fp;
00666   bool nlr_target_found     = false; // For verification
00667 
00668   // link for the current frame
00669   int* link_addr = (int*) new_sp - 2;
00670 
00671   oop* current_sp = new_sp;
00672   int  pos        = 3;
00673   int  length     = frame_array->length();
00674   bool first = true;
00675   frame current;
00676   // unpack one frame at at time from most recent to least recent
00677   do {
00678     oop receiver     = frame_array->obj_at(pos++);
00679     methodOop method = methodOop(frame_array->obj_at(pos++));
00680     assert(method->is_method(), "expecting method");
00681 
00682     smiOop bci_obj = smiOop(frame_array->obj_at(pos++));
00683     assert(bci_obj->is_smi(), "expecting smi");
00684     int bci        = bci_obj->value();
00685 
00686     smiOop locals_obj = smiOop(frame_array->obj_at(pos++));
00687     assert(locals_obj->is_smi(), "expecting smi");
00688     int locals   = locals_obj->value();
00689 
00690     current = frame(current_sp, (int*) current_sp + locals + 2);
00691 
00692     // fill in the locals
00693     for (int index = 0; index < locals; index++) {
00694       current.set_temp(index, frame_array->obj_at(pos++));
00695     }
00696 
00697     CodeIterator c(method, bci);
00698 
00699     char* current_pc;
00700 
00701     if (first) {
00702       // first vframe in the array
00703       if (nlr_through_unpacking) {
00704         // NLR is comming through unpacked vframes
00705         current_pc = c.interpreter_return_point();
00706         // current_pc points to a normal return point in the interpreter.
00707         // To find the nlr return point we first compute the nlr offset.
00708         current_pc = ic_info_at(current_pc)->NLR_target();
00709         current.set_hp(c.next_hp());
00710       } else if (redo_the_send) {
00711         // Deoptimizing uncommon trap
00712         current_pc = (char*) redo_bytecode_after_deoptimization;
00713         current.set_hp(c.next_hp());
00714         redo_send_offset = c.next_hp() - c.hp();
00715         redo_the_send = false;
00716       } else {
00717         // Normal case
00718         current_pc = c.interpreter_return_point(true);
00719         current.set_hp(c.next_hp());
00720  
00721         if (c.is_message_send()) {
00722           number_of_arguments_through_unpacking = c.ic()->nof_arguments();        
00723         } else if (c.is_primitive_call()) {
00724           number_of_arguments_through_unpacking = c.prim_cache()->number_of_parameters();
00725         } else if (c.is_dll_call()) {
00726           // The callee should not pop the argument since a DLL call is like a c function call.
00727           // The continuation code for the DLL call will pop the arguments!
00728           number_of_arguments_through_unpacking = 0;
00729         }
00730       }
00731     } else {
00732       current_pc = c.interpreter_return_point();
00733       current.set_hp(c.next_hp());
00734     }
00735     current.set_receiver(receiver);
00736 
00737     current.patch_pc(current_pc);
00738     current.patch_fp(current.fp());
00739     
00740     // Revive the contexts
00741     if (!method->is_blockMethod() && method->activation_has_context()) {
00742       contextOop con = contextOop(current.temp(0));
00743       assert(con->is_context(), "must be context");
00744       oop frame_oop = oop(current.fp());
00745       con->set_parent(frame_oop);
00746 
00747       if (nlr_through_unpacking && nlr_home == (int) cur_fp) {
00748         if (nlr_home_context == con) {
00749           // This frame is the target of the NLR
00750           // set nlr_home to frame pointer of current frame
00751           nlr_home = (int) current.fp();
00752           // compute number of arguments to pop
00753           nlr_home_id = ~method->number_of_arguments();
00754           nlr_target_found = true;
00755           // std->print("target frame for NLR (%d, 0x%lx):",method->number_of_arguments(), nlr_home_id);
00756         }
00757       }
00758     }
00759 
00760     if (TraceDeoptimization) {
00761       frame v(current_sp, current.fp(), current_pc);
00762       v.print_for_deoptimization(std);
00763     }
00764 
00765     first = false;
00766     // Next pc
00767     current_sp += frame::interpreter_frame_size(locals);
00768 
00769   } while (pos <= length);
00770 
00771   if (must_find_nlr_target && !nlr_target_found) {
00772     fatal("Target for NLR not found when unpacking frame");
00773   }
00774 
00775   assert (current_sp == old_sp, "We have not reached the end");
00776   current.set_link(old_fp);
00777 }
00778 
00779 extern "C" void verify_at_end_of_deoptimization() {
00780   if (PrintStackAfterUnpacking) {
00781     BlockScavenge bs;
00782     ResourceMark rm;
00783     DeltaProcess::active()->verify();
00784     std->print_cr("[Stack after unpacking]");
00785     DeltaProcess::active()->trace_stack_for_deoptimization();
00786   }
00787 }
00788 
00789 // Called when returning to an unoptimized frame
00790 // Implemented in assembly (see interpreter_asm.asm)
00791 extern "C" void unpack_unoptimized_frames();
00792 
00793 void DeltaProcess::deoptimize_stretch(frame* first_frame, frame* last_frame) {
00794   if (TraceDeoptimization) {
00795     std->print_cr("[Deoptimizing]");
00796     frame c = *first_frame;
00797     c.print_for_deoptimization(std);
00798     while (c.fp() != last_frame->fp()) {
00799       c = c.sender();
00800       c.print_for_deoptimization(std);
00801     }
00802   }
00803 
00804   StackChunkBuilder packer(first_frame->fp());
00805 
00806   vframe* vf = vframe::new_vframe(first_frame);
00807   assert(vf->is_compiled_frame(), "must be Delta frame");
00808 
00809   for (deltaVFrame* current = (deltaVFrame*) vf; 
00810        current && (current->fr().fp() <= last_frame->fp()); 
00811        current = (deltaVFrame*) current->sender()) {
00812     packer.append(current);
00813   }
00814 
00815   // Patch frame
00816   // - patch the pc first to convert the frame into a deoptimized_frame
00817   first_frame->patch_pc((char*) &unpack_unoptimized_frames); 
00818   first_frame->set_return_addr(last_frame->return_addr());
00819   first_frame->set_real_sender_sp(last_frame->sender_sp());
00820   first_frame->set_frame_array(packer.as_objArray());
00821   first_frame->set_link(last_frame->link());
00822 }
00823 
00824 void DeltaProcess::deoptimized_wrt_marked_nmethods() {
00825   // chop the stack into stretches of frames in need for deoptimization
00826   if (!has_stack()) return;
00827 
00828   frame v = last_frame();
00829   do {
00830     if (v.should_be_deoptimized())
00831       deoptimize_stretch(&v, &v);
00832     v = v.sender();
00833   } while (!v.is_first_frame());
00834 }
00835 
00836 frame DeltaProcess::last_frame() {
00837   assert(last_Delta_fp(), "must have last_Delta_fp() when suspended");
00838   if (last_Delta_pc() == NULL) {
00839     frame c(last_Delta_sp(), last_Delta_fp());
00840     return c;
00841   } else {
00842     frame c(last_Delta_sp(), last_Delta_fp(), last_Delta_pc());
00843     return c;
00844   }
00845 }
00846 
00847 deltaVFrame* DeltaProcess::last_delta_vframe() {
00848   // If no stack is present return NULL
00849   if (!has_stack()) return NULL;
00850 
00851   frame f = last_frame();
00852   for (vframe* vf = vframe::new_vframe(&f); vf; vf = vf->sender() ) {
00853     if (vf->is_delta_frame()) return (deltaVFrame*) vf;
00854   }
00855   return NULL;
00856 }
00857 
00858 
00859 int DeltaProcess::depth() {
00860   int d = 0;
00861   for(frame v = last_frame(); v.link(); v = v.sender()) d++;
00862   return d;
00863 }
00864 
00865 int DeltaProcess::vdepth(frame* f) {
00866   Unimplemented();
00867   return 0;
00868 }
00869 
00870 void DeltaProcess::trace_stack() {
00871   trace_stack_from(last_delta_vframe());
00872 }
00873 
00874 void DeltaProcess::trace_stack_from(vframe* start_frame) {
00875   std->print_cr("- Stack trace");
00876   int  vframe_no   = 1;
00877   for (vframe* f = start_frame; f; f = f->sender() ) {
00878     if (f->is_delta_frame()) {
00879       ((deltaVFrame*) f)->print_activation(vframe_no++);
00880     } else {
00881       f->print();
00882     }
00883     if (vframe_no == StackPrintLimit) {
00884       std->print_cr("...<more frames>...");
00885       return;
00886     }
00887   }
00888 }
00889 
00890 void DeltaProcess::trace_stack_for_deoptimization(frame* f) {
00891   if (has_stack()) {
00892     int  vframe_no   = 1;
00893     frame v = f ? *f : last_frame();
00894     do {
00895       v.print_for_deoptimization(std);
00896       v = v.sender();
00897       if (vframe_no == StackPrintLimit) {
00898         std->print_cr("...<more frames>...");
00899         return;
00900       }
00901       vframe_no++;
00902     } while (!v.is_first_frame());
00903   }
00904 }
00905 
00906 void DeltaProcess::trace_top(int start_frame, int number_of_frames) {
00907   FlagSetting fs(ActivationShowCode, true);
00908 
00909   std->print_cr("- Stack trace (%d, %d)", start_frame, number_of_frames);
00910   int  vframe_no = 1;
00911 
00912   for (vframe* f = last_delta_vframe(); f; f = f->sender() ) {
00913     if (vframe_no >= start_frame) {
00914       if (f->is_delta_frame()) {
00915         ((deltaVFrame*) f)->print_activation(vframe_no);
00916       } else f->print();
00917       if (vframe_no - start_frame + 1 >= number_of_frames) return;
00918     }
00919     vframe_no++;
00920   }
00921 }
00922 
00923 void DeltaProcess::update_nlr_targets(compiledVFrame* f, contextOop con) {
00924   for (unwindInfo* p = _unwind_head; p; p = p->next()) {
00925     p->update_nlr_targets(f, con);
00926   }
00927 }
00928 
00929 double DeltaProcess::user_time() {
00930   return _thread
00931        ? os:: user_time_for(_thread)
00932        : 0.0;
00933 }   
00934 
00935 double DeltaProcess::system_time() {
00936   return _thread
00937        ? os:: system_time_for(_thread)
00938        : 0.0;
00939 }
00940 
00941 // ======= Processes ========
00942 
00943 DeltaProcess* Processes::processList = NULL;
00944 
00945 void Processes::start(VMProcess* p) {
00946   processList = NULL;
00947   // activate the vm process
00948   p->activate_system();
00949 }
00950 
00951 void Processes::add(DeltaProcess* p) {
00952   p->set_next(processList);
00953   processList = p;
00954 }
00955 
00956 #define ALL_PROCESSES(X) for (DeltaProcess* X = processList; X; X = X->next())
00957 
00958 DeltaProcess* Processes::find_from_thread_id(int id) {
00959   ALL_PROCESSES(p) 
00960     if (p->thread_id() == id)
00961       return p;
00962   return NULL;
00963 }
00964 
00965 void Processes::frame_iterate(FrameClosure* blk) {
00966   ALL_PROCESSES(p) p->frame_iterate(blk);
00967 }
00968 
00969 void Processes::oop_iterate(OopClosure* blk) {
00970   ALL_PROCESSES(p) p->oop_iterate(blk);
00971 }
00972 
00973 void Processes::process_iterate(ProcessClosure* blk) {
00974   ALL_PROCESSES(p) blk->do_process(p);
00975 }
00976 
00977 void Processes::verify() {
00978   ALL_PROCESSES(p) p->verify();
00979 }
00980 
00981 bool Processes::has_completed_async_call() {
00982   ALL_PROCESSES(p) {
00983     if (p->state() == yielded_after_async_dll)
00984       return true;
00985   }
00986   return false;
00987 }
00988 
00989 void Processes::print() {
00990   std->print_cr("All processes:");
00991   ALL_PROCESSES(p) {
00992     ResourceMark rm;
00993     p->print();
00994     p->trace_stack();
00995   }
00996 }
00997 
00998 void Processes::remove(DeltaProcess* p) {
00999   assert(includes(p), "p must be present");
01000   DeltaProcess* current = processList; 
01001   DeltaProcess* prev    = NULL;
01002   
01003   while (current != p) {
01004     prev    = current;
01005     current = current->next();
01006   }
01007 
01008   if (prev) {
01009     prev->set_next(current->next());
01010   } else {
01011     processList = p->next();
01012   }
01013 }
01014 
01015 bool Processes::includes(DeltaProcess* p) {
01016   ALL_PROCESSES(q)
01017     if (q == p ) return true;
01018   return false;
01019 }
01020 
01021 
01022 DeltaProcess* Processes::last() {
01023   DeltaProcess* last = NULL;
01024   ALL_PROCESSES(q) last = q;
01025   return last;
01026 }
01027 
01028 void Processes::kill_all() {
01029   DeltaProcess* current = processList;
01030   while (current) {
01031     DeltaProcess* next = current->next();
01032     VMProcess::terminate(current);
01033     current->set_next(NULL);
01034     delete current;
01035     current = next;
01036   }
01037   processList = NULL;
01038 }
01039 
01040 class ScavengeOopClosure : public OopClosure {
01041   void do_oop(oop* o) { SCAVENGE_TEMPLATE(o); }
01042 };
01043 
01044 void Processes::scavenge_contents() {
01045   ScavengeOopClosure blk;
01046   oop_iterate(&blk);
01047 }
01048 
01049 void Processes::follow_roots() {
01050   ALL_PROCESSES(p) p->follow_roots();
01051 }
01052    
01053 class ConvertHCodePointersClosure : public FrameClosure {
01054   void do_frame(frame* f) {
01055     if (f->is_interpreted_frame()) {
01056       f->convert_hcode_pointer();
01057     }
01058   }
01059 };
01060 
01061 void Processes::convert_hcode_pointers() {
01062   ConvertHCodePointersClosure blk;
01063   frame_iterate(&blk);
01064 }
01065 
01066 class RestoreHCodePointersClosure : public FrameClosure {
01067   void do_frame(frame* f) {
01068     if (f->is_interpreted_frame()) {
01069       f->restore_hcode_pointer();
01070     }
01071   }
01072 };
01073 
01074 void Processes::restore_hcode_pointers() {
01075   RestoreHCodePointersClosure blk;
01076   frame_iterate(&blk);
01077 }
01078 
01079 void Processes::deoptimized_wrt_marked_nmethods() {
01080   StackChunkBuilder::begin_deoptimization();
01081   ALL_PROCESSES(p) p->deoptimized_wrt_marked_nmethods();
01082   StackChunkBuilder::end_deoptimization();
01083 }
01084 
01085 void Processes::deoptimize_wrt(nmethod* nm) {
01086   GrowableArray<nmethod*>* nms = nm->invalidation_family();
01087   // mark family for deoptimization
01088   for (int index = 0; index < nms->length(); index++)
01089     nms->at(index)->mark_for_deoptimization();
01090 
01091   // deoptimize
01092   deoptimized_wrt_marked_nmethods();
01093 
01094   // unmark for deoptimization
01095   for (index = 0; index < nms->length(); index++)
01096     nms->at(index)->unmark_for_deoptimization();
01097 }
01098 
01099 void Processes::deoptimize_wrt(GrowableArray<nmethod*>* list) {
01100   // mark for deoptimization
01101   for (int i = 0; i < list->length(); i++) {
01102     nmethod* nm = list->at(i);
01103     GrowableArray<nmethod*>* nms = nm->invalidation_family();
01104     for (int index = 0; index < nms->length(); index++)
01105       nms->at(index)->mark_for_deoptimization();
01106   }
01107 
01108   // deoptimize
01109   deoptimized_wrt_marked_nmethods();
01110 
01111   // unmark for deoptimization
01112   for (i = 0; i < list->length(); i++) {
01113     nmethod* nm = list->at(i);
01114     GrowableArray<nmethod*>* nms = nm->invalidation_family();
01115     for (int index = 0; index < nms->length(); index++)
01116       nms->at(index)->unmark_for_deoptimization();
01117   }
01118 }
01119 
01120 void Processes::update_nlr_targets(compiledVFrame* f, contextOop con) {
01121  ALL_PROCESSES(p) p->update_nlr_targets(f, con);
01122 }
01123 
01124 void Processes::deoptimize_all() {
01125   Universe::code->mark_all_for_deoptimization();
01126   deoptimized_wrt_marked_nmethods();
01127   Universe::code->unmark_all_for_deoptimization();
01128 }
01129 
01130 
01131 void handle_error(ProcessState error) {
01132   DeltaProcess* proc = DeltaProcess::active();
01133   if (proc->is_scheduler()) {
01134     std->print_cr("Error happend in the scheduler");
01135     std->print("Status: ");
01136     proc->status_symbol()->print_symbol_on(std);
01137     std->cr();
01138     evaluator::read_eval_loop();
01139   } else {
01140     proc->suspend(error);
01141   }
01142   ErrorHandler::abort_current_process();
01143   ShouldNotReachHere();
01144 }
01145 
01146 void handle_interpreter_error(char* message) {
01147   warning("Interpreter error: %s", message);
01148   handle_error(stopped);
01149 }
01150 
01151 
01152 extern "C" void suspend_on_error(InterpreterErrorConstants error_code) {
01153   // Called from the the interpreter
01154 
01155   // Real errors
01156   switch (error_code) {
01157     case primitive_lookup_failed: handle_error(primitive_lookup_error);
01158     case boolean_expected       : handle_error(boolean_error);
01159     case nonlocal_return_error  : handle_error(NLR_error);
01160     case float_expected         : handle_error(float_error);
01161   }
01162 
01163   // Interpreter errors
01164   switch (error_code) {
01165     case halted                 : handle_interpreter_error("executed halt bytecode");
01166     case illegal_code           : handle_interpreter_error("illegal code");
01167     case not_implemented        : handle_interpreter_error("not implemented");
01168     case stack_missaligned      : handle_interpreter_error("stack misaligned");
01169     case ebx_wrong              : handle_interpreter_error("ebx wrong");
01170     case obj_wrong              : handle_interpreter_error("obj wrong");
01171     case nlr_offset_wrong       : handle_interpreter_error("NLR offset wrong");
01172     case last_Delta_fp_wrong    : handle_interpreter_error("last Delta frame wrong");
01173     case primitive_result_wrong : handle_interpreter_error("ilast C entry frame wrong");
01174   }
01175   ShouldNotReachHere();
01176 }
01177 
01178 extern "C" void suspend_on_NLR_error() {
01179   // Called from compiled code
01180   DeltaProcess::active()->suspend(NLR_error);
01181 }
01182 
01183 
01184 void trace_stack_at_exception(int* sp, int* fp, char* pc) {
01185   ResourceMark rm;
01186 
01187   std->print_cr("Trace at exception");
01188 
01189   vframe* vf;
01190   if (last_Delta_fp) {
01191     frame c(last_Delta_sp, last_Delta_fp);
01192     vf = vframe::new_vframe(&c);
01193   } else {
01194     frame c((oop*) sp, fp, pc);
01195     vf = vframe::new_vframe(&c);
01196   }
01197   DeltaProcess::trace_stack_from(vf);
01198 }
01199 
01200 void suspend_process_at_stack_overflow(int *sp, int* fp, char* pc) {
01201   DeltaProcess* proc = DeltaProcess::active();
01202 
01203   proc->set_last_Delta_pc(pc);
01204   last_Delta_fp = fp;
01205   last_Delta_sp = (oop*) sp;
01206 
01207   if (proc->is_scheduler()) {
01208     std->print_cr("Stack overflow happend in scheduler");
01209   } else {
01210     proc->suspend(stack_overflow);
01211     proc->set_terminating();
01212   }
01213 }

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