process.hpp

Go to the documentation of this file.
00001 /* Copyright 1994, 1995 LongView Technologies L.L.C. $Revision: 1.65 $ */
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 // unwindInfo is a wrapper calls allowing a primitive like unwindprotect
00025 // to call delta even though a non local return is in progress.
00026 
00027 class unwindInfo : public StackObj {
00028  private:
00029   // NLR state
00030   int        _nlr_home;
00031   int        _nlr_home_id;
00032   contextOop _nlr_home_context; 
00033  public:
00034   oop        _nlr_result;
00035  private:
00036 
00037   bool _is_compiled;
00038 
00039   // Link to next unwindinfo
00040   unwindInfo* _next;
00041 
00042   // Return address patch state
00043   char*  saved_C_frame_return_addr;
00044   char** saved_C_frame_return_addr_location;
00045   char*  saved_patch_return_address;
00046  public:
00047   unwindInfo();
00048   ~unwindInfo();
00049 
00050   unwindInfo* next() const        { return _next; }   
00051   void set_next(unwindInfo* next) { _next = next; }
00052 
00053   int        nlr_home()         const { return _nlr_home;         }
00054   int        nlr_home_id()      const { return _nlr_home_id;      }
00055   contextOop nlr_home_context() const { return _nlr_home_context; }
00056   void update_nlr_targets(compiledVFrame* f, contextOop con);
00057 };
00058 
00059 // Class hierarchy
00060 // - Process
00061 //   - VMProcess
00062 //   - DeltaProcess
00063 
00064 class Process: public PrintableCHeapObj {
00065  public:
00066   // testers
00067   virtual bool is_vmProcess()    const { return false; }
00068   virtual bool is_deltaProcess() const { return false; }
00069 
00070   // operations
00071   void abort();
00072 
00073   int thread_id() const { return _thread_id; }
00074 
00075   static bool external_suspend_current();
00076   static void external_resume_current();
00077 
00078   // sets the current process
00079   static void set_current(Process* p) { _current_process = p; }
00080   // returns the running process DeltaProcess or VMProcess
00081   static Process* current()        { return _current_process; } 
00082 
00083  protected:
00084   // transfer to control
00085   void basic_transfer(Process* target);
00086 
00087   // OS data associated with the process
00088   Thread* _thread;    // Native thread
00089   int     _thread_id; // Native thread id (set by OS when created)
00090   Event*  _event;     // Thread lock
00091 
00092   static Process* _current_process;       //  active Delta process or vm process
00093 };
00094 
00095 
00096 // A single VMProcess (the default thread) is used for heavy 
00097 // vm operations like scavenge, garbage_collect etc.
00098 class VMProcess: public Process {
00099  public:
00100   // constructor
00101   VMProcess();
00102 
00103   // tester
00104   bool is_vmProcess() const { return true; }
00105   
00106   // activates the virtual machine
00107   void activate_system();
00108 
00109   // the ever running loop for the VMProcess
00110   void loop();
00111 
00112   // transfer 
00113   void transfer_to(DeltaProcess* target_process);
00114 
00115   // misc.
00116   void print();
00117 
00118   // Terminate  
00119   static void terminate(DeltaProcess* proc);
00120 
00121   // execution of vm operation
00122   static void execute(VM_Operation* op);
00123 
00124   // returns the current vm operation if any.
00125   static VM_Operation* vm_operation() { return _vm_operation; }
00126 
00127   // returns the single instance of VMProcess.
00128   static VMProcess* vm_process() { return _vm_process; }
00129 
00130  private:
00131   static VM_Operation* _vm_operation;
00132   static VMProcess*    _vm_process;
00133 };
00134 
00135 
00136 enum ProcessState {
00137   initialized,                  // State right after creation.
00138   running,                      // The process is running.
00139   yielded,                      // Gave up control by calling yield.
00140   stopped,                      // Gave up control by calling stop.
00141   preempted,                    // Was preempted by system.
00142   uncommon,                     // currently handling an uncommon branch
00143   in_async_dll,                 // currently executing an asynchronous dll call
00144   yielded_after_async_dll,      // completed executution of asynchronous dll call
00145   completed,                    // Ran to completion.
00146   boolean_error,                // A boolean was expected at hardcoded control structure.
00147   lookup_error,                 // The receiver does not understand doesNotUnderstand:.
00148   primitive_lookup_error,       // Binding a primitive failed.
00149   DLL_lookup_error,             // Binding a DLL function failed.
00150   float_error,                  // A float was expected at hardcoded float operation.
00151   NLR_error,                    // Context for NLR did not exist.
00152   stack_overflow,               // Stack exhausted.
00153   aborted                       // Process has been aborted
00154 };
00155 
00156 
00157 class DeltaProcess: public Process {
00158  private:
00159   oop           _receiver;           // receiver of the initial message.
00160   symbolOop     _selector;           // selector of the initial message.
00161   DeltaProcess* _next;               // the next process in the list (see Processes).
00162   processOop    _processObj;         // the Delta level process object.
00163   ProcessState  _state;              // process state.
00164 
00165   int*          _last_Delta_fp;
00166   oop*          _last_Delta_sp;
00167   char*         _last_Delta_pc;      // For now only used for stack overflow
00168 
00169   bool          _is_terminating;
00170 
00171   int           _time_stamp;
00172 
00173   friend class VMProcess;
00174  public:
00175   // constructor
00176   DeltaProcess(oop receiver, symbolOop selector);
00177   ~DeltaProcess();
00178 
00179   // testers
00180   bool is_deltaProcess() const { return true;  }
00181   bool isUncommon()      const { return _state == uncommon; }
00182 
00183   // Accessors
00184   oop       receiver() const { return _receiver; }
00185   symbolOop selector() const { return _selector; }
00186 
00187   // process chain operations
00188   DeltaProcess* next() const     { return _next; }
00189   void set_next(DeltaProcess* p) { _next = p; }
00190 
00191   // process oop
00192   processOop processObj() const { return _processObj; }
00193   void set_processObj(processOop p) { _processObj = p; }
00194 
00195   bool is_terminating()  { return _is_terminating; }
00196   void set_terminating() { _is_terminating = true; }
00197 
00198   int time_stamp() const { return _time_stamp; }
00199 
00200   void inc_time_stamp()  { _time_stamp++; }
00201 
00202   // last_Delta_fp
00203   int* last_Delta_fp() const;
00204   void set_last_Delta_fp(int* fp);
00205 
00206   // last_Delta_sp
00207   oop* last_Delta_sp() const;
00208   void set_last_Delta_sp(oop* sp);
00209 
00210   // last_Delta_pc
00211   char* last_Delta_pc() const;
00212   void set_last_Delta_pc(char* pc);
00213 
00214   ProcessState state() const { return _state; }
00215 
00216   symbolOop status_symbol() const { return symbol_from_state(state()); }
00217 
00218   static symbolOop symbol_from_state(ProcessState state);
00219 
00220  // List of active unwind protect activations for this process.
00221  // We need this list for deoptimization. If a compiled frame
00222  // is replaced with a deoptimized frame and the unwind protect
00223  // has nlr_target in the compiled frame, we have to convert
00224  // the nlr information to match the deoptimized frame.
00225  public:
00226   void push_unwind(unwindInfo *info) {
00227     info->set_next(_unwind_head);
00228     _unwind_head = info;
00229   }
00230 
00231   void pop_unwind() {
00232     _unwind_head = _unwind_head->next();
00233   }
00234 
00235   void unwinds_do(void f(unwindInfo* info)) {
00236     for (unwindInfo* p = _unwind_head; p; p = p->next())
00237       f(p);
00238   };
00239 
00240   void update_nlr_targets(compiledVFrame* f, contextOop con);
00241 
00242  private:
00243   unwindInfo* _unwind_head; // points to the most recent unwind protect activation.
00244 
00245  private:
00246   void set_state(ProcessState s) { _state = s; }
00247 
00248  public:
00249   // State operations
00250   
00251   // returns whether this process has a stack.
00252   bool has_stack() const;
00253   // returns whether this process is ready for execution.
00254   bool is_ready() const { return state() == initialized || state() == yielded; }
00255 
00256   // Memory operations
00257   void follow_roots();
00258 
00259   // Iterator
00260   void frame_iterate(FrameClosure* blk);
00261   void oop_iterate(OopClosure* blk);
00262 
00263   // Deoptimization  
00264   void deoptimized_wrt_marked_nmethods();
00265   void deoptimize_stretch(frame* first_frame, frame* last_frame);
00266   static void deoptimize_redo_last_send();
00267 
00268   // Uncommon branches
00269   void enter_uncommon();
00270   void exit_uncommon();
00271 
00272   // Misc. operations
00273   void print();
00274   void verify();
00275 
00276   // Stack operations
00277   frame        last_frame();
00278   deltaVFrame* last_delta_vframe();
00279 
00280   // Print the stack trace
00281   void trace_stack();
00282   void trace_top(int start_frame, int number_of_frames);
00283   void trace_stack_for_deoptimization(frame* f = NULL);
00284 
00285   // Print the stack starting at top_frame 
00286   static void trace_stack_from(vframe* top_frame);
00287 
00288   // Timing 
00289   double user_time();
00290   double system_time();
00291 
00292   int depth();
00293   int vdepth(frame* f = NULL);
00294 
00295 #ifdef unused
00296   // Debugging state
00297   bool stepping;        // are we in single-step mode?
00298   bool stopping;        // just returned from "finish" operation; stop ASAP
00299 #endif
00300 
00301   // Profiling operation (see fprofile.cpp)
00302   frame profile_top_frame();
00303 
00304  private:
00305   void transfer(ProcessState reason, DeltaProcess* destination);
00306 
00307  public:
00308 
00309   // returns whether this process is the active delta process.
00310   bool is_active()       const { return this == active(); }
00311 
00312   // returns whether this process is the scheduler.
00313   bool is_scheduler()    const { return this == scheduler(); }
00314 
00315   // returns whether this process currently is executing a vm_operation.
00316   bool in_vm_operation() const { return is_active() && VMProcess::vm_operation() != NULL; }
00317 
00318   // transfer control to the scheduler.
00319   void suspend(ProcessState reason);
00320   void suspend_at_creation();
00321 
00322   // asynchronous dll support
00323   void transfer_and_continue();
00324   void wait_for_control();
00325 
00326   // transfers control from the scheduler.
00327   ProcessState transfer_to(DeltaProcess* target);
00328 
00329   // transfers control to vm process.
00330   void transfer_to_vm();
00331 
00332  // Static operations
00333  private:
00334   static DeltaProcess* _active_delta_process; 
00335   static DeltaProcess* _scheduler_process;
00336   static bool          _is_idle;
00337 
00338   // sets the active process
00339   static void set_active(DeltaProcess* p) {
00340     _active_delta_process = p;
00341     if (_active_delta_process->state() != uncommon) {
00342       _active_delta_process->set_state(running);
00343     }
00344   }
00345 
00346   // sets the scheduler process
00347   static void set_scheduler(DeltaProcess* p) { _scheduler_process = p; }
00348 
00349   // The launch function for a new thread
00350   static int launch_delta(DeltaProcess* process);
00351 
00352  public:
00353     
00354   // returns the active delta process
00355   static DeltaProcess* active()    { return _active_delta_process; }
00356 
00357   // tells whether the system is idle (waiting in wait_for_async_dll).
00358   static bool is_idle() { return _is_idle; }
00359 
00360   // returns the scheduler process
00361   static DeltaProcess* scheduler() { return _scheduler_process; }
00362 
00363   static void set_terminating_process(ProcessState state) {
00364     _state_of_terminated_process = state;
00365     _process_has_terminated      = true;
00366   }
00367 
00368   static bool process_has_terminated() {
00369     bool result = _process_has_terminated;
00370     _process_has_terminated = false;
00371     return result;
00372   }
00373   static ProcessState state_of_terminated_process() {
00374     return _state_of_terminated_process;
00375   }
00376 
00377  private: 
00378   static bool         _process_has_terminated;
00379   static ProcessState _state_of_terminated_process;
00380 
00381  public:
00382   // Called whenever a async dll call completes
00383   static void async_dll_call_completed();
00384   static void initialize_async_dll_event();
00385   // Waits for a completed async call or timeout.
00386   // Returns whether the timer expired. 
00387   static bool wait_for_async_dll(int timeout_in_ms);
00388  private:
00389   // Event for waking up the process scheduler when a
00390   // async dll completes
00391   static Event* _async_dll_completion_event;
00392 };
00393 
00394 
00395 class Processes: AllStatic {
00396  private:
00397   static DeltaProcess* processList;
00398  public:
00399   // Process management
00400   static void add(DeltaProcess* p);
00401   static void remove(DeltaProcess* p);
00402   static bool includes(DeltaProcess* p);
00403   static DeltaProcess* last();
00404 
00405   static DeltaProcess* find_from_thread_id(int id);
00406 
00407   // Start the vm process
00408   static void start(VMProcess* p);
00409 
00410   // State
00411   static bool has_completed_async_call();
00412 
00413   // Killing
00414   static void kill_all();
00415    
00416   // Iterating
00417   static void frame_iterate(FrameClosure* blk);
00418   static void oop_iterate(OopClosure* blk);
00419   static void process_iterate(ProcessClosure* blk);
00420   
00421   // Scavenge
00422   static void scavenge_contents();
00423 
00424   // Garbage collection
00425   static void follow_roots();
00426   static void convert_hcode_pointers();
00427   static void restore_hcode_pointers();
00428 
00429   // Verifycation
00430   static void verify();
00431   static void print();
00432 
00433   // Deoptimization
00434  public:
00435   // deoptimizes frames dependent on a nmethod
00436   static void deoptimize_wrt(nmethod* nm); 
00437   // deoptimizes frames dependent on at least one nmethod in the list                 
00438   static void deoptimize_wrt(GrowableArray<nmethod*>* list);
00439   // deoptimizes all frames
00440   static void deoptimize_all();
00441   // deoptimizes all frames tied to marked nmethods
00442   static void deoptimized_wrt_marked_nmethods();
00443 
00444   // deoptimization support for NLR
00445   static void update_nlr_targets(compiledVFrame* f, contextOop con);
00446 };
00447 
00448 
00449 // "semaphore" to protect some vm critical sections (process transfer etc.)
00450 extern "C" bool processSemaphore; 
00451 
00452 extern "C" int* last_Delta_fp;
00453 extern "C" oop* last_Delta_sp;
00454 
00455 extern int CurrentHash;
00456 
00457 extern "C" void set_stack_overflow_for(DeltaProcess* currentProcess);
00458 
00459 // error handling routines called from compiled code
00460 
00461 extern "C" void suspend_on_NLR_error();
00462 
00463 
00464 enum InterpreterErrorConstants {
00465   start_of_runtime_system_errors =      512,
00466   primitive_lookup_failed        =  1 + start_of_runtime_system_errors,
00467   boolean_expected               =  2 + start_of_runtime_system_errors,
00468   nonlocal_return_error          =  3 + start_of_runtime_system_errors,
00469   halted                         =  4 + start_of_runtime_system_errors,
00470   illegal_code                   =  5 + start_of_runtime_system_errors,
00471   not_implemented                =  6 + start_of_runtime_system_errors,
00472   stack_missaligned              =  7 + start_of_runtime_system_errors,
00473   ebx_wrong                      =  8 + start_of_runtime_system_errors,
00474   obj_wrong                      =  9 + start_of_runtime_system_errors,
00475   nlr_offset_wrong               = 10 + start_of_runtime_system_errors,
00476   last_Delta_fp_wrong            = 11 + start_of_runtime_system_errors,
00477   primitive_result_wrong         = 12 + start_of_runtime_system_errors,
00478   float_expected                 = 13 + start_of_runtime_system_errors,
00479 };
00480 

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