changes
[IRC.git] / Robust / src / Runtime / STM / stm.c
1 /* ============================================================
2  * singleTMCommit.c
3  * - single thread commit on local machine
4  * =============================================================
5  * Copyright (c) 2009, University of California, Irvine, USA.
6  * All rights reserved.
7  * Author: Alokika Dash
8  *         adash@uci.edu
9  * =============================================================
10  *
11  */
12
13 #include "tm.h"
14 #include "garbage.h"
15
16 #define likely(x) x
17 /* Per thread transaction variables */
18 __thread objstr_t *t_cache;
19 __thread objstr_t *t_reserve;
20 __thread struct objlist * newobjs;
21
22 #ifdef SANDBOX
23 #include "sandbox.h"
24 #endif
25
26 #ifdef DELAYCOMP
27 #include "delaycomp.h"
28 __thread struct pointerlist ptrstack;
29 __thread struct primitivelist primstack;
30 __thread struct branchlist branchstack;
31 struct pointerlist *c_ptrstack;
32 struct primitivelist *c_primstack;
33 struct branchlist *c_branchstack;
34 #endif
35
36 #ifdef TRANSSTATS
37 int numTransCommit = 0;
38 int numTransAbort = 0;
39 int nSoftAbort = 0;
40 int nSoftAbortCommit = 0;
41 int nSoftAbortAbort = 0;
42 #endif
43
44 #ifdef STMSTATS
45 /* Thread variable for locking/unlocking */
46 __thread threadrec_t *trec;
47 __thread struct objlist * lockedobjs;
48 __thread int t_objnumcount=0;
49
50 /* Collect stats for object classes causing abort */
51 objtypestat_t typesCausingAbort[TOTALNUMCLASSANDARRAY];
52
53 /**
54  * Inline fuction to get Transaction size per object type for those
55  * objects that cause 
56  *
57  **/
58
59 INLINE void getTransSize(objheader_t *header , int *isObjTypeTraverse) {
60   (typesCausingAbort[TYPE(header)]).numabort++;
61   if(isObjTypeTraverse[TYPE(header)] != 1) {
62     (typesCausingAbort[TYPE(header)]).numaccess+=c_numelements;
63     (typesCausingAbort[TYPE(header)]).numtrans+=1; //should this count be kept per object
64   }
65   isObjTypeTraverse[TYPE(header)]=1;
66 }
67 #define DEBUGSTMSTAT(args...)
68 #else
69 #define DEBUGSTMSTAT(args...)
70 #endif
71
72 #ifdef STMDEBUG
73 #define DEBUGSTM(x...) printf(x);
74 #else
75 #define DEBUGSTM(x...);
76 #endif
77
78 #ifdef STATDEBUG
79 #define DEBUGSTATS(x...) printf(x);
80 #else
81 #define DEBUGSTATS(x...);
82 #endif
83
84 //#ifdef FASTMEMCPY
85 //void * A_memcpy (void * dest, const void * src, size_t count);
86 //#else
87 //#define A_memcpy memcpy
88 //#endif
89
90 void * A_memcpy (void * dest, const void * src, size_t count) {
91   int off=0;
92   INTPTR *desti=(INTPTR *)dest;
93   INTPTR *srci=(INTPTR *)src;
94
95   //word copy
96   while(count>=sizeof(INTPTR)) {
97     desti[off]=srci[off];
98     off+=1;
99     count-=sizeof(INTPTR);
100   }
101   off*=sizeof(INTPTR);
102   //byte copy
103   while(count>0) {
104     ((char *)dest)[off]=((char *)src)[off];
105     off++;
106     count--;
107   }
108 }
109
110
111 extern void * curr_heapbase;
112 extern void * curr_heapptr;
113 extern void * curr_heaptop;
114
115 #ifdef STMSTATS
116 /*** Global variables *****/
117 objlockstate_t *objlockscope;
118 /**
119  * ABORTCOUNT
120  * params: object header
121  * Increments the abort count for each object
122  **/
123 void ABORTCOUNT(objheader_t * x) {
124   int avgTransSize = typesCausingAbort[TYPE(x)].numaccess / typesCausingAbort[TYPE(x)].numtrans; 
125   float transAbortProbForObj = (PERCENT_ALLOWED_ABORT*FACTOR)/(float) avgTransSize;
126   float ObjAbortProb = x->abortCount/(float) (x->accessCount);
127   DEBUGSTM("ABORTSTATS: oid= %x, type= %2d, transAbortProb= %2.2f, ObjAbortProb= %2.2f, Typenumaccess= %3d, avgtranssize = %2d, ObjabortCount= %2d, ObjaccessCount= %3d\n", OID(x), TYPE(x), transAbortProbForObj, ObjAbortProb, typesCausingAbort[TYPE(x)].numaccess, avgTransSize, x->abortCount, x->accessCount);
128   /* Condition for locking objects */
129   if (((ObjAbortProb*100) >= transAbortProbForObj) && (x->riskyflag != 1)) {     
130     DEBUGSTATS("AFTER LOCK ABORTSTATS: oid= %x, type= %2d, transAbortProb= %2.2f, ObjAbortProb= %2.2f, Typenumaccess= %3d, avgtranssize = %2d, ObjabortCount= %2d, ObjaccessCount= %3d\n", OID(x), TYPE(x), transAbortProbForObj, ObjAbortProb, typesCausingAbort[TYPE(x)].numaccess, avgTransSize, x->abortCount, x->accessCount);
131     //makes riskflag sticky
132     pthread_mutex_lock(&lockedobjstore); 
133     if (objlockscope->offset<MAXOBJLIST) { 
134       x->objlock=&(objlockscope->lock[objlockscope->offset++]);
135     } else { 
136       objlockstate_t *tmp=malloc(sizeof(objlockstate_t)); 
137       tmp->next=objlockscope; 
138       tmp->offset=1; 
139       x->objlock=&(tmp->lock[0]); 
140       objlockscope=tmp;
141     } 
142     pthread_mutex_unlock(&lockedobjstore); 
143     pthread_mutex_init(x->objlock, NULL);
144     //should put a memory barrier here
145     x->riskyflag = 1;                    
146   }
147 }
148 #endif
149
150 /* ==================================================
151  * stmStartup
152  * This function starts up the transaction runtime.
153  * ==================================================
154  */
155 int stmStartup() {
156   return 0;
157 }
158
159 /* =================================================
160  * transStart
161  * This function initializes things required in the
162  * transaction start
163  * =================================================
164  */
165 void transStart() {
166   //Transaction start is currently free...commit and aborting is not
167 #ifdef DELAYCOMP
168   c_ptrstack=&ptrstack;
169   c_primstack=&primstack;
170   c_branchstack=&branchstack;
171 #endif
172 }
173
174 /* =======================================================
175  * transCreateObj
176  * This function creates objects in the transaction record
177  * =======================================================
178  */
179 objheader_t *transCreateObj(void * ptr, unsigned int size) {
180   objheader_t *tmp = mygcmalloc(ptr, (sizeof(objheader_t) + size));
181   objheader_t *retval=&tmp[1];
182   tmp->lock=RW_LOCK_BIAS;
183   tmp->version = 1;
184   //initialize obj lock to the header
185   STATUS(tmp)=NEW;
186   // don't insert into table
187   if (newobjs->offset<MAXOBJLIST) {
188     newobjs->objs[newobjs->offset++]=retval;
189   } else {
190     struct objlist *tmp=malloc(sizeof(struct objlist));
191     tmp->next=newobjs;
192     tmp->objs[0]=retval;
193     tmp->offset=1;
194     newobjs=tmp;
195   }
196   return retval; //want space after object header
197 }
198
199 /* This functions inserts randowm wait delays in the order of msec
200  * Mostly used when transaction commits retry*/
201 void randomdelay(int softaborted) {
202   struct timespec req;
203   struct timeval t;
204
205   gettimeofday(&t,NULL);
206
207   req.tv_sec = 0;
208   req.tv_nsec = (long)((t.tv_usec)%(1<<softaborted))<<1; //1-11 microsec
209   nanosleep(&req, NULL);
210   return;
211 }
212
213 /* =============================================================
214  * transRead
215  * -finds the objects either in main heap
216  * -copies the object into the transaction cache
217  * =============================================================
218  */
219 //__attribute__ ((pure)) 
220 void *transRead(void * oid, void *gl) {
221   objheader_t *tmp, *objheader;
222   objheader_t *objcopy;
223   int size;
224
225   /* Read from the main heap */
226   //No lock for now
227   objheader_t *header = (objheader_t *)(((char *)oid) - sizeof(objheader_t));
228   GETSIZE(size, header);
229   size += sizeof(objheader_t);
230   objcopy = (objheader_t *) objstrAlloc(size);
231 #ifdef STMSTATS
232   header->accessCount++;
233   if(header->riskyflag) {
234     header=needLock(header,gl);
235   }
236 #endif
237   A_memcpy(objcopy, header, size);
238 #ifdef STMSTATS
239   /* keep track of the object's access sequence in a transaction */
240   objheader_t *tmpheader = objcopy;
241   tmpheader->accessCount = ++t_objnumcount;
242 #endif
243
244   /* Insert into cache's lookup table */
245   STATUS(objcopy)=0;
246   if (((unsigned INTPTR)oid)<((unsigned INTPTR ) curr_heapbase)|| ((unsigned INTPTR)oid) >((unsigned INTPTR) curr_heapptr))
247     printf("ERROR! Bad object address!\n");
248   t_chashInsert(oid, &objcopy[1]);
249   return &objcopy[1];
250 }
251
252 void freenewobjs() {
253   struct objlist *ptr=newobjs;
254   while(ptr->next!=NULL) {
255     struct objlist *tmp=ptr->next;
256     free(ptr);
257     ptr=tmp;
258   }
259   ptr->offset=0;
260   newobjs=ptr;
261 }
262
263 #ifdef STMSTATS
264 void freelockedobjs() {
265   struct objlist *ptr=lockedobjs;
266   while(ptr->next!=NULL) {
267     struct objlist *tmp=ptr->next;
268     free(ptr);
269     ptr=tmp;
270   }
271   ptr->offset=0;
272   lockedobjs=ptr;
273 }
274 #endif
275
276 /* ================================================================
277  * transCommit
278  * - This function initiates the transaction commit process
279  * - goes through the transaction cache and decides
280  * - a final response
281  * ================================================================
282  */
283 #ifdef DELAYCOMP
284 int transCommit(void (*commitmethod)(void *, void *, void *), void * primitives, void * locals, void * params) {
285 #else
286 int transCommit() {
287 #endif
288 #ifdef SANDBOX
289   abortenabled=0;
290 #endif
291 #ifdef TRANSSTATS
292   numTransCommit++;
293 #endif
294   int softaborted=0;
295   do {
296     /* Look through all the objects in the transaction hash table */
297     int finalResponse;
298 #ifdef DELAYCOMP
299     if (c_numelements<(c_size>>3))
300       finalResponse= alttraverseCache(commitmethod, primitives, locals, params);
301     else
302       finalResponse= traverseCache(commitmethod, primitives, locals, params);
303 #else
304     if (c_numelements<(c_size>>3))
305       finalResponse= alttraverseCache();
306     else
307       finalResponse= traverseCache();
308 #endif
309     if(finalResponse == TRANS_ABORT) {
310 #ifdef TRANSSTATS
311       numTransAbort++;
312       if (softaborted) {
313         nSoftAbortAbort++;
314       }
315 #endif
316       freenewobjs();
317 #ifdef STMSTATS
318       freelockedobjs();
319 #endif
320       objstrReset();
321       t_chashreset();
322 #ifdef READSET
323       rd_t_chashreset();
324 #endif
325 #ifdef DELAYCOMP
326       dc_t_chashreset();
327       ptrstack.count=0;
328       primstack.count=0;
329       branchstack.count=0;
330 #endif
331 #ifdef SANDBOX
332       abortenabled=1;
333 #endif
334       return TRANS_ABORT;
335     }
336     if(finalResponse == TRANS_COMMIT) {
337 #ifdef TRANSSTATS
338       //numTransCommit++;
339       if (softaborted) {
340         nSoftAbortCommit++;
341       }
342 #endif
343       freenewobjs();
344 #ifdef STMSTATS
345       freelockedobjs();
346 #endif
347       objstrReset();
348       t_chashreset();
349 #ifdef READSET
350       rd_t_chashreset();
351 #endif
352 #ifdef DELAYCOMP
353       dc_t_chashreset();
354       ptrstack.count=0;
355       primstack.count=0;
356       branchstack.count=0;
357 #endif
358       return 0;
359     }
360
361     /* wait a random amount of time before retrying to commit transaction*/
362     if(finalResponse == TRANS_SOFT_ABORT) {
363 #ifdef TRANSSTATS
364       nSoftAbort++;
365 #endif
366       softaborted++;
367 #ifdef SOFTABORT
368       if (softaborted>1) {
369 #else
370       if (1) {
371 #endif
372         //retry if too many soft aborts
373         freenewobjs();
374 #ifdef STMSTATS
375     freelockedobjs();
376 #endif
377         objstrReset();
378         t_chashreset();
379 #ifdef READSET
380         rd_t_chashreset();
381 #endif
382 #ifdef DELAYCOMP
383         dc_t_chashreset();
384         ptrstack.count=0;
385         primstack.count=0;
386         branchstack.count=0;
387 #endif
388         return TRANS_ABORT;
389       }
390       //randomdelay(softaborted);
391     } else {
392       printf("Error: in %s() Unknown outcome", __func__);
393       exit(-1);
394     }
395   } while (1);
396 }
397
398 #ifdef STMSTATS
399   You need to add free statements for oidrdage in a way that they will not appear if this option is not defined.
400 #endif
401
402 #ifdef DELAYCOMP
403 #define freearrays if (c_numelements>=200) { \
404     free(oidrdlocked); \
405     free(oidrdversion); \
406   } \
407   if (t_numelements>=200) { \
408     free(oidwrlocked); \
409   }
410 #else
411 #define freearrays   if (c_numelements>=200) { \
412     free(oidrdlocked); \
413     free(oidrdversion); \
414     free(oidwrlocked); \
415   }
416 #endif
417
418 #ifdef STMSTATS
419     you need to set oidrdage in a way that does not appear if this macro is not defined.
420 #endif
421
422 #ifdef DELAYCOMP
423 #define allocarrays int t_numelements=c_numelements+dc_c_numelements; \
424   if (t_numelements<200) { \
425     oidwrlocked=wrlocked; \
426   } else { \
427     oidwrlocked=malloc(t_numelements*sizeof(void *)); \
428   } \
429   if (c_numelements<200) { \
430     oidrdlocked=rdlocked; \
431     oidrdversion=rdversion; \
432   } else { \
433     int size=c_numelements*sizeof(void*); \
434     oidrdlocked=malloc(size); \
435     oidrdversion=malloc(size); \
436   }
437 #else
438 #define allocarrays if (c_numelements<200) { \
439     oidrdlocked=rdlocked; \
440     oidrdversion=rdversion; \
441     oidwrlocked=wrlocked; \
442   } else { \
443     int size=c_numelements*sizeof(void*); \
444     oidrdlocked=malloc(size); \
445     oidrdversion=malloc(size); \
446     oidwrlocked=malloc(size); \
447   }
448 #endif
449
450
451
452
453 /* ==================================================
454  * traverseCache
455  * - goes through the transaction cache and
456  * - decides if a transaction should commit or abort
457  * ==================================================
458  */
459 #ifdef DELAYCOMP
460 int traverseCache(void (*commitmethod)(void *, void *, void *), void * primitives, void * locals, void * params) {
461 #else
462 int traverseCache() {
463 #endif
464   /* Create info to keep track of objects that can be locked */
465   int numoidrdlocked=0;
466   int numoidwrlocked=0;
467   void * rdlocked[200];
468   int rdversion[200];
469   void * wrlocked[200];
470   int softabort=0;
471   int i;
472   void ** oidrdlocked;
473   void ** oidwrlocked;
474 #ifdef STMSTATS
475   int rdage[200];
476   int * oidrdage;
477   int ObjSeqId;
478   int objtypetraverse[TOTALNUMCLASSANDARRAY];
479 #endif
480   int * oidrdversion;
481   allocarrays;
482
483 #ifdef STMSTATS
484   for(i=0; i<TOTALNUMCLASSANDARRAY; i++)
485     objtypetraverse[i] = 0;
486 #endif
487
488   chashlistnode_t *ptr = c_table;
489   /* Represents number of bins in the chash table */
490   unsigned int size = c_size;
491   for(i = 0; i<size; i++) {
492     chashlistnode_t *curr = &ptr[i];
493     /* Inner loop to traverse the linked list of the cache lookupTable */
494     while(curr != NULL) {
495       //if the first bin in hash table is empty
496       if(curr->key == NULL)
497         break;
498       objheader_t * headeraddr=&((objheader_t *) curr->val)[-1]; //cached object
499       objheader_t *header=(objheader_t *)(((char *)curr->key)-sizeof(objheader_t)); //real object
500       unsigned int version = headeraddr->version;
501
502       if(STATUS(headeraddr) & DIRTY) {
503         /* Read from the main heap  and compare versions */
504         if(write_trylock(&header->lock)) { //can aquire write lock
505           if (version == header->version) { /* versions match */
506             /* Keep track of objects locked */
507             oidwrlocked[numoidwrlocked++] = header;
508           } else {
509             oidwrlocked[numoidwrlocked++] = header;
510             transAbortProcess(oidwrlocked, numoidwrlocked);
511 #ifdef STMSTATS
512         header->abortCount++;
513         ObjSeqId = headeraddr->accessCount;
514             (typesCausingAbort[TYPE(header)]).numabort++;
515             (typesCausingAbort[TYPE(header)]).numaccess+=c_numelements;
516         (typesCausingAbort[TYPE(header)]).numtrans+=1; 
517         objtypetraverse[TYPE(header)]=1;
518         getTotalAbortCount(i+1, size, (void *)(curr->next), numoidrdlocked, oidrdlocked, oidrdversion, oidrdage, ObjSeqId, header, objtypetraverse);
519 #endif
520             DEBUGSTM("WR Abort: rd: %u wr: %u tot: %u type: %u ver: %u\n", numoidrdlocked, numoidwrlocked, c_numelements, TYPE(header), header->version);
521             DEBUGSTMSTAT("WR Abort: Access Count: %u AbortCount: %u type: %u ver: %u \n", header->accessCount, header->abortCount, TYPE(header), header->version);
522             freearrays;
523             if (softabort)
524             return TRANS_SOFT_ABORT;
525               else 
526             return TRANS_ABORT;
527           }
528         } else {
529           if(version == header->version) {
530             /* versions match */
531             softabort=1;
532           }
533           transAbortProcess(oidwrlocked, numoidwrlocked);
534 #ifdef STMSTATS
535       header->abortCount++;
536       ObjSeqId = headeraddr->accessCount;
537       (typesCausingAbort[TYPE(header)]).numabort++;
538       (typesCausingAbort[TYPE(header)]).numaccess+=c_numelements;
539       (typesCausingAbort[TYPE(header)]).numtrans+=1; 
540       objtypetraverse[TYPE(header)]=1;
541           //(typesCausingAbort[TYPE(header)])++;
542 #endif
543 #if defined(STMSTATS)||defined(SOFTABORT)
544       if(getTotalAbortCount(i+1, size, (void *)(curr->next), numoidrdlocked, oidrdlocked, oidrdversion, oidrdage, ObjSeqId, header, objtypetraverse))
545             softabort=0;
546 #endif
547           DEBUGSTM("WR Abort: rd: %u wr: %u tot: %u type: %u ver: %u\n", numoidrdlocked, numoidwrlocked, c_numelements, TYPE(header), header->version);
548           DEBUGSTMSTAT("WR Abort: Access Count: %u AbortCount: %u type: %u ver: %u \n", header->accessCount, header->abortCount, TYPE(header), header->version);
549           freearrays;
550           if (softabort)
551             return TRANS_SOFT_ABORT;
552           else 
553             return TRANS_ABORT;
554       
555         }
556       } else {
557 #ifdef STMSTATS
558     oidrdage[numoidrdlocked]=headeraddr->accessCount;
559 #endif
560     oidrdversion[numoidrdlocked]=version;
561     oidrdlocked[numoidrdlocked++]=header;
562       }
563       curr = curr->next;
564     }
565   } //end of for
566
567 #ifdef DELAYCOMP
568   //acquire access set locks
569   unsigned int numoidwrtotal=numoidwrlocked;
570
571   chashlistnode_t *dc_curr = dc_c_list;
572   /* Inner loop to traverse the linked list of the cache lookupTable */
573   while(likely(dc_curr != NULL)) {
574     //if the first bin in hash table is empty
575     objheader_t * headeraddr=&((objheader_t *) dc_curr->val)[-1];
576     objheader_t *header=(objheader_t *)(((char *)dc_curr->key)-sizeof(objheader_t));
577     if(write_trylock(&header->lock)) { //can aquire write lock    
578       oidwrlocked[numoidwrtotal++] = header;
579     } else {
580       //maybe we already have lock
581       void * key=dc_curr->key;
582       chashlistnode_t *node = &c_table[(((unsigned INTPTR)key) & c_mask)>>4];
583       
584       do {
585         if(node->key == key) {
586           objheader_t * headeraddr=&((objheader_t *) node->val)[-1];      
587           if(STATUS(headeraddr) & DIRTY) {
588             goto nextloop;
589           } else
590             break;
591         }
592         node = node->next;
593       } while(node != NULL);
594
595       //have to abort to avoid deadlock
596       transAbortProcess(oidwrlocked, numoidwrtotal);
597 #ifdef STMSTATS
598       ObjSeqId = headeraddr->accessCount;
599       header->abortCount++;
600       (typesCausingAbort[TYPE(header)]).numabort++;
601       (typesCausingAbort[TYPE(header)]).numaccess+=c_numelements;
602       (typesCausingAbort[TYPE(header)]).numtrans+=1; 
603       objtypetraverse[TYPE(header)]=1;
604 #endif
605 #if defined(STMSTATS)||defined(SOFTABORT)
606       if(getTotalAbortCount(i+1, size, (void *)(curr->next), numoidrdlocked, oidrdlocked, oidrdversion, oidrdage, ObjSeqId, header, objtypetraverse))
607         softabort=0;
608 #endif
609       DEBUGSTM("WR Abort: rd: %u wr: %u tot: %u type: %u ver: %u\n", numoidrdlocked, numoidwrlocked, c_numelements, TYPE(header), header->version);
610       DEBUGSTMSTAT("WR Abort: Access Count: %u AbortCount: %u type: %u ver: %u \n", header->accessCount, header->abortCount, TYPE(header), header->version);
611       freearrays;
612       if (softabort)
613         return TRANS_SOFT_ABORT;
614       else
615         return TRANS_ABORT;
616     }
617   nextloop:
618     dc_curr = dc_curr->lnext;
619   }
620 #endif
621
622   //THIS IS THE SERIALIZATION END POINT (START POINT IS END OF EXECUTION)*****
623
624   for(i=0; i<numoidrdlocked; i++) {
625     /* Read from the main heap  and compare versions */
626     objheader_t *header=oidrdlocked[i];
627     unsigned int version=oidrdversion[i];
628     if(header->lock>0) { //not write locked
629       CFENCE;
630       if(version != header->version) { /* versions do not match */
631 #ifdef DELAYCOMP
632         transAbortProcess(oidwrlocked, numoidwrtotal);
633 #else
634         transAbortProcess(oidwrlocked, numoidwrlocked);
635 #endif
636 #ifdef STMSTATS
637     ObjSeqId = oidrdage[i];
638     header->abortCount++;
639     (typesCausingAbort[TYPE(header)]).numabort++;
640     (typesCausingAbort[TYPE(header)]).numaccess+=c_numelements;
641     (typesCausingAbort[TYPE(header)]).numtrans+=1; 
642     objtypetraverse[TYPE(header)]=1;
643         getReadAbortCount(i+1, numoidrdlocked, oidrdlocked, oidrdversion, oidrdage, ObjSeqId, header, objtypetraverse);
644 #endif
645         DEBUGSTM("RD Abort: rd: %u wr: %u tot: %u type: %u ver: %u oid: %x\n", numoidrdlocked, numoidwrlocked, c_numelements, TYPE(header), header->version, OID(header));
646         DEBUGSTMSTAT("RD Abort: Access Count: %u AbortCount: %u type: %u ver: %u \n", header->accessCount, header->abortCount, TYPE(header), header->version);
647         freearrays;
648         return TRANS_ABORT;
649       }
650 #if DELAYCOMP
651     } else if (dc_t_chashSearch(((char *)header)+sizeof(objheader_t))!=NULL) {
652       //couldn't get lock because we already have it
653       //check if it is the right version number
654       if (version!=header->version) {
655         transAbortProcess(oidwrlocked, numoidwrtotal);
656 #ifdef STMSTATS
657     ObjSeqId = oidrdage[i];
658     header->abortCount++;
659     (typesCausingAbort[TYPE(header)]).numabort++;
660     (typesCausingAbort[TYPE(header)]).numaccess+=c_numelements;
661     (typesCausingAbort[TYPE(header)]).numtrans+=1; 
662     objtypetraverse[TYPE(header)]=1;
663         getReadAbortCount(i+1, numoidrdlocked, oidrdlocked, oidrdversion, oidrdage, ObjSeqId, header, objtypetraverse);
664 #endif
665         DEBUGSTM("RD Abort: rd: %u wr: %u tot: %u type: %u ver: %u, oid: %x\n", numoidrdlocked, numoidwrlocked, c_numelements, TYPE(header), header->version, OID(header));
666         DEBUGSTMSTAT("RD Abort: Access Count: %u AbortCount: %u type: %u ver: %u \n", header->accessCount, header->abortCount, TYPE(header), header->version);
667         freearrays;
668         return TRANS_ABORT;
669       }
670 #endif
671     } else { /* cannot aquire lock */
672       //do increment as we didn't get lock
673       if(version == header->version) {
674         softabort=1;
675       }
676 #ifdef DELAYCOMP
677       transAbortProcess(oidwrlocked, numoidwrtotal);
678 #else
679       transAbortProcess(oidwrlocked, numoidwrlocked);
680 #endif
681 #ifdef STMSTATS
682       ObjSeqId = oidrdage[i];
683       header->abortCount++;
684       (typesCausingAbort[TYPE(header)]).numabort++;
685       (typesCausingAbort[TYPE(header)]).numaccess+=c_numelements;
686       (typesCausingAbort[TYPE(header)]).numtrans+=1; 
687       objtypetraverse[TYPE(header)]=1;
688 #endif
689 #if defined(STMSTATS)||defined(SOFTABORT)
690       if(getReadAbortCount(i+1, numoidrdlocked, oidrdlocked, oidrdversion, oidrdage, ObjSeqId, header, objtypetraverse))
691         softabort=0;
692 #endif
693       DEBUGSTM("RD Abort: rd: %u wr: %u tot: %u type: %u ver: %u oid: %x\n", numoidrdlocked, numoidwrlocked, c_numelements, TYPE(header), header->version, OID(header));
694       DEBUGSTMSTAT("RD Abort: Access Count: %u AbortCount: %u type: %u ver: %u \n", header->accessCount, header->abortCount, TYPE(header), header->version);
695       freearrays;
696       if (softabort)
697         return TRANS_SOFT_ABORT;
698       else 
699         return TRANS_ABORT;
700     }
701   }
702
703 #ifdef READSET
704   //need to validate auxilary readset
705   rdchashlistnode_t *rd_curr = rd_c_list;
706   /* Inner loop to traverse the linked list of the cache lookupTable */
707   while(likely(rd_curr != NULL)) {
708     //if the first bin in hash table is empty
709     unsigned int version=rd_curr->version;
710     objheader_t *header=(objheader_t *)(((char *)rd_curr->key)-sizeof(objheader_t));
711     if(header->lock>0) { //object is not locked
712       if (version!=header->version) {
713         //have to abort
714 #ifdef DELAYCOMP
715         transAbortProcess(oidwrlocked, numoidwrtotal);
716 #else
717         transAbortProcess(oidwrlocked, numoidwrlocked);
718 #endif
719 #ifdef STMSTATS
720         //ABORTCOUNT(header);
721         (typesCausingAbort[TYPE(header)])++;
722 #endif
723 #if defined(STMSTATS)||defined(SOFTABORT)
724         //if(getTotalAbortCount2((void *) curr->next, numoidrdlocked, oidrdlocked, oidrdversion))
725         //  softabort=0;
726 #endif
727         DEBUGSTM("WR Abort: rd: %u wr: %u tot: %u type: %u ver: %u oid: %x\n", numoidrdlocked, numoidwrlocked, c_numelements, TYPE(header), header->version, OID(header));
728         DEBUGSTMSTAT("WR Abort: Access Count: %u AbortCount: %u type: %u ver: %u \n", header->accessCount, header->abortCount, TYPE(header), header->version);
729         freearrays;
730         if (softabort)
731           return TRANS_SOFT_ABORT;
732         else
733           return TRANS_ABORT;   
734       }
735     } else {
736       //maybe we already have lock
737       if (version==header->version) {
738         void * key=rd_curr->key;
739 #ifdef DELAYCOMP
740         //check to see if it is in the delaycomp table
741         {
742           chashlistnode_t *node = &dc_c_table[(((unsigned INTPTR)key) & dc_c_mask)>>4];
743           do {
744             if(node->key == key)
745               goto nextloopread;
746             node = node->next;
747           } while(node != NULL);
748         }
749 #endif
750         //check normal table
751         {
752           chashlistnode_t *node = &c_table[(((unsigned INTPTR)key) & c_mask)>>4];
753           do {
754             if(node->key == key) {
755               objheader_t * headeraddr=&((objheader_t *) node->val)[-1];          
756               if(STATUS(headeraddr) & DIRTY) {
757                 goto nextloopread;
758               }
759             }
760             node = node->next;
761           } while(node != NULL);
762         }
763       }
764 #ifdef DELAYCOMP
765       //have to abort to avoid deadlock
766       transAbortProcess(oidwrlocked, numoidwrtotal);
767 #else
768       transAbortProcess(oidwrlocked, numoidwrlocked);
769 #endif
770
771 #ifdef STMSTATS
772       //ABORTCOUNT(header);
773       (typesCausingAbort[TYPE(header)])++;
774 #endif
775 #if defined(STMSTATS)||defined(SOFTABORT)
776       //if(getTotalAbortCount2((void *) curr->next, numoidrdlocked, oidrdlocked, oidrdversion))
777         //softabort=0;
778 #endif
779       DEBUGSTM("WR Abort: rd: %u wr: %u tot: %u type: %u ver: %u oid: %x\n", numoidrdlocked, numoidwrlocked, c_numelements, TYPE(header), header->version, OID(header));
780       DEBUGSTMSTAT("WR Abort: Access Count: %u AbortCount: %u type: %u ver: %u \n", header->accessCount, header->abortCount, TYPE(header), header->version);
781       freearrays;
782       if (softabort)
783         return TRANS_SOFT_ABORT;
784       else
785         return TRANS_ABORT;
786     }
787   nextloopread:
788     rd_curr = rd_curr->lnext;
789   }
790 #endif
791   
792   /* Decide the final response */
793 #ifdef DELAYCOMP
794   transCommitProcess(oidwrlocked, numoidwrlocked, numoidwrtotal, commitmethod, primitives, locals, params);
795 #else
796   transCommitProcess(oidwrlocked, numoidwrlocked);
797 #endif
798   DEBUGSTM("Commit: rd: %u wr: %u tot: %u\n", numoidrdlocked, numoidwrlocked, c_numelements);
799   freearrays;
800   return TRANS_COMMIT;
801 }
802
803 /* ==================================================
804  * alttraverseCache
805  * - goes through the transaction cache and
806  * - decides if a transaction should commit or abort
807  * ==================================================
808  */
809
810 #ifdef DELAYCOMP
811 int alttraverseCache(void (*commitmethod)(void *, void *, void *), void * primitives, void * locals, void * params) {
812 #else
813 int alttraverseCache() {
814 #endif
815   /* Create info to keep track of objects that can be locked */
816   int numoidrdlocked=0;
817   int numoidwrlocked=0;
818   void * rdlocked[200];
819   int rdversion[200];
820   void * wrlocked[200];
821   int softabort=0;
822   int i;
823   void ** oidrdlocked;
824   int * oidrdversion;
825 #ifdef STMSTATS
826   int rdage[200];
827   int * oidrdage;
828   int ObjSeqId;
829   int objtypetraverse[TOTALNUMCLASSANDARRAY];
830 #endif
831   void ** oidwrlocked;
832   allocarrays;
833
834 #ifdef STMSTATS
835   for(i=0; i<TOTALNUMCLASSANDARRAY; i++)
836     objtypetraverse[i] = 0;
837 #endif
838   chashlistnode_t *curr = c_list;
839   /* Inner loop to traverse the linked list of the cache lookupTable */
840   while(likely(curr != NULL)) {
841     //if the first bin in hash table is empty
842     objheader_t * headeraddr=&((objheader_t *) curr->val)[-1];
843     objheader_t *header=(objheader_t *)(((char *)curr->key)-sizeof(objheader_t));
844     unsigned int version = headeraddr->version;
845
846     if(STATUS(headeraddr) & DIRTY) {
847       /* Read from the main heap  and compare versions */
848       if(likely(write_trylock(&header->lock))) { //can aquire write lock
849         if (likely(version == header->version)) { /* versions match */
850           /* Keep track of objects locked */
851           oidwrlocked[numoidwrlocked++] = header;
852         } else {
853           oidwrlocked[numoidwrlocked++] = header;
854           transAbortProcess(oidwrlocked, numoidwrlocked);
855 #ifdef STMSTATS
856       header->abortCount++;
857       ObjSeqId = headeraddr->accessCount; 
858       (typesCausingAbort[TYPE(header)]).numabort++;
859       (typesCausingAbort[TYPE(header)]).numaccess+=c_numelements;
860       (typesCausingAbort[TYPE(header)]).numtrans+=1; 
861       objtypetraverse[TYPE(header)]=1;
862       getTotalAbortCount2((void *) curr->next, numoidrdlocked, oidrdlocked, oidrdversion, oidrdage, ObjSeqId, header, objtypetraverse);
863 #endif
864           DEBUGSTM("WR Abort: rd: %u wr: %u tot: %u type: %u ver: %u oid: %x\n", numoidrdlocked, numoidwrlocked, c_numelements, TYPE(header), header->version, OID(header));
865           DEBUGSTMSTAT("WR Abort: Access Count: %u AbortCount: %u type: %u ver: %u \n", header->accessCount, header->abortCount, TYPE(header), header->version);
866           freearrays;
867           return TRANS_ABORT;
868         }
869       } else { /* cannot aquire lock */
870         if(version == header->version) {
871           /* versions match */
872           softabort=1;
873         }
874         transAbortProcess(oidwrlocked, numoidwrlocked);
875 #ifdef STMSTATS
876     header->abortCount++;
877     ObjSeqId = headeraddr->accessCount; 
878     (typesCausingAbort[TYPE(header)]).numabort++;
879     (typesCausingAbort[TYPE(header)]).numaccess+=c_numelements;
880     (typesCausingAbort[TYPE(header)]).numtrans+=1; 
881     objtypetraverse[TYPE(header)]=1;
882 #endif
883 #if defined(STMSTATS)||defined(SOFTABORT)
884     if(getTotalAbortCount2((void *) curr->next, numoidrdlocked, oidrdlocked, oidrdversion, oidrdage, ObjSeqId, header, objtypetraverse))
885           softabort=0;
886 #endif
887         DEBUGSTM("WR Abort: rd: %u wr: %u tot: %u type: %u ver: %u oid: %x\n", numoidrdlocked, numoidwrlocked, c_numelements, TYPE(header), header->version, OID(header));
888         DEBUGSTMSTAT("WR Abort: Access Count: %u AbortCount: %u type: %u ver: %u \n", header->accessCount, header->abortCount, TYPE(header), header->version);
889         freearrays;
890         if (softabort)
891           return TRANS_SOFT_ABORT;
892         else 
893           return TRANS_ABORT;
894       }
895     } else {
896       /* Read from the main heap  and compare versions */
897       oidrdversion[numoidrdlocked]=version;
898       oidrdlocked[numoidrdlocked++] = header;
899     }
900     curr = curr->lnext;
901   }
902
903 #ifdef DELAYCOMP
904   //acquire other locks
905   unsigned int numoidwrtotal=numoidwrlocked;
906   chashlistnode_t *dc_curr = dc_c_list;
907   /* Inner loop to traverse the linked list of the cache lookupTable */
908   while(likely(dc_curr != NULL)) {
909     //if the first bin in hash table is empty
910     objheader_t * headeraddr=&((objheader_t *) dc_curr->val)[-1];
911     objheader_t *header=(objheader_t *)(((char *)dc_curr->key)-sizeof(objheader_t));
912     if(write_trylock(&header->lock)) { //can aquire write lock
913       oidwrlocked[numoidwrtotal++] = header;
914     } else {
915       //maybe we already have lock
916       void * key=dc_curr->key;
917       chashlistnode_t *node = &c_table[(((unsigned INTPTR)key) & c_mask)>>4];
918       
919       do {
920         if(node->key == key) {
921           objheader_t * headeraddr=&((objheader_t *) node->val)[-1];
922           if(STATUS(headeraddr) & DIRTY) {
923             goto nextloop;
924           }
925         }
926         node = node->next;
927       } while(node != NULL);
928
929       //have to abort to avoid deadlock
930       transAbortProcess(oidwrlocked, numoidwrtotal);
931 #ifdef STMSTATS
932       header->abortCount++;
933       ObjSeqId = headeraddr->accessCount; 
934       (typesCausingAbort[TYPE(header)]).numabort++;
935       (typesCausingAbort[TYPE(header)]).numaccess+=c_numelements;
936       (typesCausingAbort[TYPE(header)]).numtrans+=1; 
937       objtypetraverse[TYPE(header)]=1;
938 #endif
939 #if defined(STMSTATS)||defined(SOFTABORT)
940       if(getTotalAbortCount2((void *) curr->next, numoidrdlocked, oidrdlocked, oidrdversion, oidrdage, ObjSeqId, header, objtypetraverse))
941         softabort=0;
942 #endif
943       DEBUGSTM("WR Abort: rd: %u wr: %u tot: %u type: %u ver: %u oid: %x\n", numoidrdlocked, numoidwrlocked, c_numelements, TYPE(header), header->version, OID(header));
944       DEBUGSTMSTAT("WR Abort: Access Count: %u AbortCount: %u type: %u ver: %u \n", header->accessCount, header->abortCount, TYPE(header), header->version);
945       freearrays;
946       if (softabort)
947         return TRANS_SOFT_ABORT;
948       else
949         return TRANS_ABORT;
950     }
951   nextloop:
952     dc_curr = dc_curr->lnext;
953   }
954 #endif
955
956   //THIS IS THE SERIALIZATION END POINT (START POINT IS END OF EXECUTION)*****
957
958   for(i=0; i<numoidrdlocked; i++) {
959     objheader_t * header=oidrdlocked[i];
960     unsigned int version=oidrdversion[i];
961     if(header->lock>0) {
962       CFENCE;
963       if(version != header->version) {
964 #ifdef DELAYCOMP
965         transAbortProcess(oidwrlocked, numoidwrtotal);
966 #else
967         transAbortProcess(oidwrlocked, numoidwrlocked);
968 #endif
969 #ifdef STMSTATS
970     ObjSeqId = oidrdage[i];
971     header->abortCount++;
972     (typesCausingAbort[TYPE(header)]).numabort++;
973     (typesCausingAbort[TYPE(header)]).numaccess+=c_numelements;
974     (typesCausingAbort[TYPE(header)]).numtrans+=1; 
975     objtypetraverse[TYPE(header)]=1;
976         getReadAbortCount(i+1, numoidrdlocked, oidrdlocked, oidrdversion, oidrdage, ObjSeqId, header, objtypetraverse);
977 #endif
978         DEBUGSTM("RD Abort: rd: %u wr: %u tot: %u type: %u ver: %u oid: %x\n", numoidrdlocked, numoidwrlocked, c_numelements, TYPE(header), header->version, OID(header));
979         DEBUGSTMSTAT("RD Abort: Access Count: %u AbortCount: %u type: %u ver: %u \n", header->accessCount, header->abortCount, TYPE(header), header->version);
980         freearrays;
981         return TRANS_ABORT;
982       }
983 #ifdef DELAYCOMP
984     } else if (dc_t_chashSearch(((char *)header)+sizeof(objheader_t))!=NULL) {
985       //couldn't get lock because we already have it
986       //check if it is the right version number
987       if (version!=header->version) {
988         transAbortProcess(oidwrlocked, numoidwrtotal);
989 #ifdef STMSTATS
990     ObjSeqId = oidrdage[i];
991     header->abortCount++;
992         getReadAbortCount(i+1, numoidrdlocked, oidrdlocked, oidrdversion, oidrdage, ObjSeqId, header, objtypetraverse);
993 #endif
994         DEBUGSTM("RD Abort: rd: %u wr: %u tot: %u type: %u ver: %u oid: %x\n", numoidrdlocked, numoidwrlocked, c_numelements, TYPE(header), header->version, OID(header));
995         DEBUGSTMSTAT("RD Abort: Access Count: %u AbortCount: %u type: %u ver: %u \n", header->accessCount, header->abortCount, TYPE(header), header->version);
996         freearrays;
997         return TRANS_ABORT;
998       }
999 #endif
1000     } else { /* cannot aquire lock */
1001       if(version == header->version) {
1002         softabort=1;
1003       }
1004 #ifdef DELAYCOMP
1005       transAbortProcess(oidwrlocked, numoidwrtotal);
1006 #else
1007       transAbortProcess(oidwrlocked, numoidwrlocked);
1008 #endif
1009 #ifdef STMSTATS
1010       ObjSeqId = oidrdage[i];
1011       header->abortCount++;
1012       (typesCausingAbort[TYPE(header)]).numabort++;
1013       (typesCausingAbort[TYPE(header)]).numaccess+=c_numelements;
1014       (typesCausingAbort[TYPE(header)]).numtrans+=1; 
1015       objtypetraverse[TYPE(header)]=1;
1016 #endif
1017 #if defined(STMSTATS)||defined(SOFTABORT)
1018       if(getReadAbortCount(i+1, numoidrdlocked, oidrdlocked, oidrdversion, oidrdage, ObjSeqId, header, objtypetraverse))
1019         softabort=0;
1020 #endif
1021       DEBUGSTM("RD Abort: rd: %u wr: %u tot: %u type: %u ver: %u\n", numoidrdlocked, numoidwrlocked, c_numelements, TYPE(header), header->version);
1022       DEBUGSTMSTAT("RD Abort: Access Count: %u AbortCount: %u type: %u ver: %u \n", header->accessCount, header->abortCount, TYPE(header), header->version);
1023       freearrays;
1024       if (softabort)
1025         return TRANS_SOFT_ABORT;
1026       else 
1027         return TRANS_ABORT;
1028     }
1029   }
1030
1031 #ifdef READSET
1032   //need to validate auxilary readset
1033   rdchashlistnode_t *rd_curr = rd_c_list;
1034   /* Inner loop to traverse the linked list of the cache lookupTable */
1035   while(likely(rd_curr != NULL)) {
1036     //if the first bin in hash table is empty
1037     int version=rd_curr->version;
1038     objheader_t *header=(objheader_t *)(((char *)rd_curr->key)-sizeof(objheader_t));
1039     if(header->lock>0) { //object is not locked
1040       if (version!=header->version) {
1041         //have to abort
1042 #ifdef DELAYCOMP
1043         transAbortProcess(oidwrlocked, numoidwrtotal);
1044 #else
1045         transAbortProcess(oidwrlocked, numoidwrlocked);
1046 #endif
1047 #ifdef STMSTATS
1048         //ABORTCOUNT(header);
1049         (typesCausingAbort[TYPE(header)])++;
1050 #endif
1051 #if defined(STMSTATS)||defined(SOFTABORT)
1052         //if(getTotalAbortCount2((void *) curr->next, numoidrdlocked, oidrdlocked, oidrdversion))
1053         //  softabort=0;
1054 #endif
1055         DEBUGSTM("WR Abort: rd: %u wr: %u tot: %u type: %u ver: %u\n", numoidrdlocked, numoidwrlocked, c_numelements, TYPE(header), header->version);
1056         DEBUGSTMSTAT("WR Abort: Access Count: %u AbortCount: %u type: %u ver: %u \n", header->accessCount, header->abortCount, TYPE(header), header->version);
1057         freearrays;
1058         if (softabort)
1059           return TRANS_SOFT_ABORT;
1060         else
1061           return TRANS_ABORT;   
1062       }
1063     } else {
1064       if (version==header->version) {
1065         void * key=rd_curr->key;
1066 #ifdef DELAYCOMP
1067         //check to see if it is in the delaycomp table
1068         {
1069           chashlistnode_t *node = &dc_c_table[(((unsigned INTPTR)key) & dc_c_mask)>>4];
1070           do {
1071             if(node->key == key)
1072               goto nextloopread;
1073             node = node->next;
1074           } while(node != NULL);
1075         }
1076 #endif
1077         //check normal table
1078         {
1079           chashlistnode_t *node = &c_table[(((unsigned INTPTR)key) & c_mask)>>4];
1080           do {
1081             if(node->key == key) {
1082               objheader_t * headeraddr=&((objheader_t *) node->val)[-1];          
1083               if(STATUS(headeraddr) & DIRTY) {
1084                 goto nextloopread;
1085               }
1086             }
1087             node = node->next;
1088           } while(node != NULL);
1089         }
1090       }
1091 #ifdef DELAYCOMP
1092         //have to abort to avoid deadlock
1093         transAbortProcess(oidwrlocked, numoidwrtotal);
1094 #else
1095         transAbortProcess(oidwrlocked, numoidwrlocked);
1096 #endif
1097 #ifdef STMSTATS
1098       //ABORTCOUNT(header);
1099       (typesCausingAbort[TYPE(header)])++;
1100 #endif
1101 #if defined(STMSTATS)||defined(SOFTABORT)
1102      // if(getTotalAbortCount2((void *) curr->next, numoidrdlocked, oidrdlocked, oidrdversion))
1103         //softabort=0;
1104 #endif
1105       DEBUGSTM("WR Abort: rd: %u wr: %u tot: %u type: %u ver: %u\n", numoidrdlocked, numoidwrlocked, c_numelements, TYPE(header), header->version);
1106       DEBUGSTMSTAT("WR Abort: Access Count: %u AbortCount: %u type: %u ver: %u \n", header->accessCount, header->abortCount, TYPE(header), header->version);
1107       freearrays;
1108       if (softabort)
1109         return TRANS_SOFT_ABORT;
1110       else
1111         return TRANS_ABORT;
1112     }
1113   nextloopread:
1114     rd_curr = rd_curr->lnext;
1115   }
1116 #endif
1117
1118   /* Decide the final response */
1119 #ifdef DELAYCOMP
1120   transCommitProcess(oidwrlocked, numoidwrlocked, numoidwrtotal, commitmethod, primitives, locals, params);
1121 #else
1122   transCommitProcess(oidwrlocked, numoidwrlocked);
1123 #endif
1124   DEBUGSTM("Commit: rd: %u wr: %u tot: %u\n", numoidrdlocked, numoidwrlocked, c_numelements);
1125   freearrays;
1126   return TRANS_COMMIT;
1127 }
1128
1129 /* ==================================
1130  * transAbortProcess
1131  *
1132  * =================================
1133  */
1134 void transAbortProcess(void **oidwrlocked, int numoidwrlocked) {
1135   int i;
1136   objheader_t *header;
1137   /* Release read locks */
1138
1139   /* Release write locks */
1140   for(i=numoidwrlocked-1; i>=0; i--) {
1141     /* Read from the main heap */
1142     header = (objheader_t *)oidwrlocked[i];
1143     write_unlock(&header->lock);
1144   }
1145
1146 #ifdef STMSTATS
1147   /* clear trec and then release objects locked */
1148   struct objlist *ptr=lockedobjs;
1149   while(ptr!=NULL) {
1150     int max=ptr->offset;
1151     for(i=max-1; i>=0; i--) {
1152       header = (objheader_t *)ptr->objs[i];
1153       header->trec = NULL;
1154       pthread_mutex_unlock(header->objlock);
1155     }
1156     ptr=ptr->next;
1157   }
1158 #endif
1159 }
1160
1161 /* ==================================
1162  * transCommitProcess
1163  *
1164  * =================================
1165  */
1166 #ifdef DELAYCOMP
1167  void transCommitProcess(void ** oidwrlocked, int numoidwrlocked, int numoidwrtotal, void (*commitmethod)(void *, void *, void *), void * primitives, void * locals, void * params) {
1168 #else
1169    void transCommitProcess(void ** oidwrlocked, int numoidwrlocked) {
1170 #endif
1171   objheader_t *header;
1172   void *ptrcreate;
1173   int i;
1174   struct objlist *ptr=newobjs;
1175   while(ptr!=NULL) {
1176     int max=ptr->offset;
1177     for(i=0; i<max; i++) {
1178       //clear the new flag
1179       ((struct ___Object___ *)ptr->objs[i])->___objstatus___=0;
1180     }
1181     ptr=ptr->next;
1182   }
1183
1184   /* Copy from transaction cache -> main object store */
1185   for (i = numoidwrlocked-1; i >=0; i--) {
1186     /* Read from the main heap */
1187     header = (objheader_t *)oidwrlocked[i];
1188     int tmpsize;
1189     GETSIZE(tmpsize, header);
1190     struct ___Object___ *dst=(struct ___Object___*)(((char *)oidwrlocked[i])+sizeof(objheader_t));
1191     struct ___Object___ *src=t_chashSearch(dst);
1192     dst->___cachedCode___=src->___cachedCode___;
1193     dst->___cachedHash___=src->___cachedHash___;
1194     A_memcpy(&dst[1], &src[1], tmpsize-sizeof(struct ___Object___));
1195   }
1196   CFENCE;
1197
1198 #ifdef DELAYCOMP
1199   //  call commit method
1200   ptrstack.count=0;
1201   primstack.count=0;
1202   branchstack.count=0;
1203   commitmethod(params, locals, primitives);
1204 #endif
1205
1206   /* Release write locks */
1207 #ifdef DELAYCOMP
1208   for(i=numoidwrtotal-1; i>=0; i--) {
1209 #else
1210   for(i=numoidwrlocked-1; i>=0; i--) {
1211 #endif
1212     header = (objheader_t *)oidwrlocked[i];
1213     header->version++;
1214     write_unlock(&header->lock);
1215   }
1216
1217 #ifdef STMSTATS
1218   /* clear trec and then release objects locked */
1219   ptr=lockedobjs;
1220   while(ptr!=NULL) {
1221     int max=ptr->offset;
1222     for(i=max-1; i>=0; i--) {
1223       header = (objheader_t *)ptr->objs[i];
1224       header->trec = NULL;
1225       pthread_mutex_unlock(header->objlock);
1226     }
1227     ptr=ptr->next;
1228   }
1229 #endif
1230 }
1231