Oops, you're right. I thought I was going to need to use
exception/logicError split in multiple places so I was going to have a
method for it.
Rick
On Tue, Aug 28, 2018 at 11:09 AM Erich Steinböck <erich.steinbo...@gmail.com>
wrote:
> 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
>
------------------------------------------------------------------------------
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