Rick, I think this adds an otherwise unused `void memoryError()`
declaration in RexxMemory.hpp
On Sun, Aug 26, 2018 at 11:48 PM, bigrixx--- via Oorexx-svn <
oorexx-...@lists.sourceforge.net> wrote:
> Revision: 11488
> http://sourceforge.net/p/oorexx/code-0/11488
> Author: bigrixx
> Date: 2018-08-26 21:48:23 +0000 (Sun, 26 Aug 2018)
> Log Message:
> -----------
> rework liveStack expansion to avoid crashes
>
> Modified Paths:
> --------------
> main/trunk/interpreter/behaviour/ClassTypeCodes.h
> main/trunk/interpreter/behaviour/PrimitiveBehaviourNames.h
> main/trunk/interpreter/behaviour/PrimitiveBehaviours.cpp
> main/trunk/interpreter/behaviour/PrimitiveClasses.xml
> main/trunk/interpreter/behaviour/VirtualFunctionTable.cpp
> main/trunk/interpreter/classes/ArrayClass.cpp
> main/trunk/interpreter/classes/support/HashContents.cpp
> main/trunk/interpreter/classes/support/ListContents.cpp
> main/trunk/interpreter/memory/Envelope.cpp
> main/trunk/interpreter/memory/Memory.hpp
> main/trunk/interpreter/memory/MemorySegment.cpp
> main/trunk/interpreter/memory/MemoryStack.cpp
> main/trunk/interpreter/memory/MemoryStack.hpp
> main/trunk/interpreter/memory/RexxMemory.cpp
> main/trunk/interpreter/memory/RexxMemory.hpp
>
> Modified: main/trunk/interpreter/behaviour/ClassTypeCodes.h
> ===================================================================
> --- main/trunk/interpreter/behaviour/ClassTypeCodes.h 2018-08-22
> 21:51:20 UTC (rev 11487)
> +++ main/trunk/interpreter/behaviour/ClassTypeCodes.h 2018-08-26
> 21:48:23 UTC (rev 11488)
> @@ -240,38 +240,37 @@
>
> T_Memory = 174,
> T_InternalStack = 175,
> - T_LiveStack = 176,
> - T_PushThroughStack = 177,
> - T_Activity = 178,
> - T_Activation = 179,
> - T_NativeActivation = 180,
> - T_ActivationFrameBuffer = 181,
> - T_Envelope = 182,
> - T_LanguageParser = 183,
> - T_Clause = 184,
> - T_Token = 185,
> - T_DoBlock = 186,
> - T_InterpreterInstance = 187,
> - T_SecurityManager = 188,
> - T_CommandHandler = 189,
> - T_MapBucket = 190,
> - T_MapTable = 191,
> - T_TrapHandler = 192,
> - T_CommandIOContext = 193,
> - T_StemOutputTarget = 194,
> - T_StreamObjectOutputTarget = 195,
> - T_StreamOutputTarget = 196,
> - T_CollectionOutputTarget = 197,
> - T_BufferingOutputTarget = 198,
> - T_StemInputSource = 199,
> - T_StreamObjectInputSource = 200,
> - T_StreamInputSource = 201,
> - T_ArrayInputSource = 202,
> - T_RexxQueueOutputTarget = 203,
> + T_PushThroughStack = 176,
> + T_Activity = 177,
> + T_Activation = 178,
> + T_NativeActivation = 179,
> + T_ActivationFrameBuffer = 180,
> + T_Envelope = 181,
> + T_LanguageParser = 182,
> + T_Clause = 183,
> + T_Token = 184,
> + T_DoBlock = 185,
> + T_InterpreterInstance = 186,
> + T_SecurityManager = 187,
> + T_CommandHandler = 188,
> + T_MapBucket = 189,
> + T_MapTable = 190,
> + T_TrapHandler = 191,
> + T_CommandIOContext = 192,
> + T_StemOutputTarget = 193,
> + T_StreamObjectOutputTarget = 194,
> + T_StreamOutputTarget = 195,
> + T_CollectionOutputTarget = 196,
> + T_BufferingOutputTarget = 197,
> + T_StemInputSource = 198,
> + T_StreamObjectInputSource = 199,
> + T_StreamInputSource = 200,
> + T_ArrayInputSource = 201,
> + T_RexxQueueOutputTarget = 202,
>
> - T_Last_Transient_Class = 203,
> - T_Last_Primitive_Class = 203,
> - T_Last_Class_Type = 203,
> + T_Last_Transient_Class = 202,
> + T_Last_Primitive_Class = 202,
> + T_Last_Class_Type = 202,
>
> } ClassTypeCode;
>
>
> Modified: main/trunk/interpreter/behaviour/PrimitiveBehaviourNames.h
> ===================================================================
> --- main/trunk/interpreter/behaviour/PrimitiveBehaviourNames.h
> 2018-08-22 21:51:20 UTC (rev 11487)
> +++ main/trunk/interpreter/behaviour/PrimitiveBehaviourNames.h
> 2018-08-26 21:48:23 UTC (rev 11488)
> @@ -225,7 +225,6 @@
> #define TheAddressWithInstructionBehaviour (&RexxBehaviour::
> primitiveBehaviours[T_AddressWithInstruction])
> #define TheMemoryBehaviour (&RexxBehaviour::
> primitiveBehaviours[T_Memory])
> #define TheInternalStackBehaviour (&RexxBehaviour::
> primitiveBehaviours[T_InternalStack])
> -#define TheLiveStackBehaviour (&RexxBehaviour::
> primitiveBehaviours[T_LiveStack])
> #define ThePushThroughStackBehaviour (&RexxBehaviour::
> primitiveBehaviours[T_PushThroughStack])
> #define TheActivityBehaviour (&RexxBehaviour::primitiveBehaviours[T_
> Activity])
> #define TheActivationBehaviour (&RexxBehaviour::
> primitiveBehaviours[T_Activation])
>
> Modified: main/trunk/interpreter/behaviour/PrimitiveBehaviours.cpp
> ===================================================================
> --- main/trunk/interpreter/behaviour/PrimitiveBehaviours.cpp
> 2018-08-22 21:51:20 UTC (rev 11487)
> +++ main/trunk/interpreter/behaviour/PrimitiveBehaviours.cpp
> 2018-08-26 21:48:23 UTC (rev 11488)
> @@ -235,7 +235,6 @@
> RexxBehaviour(T_AddressWithInstruction, (PCPPM
> *)RexxObject::operatorMethods),
> RexxBehaviour(T_Memory, (PCPPM *)RexxObject::operatorMethods),
> RexxBehaviour(T_InternalStack, (PCPPM *)RexxObject::operatorMethods),
> - RexxBehaviour(T_LiveStack, (PCPPM *)RexxObject::operatorMethods),
> RexxBehaviour(T_PushThroughStack, (PCPPM
> *)RexxObject::operatorMethods),
> RexxBehaviour(T_Activity, (PCPPM *)RexxObject::operatorMethods),
> RexxBehaviour(T_Activation, (PCPPM *)RexxObject::operatorMethods),
>
> Modified: main/trunk/interpreter/behaviour/PrimitiveClasses.xml
> ===================================================================
> --- main/trunk/interpreter/behaviour/PrimitiveClasses.xml
> 2018-08-22 21:51:20 UTC (rev 11487)
> +++ main/trunk/interpreter/behaviour/PrimitiveClasses.xml
> 2018-08-26 21:48:23 UTC (rev 11488)
> @@ -226,7 +226,6 @@
> <Transient>
> <Class id="Memory" class="MemoryObject" include="RexxMemory.hpp"
> objectvirtual="true"/>
> <Class id="InternalStack" class="InternalStack"
> include="InternalStack.hpp"/>
> -<Class id="LiveStack" class="LiveStack" include="MemoryStack.hpp"/>
> <Class id="PushThroughStack" class="PushThroughStack"
> include="MemoryStack.hpp"/>
> <Class id="Activity" class="Activity" include="Activity.hpp"/>
> <Class id="Activation" class="RexxActivation"
> include="RexxActivation.hpp"/>
>
> Modified: main/trunk/interpreter/behaviour/VirtualFunctionTable.cpp
> ===================================================================
> --- main/trunk/interpreter/behaviour/VirtualFunctionTable.cpp
> 2018-08-22 21:51:20 UTC (rev 11487)
> +++ main/trunk/interpreter/behaviour/VirtualFunctionTable.cpp
> 2018-08-26 21:48:23 UTC (rev 11488)
> @@ -734,9 +734,6 @@
> objectPtr = ::new (objectLoc) InternalStack(RESTOREIMAGE);
> virtualFunctionTable[T_InternalStack] = getVftPointer(objectLoc);
>
> - objectPtr = ::new (objectLoc) LiveStack(RESTOREIMAGE);
> - virtualFunctionTable[T_LiveStack] = getVftPointer(objectLoc);
> -
> objectPtr = ::new (objectLoc) PushThroughStack(RESTOREIMAGE);
> virtualFunctionTable[T_PushThroughStack] = getVftPointer(objectLoc);
>
>
> Modified: main/trunk/interpreter/classes/ArrayClass.cpp
> ===================================================================
> --- main/trunk/interpreter/classes/ArrayClass.cpp 2018-08-22
> 21:51:20 UTC (rev 11487)
> +++ main/trunk/interpreter/classes/ArrayClass.cpp 2018-08-26
> 21:48:23 UTC (rev 11488)
> @@ -281,8 +281,10 @@
> // add in the max size value. Note that we subtract one since
> // the first item is contained in the base object allocation.
> bytes += sizeof(RexxInternalObject *) * (maxSize - 1);
> - // now allocate the new object with that size.
> - ArrayClass *newArray = (ArrayClass *)new_object(bytes, type);
> + // now allocate the new object with that size. We also give a hint to
> + // the language process about how many objects we can potentially
> mark during
> + // a garbage collection.
> + ArrayClass *newArray = (ArrayClass *)new_object(bytes, type, maxSize);
>
> // now fill in the various control bits. Ideally, this
> // really should be done in the constructor, but that gets really too
>
> Modified: main/trunk/interpreter/classes/support/HashContents.cpp
> ===================================================================
> --- main/trunk/interpreter/classes/support/HashContents.cpp
> 2018-08-22 21:51:20 UTC (rev 11487)
> +++ main/trunk/interpreter/classes/support/HashContents.cpp
> 2018-08-26 21:48:23 UTC (rev 11488)
> @@ -1,7 +1,7 @@
> /*----------------------------------------------------------
> ------------------*/
> /*
> */
> /* Copyright (c) 1995, 2004 IBM Corporation. All rights reserved.
> */
> -/* Copyright (c) 2005-2014 Rexx Language Association. All rights
> reserved. */
> +/* Copyright (c) 2005-2018 Rexx Language Association. All rights
> reserved. */
> /*
> */
> /* This program and the accompanying materials are made available under
> */
> /* the terms of the Common Public License v1.0 which accompanies this
> */
> @@ -62,7 +62,7 @@
> size_t bytes = size + (sizeof(ContentEntry) * (capacity - 1));
>
> // now allocate the suggested bucket size
> - return new_object(bytes, T_IdentityHashContents);
> + return new_object(bytes, T_IdentityHashContents, capacity * 2);
> }
>
>
> @@ -79,7 +79,7 @@
> size_t bytes = size + (sizeof(ContentEntry) * (capacity - 1));
>
> // now allocate the suggested bucket size
> - return new_object(bytes, T_EqualityHashContents);
> + return new_object(bytes, T_EqualityHashContents, capacity * 2);
> }
>
>
> @@ -96,7 +96,7 @@
> size_t bytes = size + (sizeof(ContentEntry) * (capacity - 1));
>
> // now allocate the suggested bucket size
> - return new_object(bytes, T_MultiValueContents);
> + return new_object(bytes, T_MultiValueContents, capacity * 2);
> }
>
>
> @@ -113,7 +113,7 @@
> size_t bytes = size + (sizeof(ContentEntry) * (capacity - 1));
>
> // now allocate the suggested bucket size
> - return new_object(bytes, T_StringHashContents);
> + return new_object(bytes, T_StringHashContents, capacity * 2);
> }
>
>
>
> Modified: main/trunk/interpreter/classes/support/ListContents.cpp
> ===================================================================
> --- main/trunk/interpreter/classes/support/ListContents.cpp
> 2018-08-22 21:51:20 UTC (rev 11487)
> +++ main/trunk/interpreter/classes/support/ListContents.cpp
> 2018-08-26 21:48:23 UTC (rev 11488)
> @@ -1,7 +1,7 @@
> /*----------------------------------------------------------
> ------------------*/
> /*
> */
> /* Copyright (c) 1995, 2004 IBM Corporation. All rights reserved.
> */
> -/* Copyright (c) 2005-2014 Rexx Language Association. All rights
> reserved. */
> +/* Copyright (c) 2005-2018 Rexx Language Association. All rights
> reserved. */
> /*
> */
> /* This program and the accompanying materials are made available under
> */
> /* the terms of the Common Public License v1.0 which accompanies this
> */
> @@ -60,7 +60,7 @@
> */
> void *ListContents::operator new(size_t size, size_t initialSize)
> {
> - return new_object(size + sizeof(ListEntry) * (initialSize - 1),
> T_ListContents);
> + return new_object(size + sizeof(ListEntry) * (initialSize - 1),
> T_ListContents, initialSize);
> }
>
>
>
> Modified: main/trunk/interpreter/memory/Envelope.cpp
> ===================================================================
> --- main/trunk/interpreter/memory/Envelope.cpp 2018-08-22 21:51:20 UTC
> (rev 11487)
> +++ main/trunk/interpreter/memory/Envelope.cpp 2018-08-26 21:48:23 UTC
> (rev 11488)
> @@ -80,7 +80,6 @@
> memory_mark(saveTable);
> memory_mark(buffer);
> memory_mark(rehashTable);
> - memory_mark(flattenStack);
> }
>
>
> @@ -87,8 +86,6 @@
> /**
> * Generalized object marking
> *
> - * NOTE: Do not mark flattenStack
> - *
> * @param reason The reason for the marking call.
> */
> void Envelope::liveGeneral(MarkReason reason)
> @@ -99,7 +96,6 @@
> memory_mark_general(saveTable);
> memory_mark_general(buffer);
> memory_mark_general(rehashTable);
> - memory_mark_general(flattenStack);
> }
>
>
> @@ -202,11 +198,7 @@
> dupTable = new MapTable(DefaultDupTableSize);
> buffer = new SmartBuffer(DefaultEnvelopeBuffer);
> // Allocate a flatten stack
> - flattenStack = new (Memory::LiveStackSize, true) LiveStack
> (Memory::LiveStackSize);
> - // we need to mark the flatten stack to protect it from GC, but we're
> - // going to be storing offsets in here, not object references, so we
> don't want
> - // this to be marked.
> - flattenStack->setHasNoReferences();
> + flattenStack = new (Memory::LiveStackSize) LiveStack
> (Memory::LiveStackSize);
> // push unique terminator onto stack
> flattenStack->push(OREF_NULL);
>
> @@ -244,6 +236,8 @@
> // behind it to the size we've written to it.
> BufferClass *letter = buffer->getBuffer();
> letter->setDataLength(buffer->getDataLength());
> + // delete the flatten stack, since that is not allocated from the
> object heap.
> + delete flattenStack;
> return letter;
> }
>
>
> Modified: main/trunk/interpreter/memory/Memory.hpp
> ===================================================================
> --- main/trunk/interpreter/memory/Memory.hpp 2018-08-22 21:51:20 UTC
> (rev 11487)
> +++ main/trunk/interpreter/memory/Memory.hpp 2018-08-26 21:48:23 UTC
> (rev 11488)
> @@ -94,8 +94,14 @@
> // possible size
> static const size_t MaximumObjectSize = SIZE_MAX - ObjectGrain;
>
> - // default size for the live stack (in entries)
> - static const size_t LiveStackSize = 32 * 1024;
> + // default size for the live stack (in entries). We make the initial
> one
> + // much larger if building for 64-bit mode because there is a much
> higher
> + // possibility of getting large complex collections
> +#ifdef __REXX64__
> + static const size_t LiveStackSize = 256 * 1024;
> +#else
> + static const size_t LiveStackSize = 64 * 1024;
> +#endif
> // the number of newly created items to stack in the save stack
> static const size_t SaveStackSize = 10;
> // the maximum size for the startup image size
> @@ -102,8 +108,6 @@
> static const size_t MaxImageSize = 3000000;
> // the size of a page
> static const size_t PageSize = 4096;
> - // the standard memory pool allocation size.
> - static const size_t MemoryAllocationSize = PageSize * 1024;
> };
>
> #endif
>
> Modified: main/trunk/interpreter/memory/MemorySegment.cpp
> ===================================================================
> --- main/trunk/interpreter/memory/MemorySegment.cpp 2018-08-22
> 21:51:20 UTC (rev 11487)
> +++ main/trunk/interpreter/memory/MemorySegment.cpp 2018-08-26
> 21:48:23 UTC (rev 11488)
> @@ -1166,25 +1166,21 @@
> // still no luck?
> if (newObject == OREF_NULL)
> {
> - // absolute last chance to fix this. We allocated a
> - // recovery segment at start up and have been hiding this
> - // in our back pocket. It is now time to bring this into
> - // play, because we're running on fumes! */
> + // We have a recovery segment in our back pocket, but this
> + // is needed to allow us to actually report that we have
> an
> + // out of memory condition. We add this to the segment
> set, but
> + // we will not try to use it to satisfy this request. We
> need this
> + // to keep from crashing.
> if (recoverSegment != NULL)
> {
> addSegment(recoverSegment);
> recoverSegment = NULL;
> - // And try to find it once more
> - newObject = findObject(allocationLength);
> }
>
> // if we have gone through all of that and still have
> nothing,
> // this is a real out-of-memory situation.
> - if (newObject == OREF_NULL)
> - {
> - // can't allocate, report resource error.
> - reportException(Error_System_resources);
> - }
> + // can't allocate, report resource error.
> + reportException(Error_System_resources);
> }
> }
> }
>
> Modified: main/trunk/interpreter/memory/MemoryStack.cpp
> ===================================================================
> --- main/trunk/interpreter/memory/MemoryStack.cpp 2018-08-22
> 21:51:20 UTC (rev 11487)
> +++ main/trunk/interpreter/memory/MemoryStack.cpp 2018-08-26
> 21:48:23 UTC (rev 11488)
> @@ -1,7 +1,7 @@
> /*----------------------------------------------------------
> ------------------*/
> /*
> */
> /* Copyright (c) 1995, 2004 IBM Corporation. All rights reserved.
> */
> -/* Copyright (c) 2005-2014 Rexx Language Association. All rights
> reserved. */
> +/* Copyright (c) 2005-2018 Rexx Language Association. All rights
> reserved. */
> /*
> */
> /* This program and the accompanying materials are made available under
> */
> /* the terms of the Common Public License v1.0 which accompanies this
> */
> @@ -56,81 +56,79 @@
> *
> * @return A newly allocated stack object.
> */
> -void *LiveStack::operator new(size_t size, size_t stksize, bool temporary)
> +void *LiveStack::operator new(size_t size, size_t stksize)
> {
> // This is a special allocation. We use this if we need to expand
> the livestack
> // during a GC operation, which of course is when we are not able to
> allocate from
> // the Rexx heap.
> - RexxInternalObject *newObject = memoryObject.temporaryObject(size +
> ((stksize-1) * sizeof(RexxObject *)));
> - // set the behaviour
> - newObject->setBehaviour(TheLiveStackBehaviour);
> - return newObject;
> + return memoryObject.temporaryObject(size + ((stksize-1) *
> sizeof(RexxObject *)));
> }
>
>
> /**
> - * Allocate a live stack with the given number of slots.
> + * Delete a LiveStack object.
> *
> - * @param _size The stack size.
> + * @param storage The pointer to the object storage
> */
> -LiveStack::LiveStack(size_t _size)
> +void LiveStack::operator delete(void *storage)
> {
> - // we can get created via means other than normal memory allocation,
> so
> - // ensure we're completely cleared out
> - clearObject();
> - // set the size and top element
> - size = _size;
> - top = 0;
> + memoryObject.deleteTemporaryObject(storage);
> }
>
>
> /**
> - * Perform garbage collection on a live object.
> + * Allocate a live stack with the given number of slots.
> *
> - * @param liveMark The current live mark.
> + * @param _size The stack size.
> */
> -void LiveStack::live(size_t liveMark)
> +LiveStack::LiveStack(size_t _size)
> {
> - // note, we only mark the array up to (but not including) the top
> position.
> - if (top > 0)
> - {
> - memory_mark_array(top - 1, stack);
> - }
> + // set the size and top element
> + size = _size;
> + top = 0;
> }
>
>
> /**
> - * Perform generalized live marking on an object. This is
> - * used when mark-and-sweep processing is needed for purposes
> - * other than garbage collection.
> + * Reallocate the stack to one that is larger by a given multiplier.
> *
> - * @param reason The reason for the marking call.
> + * @param delta The size to expand by
> + *
> + * @return A newly allocated stack with the entries from this
> + * stack copied over to it.
> */
> -void LiveStack::liveGeneral(MarkReason reason)
> +LiveStack *LiveStack::reallocate(size_t delta)
> {
> - // note, we only mark the array up to (but not including) the top
> position.
> - if (top > 0)
> - {
> - memory_mark_general_array(top - 1, stack);
> - }
> + // create a new stack that is larger by the given multiplier
> + LiveStack *newStack = new (size + delta) LiveStack (size + delta);
> + // copy the entries over to the new stack
> + newStack->copyEntries(this);
> + return newStack;
> }
>
>
> /**
> - * Reallocate the stack to one that is larger by a given multiplier.
> + * Ensure that the live stack is going to be large enough to fit
> + * all of the objects that might be marked from a large
> + * collection. This allows us to proactively expand the stack
> + * before a GC event is taking place, and potentially raise a
> + * real Rexx EOM condition before we're at a critical point.
> *
> - * @param multiplier The multiplier value.
> + * @param needed The number of live stack slots this object
> + * might require. It is assumed that the stack
> + * needs to be expanded at this point.
> *
> * @return A newly allocated stack with the entries from this
> * stack copied over to it.
> */
> -LiveStack *LiveStack::reallocate(size_t multiplier)
> +LiveStack *LiveStack::ensureSpace(size_t needed)
> {
> - // create a new stack that is larger by the given multiplier
> - LiveStack *newStack = new (size * multiplier, true) LiveStack (size *
> multiplier);
> - // copy the entries over to the new stack
> - newStack->copyEntries(this);
> - return newStack;
> + // NB: we've already determined expansion is needed, so
> + // this should be non-zero. We only expand by LiveStackSize increments
> + size_t shortFall = Memory::roundUp(needed - size,
> Memory::LiveStackSize);
> +
> + // now expand by that increment
> + return reallocate(shortFall);
> }
>
>
>
> Modified: main/trunk/interpreter/memory/MemoryStack.hpp
> ===================================================================
> --- main/trunk/interpreter/memory/MemoryStack.hpp 2018-08-22
> 21:51:20 UTC (rev 11487)
> +++ main/trunk/interpreter/memory/MemoryStack.hpp 2018-08-26
> 21:48:23 UTC (rev 11488)
> @@ -52,19 +52,14 @@
> * the using code needs to perform appropriate "stack is full"
> * checks.
> */
> -class LiveStack : public RexxInternalObject
> +class LiveStack
> {
> public:
> void *operator new(size_t, size_t);
> - void *operator new(size_t, size_t, bool temporary);
> - inline void operator delete(void *) { };
> + void operator delete(void *);
>
> - inline LiveStack(RESTORETYPE restoreType) { ; };
> LiveStack(size_t size);
>
> - virtual void live(size_t);
> - virtual void liveGeneral(MarkReason reason);
> -
> // the position is origin zero, relative to the top, which is an
> empty slot. So, position 0
> // is the top element, 1 is the penultimate elements, etc.
> inline RexxInternalObject *get(size_t pos)
> @@ -115,8 +110,10 @@
> }
>
> LiveStack *reallocate(size_t increment);
> + LiveStack *ensureSpace(size_t needed);
>
> inline bool checkRoom() { return top < size; }
> + inline bool checkRoom(size_t needed) { return size - top >
> needed; }
> inline size_t stackSize() { return size; };
> inline RexxInternalObject *stackTop() { return top == 0 ? OREF_NULL :
> stack[top - 1]; };
> inline void copyEntries(LiveStack *other) { memcpy((char
> *)stack, (char *)other->stack, other->size * sizeof(RexxInternalObject *));
> top = other->top; }
>
> Modified: main/trunk/interpreter/memory/RexxMemory.cpp
> ===================================================================
> --- main/trunk/interpreter/memory/RexxMemory.cpp 2018-08-22
> 21:51:20 UTC (rev 11487)
> +++ main/trunk/interpreter/memory/RexxMemory.cpp 2018-08-26
> 21:48:23 UTC (rev 11488)
> @@ -160,11 +160,9 @@
> // before we can allocate our first real object.
> buildVirtualFunctionTable();
>
> - // our first object allocation. This is the live stack used for
> - // sweep marking.
> - liveStack = (LiveStack *)oldSpaceSegments.allocateObject(
> MemorySegmentSet::SegmentDeadSpace);
> - // remember the original one
> - originalLiveStack = liveStack;
> + // This is the live stack used for
> + // sweep marking (not allocated from the object heap)
> + liveStack = new(Memory::LiveStackSize) LiveStack(Memory::
> LiveStackSize);
>
> // if we're restoring, load everything from the image file. All of
> the
> // classes will exist then, as well as restoring all of the
> @@ -233,6 +231,9 @@
> return;
> }
>
> + // flag that we're in the middle of a mark operation
> + markingObjects = true;
> +
> // set up the live marking word passed to the live() routines
> // we include the OldSpaceBit here to allow both conditions to be
> tested
> // in one shot.
> @@ -254,6 +255,9 @@
> allocations++;
> markObject->live(liveMark);
> }
> +
> + // we are done marking, no longer in a critical section
> + markingObjects = false;
> }
>
>
> @@ -422,13 +426,9 @@
> markObjectsMain(uninitTable);
>
> // if we had to expand the live stack previously, we allocated a
> temporary
> - // one from malloc() storage rather than the object heap. We need to
> - // explicitly free this version when that happens.
> - if (liveStack != originalLiveStack)
> - {
> - free((void *)liveStack);
> - liveStack = originalLiveStack;
> - }
> + // one from malloc() storage rather than the object heap. We will
> hold on
> + // to the expanded one because once we've hit the threshold where we
> expand,
> + // it's likely we'll need to in the future.
> verboseMessage("Mark operation completed\n");
> }
>
> @@ -1064,17 +1064,11 @@
> */
> void MemoryObject::liveStackFull()
> {
> - // create a new stack that is double in size
> - LiveStack *newLiveStack = liveStack->reallocate(2);
> + // create a new stack that a stack increment larger
> + LiveStack *newLiveStack = liveStack->reallocate(Memory::
> LiveStackSize);
>
> - // if we've already been expanded, we need to release the
> - // storage for the existing livestack. When we expand, we create a
> - // new object using malloc() storage rather than the object heap, so
> we
> - // use free() to release it.
> - if (liveStack != originalLiveStack)
> - {
> - free((void *)liveStack);
> - }
> + // delete the existing liveStack
> + delete liveStack;
> // we can set the new stack
> liveStack = newLiveStack;
> }
> @@ -1081,6 +1075,21 @@
>
>
> /**
> + * Process a predictive live-stack overflow situation
> + */
> +void MemoryObject::liveStackFull(size_t needed)
> +{
> + // create a new stack that a stack increment larger
> + LiveStack *newLiveStack = liveStack->ensureSpace(needed);
> +
> + // delete the existing liveStack
> + delete liveStack;
> + // we can set the new stack
> + liveStack = newLiveStack;
> +}
> +
> +
> +/**
> * Perform a memory management mark operation. This is only
> * used during a real garbage collection.
> *
> @@ -1136,22 +1145,48 @@
> *
> * @return Storage for creating a new object.
> */
> -RexxInternalObject *MemoryObject::temporaryObject(size_t requestLength)
> +void *MemoryObject::temporaryObject(size_t requestLength)
> {
> size_t allocationLength = Memory::roundObjectBoundary(requestLength);
> // allocate just using malloc()
> - RexxInternalObject *newObj = (RexxInternalObject
> *)malloc(allocationLength);
> - if (newObj == OREF_NULL) /* unable to allocate a new
> one? */
> + void *newObj = malloc(allocationLength);
> + // there are two times where we can get an allocation failure. When
> + // collection objects are allocated, we try to predict if we will
> need a
> + // larger live stack to handle large collections. If we get an
> allocation
> + // failure at that point, we can raise this as a normal error. This
> is not
> + // a perfect process, so we might need to expand the live stack
> during a
> + // a marking operation. A failure at that time is fatal, so we can
> only
> + // handle this as a fatal internal error.
> + if (newObj == OREF_NULL)
> {
> - reportException(Error_System_resources);
> + // If we're marking, then we can't recover from this.
> + if (markingObjects)
> + {
> + // This is an unrecoverable logic error
> + Interpreter::logicError("Unrecoverable out of memory error");
> + }
> + // a failure during the predictive process, we can raise a real
> error
> + else
> + {
> + reportException(Error_System_resources);
> + }
> }
> - // initialize the new object
> - ((RexxObject *)newObj)->initializeNewObject(allocationLength,
> markWord, virtualFunctionTable[T_Object], TheObjectBehaviour);
> return newObj;
> }
>
>
> /**
> + * Delete a temporary object.
> + *
> + * @param storage The storage pointer to release,
> + */
> +void MemoryObject::deleteTemporaryObject(void *storage)
> +{
> + free(storage);
> +}
> +
> +
> +/**
> * When we are doing a general marking operation, all
> * objects call markGeneral for all of its object references.
> * We perform different functions based on what the
> @@ -1562,6 +1597,9 @@
> {
> SystemInterpreter::releaseSegmentMemory(*it);
> }
> +
> + // release the livestack also, which is allocated separately.
> + delete liveStack;
> }
>
>
> @@ -1573,10 +1611,6 @@
> */
> void MemoryObject::setUpMemoryTables(MapTable *old2newTable)
> {
> - // fix up the previously allocated live stack to have the correct
> - // characteristics...we're almost ready to go on the air.
> - liveStack->setBehaviour(TheLiveStackBehaviour);
> - liveStack = ::new ((void *)liveStack) LiveStack(Memory::
> LiveStackSize);
> // set up the old 2 new table provided for us
> old2new = old2newTable;
> // Now get our savestack
>
> Modified: main/trunk/interpreter/memory/RexxMemory.hpp
> ===================================================================
> --- main/trunk/interpreter/memory/RexxMemory.hpp 2018-08-22
> 21:51:20 UTC (rev 11487)
> +++ main/trunk/interpreter/memory/RexxMemory.hpp 2018-08-26
> 21:48:23 UTC (rev 11488)
> @@ -111,7 +111,8 @@
> RexxInternalObject *oldObject(size_t size);
> inline RexxInternalObject *newObject(size_t size) { return
> newObject(size, T_Object); }
> RexxInternalObject *newObject(size_t size, size_t type);
> - RexxInternalObject *temporaryObject(size_t size);
> + void *temporaryObject(size_t size);
> + void deleteTemporaryObject(void *obj);
> ArrayClass *newObjects(size_t size, size_t count, size_t objectType);
> void reSize(RexxInternalObject *, size_t);
> void checkUninit();
> @@ -134,8 +135,11 @@
> void setOref(RexxInternalObject *variable, RexxInternalObject
> *value);
> void shutdown();
> void liveStackFull();
> + void liveStackFull(size_t needed);
> char * allocateImageBuffer(size_t size);
> void logVerboseOutput(const char *message, void *sub1, void
> *sub2, void*sub3);
> + void memoryError();
> +
> inline void verboseMessage(const char *message)
> {
> #ifdef VERBOSE_GC
> @@ -208,6 +212,7 @@
> void restoreStrings(ArrayClass *stringArray);
>
> inline void checkLiveStack() { if (!liveStack->checkRoom())
> liveStackFull(); }
> + inline void checkLiveStack(size_t needed) { if
> (!liveStack->checkRoom(needed)) liveStackFull(needed); }
> inline void pushLiveStack(RexxInternalObject *obj) {
> checkLiveStack(); liveStack->push(obj); }
> inline RexxInternalObject * popLiveStack() { return liveStack->pop();
> }
> inline void bumpMarkWord() { markWord ^= ObjectHeader::MarkMask; }
> @@ -274,6 +279,7 @@
>
> LiveStack *liveStack; // stack used for memory marking
> PushThroughStack *saveStack; // our temporary protection stack
> + bool markingObjects; // a flag to indicate we are
> marking objects.
>
> MapTable *old2new; // the table for tracking
> old2new references.
> IdentityTable *uninitTable; // the table of objects with
> uninit methods
> @@ -290,7 +296,6 @@
> MarkHandler *currentMarkHandler; // current handler for
> liveGeneral marking
> MarkHandler defaultMarkHandler; // the default mark handler
>
> - LiveStack *originalLiveStack; // original live stack allocation
> MemoryStats *imageStats; // current statistics collector
>
> size_t allocations; // number of allocations since
> last GC
> @@ -426,6 +431,7 @@
>
> inline RexxInternalObject *new_object(size_t s) { return
> memoryObject.newObject(s); }
> inline RexxInternalObject *new_object(size_t s, size_t t) { return
> memoryObject.newObject(s, t); }
> +inline RexxInternalObject *new_object(size_t s, size_t t, size_t i) {
> memoryObject.checkLiveStack(i); return memoryObject.newObject(s, t); }
>
> inline ArrayClass *new_arrayOfObject(size_t s, size_t c, size_t t) {
> return memoryObject.newObjects(s, c, t); }
>
>
>
> ------------------------------------------------------------
> ------------------
> Check out the vibrant tech community on one of the world's most
> engaging tech sites, Slashdot.org! http://sdm.link/slashdot
> _______________________________________________
> Oorexx-svn mailing list
> oorexx-...@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/oorexx-svn
>
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Oorexx-devel mailing list
Oorexx-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/oorexx-devel