Oop* __fastcall Interpreter::primitiveNewFromStack(Oop* const stackPointer, unsigned) { BehaviorOTE* oteClass = reinterpret_cast<BehaviorOTE*>(*(stackPointer - 1)); Oop oopArg = (*stackPointer); SMALLINTEGER count; if (isIntegerObject(oopArg) && (count = ObjectMemoryIntegerValueOf(oopArg)) >= 0) { // Note that instantiateClassWithPointers counts up the class, PointersOTE* oteObj = ObjectMemory::newUninitializedPointerObject(oteClass, count); VariantObject* obj = oteObj->m_location; Oop* sp = stackPointer; sp = sp - count - 1; while (--count >= 0) { oopArg = *(sp + count); ObjectMemory::countUp(oopArg); obj->m_fields[count] = oopArg; } // Save down SP in case ZCT is reconciled on adding result m_registers.m_stackPointer = sp; *sp = reinterpret_cast<Oop>(oteObj); ObjectMemory::AddToZct((OTE*)oteObj); return sp; } else { return primitiveFailure(0); } }
primitiveAtPut(void) { float *floatPtr; double floatValue; sqInt index; sqInt rcvr; sqInt value; value = stackValue(0); if (isIntegerObject(value)) { floatValue = ((double) (integerValueOf(value)) ); } else { floatValue = floatValueOf(value); } index = stackIntegerValue(1); rcvr = stackValue(2); if (!((!(failed())) && ((isWords(rcvr)) && ((index > 0) && (index <= (slotSizeOf(rcvr))))))) { return primitiveFail(); } floatPtr = firstIndexableField(rcvr); floatPtr[index - 1] = (((float) floatValue)); popthenPush(3, value); return 0; }
static sqInt stackLightArrayValue(sqInt stackIndex) { // B3DAcceleratorPlugin>>#stackLightArrayValue: sqInt array; sqInt arraySize; sqInt i; sqInt oop; array = stackObjectValue(stackIndex); if (array == null) { return null; } if (array == (nilObject())) { return null; } if (!((fetchClassOf(array)) == (classArray()))) { return primitiveFail(); } arraySize = slotSizeOf(array); for (i = 0; i <= (arraySize - 1); i += 1) { oop = fetchPointerofObject(i, array); if (isIntegerObject(oop)) { return primitiveFail(); } if (!((isWords(oop)) && ((slotSizeOf(oop)) == 32))) { return primitiveFail(); } } return array; }
primitiveAtPut(void) { // FloatArrayPlugin>>#primitiveAtPut float *floatPtr; double floatValue; sqInt index; sqInt rcvr; sqInt value; value = stackValue(0); if (isIntegerObject(value)) { floatValue = ((double) (integerValueOf(value)) ); } else { floatValue = floatValueOf(value); } index = stackIntegerValue(1); rcvr = stackObjectValue(2); if (failed()) { return null; } success(isWords(rcvr)); success((index > 0) && (index <= (slotSizeOf(rcvr)))); if (failed()) { return null; } floatPtr = firstIndexableField(rcvr); floatPtr[index - 1] = (((float) floatValue)); if (!(failed())) { popthenPush(3, value); } }
Oop* __fastcall Interpreter::primitiveNewPinned(Oop* const sp, unsigned) { BehaviorOTE* oteClass = reinterpret_cast<BehaviorOTE*>(*(sp - 1)); Oop oopArg = (*sp); SMALLINTEGER size; if (isIntegerObject(oopArg) && (size = ObjectMemoryIntegerValueOf(oopArg)) >= 0) { InstanceSpecification instSpec = oteClass->m_location->m_instanceSpec; if (!(instSpec.m_pointers || instSpec.m_nonInstantiable)) { BytesOTE* newObj = ObjectMemory::newByteObject<true, true>(oteClass, size); *(sp - 1) = reinterpret_cast<Oop>(newObj); ObjectMemory::AddToZct(reinterpret_cast<OTE*>(newObj)); return sp - 1; } else { // Not indexable, or non-instantiable return primitiveFailure(instSpec.m_nonInstantiable ? 1 : 2); } } else { return primitiveFailure(0); // Size must be positive SmallInteger } }
primitiveFileTruncate(void) { // FilePlugin>>#primitiveFileTruncate SQFile *file; sqInt objectPointer; sqInt sz; squeakFileOffsetType truncatePosition; if (!(isIntegerObject(stackValue(0)))) { sz = sizeof(squeakFileOffsetType); if ((byteSizeOf(stackValue(0))) > sz) { return primitiveFail(); } } truncatePosition = positive64BitValueOf(stackValue(0)); /* begin fileValueOf: */ objectPointer = stackValue(1); if (!((isBytes(objectPointer)) && ((byteSizeOf(objectPointer)) == (sizeof(SQFile))))) { primitiveFail(); file = null; goto l1; } file = firstIndexableField(objectPointer); l1: /* end fileValueOf: */; if (!(failed())) { sqFileTruncate(file, truncatePosition); } if (!(failed())) { pop(2); } }
OTE* __fastcall ObjectMemory::recursiveFree(OTE* rootOTE) { HARDASSERT(!isIntegerObject(rootOTE)); HARDASSERT(!isPermanent(rootOTE)); HARDASSERT(!rootOTE->isFree()); HARDASSERT(rootOTE->m_flags.m_count == 0); #ifndef _AFX if (rootOTE->isFinalizable()) { finalize(rootOTE); rootOTE->beUnfinalizable(); } else #endif { // Deal with the class first, as this is now held in the OTE recursiveCountDown(reinterpret_cast<POTE>(rootOTE->m_oteClass)); if (rootOTE->isPointers()) { // Recurse through referenced objects as necessary const MWORD lastPointer = rootOTE->getWordSize(); Oop* pFields = reinterpret_cast<Oop*>(rootOTE->m_location); // Start after the header (only includes size now, which is not an Oop) for (MWORD i = ObjectHeaderSize; i < lastPointer; i++) { Oop fieldPointer = pFields[i]; if (!isIntegerObject(fieldPointer)) { OTE* fieldOTE = reinterpret_cast<OTE*>(fieldPointer); recursiveCountDown(fieldOTE); } } } deallocate(rootOTE); } return rootOTE; // Important for some assembler routines - will be non-zero, so can act as TRUE }
static AsyncFile * asyncFileValueOf(sqInt oop) { // AsynchFilePlugin>>#asyncFileValueOf: success((!(isIntegerObject(oop))) && ((isBytes(oop)) && ((slotSizeOf(oop)) == (sizeof(AsyncFile))))); if (failed()) { return null; } return (AsyncFile *) (oop + 4); }
STDMETHODIMP_(VOID) CDolphinSmalltalk::MakeImmutable( /* [in] */ Oop oop, /* [in] */ BOOL bImmutable) { if (isIntegerObject(oop)) return; if (bImmutable) reinterpret_cast<OTE*>(oop)->beImmutable(); else reinterpret_cast<OTE*>(oop)->beMutable(); }
Oop* __fastcall Interpreter::primitiveShallowCopy(Oop* const sp, unsigned) { OTE* receiver = reinterpret_cast<OTE*>(*sp); ASSERT(!isIntegerObject(receiver)); OTE* copy = receiver->m_flags.m_pointer ? (OTE*)ObjectMemory::shallowCopy(reinterpret_cast<PointersOTE*>(receiver)) : (OTE*)ObjectMemory::shallowCopy(reinterpret_cast<BytesOTE*>(receiver)); *sp = (Oop)copy; ObjectMemory::AddToZct(copy); return sp; }
/* Matrix2x3Plugin>>#loadArgumentPoint: */ static sqInt loadArgumentPoint(sqInt point) { int isInt; sqInt oop; if (failed()) { return null; } if (!((fetchClassOf(point)) == (classPoint()))) { return primitiveFail(); } oop = fetchPointerofObject(0, point); isInt = isIntegerObject(oop); if (!(isInt || (isFloatObject(oop)))) { return primitiveFail(); } if (isInt) { m23ArgX = integerValueOf(oop); } else { m23ArgX = floatValueOf(oop); } oop = fetchPointerofObject(1, point); isInt = isIntegerObject(oop); if (!(isInt || (isFloatObject(oop)))) { return primitiveFail(); } if (isInt) { m23ArgY = integerValueOf(oop); } else { m23ArgY = floatValueOf(oop); } return 0; }
Oop* __fastcall Interpreter::primitiveNewWithArg(Oop* const sp, unsigned) { BehaviorOTE* oteClass = reinterpret_cast<BehaviorOTE*>(*(sp - 1)); Oop oopArg = (*sp); // Unfortunately the compiler can't be persuaded to perform this using just the sar and conditional jumps on no-carry and signed; // it generates both the bit test and the shift. SMALLINTEGER size; if (isIntegerObject(oopArg) && (size = ObjectMemoryIntegerValueOf(oopArg)) >= 0) { InstanceSpecification instSpec = oteClass->m_location->m_instanceSpec; if ((instSpec.m_value & (InstanceSpecification::IndexableMask | InstanceSpecification::NonInstantiableMask)) == InstanceSpecification::IndexableMask) { if (instSpec.m_pointers) { PointersOTE* newObj = ObjectMemory::newPointerObject(oteClass, size + instSpec.m_fixedFields); *(sp - 1) = reinterpret_cast<Oop>(newObj); ObjectMemory::AddToZct(reinterpret_cast<OTE*>(newObj)); return sp - 1; } else { BytesOTE* newObj = ObjectMemory::newByteObject<true, true>(oteClass, size); *(sp - 1) = reinterpret_cast<Oop>(newObj); ObjectMemory::AddToZct(reinterpret_cast<OTE*>(newObj)); return sp - 1; } } else { // Not indexable, or non-instantiable return primitiveFailure(instSpec.m_nonInstantiable ? 1 : 2); } } else { return primitiveFailure(0); // Size must be positive SmallInteger } }
// Compact an object by updating all the Oops it contains using the // forwarding pointers in the old OT. void ObjectMemory::compactObject(OTE* ote) { // We shouldn't come in here unless OTE already fixed for this object HARDASSERT(ote >= m_pOT && ote < m_pFreePointerList); // First fix up the class (remember that the new object pointer is stored in the // old one's object location slot compactOop(ote->m_oteClass); if (ote->isPointers()) { VariantObject* varObj = static_cast<VariantObject*>(ote->m_location); const MWORD lastPointer = ote->pointersSize(); for (MWORD i = 0; i < lastPointer; i++) { // This will get nicely optimised by the Compiler Oop fieldPointer = varObj->m_fields[i]; // We don't need to visit SmallIntegers and objects we've already visited if (!isIntegerObject(fieldPointer)) { OTE* fieldOTE = reinterpret_cast<OTE*>(fieldPointer); // If pointing at a free'd object ,then it has been moved if (fieldOTE->isFree()) { // Should be one of the old OT entries, pointing outside the o Oop movedTo = reinterpret_cast<Oop>(fieldOTE->m_location); HARDASSERT(movedTo >= (Oop)m_pOT && movedTo < (Oop)m_pFreePointerList); // Get the new OTE from the old ... varObj->m_fields[i] = movedTo; } } } } // else, we don't even need to look at the body of byte objects any more }
static sqInt isNonIntegerObject(sqInt objectPointer) { return !isIntegerObject(objectPointer); }
STDMETHODIMP_(BOOL) CDolphinSmalltalk::IsImmutable( /* [in] */ Oop oop) { return isIntegerObject(oop) || (reinterpret_cast<OTE*>(oop)->isImmutable()); }
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)); } } }
POBJECT ObjectMemory::basicResize(POTE ote, MWORD byteSize, int extra) { ASSERT(!isIntegerObject(ote)); POBJECT pObject; /* #ifdef _DEBUG TRACESTREAM << "Resizing "; Interpreter::printObject(Oop(ote), TRACESTREAM); TRACESTREAM << " (" << ote->m_location << ") from size " << ObjectMemory::sizeOf(ote) << " to size " << byteSize << "\n"; #endif */ switch(ote->heapSpace()) { case OTEFlags::NormalSpace: { // TRACE("Resizing normal object...\n"); pObject = ote->m_location; pObject = reallocChunk(pObject, byteSize+extra); if (pObject) { ote->m_location = pObject; ote->setSize(byteSize); } break; } case OTEFlags::VirtualSpace: // TRACE("Resizing virtual object...\n"); pObject = resizeVirtual(ote, byteSize+extra); break; case OTEFlags::PoolSpace: { #if defined(_DEBUG) if (abs(Interpreter::executionTrace) > 0) checkPools(); #endif // May be able to do some quicker resizing here if size is still in same pool? if ((byteSize+extra) > MaxSmallObjectSize) { pObject = allocChunk(byteSize+extra); ote->m_flags.m_space = OTEFlags::NormalSpace; } else pObject = allocSmallChunk(byteSize+extra); POBJECT pOldObject = ote->m_location; MWORD oldSize = ote->getSize(); memcpy(pObject, pOldObject, min(oldSize, byteSize)); freeSmallChunk(pOldObject, ote->sizeOf()); ote->m_location = pObject; ote->setSize(byteSize); break; } default: // Not resizeable return NULL; } #if defined(_DEBUG) if (abs(Interpreter::executionTrace) > 0) checkPools(); // TRACESTREAM << "After Resize: "; // Interpreter::printObject(Oop(ote), TRACESTREAM); // TRACESTREAM << "\n"; #endif return pObject; }
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; }