/vm/src/any/runtime/process.hh

http://github.com/ticking/self · C++ Header · 367 lines · 262 code · 80 blank · 25 comment · 14 complexity · 73e72f1f8b562ad76bc844cfb65afc0e MD5 · raw file

  1. /* Sun-$Revision: 30.12 $ */
  2. /* Copyright 1992-2006 Sun Microsystems, Inc. and Stanford University.
  3. See the LICENSE file for license information. */
  4. # ifdef INTERFACE_PRAGMAS
  5. # pragma interface
  6. # endif
  7. // A Process is the VM-level process descriptor of a Self process;
  8. // Self-level process objects (see processOop/Map) contain a pointer
  9. // to their respective Process object and vice versa.
  10. extern Process* prevProcess;
  11. extern Process* currentProcess;
  12. extern Process* twainsProcess;
  13. extern Process* vmProcess;
  14. extern bool8 processSemaphore; // "semaphore" to protect some critical sections
  15. extern bool ConversionInProgress; // true during programming conversions
  16. extern bool traceP;
  17. extern bool traceV;
  18. class CSect {
  19. bool b;
  20. bool* sem;
  21. public:
  22. CSect(bool& sema) { b = sema; sem = &sema; sema = true; }
  23. ~CSect() { *sem = b; }
  24. };
  25. class PreservedList {
  26. public:
  27. preservedVmObjBList list;
  28. PreservedList() : list(32, true) { }
  29. void clear() { list.clear(); }
  30. void oops_do(oopsDoFn f, Process* p);
  31. };
  32. enum ProcessState {
  33. initialized, // ready, but has no stack yet and hasn't run Self code
  34. ready, // could continue at any time, or is currently running
  35. stopped, // stopped because of error; cannot continue but
  36. // still has a stack which can be inspected
  37. aborting, // currently unwinding its stack, or already dead
  38. // but not yet destroyed; has no stack
  39. defunct // not a real process
  40. };
  41. typedef void (*process_p)();
  42. class Process: public CHeapObj {
  43. char* suspendedSP; // process state - saved in runtime_(sparc_mac_ppc).s
  44. char* suspendedPC;
  45. bool pcWasSet; // Intel needs to know this
  46. Process* next;
  47. Stack stk;
  48. oop method; // top-level doIt method
  49. PreservedList preservedList;
  50. processOop procObj;
  51. frame* check_vfo_locals; // for checking vframeOop liveness
  52. frame* check_vfo_locals_sender; // check_vfo_locals->sender()
  53. // for debugging only
  54. bool check_vfo_locals_is_uncommon; // is check_vfo_locals's nmethod an uncommon branch?
  55. bool stepping; // are we in single-step mode?
  56. bool stopping; // just returned from "finish" operation; stop ASAP
  57. char* _uncommonPC; // PC of uncommon trap (if currently handling unc.trap)
  58. vframeOop _killUpToVF;// first survivor when cutting back the stack
  59. bool deoptimizing; // currently deoptimizing the last stack frame
  60. public:
  61. bool zombie; // true if it was unreachable at the last GC
  62. bool restartAfterConversion; // for controlling restarting after conversion
  63. protected:
  64. Process* aborter; // process aborting us
  65. public:
  66. ResourceArea resource_area;
  67. int32 nesting; // e.g. 2 means Self called VM called Self
  68. int32 current_hash; // Counter used when assigning hash-values to objects.
  69. ProcessState state;
  70. vframeOop stopActivation; // activation of "finish" operation
  71. Profiler* profiler; // profiler for this process.
  72. friend void startCurrentProcess();
  73. friend void interruptCheck();
  74. friend class Processes;
  75. friend class processOopClass;
  76. friend class vframeMirror;
  77. Process(processOop p, int32 sSize, oop rcvr = NULL,
  78. stringOop sel = NULL, objVectorOop args = NULL);
  79. ~Process();
  80. void init(char* pcVal);
  81. void print();
  82. void print_short();
  83. // execution
  84. bool hasStack() { return stk.base != NULL; }
  85. bool allocate();
  86. void start();
  87. void terminate();
  88. void abort();
  89. void transfer(); // coroutine transfer to this process
  90. // termination functions
  91. static void volatile abort_process();
  92. static void volatile terminate_process();
  93. void setupPreemption() { setSPLimit(stackEnd()); } // set up for preemption
  94. void clearPreemption() { setSPLimit(spLimit()); } // reset
  95. bool preemptionPending();
  96. void nonLifoError();
  97. void setSingleStepping(); // set up single step mode
  98. void patchForSingleStepping(frame* f = NULL);
  99. // sets SPLimit & frame patch if necessary
  100. bool isSingleStepping() { return stepping; }
  101. void resetSingleStepping();
  102. void setUncommon(char* pc) { _uncommonPC = pc; }
  103. char* uncommonPC() { return _uncommonPC; }
  104. bool isUncommon() { return _uncommonPC != NULL; }
  105. void resetUncommon() { _uncommonPC = NULL; }
  106. void setStopPoint(vframeOop stop);
  107. bool isStopping() { return stopping; }
  108. frame* stopFrame();
  109. void resetStopping() { stopping = false; }
  110. void killFrames(abstract_vframe* vf);
  111. bool isKilling() { return _killUpToVF != NULL; }
  112. void resetKilling() { _killUpToVF = NULL; }
  113. vframeOop killVF() { return _killUpToVF; }
  114. void setDeoptimizing() { deoptimizing = true; }
  115. bool isDeoptimizing() { return deoptimizing; }
  116. void resetDeoptimizing() { deoptimizing = false; }
  117. void deoptimize(frame* last); // deoptimize last stack frame
  118. bool isKillingOrDeoptimizing() { return isKilling() || isDeoptimizing(); }
  119. bool verifyFramePatches();
  120. void gotoByteCode(abstract_vframe* last, smi bci, objVectorOop exprStack, void* FH);
  121. bool isClean() {
  122. return !stopping
  123. && !stepping
  124. && !isUncommon()
  125. && !check_vfo_locals
  126. && !isKilling()
  127. && !isDeoptimizing(); }
  128. // methods for top-level running of self code
  129. oop runDoItMethod( oop rcv,
  130. oop meth,
  131. oop* args = NULL,
  132. fint arg_count = 0);
  133. oop prepare_to_call_self();
  134. void cleanup_after_calling_self();
  135. void cleanup_after_eval_prim(oop res);
  136. private:
  137. void initialize(oop rcvr, stringOop sel, objVectorOop args);
  138. void kill();
  139. public:
  140. // stack operations
  141. int32 selfNesting() { return nesting; }
  142. bool inSelf(bool including_prologue = false); // "in Self" = has visible Self activations
  143. // (false if !including_prologue && topmost activation is in prologue)
  144. char* stackEnd() { return stk.end(); }
  145. bool contains(void* sp) { return stk.contains(sp); }
  146. char* spLimit() { return stk.spLimit(); }
  147. char* lastSP() { return suspendedSP; }
  148. bool isStackOverflow(char* sp) { return stk.isStackOverflow(sp); }
  149. bool hadStackOverflow() { return stk.markDestroyed(); }
  150. bool hasEmptyStack();
  151. void resetStackOverflow() { stk.mark(); }
  152. frame* last_self_frame(bool includePrologue, RegisterLocator** rl = NULL) {
  153. return stk.last_self_frame(includePrologue, rl); }
  154. void setPC(process_p newPC) { suspendedPC= first_inst_addr((char*)newPC); pcWasSet= true; }
  155. bool isRunnable() { return state <= ready; }
  156. processOop processObj() { return procObj; }
  157. Stack* stack() { return &stk; }
  158. // memory operations
  159. void preserve(preservedVmObj* p);
  160. void un_preserve(preservedVmObj* p);
  161. void scavenge_contents();
  162. void gc_mark_contents();
  163. void gc_unmark_contents();
  164. bool verify();
  165. void switch_pointers();
  166. void read_snapshot(FILE* f);
  167. void write_snapshot(FILE* f);
  168. void chainFrames() { if (nesting > 0) stack()->chainFrames(); }
  169. void unchainFrames() { if (nesting > 0) stack()->unchainFrames(); }
  170. // programming operations
  171. void convert();
  172. void prepare_to_return_to_self_after_conversion(frame* new_last_self_frame,
  173. bool& resetartSend,
  174. bool& wasUncommon,
  175. int32*& uncommonPC);
  176. bool is_done_with_killing_or_deoptimizing(frame* dest_self_fr);
  177. // vframe mirror operations
  178. vframeOop insertVFrameOop(vframeOop vfm);
  179. vframeOop findVFrameOop(abstract_vframe* vfs);
  180. vframeOop findInsertionPoint(abstract_vframe* vf);
  181. protected:
  182. void killVFrameOops(abstract_vframe* currentVF);
  183. void killVFrameOopsInCurrentFrame(abstract_vframe* currentVF);
  184. frame* frame_for_check_vfo_locals(abstract_vframe* currentVF);
  185. void trace_killVFrameOopsInCurrentFrame(vframeOop, abstract_vframe*);
  186. void set_check_vfo_locals( abstract_vframe* currentVF);
  187. void clear_check_vfo_locals();
  188. public:
  189. void convertVFrameOops(frame* fr, frame* vfoLocals,
  190. nmethod* invalidNM,
  191. int32 vdepth, abstract_vframe** old_vf, abstract_vframe** new_vf);
  192. void killVFrameOopsAndSetWatermark(frame* currentFrame);
  193. void printVFrameList(fint howMany);
  194. bool verifyVFrameList();
  195. protected:
  196. void clearWatermark();
  197. void setWatermark(abstract_vframe*);
  198. void traceAndLog_killVFrameOopsAndSetWatermark(frame*, abstract_vframe*);
  199. void traceEpilog_killVFrameOopsAndSetWatermark();
  200. // queuing
  201. public:
  202. void addAfter(Process* p) { next = p->next; p->next = this; }
  203. void remove(Process* p) { p->next = next; next = NULL; }
  204. };
  205. bool isStackOverflow(char* sp);
  206. bool isOnVMStack(void* sp);
  207. extern frame* frameSwitchingToVMStack;
  208. enum PreemptCause {
  209. cNoCause = -1,
  210. cTerminated, cAborted, cStackOverflowed, cNonLIFOBlock,
  211. cLastFatalCause = cNonLIFOBlock,
  212. cYielded,
  213. cSingleStepped, cFinishedActivation,
  214. cSignal,
  215. cLowOnSpace,
  216. cCouldntAllocateStack, // this isn't really a source of preemption; the
  217. // process never got started
  218. cLast // insert new causes before this line
  219. };
  220. inline bool isFatalCause(PreemptCause c) {
  221. return c <= cLastFatalCause && c != cNoCause; }
  222. extern PreemptCause preemptCause;
  223. extern int32 causeString[cLast]; // translates PreemptCause --> VMString index
  224. extern oop yieldArg; // argument passed with _Yield
  225. extern oop yieldRcvr; // receiver of _Yield
  226. class Processes: public CHeapObj {
  227. public:
  228. bool idle;
  229. bool needsInvalidate; // needs to mark invalid stack frames
  230. Processes();
  231. void startVMProcess(); // init and start; won't return!
  232. void discardAll();
  233. void processesDo(processesDoFn f, bool doItForAll = false);
  234. bool isIdle() { return idle; }
  235. void print();
  236. // memory operations
  237. void scavenge_contents();
  238. void gc_mark_contents();
  239. void gc_unmark_contents();
  240. void gc_mark_remaining_processes();
  241. void enumerate_references(enumeration *e);
  242. void enumerate_families(enumeration *e);
  243. bool verify();
  244. void switch_pointers(oop from, oop to);
  245. void read_snapshot(FILE* f);
  246. void write_snapshot(FILE* f);
  247. void chainFrames();
  248. void unchainFrames();
  249. objVectorOop zombies();
  250. // programming
  251. void convert(); // convert all stacks after programming change
  252. void convert_cont();
  253. // son-of operation
  254. Stack* stackFor(void* f) {
  255. // try it the fast way (covers almost all calls)
  256. return currentProcess->contains(f) || isOnVMStack(f)
  257. ? currentProcess->stack()
  258. : slowStackFor(f); // have to do it the slow way
  259. }
  260. private:
  261. void init();
  262. Stack* slowStackFor(void* f);
  263. public:
  264. friend void doTerminateAll_VM();
  265. friend void doAbortAll_VM();
  266. friend void doDiscardAll_VM();
  267. };
  268. extern Processes* processes;
  269. oop zombie_prim();
  270. void preemptor(); // set up things to preempt Self process
  271. void interruptCheck();
  272. inline char* allocateResource(size_t size) {
  273. return currentProcess->resource_area.allocate_bytes(size);
  274. }
  275. // stack-switching functions; execute the continuation function on the VM stack
  276. void switchToVMStack(doFn continuation);
  277. oop switchToVMStack(fntype continuation, void* arg1);
  278. nmethod* switchToVMStack(nmethod *cont(compilingLookup *),
  279. compilingLookup *L);
  280. typedef nmethod* (*constructDoItMethodContinuation)(oop receiver, oop method);
  281. nmethod* switchToVMStack(oop receiver,
  282. oop method,
  283. constructDoItMethodContinuation continuation);
  284. typedef void (*intLookupContinuation)( simpleLookup* L, int32 arg_count );
  285. void switchToVMStack_intSend( simpleLookup* L,
  286. int32 arg_count,
  287. intLookupContinuation continuation);