[Scummvm-git-logs] scummvm master -> 542742e2aa7d088330d3e970a1910ce29b9f080f

elasota noreply at scummvm.org
Sat Aug 24 19:13:48 UTC 2024


This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
542742e2aa MTROPOLIS: Refactor VThread to use statically-located stacks


Commit: 542742e2aa7d088330d3e970a1910ce29b9f080f
    https://github.com/scummvm/scummvm/commit/542742e2aa7d088330d3e970a1910ce29b9f080f
Author: elasota (1137273+elasota at users.noreply.github.com)
Date: 2024-08-24T15:11:48-04:00

Commit Message:
MTROPOLIS: Refactor VThread to use statically-located stacks

Changed paths:
    engines/mtropolis/vthread.cpp
    engines/mtropolis/vthread.h


diff --git a/engines/mtropolis/vthread.cpp b/engines/mtropolis/vthread.cpp
index 14cf5ba18c7..aa477d0cdf3 100644
--- a/engines/mtropolis/vthread.cpp
+++ b/engines/mtropolis/vthread.cpp
@@ -29,6 +29,26 @@ VThreadTaskData::VThreadTaskData() {
 VThreadTaskData::~VThreadTaskData() {
 }
 
+VThreadStackChunk::VThreadStackChunk(size_t capacity)
+	: _memory(nullptr), _size(capacity), _topFrame(nullptr) {
+
+	_memory = static_cast<byte *>(malloc(capacity));
+	if (!_memory)
+		error("Out of memory");
+}
+
+VThreadStackChunk::VThreadStackChunk(VThreadStackChunk &&other)
+	: _memory(other._memory), _size(other._size), _topFrame(other._topFrame) {
+	other._memory = nullptr;
+	other._size = 0;
+	other._topFrame = nullptr;
+}
+
+VThreadStackChunk::~VThreadStackChunk() {
+	if (_memory)
+		free(_memory);
+}
+
 #ifdef MTROPOLIS_DEBUG_ENABLE
 void VThreadTaskData::debugInit(const char *name) {
 	_debugName = name;
@@ -39,176 +59,145 @@ void VThreadTaskData::debugInspect(IDebugInspectionReport *report) const {
 #endif
 
 VThread::VThread()
-	: _faultID(nullptr), _stackUnalignedBase(nullptr), _stackAlignedBase(nullptr), /* _size(0), */_alignment(1), _used(0)
-#ifdef MTROPOLIS_DEBUG_VTHREAD_STACKS
-	, _topFrame(nullptr)
-#endif
+	: _numActiveStackChunks(0)
 {
 }
 
 VThread::~VThread() {
-	void *dataPtr;
-	void *framePtr;
-	while (popFrame(dataPtr, framePtr)) {
-		static_cast<VThreadStackFrame *>(framePtr)->~VThreadStackFrame();
-		static_cast<VThreadTaskData *>(dataPtr)->~VThreadTaskData();
+	while (popFrame()) {
 	}
-
-	if (_stackUnalignedBase)
-		free(_stackUnalignedBase);
 }
 
 VThreadState VThread::step() {
-	void *dataPtr;
-	void *framePtr;
-	while (popFrame(dataPtr, framePtr)) {
-		VThreadTaskData *data = static_cast<VThreadTaskData *>(dataPtr);
-
-		VThreadStackFrame *stackFrame = static_cast<VThreadStackFrame *>(framePtr);
-
-		const bool isHandling = (data->handlesFault(_faultID));
-		stackFrame->~VThreadStackFrame();
-		if (isHandling) {
-			_faultID = nullptr;
-			VThreadState state = data->destructAndRunTask();
-			if (state != kVThreadReturn)
-				return state;
-		} else {
-			static_cast<VThreadTaskData *>(dataPtr)->~VThreadTaskData();
-		}
+	while (hasTasks()) {
+		VThreadStackFrame *frame = _stackChunks[_numActiveStackChunks - 1]._topFrame;
+
+		VThreadState state = frame->data->execute(this);
+		if (state != kVThreadReturn)
+			return state;
 	}
 
 	return kVThreadReturn;
 }
 
 bool VThread::hasTasks() const {
-	return _used > 0;
+	return _numActiveStackChunks > 0;
 }
 
-void VThread::reserveFrame(size_t size, size_t alignment, void *&outFramePtr, void *&outUnadjustedDataPtr, size_t &outPrevFrameOffset) {
-	const size_t frameAlignment = alignof(VThreadStackFrame);
-	const size_t frameAlignmentMask = frameAlignment - 1;
+bool VThread::reserveFrameInChunk(VThreadStackChunk *chunk, size_t frameAlignment, size_t frameSize, VThreadStackFrame *&outFramePtr, size_t dataAlignment, size_t dataSize, void *&outDataPtr) {
+	VThreadStackFrame *framePtr = nullptr;
+	void *dataPtr = nullptr;
 
-	size_t dataAlignmentMask = alignment - 1;
+	uintptr address = 0;
+	size_t bytesAvailable = 0;
 
-	bool needToReallocate = false;
-	if (alignment > _alignment || frameAlignment > _alignment) {
-		if ((reinterpret_cast<uintptr>(_stackAlignedBase) & dataAlignmentMask) != 0) {
-			needToReallocate = true;
-		}
+	if (chunk->_topFrame) {
+		address = reinterpret_cast<uintptr>(chunk->_topFrame);
+		bytesAvailable = static_cast<size_t>(reinterpret_cast<const byte *>(chunk->_topFrame) - chunk->_memory);
+	} else {
+		address = reinterpret_cast<uintptr>(chunk->_memory + chunk->_size);
+		bytesAvailable = chunk->_size;
 	}
 
-	size_t dataAlignmentPaddingNeeded = (alignment - (_used & dataAlignmentMask));
-	if (dataAlignmentPaddingNeeded == alignment)
-		dataAlignmentPaddingNeeded = 0;
+	if (bytesAvailable < dataSize)
+		return false;
 
-	size_t offsetOfData = dataAlignmentPaddingNeeded + _used;
-	size_t offsetOfEndOfData = offsetOfData + size;
-	size_t frameAlignmentPaddingNeeded = (frameAlignment - (offsetOfData & frameAlignmentMask));
-	if (frameAlignmentPaddingNeeded == frameAlignment)
-		frameAlignmentPaddingNeeded = 0;
+	bytesAvailable -= dataSize;
+	address -= dataSize;
 
-	size_t offsetOfFrame = offsetOfEndOfData + frameAlignmentPaddingNeeded;
-	size_t offsetOfEndOfFrame = offsetOfFrame + sizeof(VThreadStackFrame);
+	size_t dataAlignPadding = static_cast<size_t>(dataAlignment % dataAlignment);
 
-	size_t offsetOfPrevFrame = 0;
-	if (_used > 0)
-		offsetOfPrevFrame = _used - sizeof(VThreadStackFrame);
+	if (bytesAvailable < dataAlignPadding)
+		return false;
 
-	if (offsetOfEndOfFrame > _used)
-		needToReallocate = true;
+	bytesAvailable -= dataAlignPadding;
+	address -= dataAlignPadding;
 
-	if (needToReallocate) {
-		size_t maxAlignment = alignment;
-		if (maxAlignment < frameAlignment)
-			maxAlignment = frameAlignment;
+	dataPtr = reinterpret_cast<void *>(address);
 
-		void *unalignedBase = malloc(offsetOfEndOfFrame + maxAlignment - 1);
-		size_t alignPadding = maxAlignment - (reinterpret_cast<uintptr>(unalignedBase) % maxAlignment);
-		if (alignPadding == maxAlignment)
-			alignPadding = 0;
+	if (bytesAvailable < frameSize)
+		return false;
 
-		void *alignedBase = static_cast<char *>(unalignedBase) + alignPadding;
+	bytesAvailable -= frameSize;
+	address -= frameSize;
 
-		// Copy the previous frames
-		size_t framePos = 0;
-		if (_used > 0) {
-			framePos = _used - sizeof(VThreadStackFrame);
-#ifdef MTROPOLIS_DEBUG_VTHREAD_STACKS
-			VThreadStackFrame *nextFrame = nullptr;
-#endif
+	size_t frameAlignPadding = static_cast<size_t>(address % frameAlignment);
 
-			while (framePos != 0) {
-				VThreadStackFrame *oldFrame = reinterpret_cast<VThreadStackFrame *>(static_cast<char *>(_stackAlignedBase) + framePos);
-				size_t dataPos = oldFrame->taskDataOffset;
-				VThreadTaskData *oldData = reinterpret_cast<VThreadTaskData *>(static_cast<char *>(_stackAlignedBase) + dataPos);
-				size_t nextPos = oldFrame->prevFrameOffset;
+	if (bytesAvailable < frameAlignPadding)
+		return false;
 
-				VThreadStackFrame *newFrame = reinterpret_cast<VThreadStackFrame *>(static_cast<char *>(alignedBase) + framePos);
-				VThreadTaskData *newData = reinterpret_cast<VThreadTaskData *>(static_cast<char *>(alignedBase) + dataPos);
+	bytesAvailable -= frameAlignPadding;
+	address -= frameAlignPadding;
 
-				// Relocate the frame
-				new (newFrame) VThreadStackFrame(*oldFrame);
-				oldFrame->~VThreadStackFrame();
+	framePtr = reinterpret_cast<VThreadStackFrame *>(address);
 
-				// Relocate the data
-				oldData->relocateTo(newData);
-				oldData->~VThreadTaskData();
+	chunk->_topFrame = framePtr;
 
-#ifdef MTROPOLIS_DEBUG_VTHREAD_STACKS
-				newFrame->data = newData;
-				newFrame->prevFrame = nullptr;
-				if (nextFrame)
-					nextFrame->prevFrame = newFrame;
+	outDataPtr = dataPtr;
+	outFramePtr = framePtr;
 
-				nextFrame = newFrame;
-#endif
+	return true;
+}
+
+void VThread::reserveFrame(size_t frameAlignment, size_t frameSize, VThreadStackFrame *&outFramePtr, size_t dataAlignment, size_t dataSize, void *&outDataPtr, bool &outIsNewChunk) {
+	// See if this fits in the last active chunk
+	if (_numActiveStackChunks > 0) {
+		VThreadStackChunk &lastChunk = _stackChunks[_numActiveStackChunks - 1];
 
-				framePos = nextPos;
-			}
+		if (reserveFrameInChunk(&lastChunk, frameAlignment, frameSize, outFramePtr, dataAlignment, dataSize, outDataPtr)) {
+			outIsNewChunk = false;
+			return;
 		}
+	}
 
-		if (_stackUnalignedBase)
-			free(_stackUnalignedBase);
+	// Didn't fit, this is the first one in the chunk
+	size_t requiredSize = (frameAlignment - 1) + (dataAlignment - 1) + frameSize + dataSize;
 
-		_stackUnalignedBase = unalignedBase;
-		_stackAlignedBase = alignedBase;
+	if (_numActiveStackChunks >= _stackChunks.size() || _stackChunks[_numActiveStackChunks]._size < requiredSize) {
+		// Doesn't fit in the next chunk, deallocate the chunk and all subsequent chunks and reallocate
+
+		const size_t kChunkMinSize = 1024 * 1024;	// 1MB chunks
+		size_t chunkSize = requiredSize;
+		if (chunkSize < kChunkMinSize)
+			chunkSize = kChunkMinSize;
+
+		while (_stackChunks.size() > _numActiveStackChunks)
+			_stackChunks.pop_back();
+
+		_stackChunks.push_back(VThreadStackChunk(chunkSize));
 	}
 
-	VThreadStackFrame *newFrame = reinterpret_cast<VThreadStackFrame *>(static_cast<char *>(_stackAlignedBase) + offsetOfFrame);
-	void *newData = static_cast<char *>(_stackAlignedBase) + offsetOfData;
-	_used = offsetOfEndOfFrame;
+	VThreadStackChunk &lastChunk = _stackChunks[_numActiveStackChunks++];
 
-	outFramePtr = newFrame;
-	outUnadjustedDataPtr = newData;
-	outPrevFrameOffset = offsetOfPrevFrame;
+	bool reservedOK = reserveFrameInChunk(&lastChunk, frameAlignment, frameSize, outFramePtr, dataAlignment, dataSize, outDataPtr);
+	assert(reservedOK);
+	(void)reservedOK;
 
-#ifdef MTROPOLIS_DEBUG_VTHREAD_STACKS
-	_topFrame = newFrame;
-#endif
+	outIsNewChunk = true;
 }
 
-bool VThread::popFrame(void *&dataPtr, void *&outFramePtr) {
-	if (_used == 0)
+bool VThread::popFrame() {
+	if (_numActiveStackChunks == 0)
 		return false;
 
-	VThreadStackFrame *frame = reinterpret_cast<VThreadStackFrame *>(static_cast<char *>(_stackAlignedBase) + _used - sizeof(VThreadStackFrame));
-	VThreadTaskData *data = reinterpret_cast<VThreadTaskData *>(static_cast<char *>(_stackAlignedBase) + frame->taskDataOffset);
+	VThreadStackChunk &lastChunk = _stackChunks[_numActiveStackChunks - 1];
+	VThreadStackFrame *topFrame = lastChunk._topFrame;
 
-	dataPtr = data;
-	outFramePtr = frame;
+	VThreadStackFrame *secondFrame = topFrame->prevFrame;
+	bool isLastFrameInChunk = topFrame->isLastInChunk;
 
-	if (frame->prevFrameOffset == 0)
-		_used = 0;
-	else
-		_used = frame->prevFrameOffset + sizeof(VThreadStackFrame);
+	if (isLastFrameInChunk) {
+		lastChunk._topFrame = nullptr;
+		_numActiveStackChunks--;
+	} else {
+		assert(reinterpret_cast<byte *>(secondFrame) >= lastChunk._memory);
+		assert(reinterpret_cast<byte *>(secondFrame) < lastChunk._memory + lastChunk._size);
 
-#ifdef MTROPOLIS_DEBUG_VTHREAD_STACKS
-	if (_used == 0)
-		_topFrame = nullptr;
-	else
-		_topFrame = reinterpret_cast<VThreadStackFrame *>(static_cast<char *>(_stackAlignedBase) + frame->prevFrameOffset);
-#endif
+		lastChunk._topFrame = secondFrame;
+	}
+
+	topFrame->data->~VThreadTaskData();
+	topFrame->~VThreadStackFrame();
 
 	return true;
 }
diff --git a/engines/mtropolis/vthread.h b/engines/mtropolis/vthread.h
index 96518fb3eea..96e99154b27 100644
--- a/engines/mtropolis/vthread.h
+++ b/engines/mtropolis/vthread.h
@@ -26,6 +26,8 @@
 
 namespace MTropolis {
 
+class VThread;
+
 // Virtual thread, really a task stack
 enum VThreadState {
 	kVThreadReturn,
@@ -49,9 +51,7 @@ public:
 	VThreadTaskData();
 	virtual ~VThreadTaskData();
 
-	virtual VThreadState destructAndRunTask() = 0;
-	virtual void relocateTo(void *newPosition) = 0;
-	virtual bool handlesFault(const VThreadFaultIdentifier *faultID) const = 0;
+	virtual VThreadState execute(VThread *thread) = 0;
 
 #ifdef MTROPOLIS_DEBUG_ENABLE
 public:
@@ -67,14 +67,27 @@ protected:
 #endif
 };
 
-struct VThreadStackFrame {
-	size_t taskDataOffset;	// Offset to VThreadTaskData
-	size_t prevFrameOffset;
+struct VThreadStackFrame;
+
+class VThreadStackChunk {
+public:
+	explicit VThreadStackChunk(size_t capacity);
+	VThreadStackChunk(VThreadStackChunk &&other);
+	~VThreadStackChunk();
+
+	VThreadStackFrame *_topFrame;
+	byte *_memory;
+	size_t _size;
+
+private:
+	VThreadStackChunk() = delete;
+	VThreadStackChunk(const VThreadStackChunk &) = delete;
+};
 
-#ifdef MTROPOLIS_DEBUG_VTHREAD_STACKS
+struct VThreadStackFrame {
 	VThreadTaskData *data;
 	VThreadStackFrame *prevFrame;
-#endif
+	bool isLastInChunk;
 };
 
 template<typename TClass, typename TData>
@@ -84,9 +97,7 @@ public:
 	VThreadMethodData(const VThreadMethodData &other);
 	VThreadMethodData(VThreadMethodData &&other);
 
-	VThreadState destructAndRunTask() override;
-	void relocateTo(void *newPosition) override;
-	bool handlesFault(const VThreadFaultIdentifier *faultID) const override;
+	VThreadState execute(VThread *thread) override;
 
 	TData &getData();
 
@@ -106,9 +117,7 @@ public:
 
 	VThreadFunctionData(VThreadFunctionData &&other);
 
-	VThreadState destructAndRunTask() override;
-	void relocateTo(void *newPosition) override;
-	bool handlesFault(const VThreadFaultIdentifier *faultID) const override;
+	VThreadState execute(VThread *thread) override;
 
 	TData &getData();
 
@@ -119,7 +128,6 @@ private:
 };
 
 class VThread {
-
 public:
 	VThread();
 	~VThread();
@@ -130,36 +138,24 @@ public:
 	template<typename TData>
 	TData *pushTask(const char *name, VThreadState (*func)(const TData &data));
 
-	template<typename TFaultType, typename TClass, typename TData>
-	TData *pushFaultHandler(const char *name, TClass *obj, VThreadState (TClass::*method)(const TData &data));
-
-	template<typename TFaultType, typename TData>
-	TData *pushFaultHandler(const char *name, VThreadState (*func)(const TData &data));
-
 	VThreadState step();
 
 	bool hasTasks() const;
 
+	bool popFrame();
+
 private:
+	void reserveFrame(size_t frameAlignment, size_t frameSize, VThreadStackFrame *&outFramePtr, size_t dataAlignment, size_t dataSize, void *&outDataPtr, bool &outIsNewChunk);
+	static bool reserveFrameInChunk(VThreadStackChunk *chunk, size_t frameAlignment, size_t frameSize, VThreadStackFrame *&outFramePtr, size_t dataAlignment, size_t dataSize, void *&outDataPtr);
+
 	template<typename TClass, typename TData>
 	TData *pushTaskWithFaultHandler(const VThreadFaultIdentifier *faultID, const char *name, TClass *obj, VThreadState (TClass::*method)(const TData &data));
 
 	template<typename TData>
 	TData *pushTaskWithFaultHandler(const VThreadFaultIdentifier *faultID, const char *name, VThreadState (*func)(const TData &data));
 
-	void reserveFrame(size_t size, size_t alignment, void *&outFramePtr, void *&outUnadjustedDataPtr, size_t &outPrevFrameOffset);
-	bool popFrame(void *&dataPtr, void *&outFramePtr);
-
-	void *_stackUnalignedBase;
-	void *_stackAlignedBase;
-	//size_t _size;
-	size_t _alignment;
-	size_t _used;
-	VThreadFaultIdentifier *_faultID;
-
-#ifdef MTROPOLIS_DEBUG_VTHREAD_STACKS
-	const VThreadStackFrame *_topFrame;
-#endif
+	Common::Array<VThreadStackChunk> _stackChunks;
+	uint _numActiveStackChunks;
 };
 
 template<typename TClass, typename TData>
@@ -178,29 +174,17 @@ VThreadMethodData<TClass, TData>::VThreadMethodData(VThreadMethodData &&other)
 }
 
 template<typename TClass, typename TData>
-VThreadState VThreadMethodData<TClass, TData>::destructAndRunTask() {
+VThreadState VThreadMethodData<TClass, TData>::execute(VThread *thread) {
 	TData data(static_cast<TData &&>(_data));
 
 	TClass *target = _target;
 	VThreadState (TClass::*method)(const TData &) = _method;
 
-	this->~VThreadMethodData<TClass, TData>();
+	thread->popFrame();
 
 	return (target->*method)(data);
 }
 
-template<typename TClass, typename TData>
-void VThreadMethodData<TClass, TData>::relocateTo(void *newPosition) {
-	void *adjustedPtr = static_cast<VThreadMethodData<TClass, TData> *>(static_cast<VThreadTaskData *>(newPosition));
-
-	new (adjustedPtr) VThreadMethodData<TClass, TData>(static_cast<VThreadMethodData<TClass, TData> &&>(*this));
-}
-
-template<typename TClass, typename TData>
-bool VThreadMethodData<TClass, TData>::handlesFault(const VThreadFaultIdentifier* faultID) const {
-	return _faultID == faultID;
-}
-
 template<typename TClass, typename TData>
 TData &VThreadMethodData<TClass, TData>::getData() {
 	return _data;
@@ -222,28 +206,16 @@ VThreadFunctionData<TData>::VThreadFunctionData(VThreadFunctionData &&other)
 }
 
 template<typename TData>
-VThreadState VThreadFunctionData<TData>::destructAndRunTask() {
+VThreadState VThreadFunctionData<TData>::execute(VThread *thread) {
 	TData data(static_cast<TData &&>(_data));
 
 	VThreadState (*func)(const TData &) = _func;
 
-	this->~VThreadFunctionData<TData>();
+	thread->popFrame();
 
 	return func(data);
 }
 
-template<typename TData>
-void VThreadFunctionData<TData>::relocateTo(void *newPosition) {
-	void *adjustedPtr = static_cast<VThreadFunctionData<TData> *>(static_cast<VThreadTaskData *>(newPosition));
-
-	new (adjustedPtr) VThreadFunctionData<TData>(static_cast<VThreadFunctionData<TData> &&>(*this));
-}
-
-template<typename TData>
-bool VThreadFunctionData<TData>::handlesFault(const VThreadFaultIdentifier *faultID) const {
-	return _faultID == faultID;
-}
-
 template<typename TData>
 TData &VThreadFunctionData<TData>::getData() {
 	return _data;
@@ -259,44 +231,29 @@ TData *VThread::pushTask(const char *name, VThreadState (*func)(const TData &dat
 	return this->pushTaskWithFaultHandler(nullptr, name, func);
 }
 
-template<typename TFaultType, typename TClass, typename TData>
-TData *VThread::pushFaultHandler(const char *name, TClass *obj, VThreadState (TClass::*method)(const TData &data)) {
-	return this->pushTaskWithFaultHandler(&VThreadFaultIdentifierSingleton<TFaultType>::_identifier, name, obj, method);
-}
-
-template<typename TFaultType, typename TData>
-TData *VThread::pushFaultHandler(const char *name, VThreadState (*func)(const TData &data)) {
-	return this->pushTaskWithFaultHandler(&VThreadFaultIdentifierSingleton<TFaultType>::_identifier, name, func);
-}
-
-
 template<typename TClass, typename TData>
 TData *VThread::pushTaskWithFaultHandler(const VThreadFaultIdentifier *faultID, const char *name, TClass *obj, VThreadState (TClass::*method)(const TData &data)) {
 	typedef VThreadMethodData<TClass, TData> FrameData_t;
 
 	const size_t frameAlignment = alignof(VThreadStackFrame);
 	const size_t dataAlignment = alignof(FrameData_t);
-	const size_t maxAlignment = (frameAlignment < dataAlignment) ? dataAlignment : frameAlignment;
 
-	void *framePtr;
-	void *dataPtr;
-	size_t prevFrameOffset;
-	reserveFrame(sizeof(FrameData_t), maxAlignment, framePtr, dataPtr, prevFrameOffset);
+	VThreadStackFrame *prevFrame = nullptr;
+	if (_numActiveStackChunks > 0)
+		prevFrame = _stackChunks[_numActiveStackChunks - 1]._topFrame;
 
-	VThreadStackFrame *frame = new (framePtr) VThreadStackFrame();
-	frame->prevFrameOffset = prevFrameOffset;
+	VThreadStackFrame *framePtr = nullptr;
+	void *dataPtr = nullptr;
+	bool isNewChunk = false;
+	reserveFrame(frameAlignment, sizeof(VThreadStackFrame), framePtr, dataAlignment, sizeof(FrameData_t), dataPtr, isNewChunk);
 
+	VThreadStackFrame *frame = new (framePtr) VThreadStackFrame();
 	FrameData_t *frameData = new (dataPtr) FrameData_t(faultID, obj, method);
-	frame->taskDataOffset = reinterpret_cast<char *>(static_cast<VThreadTaskData *>(frameData)) - static_cast<char *>(_stackAlignedBase);
-
-#ifdef MTROPOLIS_DEBUG_VTHREAD_STACKS
-	if (frame->prevFrameOffset == 0)
-		frame->prevFrame = nullptr;
-	else
-		frame->prevFrame = reinterpret_cast<VThreadStackFrame *>(static_cast<char *>(_stackAlignedBase) + prevFrameOffset);
 
 	frame->data = frameData;
-#endif
+	frame->prevFrame = prevFrame;
+	frame->isLastInChunk = isNewChunk;
+
 #ifdef MTROPOLIS_DEBUG_ENABLE
 	frameData->debugInit(name);
 #endif
@@ -310,27 +267,23 @@ TData *VThread::pushTaskWithFaultHandler(const VThreadFaultIdentifier *faultID,
 
 	const size_t frameAlignment = alignof(VThreadStackFrame);
 	const size_t dataAlignment = alignof(FrameData_t);
-	const size_t maxAlignment = (frameAlignment < dataAlignment) ? dataAlignment : frameAlignment;
 
-	void *framePtr;
-	void *dataPtr;
-	size_t prevFrameOffset;
-	reserveFrame(sizeof(FrameData_t), maxAlignment, framePtr, dataPtr, prevFrameOffset);
+	VThreadStackFrame *prevFrame = nullptr;
+	if (_numActiveStackChunks > 0)
+		prevFrame = _stackChunks[_numActiveStackChunks - 1]._topFrame;
 
-	VThreadStackFrame *frame = new (framePtr) VThreadStackFrame();
-	frame->prevFrameOffset = prevFrameOffset;
+	VThreadStackFrame *framePtr = nullptr;
+	void *dataPtr = nullptr;
+	bool isNewChunk = false;
+	reserveFrame(frameAlignment, sizeof(VThreadStackFrame), framePtr, dataAlignment, sizeof(FrameData_t), dataPtr, isNewChunk);
 
+	VThreadStackFrame *frame = new (framePtr) VThreadStackFrame();
 	FrameData_t *frameData = new (dataPtr) FrameData_t(faultID, func);
-	frame->taskDataOffset = reinterpret_cast<char *>(static_cast<VThreadTaskData *>(frameData)) - static_cast<char *>(_stackAlignedBase);
-
-#ifdef MTROPOLIS_DEBUG_VTHREAD_STACKS
-	if (frame->prevFrameOffset == 0)
-		frame->prevFrame = nullptr;
-	else
-		frame->prevFrame = reinterpret_cast<VThreadStackFrame *>(static_cast<char *>(_stackAlignedBase) + prevFrameOffset);
 
 	frame->data = frameData;
-#endif
+	frame->prevFrame = prevFrame;
+	frame->isLastInChunk = isNewChunk;
+
 #ifdef MTROPOLIS_DEBUG_ENABLE
 	frameData->debugInit(name);
 #endif




More information about the Scummvm-git-logs mailing list