Exemple #1
0
// N.B. Like the other instantiate methods in ObjectMemory, this method for instantiating
// objects in virtual space (used for allocating Processes, for example), does not adjust
// the ref. count of the class, because this is often unecessary, and does not adjust the
// sizes to allow for fixed fields - callers must do this
VirtualOTE* ObjectMemory::newVirtualObject(BehaviorOTE* classPointer, MWORD initialSize, MWORD maxSize)
{
	#ifdef _DEBUG
	{
		ASSERT(isBehavior(Oop(classPointer)));
		Behavior& behavior = *classPointer->m_location;
		ASSERT(behavior.isIndexable());
	}
	#endif

	// Trim the sizes to acceptable bounds
	if (initialSize <= dwOopsPerPage)
		initialSize = dwOopsPerPage;
	else
		initialSize = _ROUND2(initialSize, dwOopsPerPage);

	if (maxSize < initialSize)
		maxSize = initialSize;
	else
		maxSize = _ROUND2(maxSize, dwOopsPerPage);

	// We have to allow for the virtual allocation overhead. The allocation function will add in
	// space for this. The maximum size should include this, the initial size should not
	initialSize -= sizeof(VirtualObjectHeader)/sizeof(MWORD);

	unsigned byteSize = initialSize*sizeof(MWORD);
	VariantObject* pLocation = reinterpret_cast<VariantObject*>(AllocateVirtualSpace(maxSize * sizeof(MWORD), byteSize));
	if (pLocation)
	{
		// No need to alter ref. count of process class, as it is sticky

		// Fill space with nils for initial values
		const Oop nil = Oop(Pointers.Nil);
		const unsigned loopEnd = initialSize;
		for (unsigned i = 0; i < loopEnd; i++)
			pLocation->m_fields[i] = nil;

		OTE* ote = ObjectMemory::allocateOop(static_cast<POBJECT>(pLocation));
		ote->setSize(byteSize);
		ote->m_oteClass = classPointer;
		classPointer->countUp();
		ote->m_flags = m_spaceOTEBits[OTEFlags::VirtualSpace];
		ASSERT(ote->isPointers());

		return reinterpret_cast<VirtualOTE*>(ote);
	}

	return nullptr;
}
Exemple #2
0
VariantObject* ObjectMemory::resize(PointersOTE* ote, MWORD newPointers, bool bRefCount)
{
	ASSERT(!ObjectMemoryIsIntegerObject(ote) && ote->isPointers());

	VariantObject* pObj = ote->m_location;
	const MWORD oldPointers = ote->pointersSize();

	// If resizing the active process, then we don't do any ref. counting as refs from
	// the current stack are not counted (we used deferred ref. counting)
	if (bRefCount)
	{
		for (MWORD i=newPointers;i<oldPointers;i++)
			countDown(pObj->m_fields[i]);
	}

	// Reallocate the object to the new size (bigger or smaller)
	pObj = reinterpret_cast<VariantObject*>(basicResize(reinterpret_cast<POTE>(ote), SizeOfPointers(newPointers), 0));

	if (pObj)
	{
		ASSERT(newPointers == ote->pointersSize());
		newPointers = ote->pointersSize();

		// Initialize any new pointers to Nil (indices must fit in a SmallInteger)
		const Oop nil = Oop(Pointers.Nil);
		for (MWORD i=oldPointers; i<newPointers; i++)
			pObj->m_fields[i] = nil;
	}

	return pObj;
}
Exemple #3
0
BOOL __fastcall Interpreter::primitiveHookWindowCreate()
{
	Oop argPointer = stackTop();
	OTE* underConstruction = m_oteUnderConstruction;
	OTE* receiverPointer = reinterpret_cast<OTE*>(stackValue(1));

	if (!underConstruction->isNil() && underConstruction != receiverPointer)
	{
		// Hooked by another window - fail the primitive
		return primitiveFailureWith(1, underConstruction);
	}


	if (argPointer == Oop(Pointers.True))
	{
		// Hooking

		if (underConstruction != receiverPointer)
		{
			ASSERT(underConstruction->isNil());
			m_oteUnderConstruction= receiverPointer;
			receiverPointer->countUp();
		}
	}
	else
	{
		if (argPointer == Oop(Pointers.False))
		{
			// Unhooking
			if (underConstruction == receiverPointer)
			{
				tracelock lock(TRACESTREAM);
				TRACESTREAM << "WARNING: Unhooking create for " << hex << underConstruction << " before HCBT_CREATEWND" << endl;
				ObjectMemory::nilOutPointer(m_oteUnderConstruction);
			}
			else
				ASSERT(underConstruction->isNil());
		}
		else
			return primitiveFailureWith(0, argPointer);	// Invalid argument
	}

	popStack();
	return TRUE;
}
Exemple #4
0
inline void Interpreter::subclassWindow(OTE* window, HWND hWnd)
{
	ASSERT(!ObjectMemoryIsIntegerObject(window));
	// As this is called from an external entry point, we must ensure that OT/stack overflows
	// are handled, and also that we catch the SE_VMCALLBACKUNWIND exceptions
	__try
	{
		bool bDisabled = disableInterrupts(true);
		Oop retVal = performWith(Oop(window), Pointers.subclassWindowSymbol, Oop(ExternalHandle::New(hWnd)));
		ObjectMemory::countDown(retVal);
		ASSERT(m_bInterruptsDisabled);
		disableInterrupts(bDisabled);
	}
	__except (callbackExceptionFilter(GetExceptionInformation()))
	{
		trace("WARNING: Unwinding Interpreter::subclassWindow(%#x, %#x)\n", window, hWnd);
	}
}
Exemple #5
0
extern "C" Oop __stdcall PrimCompileForEval(Oop compilerOop, const char* szSource, Oop aClass, Oop aWorkspacePool, int flags, Oop notifier)
{
	ICompilerPtr piCompiler = NewCompiler();
	if (piCompiler == NULL)
		return Oop(GetVM()->NilPointer());

#ifdef _AFX
	flags |= Boot;
#endif
	return (Oop)piCompiler->CompileForEval(GetVM(), compilerOop, szSource, (POTE)aClass, (POTE)aWorkspacePool, FLAGS(flags), notifier);
}
Exemple #6
0
PointersOTE* __fastcall ObjectMemory::newPointerObject(BehaviorOTE* classPointer, MWORD oops)
{
	PointersOTE* ote = newUninitializedPointerObject(classPointer, oops);

	// Initialise the fields to nils
	const Oop nil = Oop(Pointers.Nil);		// Loop invariant (otherwise compiler reloads each time)
	VariantObject* pLocation = ote->m_location;
	const MWORD loopEnd = oops;
	for (MWORD i = 0; i<loopEnd; i++)
		pLocation->m_fields[i] = nil;

	ASSERT(ote->isPointers());

	return reinterpret_cast<PointersOTE*>(ote);
}
Exemple #7
0
void GarbageCollector::updatePointer(Oop *pointer)
{
    // I only can update reference objects.
    if(!pointer->isPointer())
        return;

    // Is this a weak reference that was collected?
    if(pointer->header->gcColor == White)
    {
        *pointer = Oop();
        return;
    }

    // Is this object in the heap?
    auto heap = memoryManager->getHeap();
    if(!heap->containsPointer(pointer->pointer))
        return;

    // Use the forwarding pointer.
    uint8_t **forwardingPointer = reinterpret_cast<uint8_t**> (pointer->pointer - sizeof(uint8_t*));
    pointer->pointer = *forwardingPointer;
}
Exemple #8
0
Oop* __fastcall Interpreter::primitivePerformMethod(CompiledMethod& , unsigned)
{
	Oop * sp = m_registers.m_stackPointer;
	ArrayOTE* oteArg = reinterpret_cast<ArrayOTE*>(*(sp));
	if (ObjectMemory::fetchClassOf(Oop(oteArg)) != Pointers.ClassArray)
		return primitiveFailure(0);		// Arguments not an Array
	Array* arguments = oteArg->m_location;
	Oop receiverPointer = *(sp-1);
	MethodOTE* oteMethod = reinterpret_cast<MethodOTE*>(*(sp-2));
	// Adjust sp to point at slot where receiver will be moved
	sp -= 2;

	//ASSERT(ObjectMemory::isKindOf(oteMethod, Pointers.ClassCompiledMethod));
	CompiledMethod* method = oteMethod->m_location;
	if (!ObjectMemory::isKindOf(receiverPointer, method->m_methodClass))
		return primitiveFailure(1);		// Wrong class of receiver

	const unsigned argCount = oteArg->pointersSize();
	const unsigned methodArgCount = method->m_header.argumentCount;
	if (methodArgCount != argCount)
		return primitiveFailure(2);		// Wrong number of arguments

	// Push receiver and arguments on stack (over the top of array and receiver)
	sp[0] = receiverPointer;					// Write receiver over the top of the method
	for (MWORD i = 0; i < argCount; i++)
	{
		Oop pushee = arguments->m_elements[i];
		// Don't count up because we are adding a stack ref.
		sp[i+1] = pushee;
	}
	m_registers.m_stackPointer = sp+argCount;

	// Don't count down any args
	executeNewMethod(oteMethod, argCount);
	return primitiveSuccess(0);
}
Exemple #9
0
BOOL __fastcall Interpreter::primitiveSnapshot(CompiledMethod&, unsigned argCount)
{
	Oop arg = stackValue(argCount - 1);
	char* szFileName;
	if (arg == Oop(Pointers.Nil))
		szFileName = 0;
	else if (ObjectMemory::fetchClassOf(arg) == Pointers.ClassString)
	{
		StringOTE* oteString = reinterpret_cast<StringOTE*>(arg);
		String* fileName = oteString->m_location;
		szFileName = fileName->m_characters;
	}
	else
		return primitiveFailure(0);

	bool bBackup;
	if (argCount >= 2)
		bBackup = reinterpret_cast<OTE*>(stackValue(argCount - 2)) == Pointers.True;
	else
		bBackup = false;

	SMALLINTEGER nCompressionLevel;
	if (argCount >= 3)
	{
		Oop oopCompressionLevel = stackValue(argCount - 3);
		nCompressionLevel = ObjectMemoryIsIntegerObject(oopCompressionLevel) ? ObjectMemoryIntegerValueOf(oopCompressionLevel) : 0;
	}
	else
		nCompressionLevel = 0;

	SMALLUNSIGNED nMaxObjects = 0;
	if (argCount >= 4)
	{
		Oop oopMaxObjects = stackValue(argCount - 4);
		if (ObjectMemoryIsIntegerObject(oopMaxObjects))
		{
			nMaxObjects = ObjectMemoryIntegerValueOf(oopMaxObjects);
		}
	}

	// N.B. It is not necessary to clear down the memory pools as the free list is rebuild on every image
	// load and the pool members, though not on the free list at present, are marked as free entries
	// in the object table

	// ZCT is reconciled, so objects may be deleted
	flushAtCaches();

	// Store the active frame of the active process before saving so available on image reload
	// We're not actually suspending the process now, but it appears like that to the snapshotted
	// image on restarting
	m_registers.PrepareToSuspendProcess();

#ifdef OAD
	DWORD timeStart = timeGetTime();
#endif

	int saveResult = ObjectMemory::SaveImageFile(szFileName, bBackup, nCompressionLevel, nMaxObjects);

#ifdef OAD
	DWORD timeEnd = timeGetTime();
	TRACESTREAM << "Time to save image: " << (timeEnd - timeStart) << " mS" << endl;
#endif

	if (!saveResult)
	{
		// Success
		popStack();
		return primitiveSuccess();
	}
	else
	{
		// Failure
		return primitiveFailure(saveResult);
	}
}
Exemple #10
0
// Value with args takes an array of arguments
Oop* __fastcall Interpreter::primitiveValueWithArgs()
{
	Oop* bp = m_registers.m_stackPointer;

	ArrayOTE* argumentArray = reinterpret_cast<ArrayOTE*>(*(bp));
	BlockOTE* oteBlock = reinterpret_cast<BlockOTE*>(*(bp-1));
	ASSERT(ObjectMemory::fetchClassOf(Oop(oteBlock)) == Pointers.ClassBlockClosure);
	BlockClosure* block = oteBlock->m_location;
	const MWORD blockArgumentCount = block->m_info.argumentCount;

	BehaviorOTE* arrayClass = ObjectMemory::fetchClassOf(Oop(argumentArray));
	if (arrayClass != Pointers.ClassArray)
		return primitiveFailure(1);

	const MWORD arrayArgumentCount = argumentArray->pointersSize();
	if (arrayArgumentCount != blockArgumentCount)
		return primitiveFailure(0);

	pop(2);								// N.B. ref count of Block will be assumed by storing into frame
	// Store old context details from interpreter registers
	m_registers.StoreContextRegisters();

	// Overwrite receiver block with receiver at time of closure.
	Oop closureReceiver = block->m_receiver;
	*(bp-1) = closureReceiver;
	// No need to count up the receiver since we've written it into a stack slot

	Array* args = argumentArray->m_location;

	// Code this carefully so compiler generates optimal code (it makes a poor job on its own)
	Oop* sp = bp;

	// Push the args from the array
	{
		for (unsigned i=0;i<arrayArgumentCount;i++)
		{
			Oop pushee = args->m_elements[i];
			*sp++ = pushee;
			// No need to count up since pushing on the stack
		}
	}

	const unsigned copiedValues = block->copiedValuesCount(oteBlock);
	{
		for (unsigned i=0;i<copiedValues;i++)
		{
			Oop oopCopied = block->m_copiedValues[i];
			*sp++ = oopCopied;
			// No need to count up since pushing on the stack
		}
	}

	// Nil out any extra stack temp slots we need
	const unsigned extraTemps = block->stackTempsCount();
	{
		const Oop nilPointer = Oop(Pointers.Nil);
		for (unsigned i=0;i<extraTemps;i++)
			*sp++ = nilPointer;
	}

	// Stack frame follows args...
	StackFrame* pFrame = reinterpret_cast<StackFrame*>(sp);

	pFrame->m_bp = reinterpret_cast<Oop>(bp)+1;
	m_registers.m_basePointer = reinterpret_cast<Oop*>(bp);

	// stack ref. removed so don't need to count down

	pFrame->m_caller = m_registers.activeFrameOop();
	// Having set caller can update the active frame Oop
	m_registers.m_pActiveFrame = pFrame;

	// Note that ref. count remains the same due dto overwritten receiver slot
	const unsigned envTemps = block->envTempsCount();
	if (envTemps > 0)
	{
		ContextOTE* oteContext = Context::New(envTemps, reinterpret_cast<Oop>(block->m_outer));
		pFrame->m_environment = reinterpret_cast<Oop>(oteContext);
		Context* context = oteContext->m_location;
		context->m_block = oteBlock;
		// Block has been written into a heap object slot, so must count up
		oteBlock->countUp();
	}
	else
		pFrame->m_environment = reinterpret_cast<Oop>(oteBlock);

	// We don't need to store down the IP and SP into the frame until it is suspended
	pFrame->m_ip = ZeroPointer;
	pFrame->m_sp = ZeroPointer;
	MethodOTE* oteMethod = block->m_method;
	pFrame->m_method = oteMethod;
	// Don't need to inc ref count for stack frame ref to method
	CompiledMethod* method = oteMethod->m_location;
	m_registers.m_pMethod = method;

	m_registers.m_instructionPointer = ObjectMemory::ByteAddressOfObjectContents(method->m_byteCodes) +
											block->initialIP() - 1;

	// New stack pointer points at last field of stack frame
	m_registers.m_stackPointer = reinterpret_cast<Oop*>(reinterpret_cast<BYTE*>(pFrame)+sizeof(StackFrame)) - 1;
	ASSERT(m_registers.m_stackPointer == &pFrame->m_bp);

	return primitiveSuccess(0);
}
Exemple #11
0
Oop* __fastcall Interpreter::primitivePerformWithArgs()
{
	Oop* const sp = m_registers.m_stackPointer;
	ArrayOTE* argumentArray = reinterpret_cast<ArrayOTE*>(*(sp));
	BehaviorOTE* arrayClass = ObjectMemory::fetchClassOf(Oop(argumentArray));
	if (arrayClass != Pointers.ClassArray)
		return primitiveFailure(0);
	
	// N.B. We're using a large stack, so don't bother checking for overflow
	//		(standard stack overflow mechanism should catch it)
									   
	// We must not get the length outside, in case small integer arg
	const unsigned argCount = argumentArray->pointersSize();
	
	// Save old message selector in case of prim failure (need to reinstate)
	SymbolOTE* performSelector = m_oopMessageSelector;

	// To ensure the argumentArray doesn't go away when we push its contents
	// onto the stack, in case we need it for recovery from an argument
	// count mismatch we leave its ref. count elevated

	SymbolOTE* selectorToPerform = reinterpret_cast<SymbolOTE*>(*(sp-1));
	if (ObjectMemoryIsIntegerObject(selectorToPerform))
		return primitiveFailure(1);

	m_oopMessageSelector = selectorToPerform;	// Get selector from stack
	// Don't need to count down the stack ref.
	ASSERT(!selectorToPerform->isFree());

	Oop newReceiver = *(sp-2);			// receiver is under selector and arg array

	// Push the args from the array onto the stack. We must do this before
	// looking up the method, because if the receiver does not understand
	// the method then the lookup routines copy the arguments off the stack
	// into a Message object
	Array* args = argumentArray->m_location;
	for (MWORD i=0; i<argCount; i++)
	{
		Oop pushee = args->m_elements[i];
		// Note no need to inc the ref. count when pushing on the stack
		sp[i-1] = pushee;
	}
	// Args written over top of selector and argument array (hence -2)
	m_registers.m_stackPointer = sp+argCount-2;

	// There is a subtle complication here when the receiver does not
	// understand the message, by which lookupMethodInClass() converts
	// the message we're trying to perform to a #doesNotUnderstand: with
	// all arguments moved to a Message. We still want to execute this
	// does not understand, so we also execute the method if the argument
	// counts do not match, but it was not understood. Note that it is
	// possible for a doesNotUnderstand: to be executed thru the first
	// test if the argumentArray contained only one argument. We allow
	// this to happen to avoid testing for not understood in the normal
	// case - just be aware of this anomaly.
	MethodOTE* methodPointer = findNewMethodInClass(ObjectMemory::fetchClassOf(newReceiver), argCount);
	CompiledMethod& method = *methodPointer->m_location;
	const unsigned methodArgCount = method.m_header.argumentCount;
	if (methodArgCount == argCount ||
			m_oopMessageSelector == Pointers.DoesNotUnderstandSelector)
	{
		// WE no longer need the argument array, but don't count it down since we only have a stack ref.
		executeNewMethod(methodPointer, methodArgCount);
		return primitiveSuccess(0);
	}
	else
	{
		// Receiver must have understood the message, but we had wrong 
		// number of arguments, so reinstate the stack and fail the primitive
		pop(argCount);
		pushObject((OTE*)m_oopMessageSelector);
		// Argument array already has artificially increased ref. count
		push(Oop(argumentArray));
		m_oopMessageSelector = performSelector;
		return primitiveFailure(1);
	}
}
Exemple #12
0
inline void Process::SetThread(void* handle)
{
	ObjectMemory::storePointerWithUnrefCntdValue(m_thread, Oop(handle) + 1);
}
Exemple #13
0
void Process::PostLoadFix(ProcessOTE* oteThis)
{
	// Any overlapped call running when the image was saved is no longer valid, so
	// we must clear down the "pointer" and remove the back reference
	if (m_thread != reinterpret_cast<Oop>(Pointers.Nil))
	{
		m_thread = reinterpret_cast<Oop>(Pointers.Nil);
		oteThis->countDown();
	}

	// Patch any badly created or corrupted processes
	if (!ObjectMemoryIsIntegerObject(m_fpControl))
	{
		m_fpControl = ObjectMemoryIntegerObjectOf(_DN_SAVE | _RC_NEAR | _PC_64 | _EM_INEXACT | _EM_UNDERFLOW | _EM_OVERFLOW | _EM_DENORMAL);
	}

	Oop* pFramePointer = &m_suspendedFrame;
	Oop framePointer = *pFramePointer;
	const void* stackBase = m_stack;
	const void* stackEnd = reinterpret_cast<BYTE*>(this) + oteThis->getSize() - 1;

	// Wind down the stack adjusting references to self as we go
	// Start with the suspended context
	const int delta = m_callbackDepth - 1;
	while (isIntegerObject(framePointer) && framePointer != ZeroPointer)
	{
		framePointer += delta;
		if (framePointer < Oop(stackBase) || framePointer > Oop(stackEnd))
		{
			trace(L"Warning: Process at %#x has corrupt frame pointer at %#x which will be nilled\n", this, pFramePointer);
			*pFramePointer = Oop(Pointers.Nil);
			break;
		}
		else
			*pFramePointer += delta;

		StackFrame* pFrame = StackFrame::FromFrameOop(*pFramePointer);
		if (isIntegerObject(pFrame->m_bp))
		{
			pFrame->m_bp += delta;
		}

		ASSERT(reinterpret_cast<void*>(pFrame->m_bp) > stackBase && reinterpret_cast<void*>(pFrame->m_bp) < stackEnd);

		// If a stack only frame, then adjust the BP
		if (!isIntegerObject(pFrame->m_environment))
		{
			// The frame has an object context, we need to adjust
			// its back pointer to the frame if it is a MethodContext
			// The context objects contain no other addresses any more
			OTE* oteContext = reinterpret_cast<OTE*>(pFrame->m_environment);
			if (ObjectMemory::isAContext(oteContext))
			{
				Context* ctx = static_cast<Context*>(oteContext->m_location);
				if (isIntegerObject(ctx->m_frame) && ctx->m_frame != ZeroPointer)
				{
					ctx->m_frame += delta;
					ASSERT(reinterpret_cast<void*>(ctx->m_frame) > stackBase && reinterpret_cast<void*>(ctx->m_frame) < stackEnd);
				}
			}
		}

		// Adjust the contexts SP
		if (isIntegerObject(pFrame->m_sp))
		{
			pFrame->m_sp += delta;
			ASSERT(reinterpret_cast<void*>(pFrame->m_sp) >= stackBase && reinterpret_cast<void*>(pFrame->m_sp) <= stackEnd);
		}

		pFramePointer = &pFrame->m_caller;
		framePointer = *pFramePointer;
	}

	framePointer = SuspendedFrame();
	if (isIntegerObject(framePointer) && framePointer != ZeroPointer)
	{
		// The size of the process should exactly correspond with that required to
		// hold up to the SP of the suspended frame
		StackFrame* pFrame = StackFrame::FromFrameOop(framePointer);
		int size = (pFrame->m_sp - 1) - reinterpret_cast<DWORD>(this) + sizeof(Oop);
		if (size > 0 && unsigned(size) < oteThis->getSize())
		{
			TRACE(L"WARNING: Resizing process %p from %u to %u\n", oteThis, oteThis->getSize(), size);
			oteThis->setSize(size);
		}
	}
	// else its dead or not started yet

	// Later we'll use this slot to count the callback depth
	m_callbackDepth = ZeroPointer;
}
Exemple #14
0
void ObjectMemory::FixupObject(OTE* ote, MWORD* oldLocation, const ImageHeader* pHeader)
{
	// Convert the class now separately
	BehaviorOTE* classPointer = reinterpret_cast<BehaviorOTE*>(FixupPointer(reinterpret_cast<OTE*>(ote->m_oteClass), static_cast<OTE*>(pHeader->BasePointer)));
#ifdef _DEBUG
	{
		PointersOTE* oteObj = reinterpret_cast<PointersOTE*>(ote);
		if (ote->isPointers() && (oteObj->getSize() % 2 == 1 ||
			classPointer == _Pointers.ClassByteArray ||
			classPointer == _Pointers.ClassAnsiString ||
			classPointer == _Pointers.ClassUtf8String ||
			classPointer == _Pointers.ClassSymbol))
		{
			TRACESTREAM<< L"Bad OTE for byte array " << LPVOID(&ote)<< L" marked as pointer" << std::endl;
			ote->beBytes();
		}
	}
#endif

	ote->m_oteClass = classPointer;

	if (ote->isPointers())
	{
		PointersOTE* otePointers = reinterpret_cast<PointersOTE*>(ote);
		VariantObject* obj = otePointers->m_location;

		const SMALLUNSIGNED numFields = ote->pointersSize();
		ASSERT(SMALLINTEGER(numFields) >= 0);
		// Fixup all the Oops
		for (SMALLUNSIGNED i = 0; i < numFields; i++)
		{
			Oop instPointer = obj->m_fields[i];
			if (!isIntegerObject(instPointer))
				obj->m_fields[i] = Oop(FixupPointer(reinterpret_cast<OTE*>(instPointer), static_cast<OTE*>(pHeader->BasePointer)));
		}

		if (classPointer == _Pointers.ClassProcess)
		{
			Process* process = static_cast<Process*>(ote->m_location);
			// We use the callbackDepth slot to store the delta in location
			// which we later use to adjust all the stack references.
			// The previous value is lost, but this is not important
			// as it must be reestablished as zero anyway
			process->BasicSetCallbackDepth(Oop(process) - Oop(oldLocation) + 1);
		}
		// else
		// MethodContext objects contain a pointer to their frame in the
		// stack, but we must fix that up later when walking down the stack.
	}
	else
	{
		if (classPointer == _Pointers.ClassExternalHandle)
		{
			// In Dolphin 4.0, all ExternalHandles are automatically nulled
			// on image load.

			ExternalHandle* handle = static_cast<ExternalHandle*>(ote->m_location);
			handle->m_handle = NULL;
		}
		// Look for the special image stamp object
		else if (classPointer == _Pointers.ClassContext)
		{
			ASSERT(ote->heapSpace() == OTEFlags::PoolSpace || ote->heapSpace() == OTEFlags::NormalSpace);

			// Can't deallocate now - must leave for collection later - maybe could go in the Zct though.
			VERIFY(ote->decRefs());
			deallocate(reinterpret_cast<OTE*>(ote));
		}
	}
}
Exemple #15
0
PointersOTE* __fastcall ObjectMemory::newPointerObject(BehaviorOTE* classPointer)
{
	ASSERT(isBehavior(Oop(classPointer)));
	return newPointerObject(classPointer, classPointer->m_location->fixedFields());
}