00001
00002
00003
00004
00005
00006
00007 #include "RTH.h"
00008 #include <stdio.h>
00009 #include <stdlib.h>
00010
00011 enum {
00012 PC_START=0
00013 };
00014
00019 struct RTH_StackFrame {
00020 public:
00021 RTH_Routine fn;
00022 int pc;
00023 int localsSize;
00024 RTH_Locals *locals;
00025
00026 RTH_StackFrame(void)
00027 :fn(0), pc(-123), localsSize(0), locals(0) {}
00028 RTH_StackFrame(RTH_Routine f,int p,int ls)
00029 :fn(f), pc(p), localsSize(ls), locals(0) {}
00030 void invoke(RTH_Runtime *runtime);
00031
00032 void pup(PUP::er &p);
00033 };
00034
00035
00036 RTH_Locals *allocLocals(int localsSize) {
00037 char *ret=new char[localsSize];
00038
00039
00040 return (RTH_Locals *)ret;
00041 }
00042
00043
00044 void freeLocals(RTH_Locals *locals) {
00045
00046 locals->~RTH_Locals();
00047 delete[] (char *)locals;
00048 }
00049
00050 void RTH_StackFrame::pup(PUP::er &p)
00051 {
00052 p((char *)&fn,sizeof(fn));
00053 p|pc;
00054 p|localsSize;
00055 if (p.isUnpacking()) {
00056 locals=allocLocals(localsSize);
00057 }
00058 p((char *)locals,localsSize);
00059 locals->pup(p);
00060 }
00061
00065 class RTH_Runtime {
00066
00067
00068 int stackptr;
00069 enum {maxStack=16};
00070 RTH_StackFrame stack[maxStack];
00071
00072 public:
00073
00074 inline RTH_StackFrame &tos(void) {return stack[stackptr];}
00075
00076 void push(const RTH_StackFrame &f) {
00077
00078 stack[++stackptr]=f;
00079 tos().locals=allocLocals(tos().localsSize);
00080 }
00081
00082 bool pop(void) {
00083 freeLocals(tos().locals);
00084 if (stackptr==0) {
00085 terminated=true;
00086 return false;
00087 } else {
00088 --stackptr;
00089 return true;
00090 }
00091 }
00092
00093 void *obj;
00094 int terminated;
00095
00096 RTH_Runtime(void *obj_,const RTH_StackFrame &start);
00097 ~RTH_Runtime();
00098
00099 void pup(PUP::er &p) {
00100 p|stackptr;
00101 for (int s=0;s<=stackptr;s++) {
00102 stack[s].pup(p);
00103 }
00104 p|terminated;
00105 }
00106 };
00107
00108 RTH_Runtime::RTH_Runtime(void *obj_, const RTH_StackFrame &start) {
00109 obj=obj_;
00110 terminated=false;
00111 stackptr=-1;
00112 push(start);
00113 }
00114 RTH_Runtime::~RTH_Runtime() {
00115
00116 while (!terminated) pop();
00117 }
00118 inline void RTH_StackFrame::invoke(RTH_Runtime *runtime) {
00119 (fn)(runtime,runtime->obj,locals,pc);
00120 }
00121
00122 RTH_Runtime *RTH_Runtime_create(RTH_Routine fn,int localsSize,void *obj) {
00123 return new RTH_Runtime(obj,RTH_StackFrame(fn,PC_START,localsSize));
00124 }
00125
00126 RTH_Runtime *RTH_Runtime_pup(RTH_Runtime *runtime,PUP::er &p,void *obj) {
00127 if (p.isUnpacking()) {
00128 runtime=new RTH_Runtime(obj,RTH_StackFrame());
00129 }
00130 runtime->pup(p);
00131 return runtime;
00132 }
00133
00139 void RTH_Runtime_suspend(RTH_Runtime *runtime,int nextPC) {
00140 runtime->tos().pc=nextPC;
00141 }
00142
00146 void RTH_Runtime_resume(RTH_Runtime *runtime) {
00147 if (!runtime->terminated)
00148 runtime->tos().invoke(runtime);
00149 }
00150
00154 void RTH_Runtime_done(RTH_Runtime *runtime) {
00155 RTH_StackFrame &topFrame=runtime->tos();
00156 if (runtime->pop())
00157 {
00158 if (topFrame.pc!=PC_START)
00159 runtime->tos().invoke(runtime);
00160
00161 }
00162
00163 }
00164
00166 void RTH_Runtime_destroy(RTH_Runtime *runtime) {
00167 delete runtime;
00168 }
00169
00170
00172 int RTH_Runtime_call(RTH_Runtime *runtime,RTH_Routine fn,int localsSize,int nextPC) {
00173
00174 RTH_StackFrame &oldFrame=runtime->tos();
00175 oldFrame.pc==PC_START;
00176
00177
00178 runtime->push(RTH_StackFrame(fn,PC_START,localsSize));
00179 RTH_StackFrame &newFrame=runtime->tos();
00180
00181
00182 newFrame.invoke(runtime);
00183
00184
00185 if (newFrame.pc==PC_START)
00186 {
00187 return 1;
00188 }
00189 else {
00190 oldFrame.pc=nextPC;
00191 return 0;
00192 }
00193 }
00194
00195
00196 RTH_Locals::~RTH_Locals() {}
00197 void RTH_Locals::pup(PUP::er &p) {}