ooRexx  4.2.0-source
About: ooRexx (Open Object Rexx) is a free implementation of Object Rexx. Object Rexx is an enhancement of the classic Rexx interpreter; a full-featured programming language with a human-oriented syntax.
  Fossies Dox: ooRexx-4.2.0-source.tar.gz  ("inofficial" and yet experimental doxygen-generated source code documentation)  

RexxMemory.cpp
Go to the documentation of this file.
1 /*----------------------------------------------------------------------------*/
2 /* */
3 /* Copyright (c) 1995, 2004 IBM Corporation. All rights reserved. */
4 /* Copyright (c) 2005-2009 Rexx Language Association. All rights reserved. */
5 /* */
6 /* This program and the accompanying materials are made available under */
7 /* the terms of the Common Public License v1.0 which accompanies this */
8 /* distribution. A copy is also available at the following address: */
9 /* http://www.oorexx.org/license.html */
10 /* */
11 /* Redistribution and use in source and binary forms, with or */
12 /* without modification, are permitted provided that the following */
13 /* conditions are met: */
14 /* */
15 /* Redistributions of source code must retain the above copyright */
16 /* notice, this list of conditions and the following disclaimer. */
17 /* Redistributions in binary form must reproduce the above copyright */
18 /* notice, this list of conditions and the following disclaimer in */
19 /* the documentation and/or other materials provided with the distribution. */
20 /* */
21 /* Neither the name of Rexx Language Association nor the names */
22 /* of its contributors may be used to endorse or promote products */
23 /* derived from this software without specific prior written permission. */
24 /* */
25 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */
26 /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */
27 /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */
28 /* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */
29 /* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
30 /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */
31 /* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, */
32 /* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY */
33 /* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */
34 /* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */
35 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
36 /* */
37 /*----------------------------------------------------------------------------*/
38 /******************************************************************************/
39 /* Kernel RexxMemory.cpp */
40 /* */
41 /* Memory Object */
42 /* */
43 /******************************************************************************/
44 #include <stdlib.h>
45 #include <string.h>
46 #include "RexxCore.h"
47 #include "RexxMemory.hpp"
48 #include "StackClass.hpp"
49 #include "StringClass.hpp"
50 #include "MutableBufferClass.hpp"
51 #include "DirectoryClass.hpp"
52 #include "RexxActivity.hpp"
53 #include "IntegerClass.hpp"
54 #include "ArrayClass.hpp"
55 #include "TableClass.hpp"
56 #include "RexxActivation.hpp"
57 #include "ActivityManager.hpp"
58 #include "MessageClass.hpp"
59 #include "MethodClass.hpp"
60 #include "RelationClass.hpp"
61 #include "SupplierClass.hpp"
62 #include "PointerClass.hpp"
63 #include "BufferClass.hpp"
64 #include "PackageClass.hpp"
65 #include "WeakReferenceClass.hpp"
66 #include "StackFrameClass.hpp"
67 #include "Interpreter.hpp"
68 #include "SystemInterpreter.hpp"
69 #include "Interpreter.hpp"
70 #include "PackageManager.hpp"
71 #include "SysFileSystem.hpp"
72 #include "UninitDispatcher.hpp"
74 
75 // restore a class from its
76 // associated primitive behaviour
77 // (already restored by memory_init)
78 #define RESTORE_CLASS(name, className) The##name##Class = (className *)RexxBehaviour::getPrimitiveBehaviour(T_##name)->restoreClass();
79 
80 
81 bool SysAccessPool(MemorySegmentPool **pool);
82 /* NOTE: There is just a single memory object in global storage. We'll define */
83 /* memobj to be the direct address of this memory object. */
85 
86 #define LiveStackSize 16370 /* live stack size */
87 
88 #define SaveStackSize 10 /* newly created objects to save */
89 #define SaveStackAllocSize 500 /* pre-allocation for save stack */
90 
91 #define MaxImageSize 1800000 /* maximum startup image size */
92 
94 RexxDirectory *RexxMemory::environment = OREF_NULL; // global environment
95 RexxDirectory *RexxMemory::functionsDir = OREF_NULL; // statically defined requires
99 
100 // locks for the memory process access
104 
105 static void logMemoryCheck(FILE *outfile, const char *message, ...)
106 {
107  va_list args;
108  va_start(args, message);
109  vprintf(message, args);
110  if (outfile != NULL) {
111  vfprintf(outfile, message, args);
112  }
113  va_end(args);
114 }
115 
116 
118 /******************************************************************************/
119 /* Function: Main Constructor for Rexxmemory, called once during main */
120 /* initialization. Will create the initial memory Pool(s), etc. */
121 /******************************************************************************/
122 {
123  /* we need to set a valid size for this object. We round it up */
124  /* to the minimum allocation boundary, even though that might be */
125  /* a lie. Since this never participates in a sweep operation, */
126  /* this works ok in the end. */
128  // our first pool is the current one
130 
131  /* make sure we hand craft memory's */
132  /* header information. */
133 
134  /* See if we want this debug info */
135  /*or not by default, its always */
136  /*setable from OREXX code. */
137 #ifdef CHECKOREFS
138  this->orphanCheck = true; /* default value for OREF checking */
139 #else
140  this->orphanCheck = false; /* default value for OREF checking */
141 #endif
142  /* OR'ed into object headers to */
143  /*mark */
144  this->markWord = 1;
145  /* objects as being alive in mark */
146  /*phase */
147  this->saveStack = NULL;
148  this->saveTable = NULL;
149  this->dumpEnable = false;
150  this->objOffset = 0;
151  this->envelope = NULL;
152 
153  // we always start out with an empty list. WeakReferences that are in the
154  // saved image will (MUST) never be set to a new value, so it's not necessary
155  // to hook those back up again.
157 }
158 
159 
160 void RexxMemory::initialize(bool _restoringImage)
161 /******************************************************************************/
162 /* Function: Gain access to all Pools */
163 /******************************************************************************/
164 {
165  /* access 1st pool directly. SysCall */
166  /* Did the pool exist? */
167 
170 
171  disableOrefChecks(); /* Make sure we don't try to validate*/
172  /* OrefSets just yet. */
173  /* Make sure memory is fully */
174  /*constructed, mainlyt a concern on */
175  /*2nd entry and DLL not unloaded. */
176  new (this) RexxMemory;
179 
180  /* and the new/old Space segments */
182 
183  collections = 0;
184  allocations = 0;
187 
188  // get our table of virtual functions setup first thing.
190 
191  /* NOTE: we don't set livestack */
192  /*via the OrefSet macro, since we */
193  /*are so early on in the system, */
194  /*that we can't use it right now, */
195  /*we will fix this all */
197  /* remember the original one */
199 
200  if (_restoringImage) /* restoring the image? */
201  {
202  restoreImage(); /* do it now... */
203  }
204 
205  /* set memories behaviour */
207  /* initial marktable value is */
208  /* TheKernel */
209  this->markTable = OREF_NULL; /* fix by CHM/Rick: set initial table*/
210  /* to NULL since TheKernel could */
211  /* point to an invalid memory address*/
212  /* if one OREXX session is started */
213  /* while another one is closed */
214 
215  /* make sure we have an inital segment set to allocate from. */
217 
218  // get the initial uninit table
220 
221  // is this image creation? This will build and save the image, then
222  // terminate
223  if (!_restoringImage)
224  {
225  createImage();
226  }
227  restore(); // go restore the state of the memory object
228 }
229 
230 
231 void RexxMemory::logVerboseOutput(const char *message, void *sub1, void *sub2)
232 /******************************************************************************/
233 /* Function: Log verbose output events */
234 /******************************************************************************/
235 {
236  logMemoryCheck(NULL, message, sub1, sub2);
237 }
238 
240 {
241  FILE *outFile; /* memory stat output file */
242 
243  outFile = fopen("memory.prf","wb"); /* open the file */
244  /* have each of the memory segments dump their own profile information */
247  fclose(outFile); /* close the file */
248 }
249 
250 
251 void RexxMemory::dumpObject(RexxObject *objectRef, FILE *outfile)
252 /******************************************************************************/
253 /* Arguments: none, */
254 /* */
255 /* Function: Dump out the contents of an object, to screen and optionally */
256 /* a file. */
257 /******************************************************************************/
258 {
259  void **dmpPtr;
260  void **ObjEnd;
261 
262  ObjEnd = (void **)((char *)objectRef + objectRef->getObjectSize());
263  for (dmpPtr = (void **)objectRef; dmpPtr <= ObjEnd ; dmpPtr++)
264  {
265  logMemoryCheck(outfile, " >Parent Dump -->%p %p %p %p \n", *dmpPtr, *(dmpPtr+1), *(dmpPtr+2), *(dmpPtr+3));
266  }
267 }
268 
270 /******************************************************************************/
271 /* Arguments: Any OREF */
272 /* */
273 /* Returned: true if object is in object storage, else false */
274 /******************************************************************************/
275 {
276  /* 1st Check Old Space. */
277  if (oldSpaceSegments.isInSegmentSet(object))
278  {
279  return true;
280  }
281 
282  /* Now Check New Space. */
284  {
285  return true;
286  }
287 
288  /* Now Check New Space large segments*/
290  {
291  return true;
292  }
293 
294  /* this is bad, definitely very bad... */
295  return false;
296 }
297 
298 
300 /******************************************************************************/
301 /* Arguments: Any OREF */
302 /* */
303 /* Returned: true if object is in object storage, else false */
304 /******************************************************************************/
305 {
306  /* check for a few valid locations in 'C' storage */
308  (object == (RexxObject *)this))
309  {
310  return true;
311  }
312 
313  return inSharedObjectStorage(object);
314 }
315 
316 
317 /* object validation method --used to find and diagnose broken object references */
319 /******************************************************************************/
320 /* Function: Object validation...used to find and diagnose broken object */
321 /* references. */
322 /******************************************************************************/
323 {
324  if (!inObjectStorage(o))
325  {
326  return false;
327  }
329  if (inObjectStorage((RexxObject *)type) && type->getObjectType() == TheBehaviourBehaviour)
330  {
331  return true;
332  }
333  /* these last two checks are for very early checking...we can */
334  /* possibly be testing this before TheBehaviourBehaviour is */
335  /* set up, so we have two additional means of verifying the */
336  /* behaviour object. */
338 }
339 
340 
342 /******************************************************************************/
343 /* Function: Main memory_mark driving loop */
344 /******************************************************************************/
345 {
346  // for some of the root objects, we get called to mark them before they get allocated.
347  // make sure we don't process any null references.
348  if (rootObject == OREF_NULL)
349  {
350  return;
351  }
352 
353  RexxObject *markObject;
354 
355  // set up the live marking word passed to the live() routines
356  size_t liveMark = markWord | OldSpaceBit;
357 
358  allocations = 0;
359  pushLiveStack(OREF_NULL); /* push a unique terminator */
360  mark(rootObject); /* OREF_ENV or old2new */
361  for (markObject = popLiveStack();
362  markObject != OREF_NULL; /* test for unique terminator */
363  markObject = popLiveStack())
364  {
365  /* mark behaviour live */
366  memory_mark((RexxObject *)markObject->behaviour);
367  /* Mark other referenced obj. We can do this without checking */
368  /* the references flag because we only push the object on to */
369  /* the stack if it has references. */
370  allocations++;
371  markObject->live(liveMark);
372  }
373 }
374 
375 
377 /******************************************************************************/
378 /* Function: Garbage collection validity check routine */
379 /******************************************************************************/
380 {
381  // for some of the root objects, we get called to mark them before they get allocated.
382  // make sure we don't process any null references.
383  if (rootObject == OREF_NULL)
384  {
385  return;
386  }
387 
388  RexxObject *mref;
389 
391  /* This is the debugging mark code that traverses the object tree from */
392  /* OREF_ENV, verifying that the objects and their OREFs look OK, specifically */
393  /* that each one is in object storage, and has a behaviour whose behaviour */
394  /* is OREF_BEHAV_B, behaviour's behaviour. */
395 
396  /* push a unique terminator */
398  /*Push an extra marktable */
399  pushLiveStack(rootObject);
400  memory_mark_general(rootObject); /* start from the very tip-top */
401  memory_mark_general(TheNilObject); /* use .nil to mark the stack */
402  /* mark .nil behaviour live */
403  memory_mark_general(TheNilObject->behaviour);
404  /* mark .nil ovds live */
405  memory_mark_general(TheNilObject->objectVariables);
406  for (mref = popLiveStack();
407  mref != OREF_NULL; /* test for unique terminator */
408  /* get the next marked item */
409  mref = popLiveStack())
410  {
411 
412  /* OREF_NIL is used as a marker on the stack. These markers will be used to */
413  /* recreate the ancestry of any broken object found. At this point though, */
414  /* finding one indicates that we've already marked all of the descendants of */
415  /* the object just below the OREF_NIL, so we'll leave the OREF_NIL popped, */
416  /* and pop off the parent object which is no longer of any interest. */
417  if (mref == TheNilObject)
418  { /* found a marker */
419  /* pop off the completed parent */
420  popLiveStack();
421  continue; /* and back to top of loop */
422  }
423  /* mark behaviour live */
425  /* object have any references? */
426  if (mref->hasReferences())
427  {
428  /* Though this guy is already marked, and as far as gc, we're done with him, */
429  /* we'll now push him back onto the livestack followed by an OREF_NIL marker. */
430  /* If we find an invalid object later, we'll be able to find all the ancestors */
431  /* by looking for the OREF_NIL objects on the livestack. */
432  /* push the ancestor object */
433  pushLiveStack(mref);
434  /* push an ancestor marker */
436  mref->liveGeneral(LIVEMARK); /* tell the ancestor to mark his kids*/
437  } /* object have any references? */
438  }
439 }
440 
442 /******************************************************************************/
443 /* */
444 /******************************************************************************/
445 {
446  /* we might not actually have a table yet, so make sure we check */
447  /* before using it. */
448  if (uninitTable == NULL)
449  {
450  return;
451  }
452 
453  RexxObject *uninitObject;
454  /* table and any object is isn't */
455  /* alive, we indicate it should be */
456  /* sent unInit. We indiacte this */
457  /* by setting the value to 1, */
458  /* instead of NIL (the default) */
459  for (HashLink i = uninitTable->first(); (uninitObject = uninitTable->index(i)) != OREF_NULL; i = uninitTable->next(i))
460  {
461  /* is this object now dead? */
462  if (uninitObject->isObjectDead(markWord))
463  {
464  /* yes, indicate object is to be */
465  /* sent uninit. */
467  pendingUninits++;
468  }
469  }
470 }
471 
472 
479 void RexxMemory::collectAndUninit(bool clearStack)
480 {
481  // clear the save stack if we're working with a single instance
482  if (clearStack)
483  {
484  clearSaveStack();
485  }
486  collect();
487  runUninits();
488 }
489 
490 
498 {
499  // collect and run any uninits still pending
500  collectAndUninit(true);
501  // we're about to start releasing libraries, so it is critical
502  // we don't run any more uninits after this
503  uninitTable->empty();
504 }
505 
506 
508 /******************************************************************************/
509 /* Function: Run any UNINIT methods for this activity */
510 /******************************************************************************/
511 /* NOTE: The routine to iterate across uninit Table isn't quite right, since */
512 /* the removal of zombieObj may move another zombieObj and then doing */
513 /* the next will skip this zombie, we should however catch it next time */
514 /* through. */
515 /* */
516 /******************************************************************************/
517 {
518  RexxObject * zombieObj; /* obj that needs uninit run. */
519  HashLink iterTable; /* iterator for table. */
520 
521  /* if we're already processing this, don't try to do this */
522  /* recursively. */
523  if (processingUninits)
524  {
525  return;
526  }
527 
528  /* turn on the recursion flag, and also zero out the count of */
529  /* pending uninits to run */
530  processingUninits = true;
531  pendingUninits = 0;
532 
533  // get the current activity for running the uninits
535 
536  /* uninitTabe exists, run UNINIT */
537  for (iterTable = uninitTable->first();
538  (zombieObj = uninitTable->index(iterTable)) != OREF_NULL;)
539  {
540  // TODO: Ther's a bug here. Removing the object can cause the
541  // iterator to skip over an entry....something should be done to
542  // prevent this.
543 
544  /* is this object readyfor UNINIT? */
545  if (uninitTable->value(iterTable) == TheTrueObject)
546  {
547  /* make sure we don't recurse */
548  uninitTable->put(TheFalseObject, zombieObj);
549  {
550  // run this method with appropriate error trapping
551  UninitDispatcher dispatcher(zombieObj);
552  activity->run(dispatcher);
553  }
554  /* remove zombie from uninit table */
555  uninitTable->remove(zombieObj);
556 
557 
558  // because we just did a remove operation, this will effect the iteration
559  // process. There are two possibilities here. Either A) we were at the end of the
560  // chain and this is now an empty slot or B) the removal process moved an new item
561  // into this slot. If it is case A), then we need to search for the next item. If
562  // it is case B) we'll just leave the index alone and process this position again.
563  if (uninitTable->index(iterTable) == OREF_NULL)
564  {
565  iterTable = uninitTable->next(iterTable);
566  }
567  }
568  else
569  {
570  iterTable = uninitTable->next(iterTable);
571  }
572  } /* now go check next object in table */
573  /* make sure we remove the recursion protection */
574  processingUninits = false;
575 }
576 
577 
579  RexxObject *obj) /* object to remove */
580 /******************************************************************************/
581 /* Function: Remove an object from the uninit tables */
582 /******************************************************************************/
583 {
584  // just remove this object from the table
585  uninitTable->remove(obj);
586 }
587 
588 
590  RexxObject *obj) /* object to add */
591 /******************************************************************************/
592 /* Function: Add an object with an uninit method to the uninit table for */
593 /* a process */
594 /******************************************************************************/
595 {
596  /* is object already in table? */
597  if (uninitTable->get(obj) == OREF_NULL)
598  {
599  /* nope, add obj to uninitTable, */
600  /* initial value is NIL */
602  }
603 
604 }
605 
607 /******************************************************************************/
608 /* Function: Test if an object is going to require its uninit method run. */
609 /******************************************************************************/
610 {
611  return uninitTable->get(obj) != OREF_NULL;
612 }
613 
614 
616 /******************************************************************************/
617 /* Function: Main mark routine for garbage collection. This reoutine */
618 /* Determines which mark routine to call and does all additional processing */
619 /******************************************************************************/
620 {
621  verboseMessage("Beginning mark operation\n");
622 
623  if (this->orphanCheck)
624  { /* debugging bad OREF's? */
625  /* yup, call debugging mark */
626  this->killOrphans((RexxObject *)this);
627  // now process the weak reference queue...We check this before the
628  // uninit list is processed so that the uninit list doesn't mark any of the
629  // weakly referenced items. We don't want an object placed on the uninit queue
630  // to end up strongly referenced later.
632  this->checkUninit(); /* flag all objects about to be dead */
633  this->killOrphans(uninitTable); /* the uninit table */
634  }
635  else
636  {
637  /* call normal,speedy,efficient mark */
638  this->markObjectsMain((RexxObject *)this);
639  // now process the weak reference queue...We check this before the
640  // uninit list is processed so that the uninit list doesn't mark any of the
641  // weakly referenced items. We don't want an object placed on the uninit queue
642  // to end up strongly referenced later.
644  this->checkUninit(); /* flag all objects about to be dead */
645  /* now mark the unInit table and the */
647  }
648  /* have to expand the live stack? */
649  if (this->liveStack != this->originalLiveStack)
650  {
651  free((void *)this->liveStack); /* release the old one */
652  /* and set back to the original */
653  this->liveStack = this->originalLiveStack;
654  }
655  verboseMessage("Mark operation completed\n");
656 }
657 
658 
659 /******************************************************************************/
660 /* Function: Scan the weak reference queue looking for either dead weak */
661 /* objects or weak references that refer to objects that have gone out of */
662 /* scope. Objects with registered notification objects (that are still in */
663 /* scope) will be moved to a notification queue, which is processed after */
664 /* everything is scanned. */
665 /******************************************************************************/
667 {
668  WeakReference *current = weakReferenceList;
669  // list of "live" weak references...built while scanning
670  WeakReference *newList = OREF_NULL;
671 
672  // loop through the list
673  while (current != OREF_NULL)
674  {
675  // we have to save the next one in the list
676  WeakReference *next = current->nextReferenceList;
677  // this reference still in scope?
678  if (current->isObjectLive(markWord))
679  {
680  // keep this one in the list
681  current->nextReferenceList = newList;
682  newList = current;
683  // have a reference?
684  if (current->referentObject != OREF_NULL)
685  {
686  // if the object is not alive, null out the reference
687  if (!current->referentObject->isObjectLive(markWord))
688  {
689  current->referentObject = OREF_NULL;
690  }
691  }
692  }
693  // step to the new nest item
694  current = next;
695  }
696 
697  // update the list
698  weakReferenceList = newList;
699 }
700 
701 
703 /******************************************************************************/
704 /* Function: Add a new weak reference to the tracking table */
705 /******************************************************************************/
706 {
707  // just add this to the front of the list
709  weakReferenceList = ref;
710 }
711 
712 
713 MemorySegment *RexxMemory::newSegment(size_t requestedBytes, size_t minBytes)
714 /******************************************************************************/
715 /* Function: Allocate a segment of the requested size. The requested size */
716 /* is the desired size, while the minimum is the absolute minimum we can */
717 /* handle. This takes care of the overhead accounting and additional */
718 /* rounding. The requested size is assumed to have been rounded up to the */
719 /* next "appropriate" boundary already, and the segment overhead will be */
720 /* allocated from that part, if possible. Otherwise, and additional page is */
721 /* added. */
722 /******************************************************************************/
723 {
724  MemorySegment *segment;
725 
726 #ifdef MEMPROFILE
727  printf("Allocating a new segment of %d bytes\n", requestedBytes);
728 #endif
729  /* first make sure we've got enough space for the control */
730  /* information, and round this to a proper boundary */
731  requestedBytes = roundSegmentBoundary(requestedBytes + MemorySegmentOverhead);
732 #ifdef MEMPROFILE
733  printf("Allocating boundary a new segment of %d bytes\n", requestedBytes);
734 #endif
735  /*Get a new segment */
736  segment = currentPool->newSegment(requestedBytes);
737  /* Did we get a segment */
738  if (segment == NULL)
739  {
740  /* Segmentsize is the minimum size request we handle. If */
741  /* minbytes is small, then we're just adding a segment to the */
742  /* small pool. Reduce the request to SegmentSize and try again. */
743  /* For all other requests, try once more with the minimum. */
744  minBytes = roundSegmentBoundary(minBytes + MemorySegmentOverhead);
745  /* try to allocate once more...if this fails, the caller will */
746  /* have to handle it. */
747  segment = currentPool->newSegment(minBytes);
748  }
749  return segment; /* return the allocated segment */
750 }
751 
752 
753 MemorySegment *RexxMemory::newLargeSegment(size_t requestedBytes, size_t minBytes)
754 /******************************************************************************/
755 /* Function: Allocate a segment of the requested size. The requested size */
756 /* is the desired size, while the minimum is the absolute minimum we can */
757 /* handle. This takes care of the overhead accounting and additional */
758 /* rounding. The requested size is assumed to have been rounded up to the */
759 /* next "appropriate" boundary already, and the segment overhead will be */
760 /* allocated from that part, if possible. Otherwise, and additional page is */
761 /* added. */
762 /******************************************************************************/
763 {
764  MemorySegment *segment;
765 
766  /* first make sure we've got enough space for the control */
767  /* information, and round this to a proper boundary */
768  size_t allocationBytes = roundSegmentBoundary(requestedBytes + MemorySegmentOverhead);
769 #ifdef MEMPROFILE
770  printf("Allocating large boundary new segment of %d bytes for request of %d\n", allocationBytes, requestedBytes);
771 #endif
772  /*Get a new segment */
773  segment = currentPool->newLargeSegment(allocationBytes);
774  /* Did we get a segment */
775  if (segment == NULL)
776  {
777  /* Segmentsize is the minimum size request we handle. If */
778  /* minbytes is small, then we're just adding a segment to the */
779  /* small pool. Reduce the request to SegmentSize and try again. */
780  /* For all other requests, try once more with the minimum. */
781  minBytes = roundSegmentBoundary(minBytes + MemorySegmentOverhead);
782  /* try to allocate once more...if this fails, the caller will */
783  /* have to handle it. */
784  segment = currentPool->newLargeSegment(minBytes);
785  }
786  return segment; /* return the allocated segment */
787 }
788 
789 
791 /******************************************************************************/
792 /* Function: Restore a saved image to usefulness. */
793 /******************************************************************************/
794 {
795  // Nothing to restore if we have a buffer already
796  if (image_buffer != NULL)
797  {
798  return;
799  }
800 
801  markReason = RESTORINGIMAGE; // we're doing an image restore
802 
803  size_t imagesize; /* size of the image */
804  char *objectPointer, *endPointer;
805  RexxBehaviour *imageBehav; /*behaviour of OP object in image */
806  RexxArray *primitiveBehaviours; /* saved array of behaviours */
807  size_t primitiveTypeNum;
808  int i;
809 
810  /* go load the image */
812  /* get the relocation factor */
813  relocation = (size_t)image_buffer - sizeof(size_t);
814  objectPointer = image_buffer; /* address the start of the image */
815  /* and the ending location */
816  endPointer = image_buffer + imagesize;
817  /* the save Array is the 1st object */
818  RexxArray *saveArray = (RexxArray *)image_buffer;
819  restoreimage = true; /* we are now restoring */
820  /* loop through the image buffer */
821  while (objectPointer < endPointer)
822  {
823 
824  /*Fixup Behaviour pointer for obj. */
825  /* We don't do an OrefSet here, since*/
826  /* too early, and we don't need to be*/
827  /* concerned about object in pbehav */
828 
829  /* Retrieve the behaviour obj */
830  /* or a copy? */
831  if (((RexxObject *)objectPointer)->isNonPrimitive())
832  {
833  /* Working with a copy, don't use */
834  /* PBEHAV version. */
835  /* Make sure static behaviour inf */
836  /* is resolved before using the */
837  /* Behaviour. */
838  imageBehav = (RexxBehaviour *)(relocation + (uintptr_t)((RexxObject *)objectPointer)->behaviour);
839  /* give this object it behaviour. */
840  ((RexxObject *)objectPointer)->behaviour = (RexxBehaviour *)imageBehav;
841  primitiveTypeNum = imageBehav->getClassType();
842  }
843  else
844  {
845  // the original behaviour pointer has been encoded as a type number and class
846  // category to allow us to convert back to the appropriate type.
847  ((RexxObject *)objectPointer)->behaviour = RexxBehaviour::restoreSavedPrimitiveBehaviour(((RexxObject *)objectPointer)->behaviour);
848  primitiveTypeNum = ((RexxObject *)objectPointer)->behaviour->getClassType();
849  }
850  /* This will be an OldSpace object. We delay setting this */
851  /* until now, because the oldspace bit is overloaded with the */
852  /* NonPrimitive bit. Since the we are done with the */
853  /* non-primitive bit now, we can use this for the oldspace */
854  /* flag too. */
855  ((RexxObject *)objectPointer)->setOldSpace();
856  /* Force fix-up of */
857  /*VirtualFunctionTable, */
858  ((RexxObject *)objectPointer)->setVirtualFunctions(virtualFunctionTable[primitiveTypeNum]);
859 
860  /* Do this object have any */
861  /*references? */
862  if (((RexxObject *)objectPointer)->hasReferences())
863  /* Yes, mark other referenced objs */
864  ((RexxObject *)objectPointer)->liveGeneral(RESTORINGIMAGE);
865  /* Point to next object in image.. */
866  objectPointer += ((RexxObject *)objectPointer)->getObjectSize();
867 
868  }
869 
870  restoreimage = false;
871  /* OREF_ENV is the first element of */
872  /*array */
874  /* get the primitive behaviours */
875  primitiveBehaviours = (RexxArray *)saveArray->get(saveArray_PBEHAV);
876  /* restore all of the saved primitive*/
877  for (i = 0; i <= T_Last_Exported_Class; i++)
878  {
879  /* behaviours into this array */
880  RexxBehaviour::primitiveBehaviours[i].restore((RexxBehaviour *)primitiveBehaviours->get(i + 1));
881  }
882 
883  TheKernel = (RexxDirectory *)saveArray->get(saveArray_KERNEL);
884  TheSystem = (RexxDirectory *)saveArray->get(saveArray_SYSTEM);
886  TheTrueObject = (RexxInteger *)saveArray->get(saveArray_TRUE);
888  TheNilObject = saveArray->get(saveArray_NIL);
889  TheNullArray = (RexxArray *)saveArray->get(saveArray_NULLA);
891  TheClassClass = (RexxClass *)saveArray->get(saveArray_CLASS);
893 
894  /* restore the global strings */
896  // make sure we have a working thread context
899 }
900 
901 
902 void RexxMemory::live(size_t liveMark)
903 /******************************************************************************/
904 /* Arguments: None */
905 /* */
906 /* Returned: Nothing */
907 /* */
908 /******************************************************************************/
909 {
910  /* Mark the save stack first, since it will be pulled off of */
911  /* the stack after everything else. This will give other */
912  /* objects a chance to be marked before we remove them from */
913  /* the savestack. */
914  memory_mark(this->saveStack);
915  memory_mark(this->saveTable);
916  memory_mark(this->old2new);
917  memory_mark(this->envelope);
918  memory_mark(this->variableCache);
919  memory_mark(this->markTable);
921  // now call the various subsystem managers to mark their references
922  Interpreter::live(liveMark);
923  SystemInterpreter::live(liveMark);
924  ActivityManager::live(liveMark);
925  PackageManager::live(liveMark);
926  // mark any protected objects we've been watching over
927 
929  while (p != NULL)
930  {
932  p = p->next;
933  }
934 }
935 
936 void RexxMemory::liveGeneral(int reason)
937 /******************************************************************************/
938 /* Arguments: None */
939 /* */
940 /* Returned: Nothing */
941 /* */
942 /******************************************************************************/
943 {
944  memory_mark_general(this->saveStack);/* Mark the save stack last, to give it a chance to clear out entries */
951  // now call the various subsystem managers to mark their references
952  Interpreter::liveGeneral(reason);
956 }
957 
959 /******************************************************************************/
960 /* Arguments: None */
961 /* */
962 /* Returned: OREF NULL, */
963 /******************************************************************************/
964 {
965 
966 }
967 
969 /******************************************************************************/
970 /* Arguments: None */
971 /* */
972 /* Returned: OREF NULL, */
973 /******************************************************************************/
974 {
975  /* Memory Obj doesn't get moved, */
976  /*create a proxy object to */
977  /*re-establish on other system. */
978 
979 
980  /* Generate a new proxy object to */
981  /*represent this object, and then */
982  /*send flatten to this proxy. We */
983  /*then return the result from the */
984  /*proxt flatten method. */
985  return (RexxObject *)new_proxy("MEMORY");
986 }
987 
988 
990 /******************************************************************************/
991 /* Function: Interface method for external control of garbage collection. */
992 /* This forces a GC cycle. */
993 /******************************************************************************/
994 {
995  /* just drive the GC operation */
996  collect();
997  return OREF_NULL;
998 }
999 
1000 
1002 /******************************************************************************/
1003 /* Function: Collect all dead memory in the Rexx object space. The */
1004 /* collection process performs a mark operation to mark all of the live */
1005 /* objects, followed by sweep of each of the segment sets. */
1006 /******************************************************************************/
1007 {
1008  collections++;
1009  verboseMessage("Begin collecting memory, cycle #%d after %d allocations.\n", collections, allocations);
1010  allocations = 0;
1011 
1012  /* change our marker to the next value so we can distinguish */
1013  /* between objects marked on this cycle from the objects marked */
1014  /* in the pervious cycles. */
1015  bumpMarkWord();
1016 
1017  /* do the object marking now...followed by a sweep of all of the */
1018  /* segments. */
1019  markObjects();
1022 
1023  /* The space segments are now in a known, completely clean state. */
1024  /* Now based on the context that caused garbage collection to be */
1025  /* initiated, the segment sets may be expanded to add additional */
1026  /* free memory. The decision to expand the object space requires */
1027  /* the usage statistics collected by the mark-and-sweep */
1028  /* operation. */
1029 
1030  verboseMessage("End collecting memory\n");
1031  verboseMessage("Object save table contains %d objects\n", this->saveTable->items());
1032 }
1033 
1034 RexxObject *RexxMemory::oldObject(size_t requestLength)
1035 /******************************************************************************/
1036 /* Arguments: Requested length */
1037 /* */
1038 /* Returned: New object, or OREF_NULL if requested length was too large */
1039 /******************************************************************************/
1040 {
1041  /* Compute size of new object and determine where we should */
1042  /* allocate from */
1043  requestLength = roundObjectBoundary(requestLength);
1044  RexxObject *newObj = oldSpaceSegments.allocateObject(requestLength);
1045 
1046  /* if we got a new object, then perform the final setup steps. */
1047  /* Since the oldspace objects are special, we don't push them on */
1048  /* to the save stack. Also, we don't set the oldspace flag, as */
1049  /* those are a separate category of object. */
1050  if (newObj != OREF_NULL)
1051  {
1052  // initialize the hash table object
1054  }
1055 
1056  /* return the newly allocated object to our caller */
1057  return newObj;
1058 }
1059 
1060 char *RexxMemory::allocateImageBuffer(size_t imageSize)
1061 /******************************************************************************/
1062 /* Function: Allocate an image buffer for the system code. The image buffer */
1063 /* is allocated in the oldspace segment set. We create an object from that */
1064 /* space, then return this object as a character pointer. We eventually will */
1065 /* get that pointer passed back to us as the image address. */
1066 /******************************************************************************/
1067 {
1068  return (char *)oldObject(imageSize);
1069 }
1070 
1071 
1072 RexxObject *RexxMemory::newObject(size_t requestLength, size_t type)
1073 /******************************************************************************/
1074 /* Arguments: Requested length */
1075 /* */
1076 /* Returned: New object, or OREF_NULL if requested length was too large */
1077 /******************************************************************************/
1078 {
1079  RexxObject *newObj;
1080 
1081  allocations++;
1082 
1083  /* Compute size of new object and determine where we should */
1084  /* allocate from */
1085  requestLength = roundObjectBoundary(requestLength);
1086 
1087  /* is this a typical small object? */
1088  if (requestLength <= LargeBlockThreshold)
1089  {
1090  /* make sure we don't go below our minimum size. */
1091  if (requestLength < MinimumObjectSize)
1092  {
1093  requestLength = MinimumObjectSize;
1094  }
1095  newObj = newSpaceNormalSegments.allocateObject(requestLength);
1096  /* feat. 1061 moves the handleAllocationFailure code into the initial */
1097  /* allocation parts; this way an "if" instruction can be saved. */
1098  if (newObj == NULL)
1099  {
1100  newObj = newSpaceNormalSegments.handleAllocationFailure(requestLength);
1101  }
1102  }
1103  /* we keep the big objects in a separate cage */
1104  else
1105  {
1106  /* round this allocation up to the appropriate large boundary */
1107  requestLength = roundLargeObjectAllocation(requestLength);
1108  newObj = newSpaceLargeSegments.allocateObject(requestLength);
1109  if (newObj == NULL)
1110  {
1111  newObj = newSpaceLargeSegments.handleAllocationFailure(requestLength);
1112  }
1113  }
1114 
1116 
1117  if (this->saveStack != OREF_NULL)
1118  {
1119  /* saveobj doesn't get turned on */
1120  /*until the system is initialized */
1121  /*far enough but once its on, push */
1122  /*this new obj on the save stack to */
1123  /*keep him from being garbage */
1124  /*collected, before it can be used */
1125  /*and safely anchored by caller. */
1126  pushSaveStack(newObj);
1127  }
1128  /* return the newly allocated object to our caller */
1129  return newObj;
1130 }
1131 
1132 
1134  size_t size,
1135  size_t count,
1136  size_t objectType)
1137 /******************************************************************************/
1138 /* Arguments: size of individual objects, */
1139 /* number of objects to get */
1140 /* behaviour of the new objects. */
1141 /* */
1142 /* Function : Return an Array of count objects of size size, with the given */
1143 /* behaviour. Each objects will be cleared */
1144 /* Returned: Array object */
1145 /* */
1146 /******************************************************************************/
1147 {
1148  size_t i;
1149  size_t objSize = roundObjectBoundary(size);
1150  size_t totalSize; /* total size allocated */
1151  RexxObject *prototype; /* our first prototype object */
1152 
1153  RexxArray *arrayOfObjects;
1154  RexxObject *largeObject;
1155 
1156  /* Get array object to contain all the objects.. */
1157  arrayOfObjects = (RexxArray *)new_array(count);
1158 
1159  /* Get one LARGE object, that we will parcel up into the smaller */
1160  /* objects over allocate by the size of one minimum object so we */
1161  /* can handle any potential overallocations */
1162  totalSize = objSize * count; /* first get the total object size */
1163  /* We make the decision on which heap this should be allocated */
1164  /* from based on the size of the object request rather than the */
1165  /* total size of the aggregate object. Since our normal usage of */
1166  /* this is for allocating large collections of small objects, we */
1167  /* don't want those objects coming from the large block heap, */
1168  /* even if the aggregate size would suggest this should happen. */
1169  if (objSize <= LargeBlockThreshold)
1170  {
1171  largeObject = newSpaceNormalSegments.allocateObject(totalSize);
1172  if (largeObject == OREF_NULL)
1173  {
1174  largeObject = newSpaceNormalSegments.handleAllocationFailure(totalSize);
1175  }
1176  }
1177  /* we keep the big objects in a separate cage */
1178  else
1179  {
1180  largeObject = newSpaceLargeSegments.allocateObject(totalSize);
1181  if (largeObject == OREF_NULL)
1182  {
1183  largeObject = newSpaceLargeSegments.handleAllocationFailure(totalSize);
1184  }
1185  }
1186 
1188 
1189  if (this->saveStack != OREF_NULL)
1190  {
1191  /* saveobj doesn't get turned on */
1192  /*until the system is initialized */
1193  /*far enough but once its on, push */
1194  /*this new obj on the save stack to */
1195  /*keep him from being garbage */
1196  /*collected, before it can be used */
1197  /*and safely anchored by caller. */
1198  pushSaveStack(largeObject);
1199  }
1200 
1201  /* Description of defect 318: IH:
1202 
1203  The problem is caused by the constructor of RexxClause which is calling newObjects.
1204  NewObjects allocates one large Object. Immediately after this large Object is allocated,
1205  an array is allocated as well. It then can happen that while allocating the array
1206  the largeObject shall be marked. This causes a trap when objectVariables is != NULL.
1207 
1208  Solution: Set objectVariables to NULL before allocating the array. In order to make
1209  OrefOK (called if CHECKOREF is defined) work properly, the largeObject has to be
1210  set to a valid object state before calling new_array. Therefore the behaviour assignement
1211  and the virtual functions assignement has to be done in advance. */
1212 
1213  /* get the remainder object size...this is used to manage the */
1214  /* dangling piece on the end of the allocation. */
1215  totalSize = largeObject->getObjectSize() - totalSize;
1216 
1217  /* Clear out the entire object... */
1218  largeObject->clearObject();
1219 
1220  prototype = largeObject;
1221 
1222  /* IH: Object gets a valid state for the mark and sweep process. */
1223  /* Otherwise OrefOK (CHECKOREFS) will fail */
1224 
1225  // initialize the hash table object
1226  largeObject->initializeNewObject(objSize, markWord, virtualFunctionTable[objectType], RexxBehaviour::getPrimitiveBehaviour(objectType));
1227 
1228  for (i=1 ;i < count ; i++ )
1229  {
1230  /* IH: Loop one time less than before because first object is initialized
1231  outside of the loop. I had to move the following 2 statements
1232  in front of the object initialization */
1233  /* add this object to the array of objs */
1234  arrayOfObjects->put(largeObject, i);
1235  /* point to the next object space. */
1236  largeObject = (RexxObject *)((char *)largeObject + objSize);
1237  /* copy the information from the prototype */
1238  memcpy(largeObject, prototype, sizeof(RexxInternalObject));
1239  }
1240  arrayOfObjects->put(largeObject, i); /* put the last Object */
1241 
1242  /* adjust the size of the last one to account for any remainder */
1243  largeObject->setObjectSize(totalSize + objSize);
1244 
1245  return arrayOfObjects; /* Return our array of objects. */
1246 }
1247 
1248 
1249 void RexxMemory::reSize(RexxObject *shrinkObj, size_t requestSize)
1250 /******************************************************************************/
1251 /* Function: The object shrinkObj only needs to be the size of newSize */
1252 /* If the left over space is big enough to become a dead object */
1253 /* we will shrink the object to the specified size. */
1254 /* NOTE: Since memory knows nothing about any objects that are */
1255 /* in the extra space, it cannot do anything about them if this */
1256 /* is an OldSpace objetc, therefore the caller must have already */
1257 /* take care of this. */
1258 /* */
1259 /******************************************************************************/
1260 {
1261  DeadObject *newDeadObj;
1262 
1263  size_t newSize = roundObjectResize(requestSize);
1264 
1265  /* is the rounded size smaller and is remainder at least the size */
1266  /* of the smallest OBJ MINOBJSIZE */
1267  if (newSize < requestSize && (shrinkObj->getObjectSize() - newSize) >= MinimumObjectSize)
1268  {
1269  size_t deadObjectSize = shrinkObj->getObjectSize() - newSize;
1270  /* Yes, then we can shrink the object. Get starting point of */
1271  /* the extra, this will be the new Dead obj */
1272  newDeadObj = new ((void *)((char *)shrinkObj + newSize)) DeadObject (deadObjectSize);
1273  /* if an object is larger than 16 MB, the last 8 bits (256) are */
1274  /* truncated and therefore the object must have a size */
1275  /* dividable by 256 and the rest must be put to the dead chain. */
1276  /* If the resulting dead object is smaller than the size we */
1277  /* gave, then we've got a truncated remainder we need to turn */
1278  /* into a dead object. */
1279  deadObjectSize -= newDeadObj->getObjectSize();
1280  if (deadObjectSize != 0)
1281  {
1282  /* create difference object. Note: We don't bother */
1283  /* putting this back on the dead chain. It will be */
1284  /* picked up during the next GC cycle. */
1285  new ((char *)newDeadObj + newDeadObj->getObjectSize()) DeadObject (deadObjectSize);
1286  }
1287  /* Adjust size of original object */
1288  shrinkObj->setObjectSize(newSize);
1289  }
1290 }
1291 
1292 
1294  MemorySegmentSet *requestor, /* the requesting segment set */
1295  size_t allocationLength) /* the size required */
1296 /******************************************************************************/
1297 /* Function: Orchestrate sharing of sharing of storage between the segment */
1298 /* sets in low storage conditions. We do this only as a last ditch, as we'll */
1299 /* end up fragmenting the large heap with small blocks, messing up the */
1300 /* benefits of keeping the heaps separate. We first look a set to donate a */
1301 /* segment to the requesting set. If that doesn't work, we'll borrow a block */
1302 /* of storage from the other set so that we can satisfy this request. */
1303 /******************************************************************************/
1304 {
1305  MemorySegmentSet *donor;
1306 
1307  /* first determine the donor/requester relationships. */
1308  if (requestor->is(MemorySegmentSet::SET_NORMAL))
1309  {
1310  donor = &newSpaceLargeSegments;
1311  }
1312  else
1313  {
1314  donor = &newSpaceNormalSegments;
1315  }
1316 
1317  /* first look for an unused segment. We might be able to steal */
1318  /* one and just move it over. */
1319  MemorySegment *newSeg = donor->donateSegment(allocationLength);
1320  if (newSeg != NULL)
1321  {
1322  requestor->addSegment(newSeg);
1323  return;
1324  }
1325 
1326  /* we can't just move a segment over. Find the smallest block */
1327  /* we can find that will satisfy this allocation. If found, we */
1328  /* can insert it into the normal deadchains. */
1329  DeadObject *largeObject = donor->donateObject(allocationLength);
1330  if (largeObject != NULL)
1331  {
1332  /* we need to insert this into the normal dead chain */
1333  /* locations. */
1334  requestor->addDeadObject(largeObject);
1335  }
1336 }
1337 
1338 
1340 /******************************************************************************/
1341 /* Function: Process a live-stack overflow situation */
1342 /******************************************************************************/
1343 {
1344  /* create a temporary stack */
1345  RexxStack *newLiveStack = new (this->liveStack->size * 2, true) RexxStack (this->liveStack->size * 2);
1346  /* copy the live stack entries */
1347  newLiveStack->copyEntries(this->liveStack);
1348  /* has this already been expanded? */
1349  if (this->liveStack != this->originalLiveStack)
1350  {
1351  free((void *)this->liveStack); /* release the old one */
1352  }
1353  this->liveStack = newLiveStack; /* and set the new stack */
1354 }
1355 
1356 void RexxMemory::mark(RexxObject *markObject)
1357 /******************************************************************************/
1358 /* Function: Perform a memory management mark operation */
1359 /******************************************************************************/
1360 {
1361  size_t liveMark = markWord | OldSpaceBit;
1362 
1363  markObject->setObjectLive(markWord); /* Then Mark this object as live. */
1364  /* object have any references? */
1365  /* if there are no references, we don't */
1366  /* need to push this on the stack, but */
1367  /* we might need to push the behavior */
1368  /* on the stack. Since behaviors are */
1369  /* we can frequently skip that step as well */
1370  if (markObject->hasNoReferences())
1371  {
1372  if (ObjectNeedsMarking(markObject->behaviour))
1373  {
1374  /* mark the behaviour now to keep us from processing this */
1375  /* more than once. */
1376  markObject->behaviour->setObjectLive(markWord);
1377  /* push him to livestack, to mark */
1378  /* later. */
1379  pushLiveStack((RexxObject *)markObject->behaviour);
1380  }
1381  }
1382  else
1383  {
1384  /* push him to livestack, to mark */
1385  /* later. */
1386  pushLiveStack(markObject);
1387  }
1388 }
1389 
1391 /******************************************************************************/
1392 /* Function: Allocate and setup a temporary object obtained via malloc */
1393 /* storage. This is used currently only by the mark routine to */
1394 /* expand the size of the live stack during a garbage collection. */
1395 /******************************************************************************/
1396 {
1397  /* get the rounded size of the object*/
1398  size_t allocationLength = roundObjectBoundary(requestLength);
1399  /* allocate a new object */
1400  RexxObject *newObj = (RexxObject *)malloc(allocationLength);
1401  if (newObj == OREF_NULL) /* unable to allocate a new one? */
1402  {
1403  /* can't allocate, report resource */
1404  /* error. */
1406  }
1407  /* setup the new object header for */
1408  /*use */
1409  // initialize the hash table object
1411  return newObj; /* and return it */
1412 }
1413 
1415 /******************************************************************************/
1416 /* Function: Perform various general marking functions such as image save, */
1417 /* image restore, object unflatten, and debug garbage collection */
1418 /******************************************************************************/
1419 {
1420  RexxObject **pMarkObject = (RexxObject **)obj;
1421  RexxObject *markObject = *pMarkObject;
1422 
1423 
1424  if (markObject == OREF_NULL) /* is this a null reference? */
1425  {
1426  return; /* always return immediately */
1427  }
1428 
1429  /* If its a restore image mark */
1430  if (restoreimage)
1431  {
1432  /* we update the object's location */
1433  restoreMark(markObject, pMarkObject);
1434  return; /* finished */
1435  }
1436 
1437  if (objOffset != 0)
1438  { /* restoring an object? */
1439  /* we update the object's location */
1440  restoreObjectMark(markObject, pMarkObject);
1441  return; /* finished */
1442  }
1443 
1444  if (this->envelope)
1445  { /* processing an envelope? */
1446  /* do the unflatten */
1447  unflattenMark(markObject, pMarkObject);
1448  return; /* and out */
1449  }
1450 
1451 
1452  /* The OrphanCheck code is complete mark from OREF_ENV, which checks the */
1453  /* validity of each object in the entire object tree. Any invalid objects will be */
1454  /* cause the mark to terminate and output information about the invalid object and */
1455  /* its ancestry. */
1456  if ((this->orphanCheck) && !saveimage)
1457  {
1458  /* do the special validity check mark. */
1459  orphanCheckMark(markObject, pMarkObject);
1460  /* all done here, so return */
1461  return;
1462  }
1463 
1464 
1465  if (!saveimage)
1466  {
1467  Interpreter::logicError("Wrong mark routine called");
1468  }
1469 
1470  /* we're doing the image construction work */
1471  saveImageMark(markObject, pMarkObject);
1472 }
1473 
1474 
1475 void RexxMemory::saveImageMark(RexxObject *markObject, RexxObject **pMarkObject)
1476 /******************************************************************************/
1477 /* Function: Perform marking during a save image operation */
1478 /******************************************************************************/
1479 {
1480  RexxObject *bufferReference;
1481  size_t size;
1482  /* Regular GC or Saveimage processing. if a REAL object and not */
1483  /* already marked and not in Old Space. */
1484  if (markObject != OREF_NULL && !markObject->isObjectLive(markWord) && markObject->isNewSpace())
1485  {
1486  /* Then Mark this object as live. */
1487  markObject->setObjectLive(markWord);
1488  /* push him to livestack, so we can mark (at a later time) his */
1489  /* references. */
1490  pushLiveStack(markObject);
1491  /* Get size of this object. */
1492  size = markObject->getObjectSize();
1493  /* add this to our image statistics */
1494  logObjectStats(markObject);
1495 
1496  /* address the copy in the image */
1497  bufferReference = (RexxObject *)(image_buffer + image_offset);
1498  // we allocated a hard coded buffer, so we need to make sure we don't blow
1499  // the buffer size.
1500  if (image_offset + size> MaxImageSize)
1501  {
1502  Interpreter::logicError("Rexx saved image exceeds expected maximum");
1503  }
1504  /* Copy object to image buffer. */
1505  memcpy(bufferReference, markObject, size);
1506  /* clear the mark in the copy */
1507  bufferReference->clearObjectMark();
1508  /* Retrieve the behaviour obj */
1509  behaviour = bufferReference->behaviour;
1510  /* Working with a primitive behaviour or a copy? */
1511  if (behaviour->isNonPrimitive())
1512  {
1513  /* tag this as a non-primitive behav */
1514  bufferReference->setNonPrimitive();
1515  }
1516  else
1517  {
1518  if (behaviour->isTransientClass())
1519  {
1520  Interpreter::logicError("Transient class included in image buffer");
1521  }
1522  /* clear this out, as this is overloaded with the oldspace */
1523  /* flag. */
1524  bufferReference->setPrimitive();
1525  // replace behaviour with normalized type number
1526  bufferReference->behaviour = behaviour->getSavedPrimitiveBehaviour();
1527  }
1528 
1529  /* we are saving image at this point, no need to keep track of */
1530  /* Remembered set so don't use OrefSet here. */
1531  markObject->behaviour = (RexxBehaviour *)image_offset;
1532  /* update image_offset to point to where next object is to be */
1533  /* placed in image */
1534  image_offset += size;
1535  }
1536 
1537  /* If its a saveimage, modify object referencing this "moved" obj */
1538  /* with it location within the image Buffer */
1539  *pMarkObject = (RexxObject *)markObject->behaviour;
1540 }
1541 
1542 
1543 void RexxMemory::orphanCheckMark(RexxObject *markObject, RexxObject **pMarkObject)
1544 /******************************************************************************/
1545 /* Function: Perform orphan check marking on an object */
1546 /******************************************************************************/
1547 {
1548  const char *outFileName;
1549  FILE *outfile;
1550  bool firstnode;
1551  RexxString *className;
1552  const char *objectClassName;
1553 
1554  /* check for invalid objects */
1555  if (!objectReferenceOK(markObject))
1556  {
1557  /* Get a temporary file name for out */
1558  outFileName = SysFileSystem::getTempFileName();
1559  /* Open the temp file for the dump. */
1560  outfile = fopen(outFileName,"wb");
1561  logMemoryCheck(outfile, "Found non Object at %p, being marked from %p\n",markObject, pMarkObject);
1562  /* Let the traversal know we want */
1563  /* more info about first guy... */
1564  firstnode = true;
1565  /* If the object is in object storage*/
1566  if (inObjectStorage(markObject))
1567  {
1568  /* DIsplay a few words of the object's storage. */
1569  logMemoryCheck(outfile, " non-Object dump -->%8.8X %8.8X %8.8X %8.8X \n", *(int32_t *)markObject, *((int32_t *)markObject+1) , *((int32_t *)markObject+2) , *((int32_t *)markObject+3));
1570  logMemoryCheck(outfile, " non-Object dump -->%8.8X %8.8X %8.8X %8.8X \n", *((int32_t *)markObject+4) , *((int32_t *)markObject+5) , *((int32_t *)markObject+6) , *((int32_t *)markObject+7));
1571  logMemoryCheck(outfile, " non-Object dump -->%8.8X %8.8X %8.8X %8.8X \n", *((int32_t *)markObject+8) , *((int32_t *)markObject+9) , *((int32_t *)markObject+10), *((int32_t *)markObject+11));
1572  logMemoryCheck(outfile, " non-Object dump -->%8.8X %8.8X %8.8X %8.8X \n", *((int32_t *)markObject+12), *((int32_t *)markObject+13), *((int32_t *)markObject+14), *((int32_t *)markObject+15));
1573 
1574  }
1575  /* Time to traverse the livestack and get this guy's ancestry--very useful */
1576  /* information for debugging this type of problem. */
1577  for (markObject = popLiveStack();
1578  markObject != OREF_NULL; /* test for unique terminator */
1579  markObject = popLiveStack())
1580  {
1581 
1582  /* OREF_NIL marks an ancestor */
1583  if (markObject == TheNilObject)
1584  {
1585  /* pop the ancestor */
1586  markObject = popLiveStack();
1587  className = markObject->id();
1588  if (className == OREF_NULL)
1589  objectClassName = "";
1590  else
1591  objectClassName = className->getStringData();
1592  if (firstnode)
1593  { /* is this the first node?? */
1594  printf("-->Parent node was marking offset '%u'x \n", (char *)pMarkObject - (char *)markObject);
1595  dumpObject(markObject, outfile);
1596  firstnode = false;
1597  logMemoryCheck(outfile, "Parent node is at %p, of type %s(%d) \n",
1598  markObject, objectClassName, markObject->behaviour->getClassType());
1599  }
1600  else
1601  {
1602  logMemoryCheck(outfile, "Next node is at %p, of type %s(%d) \n",
1603  markObject, objectClassName, markObject->behaviour->getClassType());
1604  }
1605  }
1606  }
1607  /* reached the OREF_NULL sentinel */
1608  logMemoryCheck(outfile, "Finished popping stack !!\n");
1609  printf("All data has been captured in file %s \n", outFileName);
1610  fclose(outfile); /* Close the file, all with it. */
1611  /* Make sure we exit the GC critical */
1612  /* otherwise the cleanup from logic */
1613  /* error will hang !!! */
1614  /* we would have crashed soon anyway!*/
1615  Interpreter::logicError("Bad Object found during GC !\n");
1616  }
1617 
1618  if (!markObject->isObjectLive(markWord) && markObject->isNewSpace())
1619  {
1620  markObject->setObjectLive(markWord); /* Mark this object as live */
1621  /* push him to livestack, so we can */
1622  /*mark (at a later time) his */
1623  /*references. */
1624  pushLiveStack(markObject);
1625  }
1626 }
1627 
1628 
1630 {
1631  /* Remove object form savetable */
1632  saveTable->remove((RexxObject *)obj);
1633  /* no memory section needed */
1634  saveStack->push((RexxObject *)obj);
1635 }
1636 
1637 
1639 /******************************************************************************/
1640 /* Function: Place an object on the hold stack */
1641 /******************************************************************************/
1642 {
1643  /* Push object onto saveStack */
1644  saveStack->push((RexxObject *)obj);
1645  /* return held object */
1646  return (RexxObject *)obj;
1647 }
1648 
1650 /******************************************************************************/
1651 /* Arguments: Maximum and minimum allocations between reclamations */
1652 /******************************************************************************/
1653 {
1654  return OREF_NULL;
1655 }
1656 
1658 /******************************************************************************/
1659 /* Function: Save the memory image as part of interpreter build */
1660 /******************************************************************************/
1661 {
1662  FILE *image;
1663  RexxObject *markObject;
1664  MemoryStats _imageStats;
1665  /* array of objects needed at front */
1666  /*of image for faster restore. */
1667  int i; /* loop counter */
1668  RexxArray *primitive_behaviours; /* saved array of behaviours */
1669  RexxArray *saveArray; /* array of objects needed at front */
1670 
1671  this->imageStats = &_imageStats; /* set the pointer to the current collector */
1672  /* of image for faster restore. */
1673  _imageStats.clear(); /* clear out image counters */
1674 
1675  markReason = SAVINGIMAGE; // this is an image save
1676 
1678  /* memory Object not saved */
1680 
1681  // this has been protecting every thing critical
1682  // from GC events thus far, but now we remove it because
1683  // it contains things we don't want to save in the image.
1685 
1686  /* remove any programs left over in */
1687  /* Get an array to hold all special */
1688  /*objs */
1689  saveArray = new_array(saveArray_highest);
1690  // Note: A this point, we don't have an activity we can use ProtectedObject to save
1691  // this with, so we need to use saveObject();
1692  saveObject(saveArray);
1693  /* Add all elements needed in */
1694  /*saveArray */
1695  saveArray->put((RexxObject *)TheEnvironment, saveArray_ENV);
1696  saveArray->put((RexxObject *)TheKernel, saveArray_KERNEL);
1697  saveArray->put((RexxObject *)TheTrueObject, saveArray_TRUE);
1698  saveArray->put((RexxObject *)TheFalseObject, saveArray_FALSE);
1699  saveArray->put((RexxObject *)TheNilObject, saveArray_NIL);
1700  saveArray->put((RexxObject *)TheNullArray, saveArray_NULLA);
1702  saveArray->put((RexxObject *)TheClassClass, saveArray_CLASS);
1704  saveArray->put((RexxObject *)TheSystem, saveArray_SYSTEM);
1708 
1709  /* create the behaviour array */
1710  primitive_behaviours= (RexxArray *)new_array(T_Last_Exported_Class + 1);
1711  /* copy all of the primitive */
1712  for (i = 0; i <= T_Last_Exported_Class; i++)
1713  {
1714  /* behaviours into this array */
1715  primitive_behaviours->put((RexxObject *)RexxBehaviour::getPrimitiveBehaviour(i), i + 1);
1716  }
1717  /* add to the save array */
1718  saveArray->put(primitive_behaviours, saveArray_PBEHAV);
1719 
1720  image_buffer = (char *)malloc(MaxImageSize);
1721  image_offset = sizeof(size_t);
1722  saveimage = true;
1723  disableOrefChecks(); /* Don't try to check OrefSets now. */
1724  bumpMarkWord();
1725  /* push a unique terminator */
1727  /* don't want to save */
1728  /*savestack/savetabl */
1729  saveStack = OREF_NULL;
1730  /* or any of there references in the */
1731  saveTable = OREF_NULL;
1732  /* image, which will become OldSpace */
1734 
1735  pushLiveStack(OREF_NULL); /* push a unique terminator */
1736  memory_mark_general(saveArray); /* push live root */
1737 
1738  for (markObject = popLiveStack();
1739  markObject != OREF_NULL; /* test for unique terminator */
1740  markObject = popLiveStack())
1741  {
1742  /* The mark of this object moved it */
1743  /*to the image, its behaviour now */
1744  /*contains its offset in the image */
1745  /* so point to the object in the */
1746  /*image. */
1747  /* the buffer copy */
1748  RexxObject *copyObject = (RexxObject *)(image_buffer+(uintptr_t)markObject->behaviour);
1749 
1750  copyObject->liveGeneral(SAVINGIMAGE); /* mark other referenced objs */
1751  /* non-primitive behaviour? */
1752  if (copyObject->isNonPrimitive())
1753  /* mark/move behaviour live */
1754  memory_mark_general(copyObject->behaviour);
1755  }
1756 
1757  image = fopen(BASEIMAGE,"wb");
1758  /* PLace actual size at beginning of buffer*/
1759  memcpy(image_buffer, &image_offset, sizeof(size_t));
1760  /* Write out buffer (image) */
1761  fwrite(image_buffer, 1, image_offset, image);
1762  fclose(image);
1763  free(image_buffer);
1764 
1765  printf("Object stats for this image save are \n");
1766  _imageStats.printSavedImageStats();
1767  printf("\n\n Total bytes for this image %d bytes \n", image_offset);
1768 }
1769 
1770 
1772 /******************************************************************************/
1773 /* Function: Dump the memory tables */
1774 /******************************************************************************/
1775 {
1776 #ifdef _DEBUG
1777  FILE *dumpfile;
1778  FILE *keyfile;
1780  int i;
1781 
1782  if (dumpEnable)
1783  {
1784  /* don't allow another dump unless */
1785  /*reset by user */
1786  memoryObject.dumpEnable = false;
1787  /* first generate the dump by writing*/
1788  /* each segment to the dumpfile */
1789  printf("Dumping object memory to orexdump.dmp\n");
1790  /* open for binary write */
1791  dumpfile = fopen("orexdump.dmp","wb");
1792  /* now generate the key file which */
1793  /*is a series of REXX statements */
1794  printf("Creating dump key file in orexdump.key\n");
1795  /* open for text write */
1796  keyfile = fopen("orexdump.key","w");
1797  fprintf(keyfile, "/* Object REXX dump key file */\n");
1798  fprintf(keyfile, "memoryaddr = %p\n", this);
1799  fprintf(keyfile, "marker = %d\n", markWord);
1800  /* dump the oldspace segments */
1801  oldSpaceSegments.dumpSegments(keyfile, dumpfile);
1802  /* followed by the newer allocations */
1803  newSpaceNormalSegments.dumpSegments(keyfile, dumpfile);
1804  newSpaceLargeSegments.dumpSegments(keyfile, dumpfile);
1805 
1806  i = 0;
1807  while (currentPool)
1808  {
1809  i++;
1810  fprintf(keyfile, "Pool addr.%d = %p\n", i, currentPool);
1811  fprintf(keyfile, "Pool size.%d = %d\n", i, currentPool->reserved);
1813  }
1814 
1815  for (i = 0; i <= T_Last_Exported_Class; i++)
1816  {
1817  fprintf(keyfile, "Behaviour type %d = %p\n", i, RexxBehaviour::getPrimitiveBehaviour(i));
1818  }
1819 
1820  /* now close actual dump and key file*/
1821  fclose(dumpfile);
1822  fclose(keyfile);
1823  }
1824 #endif
1825  return OREF_NULL;
1826 }
1827 
1828 
1830 /******************************************************************************/
1831 /* Arguments: selection, 0 for no, anything else for yes */
1832 /* */
1833 /* Returned: Nothing */
1834 /******************************************************************************/
1835 {
1836  if (selection != OREF_NULL)
1837  {
1839  }
1840  return selection;
1841 }
1842 
1844 /******************************************************************************/
1845 /* Arguments: None */
1846 /* */
1847 /* Returned: Nothing */
1848 /******************************************************************************/
1849 {
1850  wholenumber_t count, testcount;
1851  HashLink j;
1852  bool restoreimagesave;
1853  RexxInteger *value;
1854  RexxInteger *testValue;
1855  RexxObject *index;
1856  /* temp OREF used to hold original */
1857  /*and test versions */
1858  RexxIdentityTable *tempold2new;
1859 
1860  printf("Comparing old2new with the current system.\n");
1861 
1862  /* build a test remembered set */
1863  tempold2new = new_identity_table();
1864  restoreimagesave = restoreimage;
1865  restoreimage = true; /* setting both of these to true will*/
1866  /* traverse System OldSpace and live */
1867  /*mark all objects */
1869 
1870  restoreimage = restoreimagesave; /* all done building remembered set */
1871  /* For all object in old2new table */
1872  for (j = old2new->first();
1873  (index = (RexxObject *)old2new->index(j)) != OREF_NULL;
1874  j = old2new->next(j))
1875  {
1876  /* Get refCount for this obj old2new */
1877  value = (RexxInteger *)this->old2new->get(index);
1878  /* new refcount for obj in newly */
1879  /*build old2new table */
1880  testValue = (RexxInteger *)tempold2new->get(index);
1881  /* Was object found in new table? */
1882  if (testValue == OREF_NULL)
1883  {
1884  /* nope, extra stuff in orig. */
1885  printf("object: %p, type: %d, is extra in old2new.\n\n",
1886  index, index->behaviour->getClassType());
1887  }
1888  else
1889  {
1890  /* now make sure both refCounts are */
1891  /* the same. */
1892  count = value->getValue();
1893  testcount = testValue->getValue();
1894  if (count != testcount)
1895  {
1896  printf("object: %p, type: %d, has an incorrect refcount.\n",
1897  index, index->behaviour->getClassType());
1898  printf("Refcount for object is %d, should be %d.\n\n", count, testcount);
1899  }
1900  /* now remove object from new table */
1901  tempold2new->remove(index);
1902  }
1903  }
1904  /* Anything left in new table was */
1905  /* missing from original old2new */
1906  /* so iterate through it and report */
1907  /* the missing objects */
1908  for (j = tempold2new->first();
1909  (index = (RexxObject *)tempold2new->index(j)) != OREF_NULL;
1910  j = tempold2new->next(j))
1911  {
1912  printf("object: %p, type: %d, is missing from old2new.\n\n",
1913  index,index->behaviour->getClassType());
1914  }
1915 
1916  /* now take a dump so that we can */
1917  /* diagnose any problems we just */
1918  /*uncovered */
1919  printf("Dumping object memory.\n"); /* tell the user what's happening */
1920  this->dumpEnable = true; /* turn dumps on */
1921  this->dump(); /* take the dump */
1922 
1923  return OREF_NULL;
1924 }
1925 
1926 
1927 void RexxMemory::setObjectOffset(size_t offset)
1928 /******************************************************************************/
1929 /* Arguments: offset, the length to add to references within arriving objects*/
1930 /* since only one unflattem can happen at a time, we need to ensure */
1931 /* serialization, so if already have an objOffset, wait unto done. */
1932 /* */
1933 /* Returned: Nothing */
1934 /******************************************************************************/
1935 {
1936  /* Starting or ending? */
1937  if (offset != 0)
1938  {
1939 
1940  /* have a value, starting unflatten. See if we can get MUTEX */
1941  /* immed */
1943  {
1944  {
1945  UnsafeBlock releaser;
1946  /* wait for current unflatten to end */
1948  }
1949  }
1950  }
1951  else
1952  {
1953  /* no value, ending an unflatten */
1954  /* Release the MUTEX. */
1956  }
1957 
1958  /* setup offSet value. */
1959  this->objOffset = offset;
1960 }
1961 
1963 /******************************************************************************/
1964 /* Arguments: envelope object, */
1965 /* since only one unflattem can happen at a time, we need to ensure */
1966 /* serialization, so if already have an envelope, wait unto done. */
1967 /* */
1968 /* Returned: Nothing */
1969 /******************************************************************************/
1970 {
1971  /* Starting or ending? */
1972  if (_envelope != OREF_NULL)
1973  {
1974  /* have a value, starting unflatt */
1975  /* See if we can get MUTEX immed */
1977  {
1978  /* Nope, have to wait for it. */
1979  /* release kernel access. */
1980  {
1981  UnsafeBlock releaser;
1982  envelopeMutex.request(); /* wait for current unflat to end */
1983  }
1984  }
1985  }
1986  else
1987  {
1988  /* no value, ending an unflatten */
1989  envelopeMutex.release(); /* Release the MUTEX. */
1990  }
1991 
1992  this->envelope = _envelope; /* set the envelope object */
1993 }
1994 
1995 
1997 /******************************************************************************/
1998 /* Arguments: index-- OREF to set; value--OREF to which objr is set */
1999 /* */
2000 /* Returned: nothing */
2001 /* */
2002 /******************************************************************************/
2003 {
2004  RexxInteger *refcount;
2005  RexxObject **oldValueLoc = (RexxObject **)oldValue;
2006  RexxObject *index = *oldValueLoc;
2007 
2008  if (old2new != OREF_NULL)
2009  {
2010  if (index != OREF_NULL && index->isNewSpace())
2011  {
2012  /* decrement reference count for */
2014  refcount = (RexxInteger *)this->old2new->get(index);
2015  if (refcount != OREF_NULL)
2016  {
2017  /* found a value for refcount, now */
2018  /*decrement the count */
2019  refcount->decrementValue();
2020  /* if the new value is 0, *index is */
2021  /*no longer ref'ed from oldspace */
2022  if (refcount->getValue() == 0)
2023  {
2024  /* delete the entry for *index */
2025  this->old2new->remove(index);
2026  }
2027  }
2028  else
2029  {
2030  /* naughty, naughty, someone didn't use SetOref */
2031  printf("******** error in memory_setoref, unable to decrement refcount\n");
2032  printf("Naughty object reference is from: %p\n", oldValueLoc);
2033  printf("Naughty object reference is at: %p\n", index);
2034  printf("Naughty object reference type is: %d\n", (index)->behaviour->getClassType());
2035  }
2036  }
2037  if (value != OREF_NULL && value->isNewSpace())
2038  {
2039  /* increment reference count for */
2040  /*value */
2041  refcount = (RexxInteger *)this->old2new->get(value);
2042  /* was there a reference here */
2043  /*already? */
2044  if (refcount)
2045  {
2046  /* yep, found one, so just increment */
2047  /*it */
2048  refcount->incrementValue();
2049  }
2050  else
2051  {
2052  /* nope, this is the first, so set */
2053  /*the refcount to 1 */
2054  // NOTE: We don't use new_integer here because we need a mutable
2055  // integer and can't use the one out of the cache.
2056  this->old2new->put(new RexxInteger(1), value);
2057  }
2058  }
2059  }
2060  /* now make the assignment, just */
2061  /*like all this stuff never happened!*/
2062  return *oldValueLoc = value;
2063 }
2064 
2065 
2067  RexxObject *setter,
2068  RexxObject **index,
2069  RexxObject *value,
2070  const char *fileName,
2071  int lineNum)
2072 /******************************************************************************/
2073 /* Arguments: index-- OREF to set; value--OREF to which objr is set */
2074 /* */
2075 /* Returned: nothing */
2076 /* */
2077 /******************************************************************************/
2078 {
2079  bool allOK = true;
2080  const char *outFileName;
2081  FILE *outfile;
2082  /* Skip all checks during saveimage */
2083  if (checkSetOK)
2084  { /* and initial part of restore Image */
2085  if (!inObjectStorage(setter))
2086  { /* Is the setter object invalid */
2087  allOK = false; /* No, just put out setters addr. */
2088  outFileName = SysFileSystem::getTempFileName();/* Get a temporary file name for out */
2089  outfile = fopen(outFileName,"wb");
2090  logMemoryCheck(outfile, "The Setter object at %p is invalid...\n");
2091 
2092  /* Is the new value a real object? */
2093  }
2095  {
2096  allOK = false; /* No, put out the info */
2097  outFileName = SysFileSystem::getTempFileName();/* Get a temporary file name for out */
2098  outfile = fopen(outFileName,"wb");
2099  logMemoryCheck(outfile, "The Setter object at %p attempted to put a non object %p, at offset %p\n",setter, value, (char *)index - (char *)setter);
2100  logMemoryCheck(outfile, " A dump of the Setting object follows: \n");
2101  dumpObject(setter, outfile);
2102 
2103  }
2104  else if (index >= (RexxObject **)((char *)setter + setter->getObjectSize()))
2105  {
2106  allOK = false; /* Yes, let them know */
2107  outFileName = SysFileSystem::getTempFileName();/* Get a temporary file name for out */
2108  outfile = fopen(outFileName,"wb");
2109  logMemoryCheck(outfile, "The Setter object at %p has tried to store at offset, which is outside his object range\n",setter, (char *)index - (char *)setter);
2110  logMemoryCheck(outfile, " A dump of the Setting object follows: \n");
2111  dumpObject(setter, outfile);
2112  }
2113 
2114 
2115  }
2116 
2117  if (!allOK)
2118  {
2119  logMemoryCheck(outfile, " The error occurred in line %u of file %s\n", lineNum, fileName);
2120  printf("The dump data has been written to file %s \n",outFileName);
2121  fclose(outfile);
2122  Interpreter::logicError("Something went really wrong in SetOref ...\n");
2123  }
2124  /* now do the normal SetOref() stuff */
2125  return(setter->isOldSpace() ? (this->setOref(index, value)) : (*index = value));
2126 
2127 }
2128 
2130 /******************************************************************************/
2131 /* Function: Allocate and lock the flatten stack capability. */
2132 /******************************************************************************/
2133 {
2135  {
2136  /* Nope, have to wait for it. */
2137  /* release kernel access. */
2138  {
2139  UnsafeBlock releaser;
2140  flattenMutex.request(); /* wait for current flattento end */
2141  }
2142  }
2143  /* create a temporary stack */
2144  this->flattenStack = new (LiveStackSize, true) RexxStack (LiveStackSize);
2145  return this->flattenStack; /* return flatten Stack */
2146 }
2147 
2149 /******************************************************************************/
2150 /* Function: Release the flatten stack */
2151 /******************************************************************************/
2152 {
2153  free((void *)this->flattenStack); /* release the flatten stack */
2154  this->flattenMutex.release(); /* and release the semaphore */
2155 }
2156 
2158 /******************************************************************************/
2159 /* */
2160 /******************************************************************************/
2161 {
2162  MemoryStats _imageStats;
2163 
2164  /* clear all of the statistics */
2165  _imageStats.clear();
2166  /* gather a fresh set of stats for all of the segments */
2167  newSpaceNormalSegments.gatherStats(&_imageStats, &_imageStats.normalStats);
2168  newSpaceLargeSegments.gatherStats(&_imageStats, &_imageStats.largeStats);
2169 
2170  /* print out the memory statistics */
2171  _imageStats.printMemoryStats();
2172  return TheNilObject;
2173 }
2174 
2175 
2183 {
2184  currentPool = pool;
2185 }
2186 
2187 
2189 /******************************************************************************/
2190 /* Function: Free all the memory pools currently accessed by this process */
2191 /* If not already released. Then set process Pool to NULL, indicate */
2192 /* pools have been released. */
2193 /******************************************************************************/
2194 {
2195  MemorySegmentPool *pool = firstPool;
2196  while (pool != NULL)
2197  {
2198  // save the one we're about to release, and get the next one.
2199  MemorySegmentPool *releasedPool = pool;
2200  pool = pool->nextPool();
2201  // go free this pool up
2202  releasedPool->freePool();
2203  }
2204  // clear out the memory pool information
2205  firstPool = NULL;
2206  currentPool = NULL;
2207 }
2208 
2209 
2211 /******************************************************************************/
2212 /* Function: Set up the initial memory table. */
2213 /******************************************************************************/
2214 {
2215  /* fix up the previously allocated live stack to have the correct */
2216  /* characteristics...we're almost ready to go on the air. */
2219  /* set up the old 2 new table provided for us */
2220  old2new = old2newTable;
2221  /* if we have a table (this is NULL if we're not running from a */
2222  /* restored image), then add the first entry to the table. */
2223  if (old2new != NULL)
2224  {
2225  /* now add old2new itself to the old2new table! */
2226  // NOTE: We don't use new_integer here because we need a mutable
2227  // integer and can't use the one out of the cache.
2228  old2new->put(new RexxInteger(1), old2new);
2229  }
2230  /* first official OrefSet!! */
2231  OrefSet(this, markTable, old2new);
2232  /* Now get our savestack and savetable */
2233  /* allocate savestack with usable and allocated size */
2234  /* NOTE: We do not use OREF_SET here. We want to control the */
2235  /* order in which these two are marked in the live(size_t) method of */
2236  /* RexxMemory. If these are added to the mark table, they'll be */
2237  /* processed earlier than we'd like. */
2239  /* from this point on, we push things on to the save stack */
2241 }
2242 
2244 /******************************************************************************/
2245 /* Function: Do the initial lock creation for memory setup. */
2246 /******************************************************************************/
2247 {
2248  /* Create/Open Shared MUTEX */
2249  /* Semophores used to serialize */
2250  /* the flatten/unflatten process */
2251  flattenMutex.create();
2254 }
2255 
2257 /******************************************************************************/
2258 /* Function: Do the initial lock creation for memory setup. */
2259 /******************************************************************************/
2260 {
2261  /* Create/Open Shared MUTEX */
2262  /* Semophores used to serialize */
2263  /* the flatten/unflatten process */
2264  flattenMutex.close();
2266  envelopeMutex.close();
2267 }
2268 
2269 
2278 {
2279  // see if we have a global table. If not collecting currently,
2280  // just return the non-unique value
2281 
2282  RexxString *stringValue = new_string(value);
2283  if (globalStrings == OREF_NULL)
2284  {
2285  return stringValue; /* just return the string */
2286  }
2287 
2288  // now see if we have this string in the table already
2290  if (result != OREF_NULL)
2291  {
2292  return result; // return the previously created one
2293  }
2294  /* add this to the table */
2296  return stringValue; // return the newly created one
2297 }
2298 
2299 
2301 /******************************************************************************/
2302 /* Function: Initial memory setup during image build */
2303 /******************************************************************************/
2304 {
2305  RexxClass::createInstance(); /* get the CLASS class created */
2307  /* Now get our savestack and */
2308  /*savetable */
2310  /* Create/Open Shared MUTEX */
2311  /* Semophores used to serialize */
2312  /* the flatten/unflatten process */
2314 }
2315 
2316 
2318 /******************************************************************************/
2319 /* Function: Memory management image restore functions */
2320 /******************************************************************************/
2321 {
2322  /* Retrieve special saved objects */
2323  /* OREF_ENV and primitive behaviours */
2324  /* are already restored */
2325  /* start restoring class OREF_s */
2326  RESTORE_CLASS(Object, RexxClass);
2327  RESTORE_CLASS(Class, RexxClass);
2328  /* (CLASS is already restored) */
2329  RESTORE_CLASS(String, RexxClass);
2330  RESTORE_CLASS(Array, RexxClass);
2331  RESTORE_CLASS(Directory, RexxClass);
2332  RESTORE_CLASS(Integer, RexxIntegerClass);
2333  RESTORE_CLASS(List, RexxClass);
2334  RESTORE_CLASS(Message, RexxClass);
2335  RESTORE_CLASS(Method, RexxClass);
2336  RESTORE_CLASS(Routine, RexxClass);
2337  RESTORE_CLASS(Package, RexxClass);
2339  RESTORE_CLASS(NumberString, RexxClass);
2340  RESTORE_CLASS(Queue, RexxClass);
2341  RESTORE_CLASS(Stem, RexxClass);
2342  RESTORE_CLASS(Supplier, RexxClass);
2343  RESTORE_CLASS(Table, RexxClass);
2344  RESTORE_CLASS(IdentityTable, RexxClass);
2345  RESTORE_CLASS(Relation, RexxClass);
2346  RESTORE_CLASS(MutableBuffer, RexxMutableBufferClass);
2347  RESTORE_CLASS(Pointer, RexxClass);
2348  RESTORE_CLASS(Buffer, RexxClass);
2350  RESTORE_CLASS(StackFrame, RexxClass);
2351 
2352  memoryObject.setOldSpace(); /* Mark Memory Object as OldSpace */
2353  /* initialize the tables used for garbage collection. */
2355  /* If first one through, generate all*/
2356  IntegerZero = new_integer(0); /* static integers we want to use...*/
2357  IntegerOne = new_integer(1); /* This will allow us to use static */
2358  IntegerTwo = new_integer(2); /* integers instead of having to do a*/
2359  IntegerThree = new_integer(3); /* new_integer evrytime.... */
2360  IntegerFour = new_integer(4);
2361  IntegerFive = new_integer(5);
2362  IntegerSix = new_integer(6);
2365  IntegerNine = new_integer(9);
2367 
2368  // the activity manager will create the local server, which will use the
2369  // stream classes. We need to get the external libraries reloaded before
2370  // that happens.
2372  ActivityManager::init(); /* do activity restores */
2373  PackageManager::restore(); // finish restoration of the packages.
2374  memoryObject.enableOrefChecks(); /* enable setCheckOrefs... */
2375 }
2376 
RexxMemory::variableCache
RexxVariable * variableCache
Definition: RexxMemory.hpp:294
RexxMemory::globalStrings
static RexxDirectory * globalStrings
Definition: RexxMemory.hpp:404
SysMutex::create
void create()
Definition: SysSemaphore.cpp:238
TheKernel
#define TheKernel
Definition: RexxCore.h:177
MemoryStats::largeStats
SegmentStats largeStats
Definition: MemoryStats.hpp:109
RexxMemory::dumpObject
void dumpObject(RexxObject *objectRef, FILE *outfile)
Definition: RexxMemory.cpp:251
RexxMemory::inSharedObjectStorage
bool inSharedObjectStorage(RexxObject *obj)
Definition: RexxMemory.cpp:269
new_array
RexxArray * new_array(size_t s)
Definition: ArrayClass.hpp:250
RexxBehaviour::getSavedPrimitiveBehaviour
RexxBehaviour * getSavedPrimitiveBehaviour()
Definition: RexxBehaviour.hpp:116
DeadObject
Definition: DeadObject.hpp:59
RexxMemory::checkWeakReferences
void checkWeakReferences()
Definition: RexxMemory.cpp:666
RexxHashTableCollection::index
RexxObject * index(HashLink pos)
Definition: RexxCollection.hpp:90
RexxMemory::logObjectStats
void logObjectStats(RexxObject *obj)
Definition: RexxMemory.hpp:255
MemorySegmentSet::dumpSegments
void dumpSegments(FILE *keyfile, FILE *dumpfile)
Definition: MemorySegment.cpp:120
RexxHashTableCollection::next
HashLink next(HashLink pos)
Definition: RexxCollection.hpp:88
NormalSegmentSet::handleAllocationFailure
RexxObject * handleAllocationFailure(size_t allocationLength)
Definition: MemorySegment.cpp:1263
RexxArray
Definition: ArrayClass.hpp:100
RexxInternalObject::setNonPrimitive
void setNonPrimitive()
Definition: ObjectClass.hpp:244
Interpreter::live
static void live(size_t)
Definition: Interpreter.cpp:83
RexxMemory::clearSaveStack
void clearSaveStack()
Definition: RexxMemory.hpp:260
SysAccessPool
bool SysAccessPool(MemorySegmentPool **pool)
IntegerFive
#define IntegerFive
Definition: RexxCore.h:193
RexxMemory::saveArray_COMMON_RETRIEVERS
Definition: RexxMemory.hpp:326
MemorySegmentSet::donateSegment
virtual MemorySegment * donateSegment(size_t allocationLength)
Definition: MemorySegment.cpp:558
RexxObject::initializeNewObject
void initializeNewObject(size_t size, size_t mark, void *vft, RexxBehaviour *b)
Definition: ObjectClass.hpp:340
RexxMemory::saveArray_FALSE
Definition: RexxMemory.hpp:316
RexxMemory
Definition: RexxMemory.hpp:169
RexxMemory::markGeneral
void markGeneral(void *)
Definition: RexxMemory.cpp:1414
RexxObject::truthValue
bool truthValue(int)
Definition: ObjectClass.cpp:468
RexxInternalObject
Definition: ObjectClass.hpp:206
TheFalseObject
#define TheFalseObject
Definition: RexxCore.h:184
SystemInterpreter::loadImage
static void loadImage(char **imageBuffer, size_t *imageSize)
Definition: FileSystem.cpp:142
RexxInternalObject::getObjectType
RexxBehaviour * getObjectType()
Definition: ObjectClass.hpp:261
RexxMemory::protectedObjects
GlobalProtectedObject * protectedObjects
Definition: RexxMemory.hpp:295
RexxMemory::newObject
RexxObject * newObject(size_t size)
Definition: RexxMemory.hpp:190
MemoryStats::normalStats
SegmentStats normalStats
Definition: MemoryStats.hpp:108
MethodClass.hpp
RexxStack::size
size_t size
Definition: StackClass.hpp:80
RexxMemory::memoryPoolAdded
void memoryPoolAdded(MemorySegmentPool *)
Definition: RexxMemory.cpp:2182
new_proxy
RexxString * new_proxy(const char *name)
Definition: StringClass.hpp:567
RexxMemory::collections
size_t collections
Definition: RexxMemory.hpp:401
SysFileSystem.hpp
PackageClass.hpp
WeakReferenceClass.hpp
RexxMemory::verboseMessage
void verboseMessage(const char *message)
Definition: RexxMemory.hpp:237
RexxMemory::logVerboseOutput
void logVerboseOutput(const char *message, void *sub1, void *sub2)
Definition: RexxMemory.cpp:231
BASEIMAGE
#define BASEIMAGE
Definition: PlatformDefinitions.h:144
new_integer
RexxInteger * new_integer(wholenumber_t v)
Definition: IntegerClass.hpp:198
RexxInternalObject::isNewSpace
bool isNewSpace()
Definition: ObjectClass.hpp:253
memory_mark_general
#define memory_mark_general(oref)
Definition: RexxMemory.hpp:437
memoryObject
RexxMemory memoryObject
Definition: RexxMemory.cpp:84
RexxHashTableCollection::empty
RexxObject * empty()
Definition: RexxCollection.cpp:517
RESTORE_CLASS
#define RESTORE_CLASS(name, className)
Definition: RexxMemory.cpp:78
RexxInternalObject::behaviour
RexxBehaviour * behaviour
Definition: ObjectClass.hpp:306
RexxMemory::saveArray_NAME_STRINGS
Definition: RexxMemory.hpp:314
RexxActivation.hpp
type
int type
Definition: cmdparse.cpp:1965
OrefSet
#define OrefSet(o, r, v)
Definition: RexxCore.h:94
RexxMemory::allocations
size_t allocations
Definition: RexxMemory.hpp:400
RexxInternalObject::setPrimitive
void setPrimitive()
Definition: ObjectClass.hpp:243
T_Object
Definition: ClassTypeCodes.h:57
LiveStackSize
#define LiveStackSize
Definition: RexxMemory.cpp:86
RexxInteger::createInstance
static void createInstance()
Definition: IntegerClass.cpp:1276
RexxMemory::processingUninits
bool processingUninits
Definition: RexxMemory.hpp:376
TheCommonRetrievers
#define TheCommonRetrievers
Definition: RexxCore.h:176
RexxInteger::incrementValue
wholenumber_t incrementValue()
Definition: IntegerClass.hpp:144
RexxMemory::RexxMemory
RexxMemory()
Definition: RexxMemory.cpp:117
RexxMemory::collectAndUninit
void collectAndUninit(bool clearStack)
Definition: RexxMemory.cpp:479
SaveStackAllocSize
#define SaveStackAllocSize
Definition: RexxMemory.cpp:89
RexxMemory::newSpaceLargeSegments
LargeSegmentSet newSpaceLargeSegments
Definition: RexxMemory.hpp:382
IntegerClass.hpp
RexxMemory::temporaryObject
RexxObject * temporaryObject(size_t size)
Definition: RexxMemory.cpp:1390
RexxBehaviour::primitiveBehaviours
static RexxBehaviour primitiveBehaviours[]
Definition: RexxBehaviour.hpp:146
RexxMemory::system
static RexxDirectory * system
Definition: RexxMemory.hpp:301
RexxContext
Definition: ContextClass.hpp:53
MemorySegmentSet::addDeadObject
virtual void addDeadObject(DeadObject *object)
Definition: MemorySegment.cpp:350
LargeSegmentSet
Definition: MemorySegment.hpp:546
RexxInternalObject::hasNoReferences
bool hasNoReferences()
Definition: ObjectClass.hpp:242
ActivityManager.hpp
SupplierClass.hpp
RexxMemory::dumpImageStats
RexxObject * dumpImageStats()
Definition: RexxMemory.cpp:2157
GlobalProtectedObject.hpp
PointerClass.hpp
RexxMemory::createLocks
static void createLocks()
Definition: RexxMemory.cpp:2243
RexxMemory::initialize
void initialize(bool restoringImage)
Definition: RexxMemory.cpp:160
IntegerSeven
#define IntegerSeven
Definition: RexxCore.h:195
RexxActivity::run
void run()
Definition: RexxActivity.cpp:1384
RexxMemory::saveArray_CLASS
Definition: RexxMemory.hpp:319
RexxMemory::addUninitObject
void addUninitObject(RexxObject *obj)
Definition: RexxMemory.cpp:589
RexxIdentityTable::put
virtual RexxObject * put(RexxObject *, RexxObject *)
Definition: IdentityTableClass.cpp:139
RexxMemory::markWord
size_t markWord
Definition: RexxMemory.hpp:292
RexxMemory::bumpMarkWord
void bumpMarkWord()
Definition: RexxMemory.hpp:334
ActivityManager::init
static void init()
Definition: ActivityManager.cpp:79
RexxBehaviour::getClassType
size_t getClassType()
Definition: RexxBehaviour.hpp:101
CHAR_KERNEL
char CHAR_KERNEL[]
RexxMemory::newSegment
MemorySegment * newSegment(size_t requestLength, size_t minLength)
Definition: RexxMemory.cpp:713
RexxMemory::disableOrefChecks
void disableOrefChecks()
Definition: RexxMemory.hpp:258
RexxMemory::saveArray_ENV
Definition: RexxMemory.hpp:312
RexxMemory::currentPool
MemorySegmentPool * currentPool
Definition: RexxMemory.hpp:379
RexxPointer
Definition: PointerClass.hpp:49
RexxHashTableCollection::items
HashLink items()
Definition: RexxCollection.hpp:86
RexxObject::id
RexxString * id()
Definition: ObjectClass.cpp:2240
UnsafeBlock
Definition: ActivityManager.hpp:280
RexxStack::copyEntries
void copyEntries(RexxStack *other)
Definition: StackClass.hpp:78
RexxDirectory::at
RexxObject * at(RexxString *)
Definition: DirectoryClass.cpp:567
TableClass.hpp
RexxMemory::virtualFunctionTable
static void * virtualFunctionTable[]
Definition: RexxMemory.hpp:289
reportException
void reportException(wholenumber_t error)
Definition: ActivityManager.hpp:136
TheObjectBehaviour
#define TheObjectBehaviour
Definition: PrimitiveBehaviourNames.h:52
LIVEMARK
Definition: RexxMemory.hpp:115
T_Last_Class_Type
Definition: ClassTypeCodes.h:200
RexxInternalObject::setOldSpace
void setOldSpace()
Definition: ObjectClass.hpp:255
RexxIntegerClass
Definition: IntegerClass.hpp:176
MemorySegmentPool
Definition: RexxMemory.hpp:140
RexxMemory::envelope
RexxEnvelope * envelope
Definition: RexxMemory.hpp:396
MaxImageSize
#define MaxImageSize
Definition: RexxMemory.cpp:91
RexxMemory::newObjects
RexxArray * newObjects(size_t size, size_t count, size_t objectType)
Definition: RexxMemory.cpp:1133
TheClassClass
#define TheClassClass
Definition: RexxCore.h:149
roundObjectBoundary
size_t roundObjectBoundary(size_t n)
Definition: RexxMemory.hpp:95
MemorySegmentSet::isInSegmentSet
bool isInSegmentSet(RexxObject *object)
Definition: MemorySegment.hpp:296
LargeSegmentSet::allocateObject
RexxObject * allocateObject(size_t allocationLength)
Definition: MemorySegment.hpp:556
RexxMemory::objectReferenceOK
bool objectReferenceOK(RexxObject *o)
Definition: RexxMemory.cpp:318
TheTrueObject
#define TheTrueObject
Definition: RexxCore.h:185
MutableBufferClass.hpp
RexxString::getStringData
const char * getStringData()
Definition: StringClass.hpp:333
RexxMemory::saveArray_NULLPOINTER
Definition: RexxMemory.hpp:323
NormalSegmentSet
Definition: MemorySegment.hpp:386
RexxIdentityTable::get
virtual RexxObject * get(RexxObject *key)
Definition: IdentityTableClass.cpp:111
RexxMemory::saveObject
RexxObject * saveObject(RexxInternalObject *saveObj)
Definition: RexxMemory.hpp:208
RexxMemory::pushSaveStack
void pushSaveStack(RexxObject *obj)
Definition: RexxMemory.hpp:256
RexxEnvelope
Definition: RexxEnvelope.hpp:53
RexxInternalObject::clearObject
void clearObject()
Definition: ObjectClass.hpp:231
PackageManager::live
static void live(size_t liveMark)
Definition: PackageManager.cpp:156
RexxInternalObject::isObjectDead
bool isObjectDead(size_t mark)
Definition: ObjectClass.hpp:251
MemorySegmentPool::createPool
static MemorySegmentPool * createPool()
Definition: MemorySupport.cpp:82
IntegerZero
#define IntegerZero
Definition: RexxCore.h:188
MemorySegmentOverhead
#define MemorySegmentOverhead
Definition: MemorySegment.hpp:52
MemorySegmentSet::is
bool is(SegmentSetID id)
Definition: MemorySegment.hpp:311
ObjectNeedsMarking
#define ObjectNeedsMarking(oref)
Definition: RexxMemory.hpp:435
RexxArray::get
RexxObject * get(size_t pos)
Definition: ArrayClass.hpp:201
SysMutex::close
void close()
Definition: SysSemaphore.cpp:287
RexxMemory::dumpMemoryProfile
void dumpMemoryProfile()
Definition: RexxMemory.cpp:239
RexxMemory.hpp
RexxMemory::restore
static void restore()
Definition: RexxMemory.cpp:2317
IntegerMinusOne
#define IntegerMinusOne
Definition: RexxCore.h:198
new_identity_table
RexxIdentityTable * new_identity_table()
Definition: IdentityTableClass.hpp:74
RexxMemory::markObjects
void markObjects(void)
Definition: RexxMemory.cpp:615
RexxBehaviour
Definition: RexxBehaviour.hpp:49
Interpreter.hpp
RexxBehaviour::getPrimitiveBehaviour
static RexxBehaviour * getPrimitiveBehaviour(size_t index)
Definition: RexxBehaviour.hpp:143
OldSpaceSegmentSet
Definition: MemorySegment.hpp:597
MemorySegmentPool::freePool
void freePool(void)
Definition: MemorySupport.cpp:278
RexxMemory::orphanCheck
bool orphanCheck
Definition: RexxMemory.hpp:392
logMemoryCheck
static void logMemoryCheck(FILE *outfile, const char *message,...)
Definition: RexxMemory.cpp:105
RexxMemory::checkSetOK
bool checkSetOK
Definition: RexxMemory.hpp:389
SystemInterpreter::liveGeneral
static void liveGeneral(int reason)
Definition: SystemInterpreter.cpp:169
RexxMemory::allocateImageBuffer
char * allocateImageBuffer(size_t size)
Definition: RexxMemory.cpp:1060
RexxMemory::buildVirtualFunctionTable
static void buildVirtualFunctionTable()
Definition: VirtualFunctionTable.cpp:169
RexxInternalObject::getObjectSize
size_t getObjectSize()
Definition: ObjectClass.hpp:224
PackageManager::liveGeneral
static void liveGeneral(int reason)
Definition: PackageManager.cpp:167
RexxHashTableCollection::first
HashLink first()
Definition: RexxCollection.hpp:87
roundSegmentBoundary
size_t roundSegmentBoundary(size_t n)
Definition: MemorySegment.hpp:118
RexxMutableBufferClass
Definition: MutableBufferClass.hpp:54
RexxInteger::decrementValue
wholenumber_t decrementValue()
Definition: IntegerClass.hpp:145
RexxMemory::unflattenMutex
static SysMutex unflattenMutex
Definition: RexxMemory.hpp:406
RexxMemory::holdObject
RexxObject * holdObject(RexxInternalObject *obj)
Definition: RexxMemory.cpp:1638
RexxInternalObject::setObjectSize
void setObjectSize(size_t s)
Definition: ObjectClass.hpp:225
RexxMemory::restoreImage
void restoreImage()
Definition: RexxMemory.cpp:790
RexxMemory::pendingUninits
size_t pendingUninits
Definition: RexxMemory.hpp:375
RexxMemory::unflattenMark
void unflattenMark(RexxObject *markObject, RexxObject **pMarkObject)
Definition: RexxMemory.hpp:340
new_string
RexxString * new_string(const char *s, stringsize_t l)
Definition: StringClass.hpp:524
MemorySegment
Definition: MemorySegment.hpp:143
MemorySegmentPoolHeader::reserved
size_t reserved
Definition: RexxMemory.hpp:137
RexxMemory::saveStrings
static RexxArray * saveStrings()
Definition: GlobalNames.cpp:64
SystemInterpreter.hpp
RexxMemory::environment
static RexxDirectory * environment
Definition: RexxMemory.hpp:297
RexxHashTableCollection::value
RexxObject * value(HashLink pos)
Definition: RexxCollection.hpp:89
RexxInteger::getValue
RexxObject * getValue(RexxActivation *)
Definition: IntegerClass.cpp:1162
SystemInterpreter::live
static void live(size_t)
Definition: SystemInterpreter.cpp:165
RexxBehaviour::isTransientClass
bool isTransientClass()
Definition: RexxBehaviour.hpp:108
OREF_NULL
#define OREF_NULL
Definition: RexxCore.h:60
NormalSegmentSet::getInitialSet
void getInitialSet()
Definition: MemorySegment.cpp:239
ArrayClass.hpp
RexxMemory::shutdown
void shutdown()
Definition: RexxMemory.cpp:2188
TheSystem
#define TheSystem
Definition: RexxCore.h:178
RexxActivity
Definition: RexxActivity.hpp:127
RexxMemory::checkUninit
void checkUninit()
Definition: RexxMemory.cpp:441
RexxArray::put
void put(RexxObject *eref, size_t pos)
Definition: ArrayClass.cpp:203
RexxMemory::saveArray_FUNCTIONS
Definition: RexxMemory.hpp:325
Error_System_resources
#define Error_System_resources
Definition: RexxErrorCodes.h:67
RexxMemory::enableOrefChecks
void enableOrefChecks()
Definition: RexxMemory.hpp:259
RexxDirectory
Definition: DirectoryClass.hpp:49
IntegerTwo
#define IntegerTwo
Definition: RexxCore.h:190
RexxSaveStack
Definition: StackClass.hpp:85
RexxMemory::saveArray_KERNEL
Definition: RexxMemory.hpp:313
RexxMemory::saveArray_highest
Definition: RexxMemory.hpp:327
RexxClass
Definition: ClassClass.hpp:49
RexxStack
Definition: StackClass.hpp:47
RexxInternalObject::setBehaviour
void setBehaviour(RexxBehaviour *b)
Definition: ObjectClass.hpp:265
RexxMemory::functionsDir
static RexxDirectory * functionsDir
Definition: RexxMemory.hpp:298
RexxMemory::saveArray_NIL
Definition: RexxMemory.hpp:317
OldSpaceBit
Definition: ObjectClass.hpp:74
IntegerThree
#define IntegerThree
Definition: RexxCore.h:191
SaveStackSize
#define SaveStackSize
Definition: RexxMemory.cpp:88
RexxMemory::uninitTable
RexxIdentityTable * uninitTable
Definition: RexxMemory.hpp:374
RexxMemory::closeLocks
static void closeLocks()
Definition: RexxMemory.cpp:2256
MessageClass.hpp
MemoryStats::clear
void clear()
Definition: MemoryStats.cpp:149
RexxMemory::restoreObjectMark
void restoreObjectMark(RexxObject *markObject, RexxObject **pMarkObject)
Definition: RexxMemory.hpp:345
GlobalProtectedObject::next
GlobalProtectedObject * next
Definition: GlobalProtectedObject.hpp:145
StringClass.hpp
SegmentDeadSpace
#define SegmentDeadSpace
Definition: MemorySegment.hpp:73
StackFrameClass.hpp
RexxMemory::weakReferenceList
WeakReference * weakReferenceList
Definition: RexxMemory.hpp:402
RexxInternalObject::isOldSpace
bool isOldSpace()
Definition: ObjectClass.hpp:252
RexxMemory::restoreStrings
static void restoreStrings(RexxArray *stringArray)
Definition: GlobalNames.cpp:92
RexxMemory::setParms
RexxObject * setParms(RexxObject *, RexxObject *)
Definition: RexxMemory.cpp:1649
RexxMemory::saveArray_SYSTEM
Definition: RexxMemory.hpp:324
RexxMemory::liveGeneral
void liveGeneral(int reason)
Definition: RexxMemory.cpp:936
RexxClass::createInstance
static void createInstance()
Definition: ClassClass.cpp:1678
RexxMemory::runUninits
void runUninits()
Definition: RexxMemory.cpp:507
IntegerSix
#define IntegerSix
Definition: RexxCore.h:194
SysMutex
Definition: SysSemaphore.hpp:73
SysMutex::request
void request()
Definition: SysSemaphore.hpp:81
MemoryStats
Definition: MemoryStats.hpp:97
RexxMemory::originalLiveStack
RexxStack * originalLiveStack
Definition: RexxMemory.hpp:397
RexxInternalObject::isNonPrimitive
bool isNonPrimitive()
Definition: ObjectClass.hpp:246
RexxMemory::saveStack
RexxSaveStack * saveStack
Definition: RexxMemory.hpp:368
OldSpaceSegmentSet::markOldSpaceObjects
void markOldSpaceObjects()
Definition: MemorySegment.cpp:1796
RexxMemory::newLargeSegment
MemorySegment * newLargeSegment(size_t requestLength, size_t minLength)
Definition: RexxMemory.cpp:753
ActivityManager::liveGeneral
static void liveGeneral(int reason)
Definition: ActivityManager.cpp:101
RexxMemory::discardHoldObject
void discardHoldObject(RexxInternalObject *obj)
Definition: RexxMemory.cpp:1629
TheEnvironment
#define TheEnvironment
Definition: RexxCore.h:173
RexxMemory::createImage
static void createImage()
Definition: Setup.cpp:132
MemorySegmentPool::newLargeSegment
MemorySegment * newLargeSegment(size_t minSize)
Definition: MemorySupport.cpp:229
RexxMemory::killOrphans
void killOrphans(RexxObject *)
Definition: RexxMemory.cpp:376
IntegerOne
#define IntegerOne
Definition: RexxCore.h:189
RexxMemory::setUpMemoryTables
void setUpMemoryTables(RexxIdentityTable *old2newTable)
Definition: RexxMemory.cpp:2210
RexxMemory::popLiveStack
RexxObject * popLiveStack()
Definition: RexxMemory.hpp:333
RexxDirectory::put
RexxObject * put(RexxObject *, RexxString *)
Definition: DirectoryClass.cpp:636
RexxIdentityTable::remove
virtual RexxObject * remove(RexxObject *key)
Definition: IdentityTableClass.cpp:95
StackClass.hpp
RexxMemory::oldSpaceSegments
OldSpaceSegmentSet oldSpaceSegments
Definition: RexxMemory.hpp:380
RexxMemory::old2new
RexxIdentityTable * old2new
Definition: RexxMemory.hpp:373
SAVINGIMAGE
Definition: RexxMemory.hpp:117
memory_mark
#define memory_mark(oref)
Definition: RexxMemory.hpp:436
RexxMemory::saveImageMark
void saveImageMark(RexxObject *markObject, RexxObject **pMarkObject)
Definition: RexxMemory.cpp:1475
RexxMemory::saveArray_PACKAGES
Definition: RexxMemory.hpp:321
Interpreter::init
static void init()
Definition: Interpreter.cpp:77
LargeSegmentSet::dumpMemoryProfile
virtual void dumpMemoryProfile(FILE *outfile)
Definition: MemorySegment.cpp:142
HashLink
size_t HashLink
Definition: RexxHashTable.hpp:49
Interpreter::liveGeneral
static void liveGeneral(int reason)
Definition: Interpreter.cpp:90
RexxMemory::firstPool
MemorySegmentPool * firstPool
Definition: RexxMemory.hpp:378
IntegerEight
#define IntegerEight
Definition: RexxCore.h:196
TheStackBehaviour
#define TheStackBehaviour
Definition: PrimitiveBehaviourNames.h:170
SysMutex::requestImmediate
bool requestImmediate()
Definition: SysSemaphore.hpp:83
ActivityManager::live
static void live(size_t)
Definition: ActivityManager.cpp:86
WeakReference::referentObject
RexxObject * referentObject
Definition: WeakReferenceClass.hpp:84
MemorySegmentSet::donateObject
virtual DeadObject * donateObject(size_t allocationLength)
Definition: MemorySegment.cpp:518
TheFunctionsDirectory
#define TheFunctionsDirectory
Definition: RexxCore.h:175
MinimumObjectSize
#define MinimumObjectSize
Definition: RexxMemory.hpp:85
TheMemoryBehaviour
#define TheMemoryBehaviour
Definition: PrimitiveBehaviourNames.h:168
RexxStack::push
RexxObject * push(RexxObject *obj)
Definition: StackClass.hpp:63
RexxMemory::dumpEnable
bool dumpEnable
Definition: RexxMemory.hpp:386
MemorySegmentSet::sweep
void sweep()
Definition: MemorySegment.cpp:1106
RexxMemory::mark
void mark(RexxObject *)
Definition: RexxMemory.cpp:1356
MemorySegmentPool::nextPool
MemorySegmentPool * nextPool()
Definition: RexxMemory.hpp:159
wholenumber_t
ssize_t wholenumber_t
Definition: rexx.h:229
RexxMemory::liveStackFull
void liveStackFull()
Definition: RexxMemory.cpp:1339
RexxStack::init
void init(size_t)
Definition: StackClass.cpp:60
GlobalProtectedObject
Definition: GlobalProtectedObject.hpp:46
MemorySegmentPool::newSegment
MemorySegment * newSegment(size_t minSize)
Definition: MemorySupport.cpp:184
RexxMemory::setOref
RexxObject * setOref(void *index, RexxObject *value)
Definition: RexxMemory.cpp:1996
RexxMemory::kernel
static RexxDirectory * kernel
Definition: RexxMemory.hpp:300
RexxMemory::setEnvelope
void setEnvelope(RexxEnvelope *)
Definition: RexxMemory.cpp:1962
RexxMemory::saveArray_PBEHAV
Definition: RexxMemory.hpp:320
RexxInternalObject::setObjectLive
void setObjectLive(size_t markword)
Definition: ObjectClass.hpp:238
TheNullArray
#define TheNullArray
Definition: RexxCore.h:182
RexxMemory::orphanCheckMark
void orphanCheckMark(RexxObject *markObject, RexxObject **pMarkObject)
Definition: RexxMemory.cpp:1543
RexxTable::replace
RexxObject * replace(RexxObject *newValue, HashLink pos)
Definition: TableClass.hpp:62
RexxMemory::getGlobalName
static RexxString * getGlobalName(const char *value)
Definition: RexxMemory.cpp:2277
MemoryStats::printMemoryStats
void printMemoryStats()
Definition: MemoryStats.cpp:105
RexxBehaviour::isNonPrimitive
bool isNonPrimitive()
Definition: RexxBehaviour.hpp:103
RexxMemory::markObjectsMain
void markObjectsMain(RexxObject *)
Definition: RexxMemory.cpp:341
roundObjectResize
size_t roundObjectResize(size_t n)
Definition: RexxMemory.hpp:97
RexxMemory::saveImage
void saveImage()
Definition: RexxMemory.cpp:1657
RexxMemory::imageStats
MemoryStats * imageStats
Definition: RexxMemory.hpp:398
RexxMemory::dump
RexxObject * dump()
Definition: RexxMemory.cpp:1771
RexxMemory::setObjectOffset
void setObjectOffset(size_t offset)
Definition: RexxMemory.cpp:1927
RexxMemory::lastChanceUninit
void lastChanceUninit()
Definition: RexxMemory.cpp:497
RexxMemory::envelopeMutex
static SysMutex envelopeMutex
Definition: RexxMemory.hpp:407
RexxMemory::live
void live(size_t)
Definition: RexxMemory.cpp:902
RESTORINGIMAGE
Definition: RexxMemory.hpp:116
RexxMemory::commonRetrievers
static RexxDirectory * commonRetrievers
Definition: RexxMemory.hpp:299
RexxMemory::oldObject
RexxObject * oldObject(size_t size)
Definition: RexxMemory.cpp:1034
PackageManager::restore
static void restore()
Definition: PackageManager.cpp:125
NormalSegmentSet::allocateObject
RexxObject * allocateObject(size_t allocationLength)
Definition: MemorySegment.hpp:395
IntegerFour
#define IntegerFour
Definition: RexxCore.h:192
TheNilObject
#define TheNilObject
Definition: RexxCore.h:180
ActivityManager::currentActivity
static RexxActivity *volatile currentActivity
Definition: ActivityManager.hpp:95
RexxMemory::markTable
RexxTable * markTable
Definition: RexxMemory.hpp:370
RexxInternalObject::hasReferences
bool hasReferences()
Definition: ObjectClass.hpp:241
RexxMemory::saveTable
RexxIdentityTable * saveTable
Definition: RexxMemory.hpp:369
RexxBehaviour::restore
void restore(RexxBehaviour *)
Definition: RexxBehaviour.cpp:426
OldSpaceSegmentSet::allocateObject
RexxObject * allocateObject(size_t allocationLength)
Definition: MemorySegment.cpp:1401
RexxMemory::relocation
size_t relocation
Definition: RexxMemory.hpp:385
RexxMemory::restoreMark
void restoreMark(RexxObject *markObject, RexxObject **pMarkObject)
Definition: RexxMemory.hpp:335
Error_Logical_value_method
#define Error_Logical_value_method
Definition: RexxErrorCodes.h:273
RexxMemory::isPendingUninit
bool isPendingUninit(RexxObject *obj)
Definition: RexxMemory.cpp:606
DeadObject::getObjectSize
size_t getObjectSize()
Definition: DeadObject.hpp:85
RexxIdentityTable
Definition: IdentityTableClass.hpp:49
RexxInternalObject::clearObjectMark
void clearObjectMark()
Definition: ObjectClass.hpp:249
T_Last_Exported_Class
Definition: ClassTypeCodes.h:106
WeakReference::nextReferenceList
WeakReference * nextReferenceList
Definition: WeakReferenceClass.hpp:85
RexxActivity.hpp
RexxMemory::checkSetOref
RexxObject * checkSetOref(RexxObject *, RexxObject **, RexxObject *, const char *, int)
Definition: RexxMemory.cpp:2066
RexxMemory::reclaim
RexxObject * reclaim()
Definition: RexxMemory.cpp:989
roundLargeObjectAllocation
size_t roundLargeObjectAllocation(size_t n)
Definition: RexxMemory.hpp:96
RexxMemory::saveimage
bool saveimage
Definition: RexxMemory.hpp:387
RexxMemory::restoreimage
bool restoreimage
Definition: RexxMemory.hpp:388
IntegerNine
#define IntegerNine
Definition: RexxCore.h:197
RexxMemory::inObjectStorage
bool inObjectStorage(RexxObject *obj)
Definition: RexxMemory.cpp:299
LargeBlockThreshold
#define LargeBlockThreshold
Definition: MemorySegment.hpp:64
RexxMemory::scavengeSegmentSets
void scavengeSegmentSets(MemorySegmentSet *requester, size_t allocationLength)
Definition: RexxMemory.cpp:1293
RexxMemory::objOffset
size_t objOffset
Definition: RexxMemory.hpp:393
T_Behaviour
Definition: ClassTypeCodes.h:111
RexxMemory::getFlattenStack
RexxStack * getFlattenStack()
Definition: RexxMemory.cpp:2129
RexxObject::liveGeneral
void liveGeneral(int reason)
Definition: ObjectClass.cpp:86
RexxMemory::saveArray_NULLA
Definition: RexxMemory.hpp:322
LargeSegmentSet::handleAllocationFailure
RexxObject * handleAllocationFailure(size_t allocationLength)
Definition: MemorySegment.cpp:1331
RexxMemory::newSpaceNormalSegments
NormalSegmentSet newSpaceNormalSegments
Definition: RexxMemory.hpp:381
RexxBehaviour::restoreSavedPrimitiveBehaviour
static RexxBehaviour * restoreSavedPrimitiveBehaviour(RexxBehaviour *b)
Definition: RexxBehaviour.hpp:129
RexxActivity::initializeThreadContext
static void initializeThreadContext()
Definition: RexxActivity.cpp:1702
TheBehaviourBehaviour
#define TheBehaviourBehaviour
Definition: PrimitiveBehaviourNames.h:101
RexxCore.h
RexxMemory::markReason
int markReason
Definition: RexxMemory.hpp:293
CHAR_MEMORY
char CHAR_MEMORY[]
DirectoryClass.hpp
RexxMemory::gutCheck
RexxObject * gutCheck()
Definition: RexxMemory.cpp:1843
MemorySegmentSet::gatherStats
void gatherStats(MemoryStats *memStats, SegmentStats *stats)
Definition: MemorySegment.cpp:1756
RexxMemory::image_offset
size_t image_offset
Definition: RexxMemory.hpp:384
RexxMemory::image_buffer
char * image_buffer
Definition: RexxMemory.hpp:383
RelationClass.hpp
Interpreter::logicError
static void logicError(const char *desc)
Definition: Interpreter.cpp:553
MemorySegmentSet
Definition: MemorySegment.hpp:227
RexxMemory::makeProxy
RexxObject * makeProxy(RexxEnvelope *)
Definition: RexxMemory.cpp:968
PackageManager::getImageData
static RexxArray * getImageData()
Definition: PackageManager.cpp:93
RexxMemory::flatten
void flatten(RexxEnvelope *)
Definition: RexxMemory.cpp:958
RexxMemory::create
static void create()
Definition: RexxMemory.cpp:2300
RexxInternalObject::stringValue
virtual RexxString * stringValue()
Definition: ObjectClass.cpp:1028
RexxInteger
Definition: IntegerClass.hpp:56
RexxMemory::pushLiveStack
void pushLiveStack(RexxObject *obj)
Definition: RexxMemory.hpp:332
RexxMemory::collect
void collect()
Definition: RexxMemory.cpp:1001
SysFileSystem::getTempFileName
static const char * getTempFileName()
Definition: SysFileSystem.cpp:168
RexxObject::live
void live(size_t)
Definition: ObjectClass.cpp:78
RexxMemory::setDump
RexxObject * setDump(RexxObject *)
Definition: RexxMemory.cpp:1829
UninitDispatcher
Definition: UninitDispatcher.hpp:52
RexxMemory::saveArray_TRUE
Definition: RexxMemory.hpp:315
RexxInternalObject::isObjectLive
bool isObjectLive(size_t mark)
Definition: ObjectClass.hpp:250
SysMutex::release
void release()
Definition: SysSemaphore.hpp:82
WeakReference
Definition: WeakReferenceClass.hpp:54
BufferClass.hpp
NormalSegmentSet::dumpMemoryProfile
virtual void dumpMemoryProfile(FILE *outfile)
Definition: MemorySegment.cpp:153
RexxMemory::reSize
void reSize(RexxObject *, size_t)
Definition: RexxMemory.cpp:1249
UninitDispatcher.hpp
MemorySegmentSet::addSegment
void addSegment(MemorySegment *segment, bool createDeadObject=1)
Definition: MemorySegment.cpp:473
RexxObject
Definition: ObjectClass.hpp:311
GlobalProtectedObject::protectedObject
RexxObject * protectedObject
Definition: GlobalProtectedObject.hpp:144
PackageManager.hpp
RexxMemory::flattenStack
RexxStack * flattenStack
Definition: RexxMemory.hpp:367
MemorySegmentSet::SET_NORMAL
Definition: MemorySegment.hpp:231
RexxMemory::flattenMutex
static SysMutex flattenMutex
Definition: RexxMemory.hpp:405
RexxMemory::addWeakReference
void addWeakReference(WeakReference *ref)
Definition: RexxMemory.cpp:702
RexxString
Definition: StringClass.hpp:119
RexxMemory::removeUninitObject
void removeUninitObject(RexxObject *obj)
Definition: RexxMemory.cpp:578
TheNullPointer
#define TheNullPointer
Definition: RexxCore.h:186
RexxMemory::liveStack
RexxStack * liveStack
Definition: RexxMemory.hpp:366
RexxMemory::returnFlattenStack
void returnFlattenStack()
Definition: RexxMemory.cpp:2148
MemoryStats::printSavedImageStats
void printSavedImageStats()
Definition: MemoryStats.cpp:90