add native copy method
[IRC.git] / Robust / src / Runtime / runtime.c
1 #include "runtime.h"
2 #include "structdefs.h"
3 #include <signal.h>
4 #include "mem.h"
5 #include <fcntl.h>
6 #include <errno.h>
7 #include <stdio.h>
8 #include "option.h"
9 #include "methodheaders.h"
10 #ifdef DSTM
11 #include "dstm.h"
12 #include "prelookup.h"
13 #include "prefetch.h"
14 #endif
15 #ifdef STM
16 #include "tm.h"
17 #include <pthread.h>
18 #endif
19
20 #if defined(THREADS)||defined(STM)
21 /* Global barrier for STM */
22 pthread_barrier_t barrier;
23 pthread_barrierattr_t attr;
24 #endif
25
26 #include <string.h>
27
28 extern int classsize[];
29 extern int typearray[];
30 extern int typearray2[];
31 jmp_buf error_handler;
32 int instructioncount;
33
34 char *options;
35 int injectfailures=0;
36 float failurechance=0;
37 int errors=0;
38 int debugtask=0;
39 int injectinstructionfailures;
40 int failurecount;
41 float instfailurechance=0;
42 int numfailures;
43 int instaccum=0;
44 #ifdef DMALLOC
45 #include "dmalloc.h"
46 #endif
47
48 int instanceof(struct ___Object___ *ptr, int type) {
49   int i=ptr->type;
50   do {
51     if (i==type)
52       return 1;
53     i=typearray[i];
54   } while(i!=-1);
55   i=ptr->type;
56   if (i>NUMCLASSES) {
57     do {
58       if (i==type)
59         return 1;
60       i=typearray2[i-NUMCLASSES];
61     } while(i!=-1);
62   }
63   return 0;
64 }
65
66 void exithandler(int sig, siginfo_t *info, void * uap) {
67   exit(0);
68 }
69
70 void initializeexithandler() {
71   struct sigaction sig;
72   sig.sa_sigaction=&exithandler;
73   sig.sa_flags=SA_SIGINFO;
74   sigemptyset(&sig.sa_mask);
75   sigaction(SIGUSR2, &sig, 0);
76 }
77
78
79 /* This function inject failures */
80
81 void injectinstructionfailure() {
82 #ifdef TASK
83   if (injectinstructionfailures) {
84     if (numfailures==0)
85       return;
86     instructioncount=failurecount;
87     instaccum+=failurecount;
88     if ((((double)random())/RAND_MAX)<instfailurechance) {
89       if (numfailures>0)
90         numfailures--;
91       printf("FAILURE!!! %d\n",numfailures);
92       longjmp(error_handler,11);
93     }
94   }
95 #else
96 #ifdef THREADS
97   if (injectinstructionfailures) {
98     if (numfailures==0)
99       return;
100     instaccum+=failurecount;
101     if ((((double)random())/RAND_MAX)<instfailurechance) {
102       if (numfailures>0)
103         numfailures--;
104       printf("FAILURE!!! %d\n",numfailures);
105       threadexit();
106     }
107   }
108 #endif
109 #endif
110 }
111
112 #ifdef D___Double______nativeparsedouble____L___String___
113 double CALL01(___Double______nativeparsedouble____L___String___,struct ___String___ * ___str___) {
114   int length=VAR(___str___)->___count___;
115   int maxlength=(length>60)?60:length;
116   char str[maxlength+1];
117   struct ArrayObject * chararray=VAR(___str___)->___value___;
118   int i;
119   int offset=VAR(___str___)->___offset___;
120   for(i=0; i<maxlength; i++) {
121     str[i]=((short *)(((char *)&chararray->___length___)+sizeof(int)))[i+offset];
122   }
123   str[i]=0;
124   double d=atof(str);
125   return d;
126 }
127 #endif
128
129 #ifdef D___String______convertdoubletochar____D__AR_C
130 int CALL12(___String______convertdoubletochar____D__AR_C, double ___val___, double ___val___, struct ArrayObject ___chararray___) {
131   int length=VAR(___chararray___)->___length___;
132   char str[length];
133   int i;
134   int num=snprintf(str, length, "%f",___val___);
135   if (num>=length)
136     num=length-1;
137   for(i=0; i<length; i++) {
138     ((short *)(((char *)&VAR(___chararray___)->___length___)+sizeof(int)))[i]=(short)str[i];
139   }
140   return num;
141 }
142 #endif
143 #ifdef D___System______deepArrayCopy____L___Object____L___Object___
144 void deepArrayCopy(struct ___Object___ * dst, struct ___Object___ * src) {
145   int dsttype=((int *)dst)[0];
146   int srctype=((int *)src)[0];
147   if (dsttype<NUMCLASSES||srctype<NUMCLASSES||srctype!=dsttype)
148     return;
149   struct ArrayObject *aodst=(struct ArrayObject *)dst;
150   struct ArrayObject *aosrc=(struct ArrayObject *)src;
151   int dstlength=aodst->___length___;
152   int srclength=aosrc->___length___;
153   if (dstlength!=srclength)
154     return;
155   unsigned INTPTR *pointer=pointerarray[srctype];
156   if (pointer==0) {
157     int elementsize=classsize[srctype];
158     int size=srclength*elementsize;
159     //primitives
160     memcpy(((char *)&aodst->___length___)+sizeof(int) , ((char *)&aosrc->___length___)+sizeof(int), size);
161   } else {
162     //objects
163     int i;
164     for(i=0;i<srclength;i++) {
165       struct ___Object___ * ptr=((struct ___Object___**)(((char*) &aosrc->___length___)+sizeof(int)))[i];
166       int ptrtype=((int *)ptr)[0];
167       if (ptrtype>=NUMCLASSES) {
168         struct ___Object___ * dstptr=((struct ___Object___**)(((char*) &aodst->___length___)+sizeof(int)))[i];
169         deepArrayCopy(dstptr,ptr);
170       } else {
171         //hit an object
172         ((struct ___Object___ **)(((char*) &aodst->___length___)+sizeof(int)))[i]=ptr;
173       }
174     }
175   }
176 }
177
178 void CALL02(___System______deepArrayCopy____L___Object____L___Object___, struct ___Object___ * ___dst___, struct ___Object___ * ___src___) {
179   deepArrayCopy(VAR(___dst___), VAR(___src___));
180 }
181 #endif
182
183 void CALL11(___System______exit____I,int ___status___, int ___status___) {
184 #ifdef TRANSSTATS
185   printf("numTransCommit = %d\n", numTransCommit);
186   printf("numTransAbort = %d\n", numTransAbort);
187   printf("nSoftAbort = %d\n", nSoftAbort);
188 #ifdef STM
189   printf("nSoftAbortCommit = %d\n", nSoftAbortCommit);
190   printf("nSoftAbortAbort = %d\n", nSoftAbortAbort);
191 #ifdef STMSTATS
192   int i;
193   for(i=0; i<TOTALNUMCLASSANDARRAY; i++) {
194     printf("typesCausingAbort[%d]= %d\n", i, typesCausingAbort[i]);
195   }
196 #endif
197 #endif
198 #endif
199   exit(___status___);
200 }
201
202 #ifdef D___Vector______removeElement_____AR_L___Object____I_I
203 void CALL23(___Vector______removeElement_____AR_L___Object____I_I, int ___index___, int ___size___, struct ArrayObject * ___array___, int ___index___, int ___size___) {
204   char* offset=((char *)(&VAR(___array___)->___length___))+sizeof(unsigned int)+sizeof(void *)*___index___;
205   memmove(offset, offset+sizeof(void *),(___size___-___index___-1)*sizeof(void *));
206 }
207 #endif
208
209 void CALL11(___System______printI____I,int ___status___, int ___status___) {
210   printf("%d\n",___status___);
211 }
212
213 long long CALL00(___System______currentTimeMillis____) {
214   struct timeval tv; long long retval;
215   gettimeofday(&tv, NULL);
216   retval = tv.tv_sec; /* seconds */
217   retval*=1000; /* milliseconds */
218   retval+= (tv.tv_usec/1000); /* adjust milliseconds & add them in */
219   return retval;
220 }
221
222 void CALL01(___System______printString____L___String___,struct ___String___ * ___s___) {
223   struct ArrayObject * chararray=VAR(___s___)->___value___;
224   int i;
225   int offset=VAR(___s___)->___offset___;
226   for(i=0; i<VAR(___s___)->___count___; i++) {
227     short sc=((short *)(((char *)&chararray->___length___)+sizeof(int)))[i+offset];
228     putchar(sc);
229   }
230 }
231
232 #ifdef DSTM
233 void CALL00(___System______clearPrefetchCache____) {
234   prehashClear();
235 }
236
237 #ifdef RANGEPREFETCH
238 void CALL02(___System______rangePrefetch____L___Object_____AR_S, struct ___Object___ * ___o___, struct ArrayObject * ___offsets___) {
239   /* Manual Prefetches to be inserted */
240   //printf("DEBUG-> %s() ___Object___ * ___o___ = %x\n", __func__, VAR(___o___));
241   //printf("DEBUG-> %s() ArrayObject * = %x\n", __func__, VAR(___offsets___));
242   int numoffset=VAR(___offsets___)->___length___;
243   int i;
244   short offArry[numoffset+2];
245   offArry[0] = 0;
246   offArry[1] = 0;
247   for(i = 2; i<(numoffset+2); i++) {
248     offArry[i] = *((short *)(((char *)&VAR(___offsets___)->___length___) + sizeof(int) + (i-2) * sizeof(short)));
249     //printf("DEBUG-> offArry[%d] = %d\n", i, offArry[i]);
250   }
251   unsigned int oid;
252   if(((unsigned int)(VAR(___o___)) & 1) != 0) { //odd
253     oid =  (unsigned int) VAR(___o___); //outside transaction therefore just an oid
254   } else { //even
255     oid = (unsigned int) COMPOID(VAR(___o___)); //inside transaction therefore a pointer to oid
256   }
257   rangePrefetch(oid, (short)(numoffset+2), offArry);
258 }
259 #else
260 void CALL02(___System______rangePrefetch____L___Object_____AR_S, struct ___Object___ * ___o___, struct ArrayObject * ___offsets___) {
261   return;
262 }
263 #endif
264
265 #endif
266
267 /* STM Barrier constructs */
268 #ifdef D___Barrier______setBarrier____I
269 void CALL11(___Barrier______setBarrier____I, int nthreads, int nthreads) {
270   // Barrier initialization
271   int ret;
272   if((ret = pthread_barrier_init(&barrier, NULL, nthreads)) != 0) {
273     printf("%s() Could not create a barrier: numthreads = 0 in %s\n", __func__, __FILE__);
274     exit(-1);
275   }
276 }
277 #endif
278
279 #ifdef D___Barrier______enterBarrier____
280 void CALL00(___Barrier______enterBarrier____) {
281   // Synchronization point
282   int ret;
283 #ifdef PRECISE_GC
284   stopforgc((struct garbagelist *)___params___);
285 #endif
286   ret = pthread_barrier_wait(&barrier);
287 #ifdef PRECISE_GC
288   restartaftergc();
289 #endif
290   if(ret != 0 && ret != PTHREAD_BARRIER_SERIAL_THREAD) {
291     printf("%s() Could not wait on barrier: error %d in %s\n", __func__, errno, __FILE__);
292     exit(-1);
293   }
294 }
295 #endif
296
297 /* Object allocation function */
298
299 #ifdef DSTM
300 __attribute__((malloc)) void * allocate_newglobal(int type) {
301   struct ___Object___ * v=(struct ___Object___ *) transCreateObj(classsize[type]);
302   v->type=type;
303 #ifdef THREADS
304   v->tid=0;
305   v->lockentry=0;
306   v->lockcount=0;
307 #endif
308   return v;
309 }
310
311 /* Array allocation function */
312
313 __attribute__((malloc)) struct ArrayObject * allocate_newarrayglobal(int type, int length) {
314   struct ArrayObject * v=(struct ArrayObject *)transCreateObj(sizeof(struct ArrayObject)+length*classsize[type]);
315   if (length<0) {
316     printf("ERROR: negative array\n");
317     return NULL;
318   }
319   v->type=type;
320   v->___length___=length;
321 #ifdef THREADS
322   v->tid=0;
323   v->lockentry=0;
324   v->lockcount=0;
325 #endif
326   return v;
327 }
328 #endif
329
330
331 #ifdef STM
332 // STM Versions of allocation functions
333
334 /* Object allocation function */
335 __attribute__((malloc)) void * allocate_newtrans(void * ptr, int type) {
336   struct ___Object___ * v=(struct ___Object___ *) transCreateObj(ptr, classsize[type]);
337   v->type=type;
338   v->___objlocation___=v;
339   return v;
340 }
341
342 /* Array allocation function */
343 __attribute__((malloc)) struct ArrayObject * allocate_newarraytrans(void * ptr, int type, int length) {
344   struct ArrayObject * v=(struct ArrayObject *)transCreateObj(ptr, sizeof(struct ArrayObject)+length*classsize[type]);
345   if (length<0) {
346     printf("ERROR: negative array\n");
347     return NULL;
348   }
349   v->___objlocation___=(struct ___Object___*)v;
350   v->type=type;
351   v->___length___=length;
352   return v;
353 }
354 __attribute__((malloc)) void * allocate_new(void * ptr, int type) {
355   objheader_t *tmp=mygcmalloc((struct garbagelist *) ptr, classsize[type]+sizeof(objheader_t));
356   struct ___Object___ * v=(struct ___Object___ *) &tmp[1];
357   initdsmlocks(&tmp->lock);
358   tmp->version = 1;
359   v->___objlocation___=v;
360   v->type = type;
361   return v;
362 }
363
364 /* Array allocation function */
365
366 __attribute__((malloc)) struct ArrayObject * allocate_newarray(void * ptr, int type, int length) {
367   objheader_t *tmp=mygcmalloc((struct garbagelist *) ptr, sizeof(struct ArrayObject)+length*classsize[type]+sizeof(objheader_t));
368   struct ArrayObject * v=(struct ArrayObject *) &tmp[1];
369   initdsmlocks(&tmp->lock);
370   tmp->version=1;
371   v->type=type;
372   if (length<0) {
373     printf("ERROR: negative array %d\n", length);
374     return NULL;
375   }
376   v->___objlocation___=(struct ___Object___ *)v;
377   v->___length___=length;
378   return v;
379 }
380 #endif
381
382 #ifndef STM
383 #if defined(PRECISE_GC)
384 __attribute__((malloc)) void * allocate_new(void * ptr, int type) {
385   struct ___Object___ * v=(struct ___Object___ *) mygcmalloc((struct garbagelist *) ptr, classsize[type]);
386   v->type=type;
387 #ifdef THREADS
388   v->tid=0;
389   v->lockentry=0;
390   v->lockcount=0;
391 #endif
392 #ifdef OPTIONAL
393   v->fses=0;
394 #endif
395   return v;
396 }
397
398 /* Array allocation function */
399
400 __attribute__((malloc)) struct ArrayObject * allocate_newarray(void * ptr, int type, int length) {
401   struct ArrayObject * v=mygcmalloc((struct garbagelist *) ptr, sizeof(struct ArrayObject)+length*classsize[type]);
402   v->type=type;
403   if (length<0) {
404     printf("ERROR: negative array\n");
405     return NULL;
406   }
407   v->___length___=length;
408 #ifdef THREADS
409   v->tid=0;
410   v->lockentry=0;
411   v->lockcount=0;
412 #endif
413 #ifdef OPTIONAL
414   v->fses=0;
415 #endif
416   return v;
417 }
418
419 #else
420 __attribute__((malloc)) void * allocate_new(int type) {
421   struct ___Object___ * v=FREEMALLOC(classsize[type]);
422   v->type=type;
423 #ifdef OPTIONAL
424   v->fses=0;
425 #endif
426   return v;
427 }
428
429 /* Array allocation function */
430
431 __attribute__((malloc)) struct ArrayObject * allocate_newarray(int type, int length) {
432   __attribute__((malloc))  struct ArrayObject * v=FREEMALLOC(sizeof(struct ArrayObject)+length*classsize[type]);
433   v->type=type;
434   v->___length___=length;
435 #ifdef OPTIONAL
436   v->fses=0;
437 #endif
438   return v;
439 }
440 #endif
441 #endif
442
443 /* Converts C character arrays into Java strings */
444 #ifdef PRECISE_GC
445 __attribute__((malloc)) struct ___String___ * NewString(void * ptr, const char *str,int length) {
446 #else
447 __attribute__((malloc)) struct ___String___ * NewString(const char *str,int length) {
448 #endif
449   int i;
450 #ifdef PRECISE_GC
451   struct ArrayObject * chararray=allocate_newarray((struct garbagelist *)ptr, CHARARRAYTYPE, length);
452   INTPTR ptrarray[]={1, (INTPTR) ptr, (INTPTR) chararray};
453   struct ___String___ * strobj=allocate_new((struct garbagelist *) &ptrarray, STRINGTYPE);
454   chararray=(struct ArrayObject *) ptrarray[2];
455 #else
456   struct ArrayObject * chararray=allocate_newarray(CHARARRAYTYPE, length);
457   struct ___String___ * strobj=allocate_new(STRINGTYPE);
458 #endif
459   strobj->___value___=chararray;
460   strobj->___count___=length;
461   strobj->___offset___=0;
462
463   for(i=0; i<length; i++) {
464     ((short *)(((char *)&chararray->___length___)+sizeof(int)))[i]=(short)str[i];
465   }
466   return strobj;
467 }
468
469 /* Generated code calls this if we fail a bounds check */
470
471 void failedboundschk() {
472 #ifndef TASK
473   printf("Array out of bounds\n");
474 #ifdef THREADS
475   threadexit();
476 #else
477   exit(-1);
478 #endif
479 #else
480   longjmp(error_handler,2);
481 #endif
482 }
483
484 /* Abort task call */
485 void abort_task() {
486 #ifdef TASK
487   longjmp(error_handler,4);
488 #else
489   printf("Aborting\n");
490   exit(-1);
491 #endif
492 }