Object *createConstructorObject(MethodBlock *mb) { Object *reflect_ob, *vm_reflect_ob, *classes; char *signature, *sig; if((reflect_ob = allocObject(cons_reflect_class)) == NULL) return NULL; if((vm_reflect_ob = allocObject(vmcons_reflect_class)) == NULL) return NULL; signature = sig = sysMalloc(strlen(mb->type) + 1); strcpy(sig, mb->type); classes = convertSig2ClassArray(&sig, mb->class); sysFree(signature); if(classes == NULL) return NULL; INST_DATA(vm_reflect_ob, Class*, vm_cons_class_offset) = mb->class; INST_DATA(vm_reflect_ob, Object*, vm_cons_param_offset) = classes; INST_DATA(vm_reflect_ob, int, vm_cons_slot_offset) = mb - CLASS_CB(mb->class)->methods; /* Link the Java-level and VM-level objects together */ INST_DATA(vm_reflect_ob, Object*, vm_cons_cons_offset) = reflect_ob; INST_DATA(reflect_ob, Object*, cons_cons_offset) = vm_reflect_ob; return reflect_ob; }
Object *initJavaThread(Thread *thread, char is_daemon, const char *name) { Object *vmthread, *jlthread, *thread_name = NULL; /* Create the java.lang.Thread object and the VMThread */ if((vmthread = allocObject(vmthread_class)) == NULL || (jlthread = allocObject(thread_class)) == NULL) return NULL; //thread->ee->thread = jlthread; thread->thread = jlthread; INST_DATA(vmthread)[vmData_offset] = (uintptr_t)thread; INST_DATA(vmthread)[thread_offset] = (uintptr_t)jlthread; /* Create the string for the thread name. If null is specified the initialiser method will generate a name of the form Thread-X */ if(name != NULL && (thread_name = Cstr2String(name)) == NULL) return NULL; /* Call the initialiser method -- this is for use by threads created or attached by the VM "outside" of Java */ DummyFrame dummy; executeMethod(&dummy, jlthread, init_mb, vmthread, thread_name, NORM_PRIORITY, is_daemon); /* Add thread to thread ID map hash table. */ addThreadToHash(thread); return jlthread; }
static void poolStatInit(PoolStat stat, mps_pool_t pool, size_t objSize) { mps_addr_t s1, s2, s3; stat->pool = pool; stat->objSize = objSize; stat->ncCount = 0; stat->aCount = 0; stat->fCount = 0; /* allocate 3 half-size sentinel objects, freeing the middle one */ /* to leave a bit of space for the control pool */ s1 = allocObject(pool, objSize / 2); stat->min = s1; stat->max = s1; stat->aCount++; s2 = allocObject(pool, objSize / 2); recordNewObjectStat(stat, s2); s3 = allocObject(pool, objSize / 2); recordNewObjectStat(stat, s3); mps_free(pool, s2, objSize / 2); recordFreedObjectStat(stat); }
Object *classlibNewDirectByteBuffer(void *addr, long long capacity) { Object *buff, *rawdata; if((buff = allocObject(buffImpl_class)) != NULL && (rawdata = allocObject(rawdata_class)) != NULL) { INST_DATA(rawdata, void*, rawdata_offset) = addr; executeMethod(buff, buffImpl_init_mb, NULL, rawdata, (int)capacity, (int)capacity, 0); } return buff; }
Object *classlibThreadPreInit(Class *thread_class, Class *thrdGrp_class) { MethodBlock *system_init_mb, *main_init_mb; FieldBlock *thread_status_fb, *eetop_fb; Object *system, *main, *main_name; init_mb_with_name = findMethod(thread_class, SYMBOL(object_init), SYMBOL(_java_lang_ThreadGroup_java_lang_String__V)); init_mb_no_name = findMethod(thread_class, SYMBOL(object_init), SYMBOL(_java_lang_ThreadGroup_java_lang_Runnable__V)); thread_status_fb = findField(thread_class, SYMBOL(threadStatus), SYMBOL(I)); eetop_fb = findField(thread_class, SYMBOL(eetop), SYMBOL(J)); system_init_mb = findMethod(thrdGrp_class, SYMBOL(object_init), SYMBOL(___V)); main_init_mb = findMethod(thrdGrp_class, SYMBOL(object_init), SYMBOL(_java_lang_ThreadGroup_java_lang_String__V)); if(init_mb_with_name == NULL || init_mb_no_name == NULL || system_init_mb == NULL || main_init_mb == NULL || thread_status_fb == NULL || eetop_fb == NULL) return NULL; CLASS_CB(thread_class)->flags |= JTHREAD; thread_status_offset = thread_status_fb->u.offset; eetop_offset = eetop_fb->u.offset; if((system = allocObject(thrdGrp_class)) == NULL) return NULL; executeMethod(system, system_init_mb); if(exceptionOccurred()) return NULL; if((main = allocObject(thrdGrp_class)) == NULL || (main_name = Cstr2String("main")) == NULL) return NULL; executeMethod(main, main_init_mb, system, main_name); if(exceptionOccurred()) return NULL; return main; }
Object *classlibCreateMethodObject(MethodBlock *mb) { AnnotationData *annotations = mb->annotations == NULL ? NULL : mb->annotations->annotations; AnnotationData *dft_val = mb->annotations == NULL ? NULL : mb->annotations->dft_val; AnnotationData *parameters = mb->annotations == NULL ? NULL : mb->annotations->parameters; Object *reflect_ob; if((reflect_ob = allocObject(method_reflect_class)) == NULL) return NULL; executeMethod(reflect_ob, mthd_init_mb, mb->class, findInternedString(createString(mb->name)), getMethodParameterTypes(mb), getMethodReturnType(mb), getMethodExceptionTypes(mb), mb->access_flags, mb - CLASS_CB(mb->class)->methods, mb->signature == NULL ? NULL : findInternedString(createString(mb->signature)), getAnnotationsAsArray(annotations), getAnnotationsAsArray(parameters), getAnnotationsAsArray(dft_val)); return reflect_ob; }
/*Create a new String *invoked by:OPC_LDC */ O createJstring(char *s) { if (java_lang_String == NULL) java_lang_String = loadClass("java/lang/String"); ClassBlock_t *cb = CLASS_CB(java_lang_String); if (!inited) initString(); O char_obj, string_obj; FieldBlock_t *fb; int length, offset; length = strlen(s); char_obj = char2Char(s); short *data = (short *) char_obj->data; unsigned char *ss = (unsigned char *) s; convertUtf8(ss, data); string_obj = allocObject(java_lang_String); string_obj->type = OBJECT_STRING; OBJECT_DATA(string_obj, value_offset - 1, O) = char_obj; OBJECT_DATA(string_obj, count_offset - 1, int) = length; //*(((Object**)string_obj->data)+offset-1) = char_obj; string_obj->cb = cb; string_obj->el_size = sizeof(int); return string_obj; }
inline void QScriptEnginePrivate::newObject(QScriptValueImpl *o, const QScriptValueImpl &proto, QScriptClassInfo *oc) { QScriptObject *od = allocObject(); od->reset(); }
BytesOTE* __fastcall ObjectMemory::shallowCopy(BytesOTE* ote) { ASSERT(ote->isBytes()); // Copying byte objects is simple and fast VariantByteObject& bytes = *ote->m_location; BehaviorOTE* classPointer = ote->m_oteClass; MWORD objectSize = ote->sizeOf(); OTE* copyPointer; // Allocate an uninitialized object ... VariantByteObject* pLocation = static_cast<VariantByteObject*>(allocObject(objectSize, copyPointer)); ASSERT((objectSize > MaxSizeOfPoolObject && copyPointer->heapSpace() == OTEFlags::NormalSpace) || copyPointer->heapSpace() == OTEFlags::PoolSpace); ASSERT(copyPointer->getSize() == objectSize); // This set does not want to copy over the immutability bit - i.e. even if the original was immutable, the // copy will never be. copyPointer->setSize(ote->getSize()); copyPointer->m_dwFlags = (copyPointer->m_dwFlags & ~OTEFlags::WeakMask) | (ote->m_dwFlags & OTEFlags::WeakMask); ASSERT(copyPointer->isBytes()); copyPointer->m_oteClass = classPointer; classPointer->countUp(); // Copy the entire object over the other one, including any null terminator and object header memcpy(pLocation, &bytes, objectSize); return reinterpret_cast<BytesOTE*>(copyPointer); }
object MemoryManager::allocByte(size_t size) { object newObj; newObj = allocObject((size + 1) / 2); /* negative size fields indicate bit objects */ objectRef(newObj).size = -size; return newObj; }
object allocByte(int size) { object newObj; newObj = allocObject((size + 1) / 2); /* negative size fields indicate bit objects */ sizeField(newObj) = -size; return newObj; }
void createJavaThread(Object *jThread, long long stack_size) { //ExecEnv *ee; Thread *thread; Thread *self = threadSelf(); Object *vmthread = allocObject(vmthread_class); if(vmthread == NULL) return; disableSuspend(self); pthread_mutex_lock(&lock); if(INST_DATA(jThread)[vmthread_offset]) { pthread_mutex_unlock(&lock); enableSuspend(self); signalException(java_lang_IllegalThreadStateException, "thread already started"); return; } //ee = (ExecEnv*)sysMalloc(sizeof(ExecEnv)); thread = new Thread; //memset(ee, 0, sizeof(ExecEnv)); // thread->ee = ee; // ee->thread = jThread; thread->thread = jThread; // ee->stack_size = stack_size; INST_DATA(vmthread)[vmData_offset] = (uintptr_t)thread; INST_DATA(vmthread)[thread_offset] = (uintptr_t)jThread; INST_DATA(jThread)[vmthread_offset] = (uintptr_t)vmthread; pthread_mutex_unlock(&lock); if(pthread_create(&thread->tid, &attributes, threadStart, thread)) { INST_DATA(jThread)[vmthread_offset] = 0; //sysFree(ee); enableSuspend(self); signalException(java_lang_OutOfMemoryError, "can't create thread"); return; } pthread_mutex_lock(&lock); /* Wait for thread to start */ while(thread->state == 0) pthread_cond_wait(&cv, &lock); pthread_mutex_unlock(&lock); enableSuspend(self); }
Object *createStringFromUnicode(unsigned short *unicode, int len) { Object *array = allocTypeArray(T_CHAR, len); Object *ob = allocObject(string_class); if(array != NULL && ob != NULL) { unsigned short *data = (unsigned short *)ARRAY_DATA(array); memcpy(data, unicode, len*sizeof(unsigned short)); INST_DATA(ob)[count_offset] = len; INST_DATA(ob)[value_offset] = (uintptr_t)array; return ob; } return NULL; }
void signalChainedExceptionClass(Class *exception, char *message, Object *cause) { Object *exp = allocObject(exception); Object *str = message == NULL ? NULL : Cstr2String(message); MethodBlock *init = lookupMethod(exception, SYMBOL(object_init), SYMBOL(_java_lang_String__V)); if(exp && init) { executeMethod(exp, init, str); if(cause && !exceptionOccurred()) { MethodBlock *mb = lookupMethod(exception, SYMBOL(initCause), SYMBOL(_java_lang_Throwable__java_lang_Throwable)); if(mb) executeMethod(exp, mb, cause); } setException(exp); } }
Object *classlibCreateFieldObject(FieldBlock *fb) { Object *reflect_ob; if((reflect_ob = allocObject(field_reflect_class)) == NULL) return NULL; executeMethod(reflect_ob, fld_init_mb, fb->class, findInternedString(createString(fb->name)), getFieldType(fb), fb->access_flags, fb - CLASS_CB(fb->class)->fields, fb->signature == NULL ? NULL : findInternedString(createString(fb->signature)), getAnnotationsAsArray(fb->annotations)); return reflect_ob; }
static void allocMultiple(PoolStat stat) { mps_addr_t objects[allocsPerIteration]; size_t i; /* allocate a few objects, and record stats for them */ for (i = 0; i < allocsPerIteration; i++) { mps_addr_t obj = allocObject(stat->pool, stat->objSize); recordNewObjectStat(stat, obj); objects[i] = obj; } /* free one of the objects, to make the test more interesting */ i = rnd() % allocsPerIteration; mps_free(stat->pool, objects[i], stat->objSize); recordFreedObjectStat(stat); }
Object *createString(const char* utf8) { int len = utf8Len(utf8); unsigned short *data; Object *array; Object *ob; if((array = allocTypeArray(T_CHAR, len)) == NULL || (ob = allocObject(string_class)) == NULL) return NULL; data = (unsigned short *)ARRAY_DATA(array); convertUtf8(utf8, data); INST_DATA(ob)[count_offset] = len; INST_DATA(ob)[value_offset] = (uintptr_t)array; return ob; }
PointersOTE* __fastcall ObjectMemory::newUninitializedPointerObject(BehaviorOTE* classPointer, MWORD oops) { // Total size must fit in a DWORD bits ASSERT(oops < ((DWORD(1) << 30) - ObjectHeaderSize)); // Don't worry, compiler will not really use multiply instruction here MWORD objectSize = SizeOfPointers(oops); OTE* ote; allocObject(objectSize, ote); ASSERT((objectSize > MaxSizeOfPoolObject && ote->heapSpace() == OTEFlags::NormalSpace) || ote->heapSpace() == OTEFlags::PoolSpace); // These are stored in the object itself ASSERT(ote->getSize() == objectSize); classPointer->countUp(); ote->m_oteClass = classPointer; // DO NOT Initialise the fields to nils ASSERT(ote->isPointers()); return reinterpret_cast<PointersOTE*>(ote); }
object MemoryManager::allocObject(size_t memorySize) { int i; size_t position; bool done; TObjectFreeListIterator tpos; /* first try the free lists, this is fastest */ if((tpos = objectFreeList.find(memorySize)) != objectFreeList.end() && tpos->second != nilobj) { position = tpos->second; objectFreeList.erase(tpos); objectFreeListInv.erase(position); } /* if not there, next try making a size zero object and making it bigger */ else if ((tpos = objectFreeList.find(0)) != objectFreeList.end() && tpos->second != nilobj) { position = tpos->second; objectFreeList.erase(tpos); objectFreeListInv.erase(position); objectTable[position].size = memorySize; objectTable[position].memory = mBlockAlloc(memorySize); } else { /* not found, must work a bit harder */ done = false; /* first try making a bigger object smaller */ TObjectFreeListIterator tbigger = objectFreeList.upper_bound(memorySize); if(tbigger != objectFreeList.end() && tbigger->second != nilobj) { position = tbigger->second; objectFreeList.erase(tbigger); objectFreeListInv.erase(position); /* just trim it a bit */ objectTable[position].size = memorySize; done = true; } /* next try making a smaller object bigger */ if (! done) { TObjectFreeListIterator tsmaller = objectFreeList.lower_bound(memorySize); if(tsmaller != objectFreeList.begin() && (--tsmaller != objectFreeList.begin()) && tsmaller->second != nilobj) { position = tsmaller->second; objectFreeList.erase(tsmaller); objectFreeListInv.erase(position); objectTable[position].size = memorySize; free(objectTable[position].memory); objectTable[position].memory = mBlockAlloc(memorySize); done = true; } } /* if we STILL don't have it then there is nothing */ /* more we can do */ if (! done) { if(debugging) fprintf(stderr, "Failed to find an available object, trying GC\n"); if(garbageCollect() > 0) { return allocObject(memorySize); } else { if(debugging) fprintf(stderr, "No suitable objects available after GC, growing store.\n"); growObjectStore(growAmount); return allocObject(memorySize); } } } /* set class and type */ objectTable[position].referenceCount = 0; objectTable[position]._class = nilobj; objectTable[position].size = memorySize; return(position << 1); }
void octGridLoadBinary( tOctGrid* pOctGrid, const char* szFileName, void* (*allocObject)( const char* szName, void* pUserData0, void* pUserData1, void* pUserData2, void* pUserData3 ), void* pUserData0, void* pUserData1, void* pUserData2, void* pUserData3 ) { char szFullPath[256]; getFullPath( szFullPath, szFileName ); //FILE* fp = fopen( szFullPath, "rb" ); FILE* fp = fopen( szFileName, "rb" ); assert( fp ); float fNodeSize = 0.0f; fread( &pOctGrid->mDimension, sizeof( tVector4 ), 1, fp ); fread( &fNodeSize, sizeof( float ), 1, fp ); fread( &pOctGrid->miNumNodesInDimension, sizeof( int ), 1, fp ); fread( &pOctGrid->mCenter, sizeof( tVector4 ), 1, fp ); pOctGrid->miNumNodes = pOctGrid->miNumNodesInDimension * pOctGrid->miNumNodesInDimension * pOctGrid->miNumNodesInDimension; int iValidNodes = 0; fread( &iValidNodes, sizeof( int ), 1, fp ); for( int i = 0; i < iValidNodes; i++ ) { // index of the node int iIndex = 0; fread( &iIndex, sizeof( int ), 1, fp ); assert( iIndex >= 0 && iIndex < pOctGrid->miNumNodes ); tOctNode* pNode = &pOctGrid->maNodes[iIndex]; // center and number of objects in the node tVector4 nodeCenter = { 0.0f, 0.0f, 0.0f, 1.0f }; fread( &nodeCenter, sizeof( tVector4 ), 1, fp ); fread( &pNode->miNumObjects, sizeof( int ), 1, fp ); // add objects to node for( int j = 0; j < pNode->miNumObjects; j++ ) { char szName[256]; fread( szName, sizeof( char ), sizeof( szName ), fp ); void* pObject = allocObject( szName, pUserData0, pUserData1, pUserData2, pUserData3 ); octGridAddObjectToNode( pOctGrid, iIndex, pObject ); tVector4 modelCenter = { 0.0f, 0.0f, 0.0f, 1.0f }; float fRadius = 0.0f; fread( &modelCenter, sizeof( tVector4 ), 1, fp ); fread( &fRadius, sizeof( float ), 1, fp ); } // for j = 0 to num objects } // for i = 0 to num valid nodes fclose( fp ); }
void octGridLoad( tOctGrid* pOctGrid, const char* szFileName, void* (*allocObject)( const char* szName, void* pUserData0, void* pUserData1, void* pUserData2, void* pUserData3 ), void* pUserData0, void* pUserData1, void* pUserData2, void* pUserData3 ) { char szFullPath[256]; getFullPath( szFullPath, szFileName ); TiXmlDocument doc( szFullPath ); bool bLoaded = doc.LoadFile(); if( bLoaded ) { TiXmlNode* pNode = doc.FirstChild(); while( pNode ) { TiXmlNode* pDimension = pNode->FirstChild( "dimensions" ); const char* szDimensions = pDimension->FirstChild()->Value(); tVector4 gridDimension; parseVector( &gridDimension, szDimensions ); TiXmlNode* pSize = pNode->FirstChild( "node_size" ); const char* szSize = pSize->FirstChild()->Value(); float fNodeSize = (float)atof( szSize ); TiXmlNode* pCenter = pNode->FirstChild( "center" ); const char* szCenter = pCenter->FirstChild()->Value(); tVector4 center; parseVector( ¢er, szCenter ); // init grid octGridInit( pOctGrid, ¢er, gridDimension.fX, fNodeSize ); // add object to oct node TiXmlNode* pOctNode = pNode->FirstChild( "node" ); while( pOctNode ) { TiXmlNode* pNumObjects = pOctNode->FirstChild( "num_obj" ); const char* szNumObjects = pNumObjects->FirstChild()->Value(); int iNumObjects = atoi( szNumObjects ); const char* szIndex = pOctNode->FirstChild( "index" )->FirstChild()->Value(); int iOctNodeIndex = (int)atoi( szIndex ); if( iNumObjects > 0 ) { TiXmlNode* pObjects = pOctNode->FirstChild( "object" ); while( pObjects ) { const char* szName = pObjects->FirstChild( "name" )->FirstChild()->Value(); void* pObject = allocObject( szName, pUserData0, pUserData1, pUserData2, pUserData3 ); octGridAddObjectToNode( pOctGrid, iOctNodeIndex, pObject ); pObjects = pObjects->NextSibling(); } } pOctNode = pOctNode->NextSibling(); ++iOctNodeIndex; } // while valid oct node pNode = pNode->NextSibling(); } // while grid } // if loaded }
template <bool MaybeZ, bool Initialized> BytesOTE* ObjectMemory::newByteObject(BehaviorOTE* classPointer, MWORD elementCount) { Behavior& byteClass = *classPointer->m_location; OTE* ote; if (!MaybeZ || !byteClass.m_instanceSpec.m_nullTerminated) { ASSERT(!classPointer->m_location->m_instanceSpec.m_nullTerminated); VariantByteObject* newBytes = static_cast<VariantByteObject*>(allocObject(elementCount + SizeOfPointers(0), ote)); ASSERT((elementCount > MaxSizeOfPoolObject && ote->heapSpace() == OTEFlags::NormalSpace) || ote->heapSpace() == OTEFlags::PoolSpace); ASSERT(ote->getSize() == elementCount + SizeOfPointers(0)); if (Initialized) { // Byte objects are initialized to zeros (but not the header) // Note that we round up to initialize to the next DWORD // This can be useful when working on a 32-bit word machine ZeroMemory(newBytes->m_fields, _ROUND2(elementCount, sizeof(DWORD))); classPointer->countUp(); } ote->m_oteClass = classPointer; ote->beBytes(); } else { ASSERT(classPointer->m_location->m_instanceSpec.m_nullTerminated); MWORD objectSize; switch (reinterpret_cast<const StringClass&>(byteClass).Encoding) { case StringEncoding::Ansi: case StringEncoding::Utf8: objectSize = elementCount * sizeof(AnsiString::CU); break; case StringEncoding::Utf16: objectSize = elementCount * sizeof(Utf16String::CU); break; case StringEncoding::Utf32: objectSize = elementCount * sizeof(Utf32String::CU); break; default: __assume(false); break; } // TODO: Allocate the correct number of null term bytes based on the encoding objectSize += NULLTERMSIZE; VariantByteObject* newBytes = static_cast<VariantByteObject*>(allocObject(objectSize + SizeOfPointers(0), ote)); ASSERT((objectSize > MaxSizeOfPoolObject && ote->heapSpace() == OTEFlags::NormalSpace) || ote->heapSpace() == OTEFlags::PoolSpace); ASSERT(ote->getSize() == objectSize + SizeOfPointers(0)); if (Initialized) { // Byte objects are initialized to zeros (but not the header) // Note that we round up to initialize to the next DWORD // This can be useful when working on a 32-bit word machine ZeroMemory(newBytes->m_fields, _ROUND2(objectSize, sizeof(DWORD))); classPointer->countUp(); } else { // We still want to ensure the null terminator is set, even if not initializing the rest of the object *reinterpret_cast<NULLTERMTYPE*>(&newBytes->m_fields[objectSize - NULLTERMSIZE]) = 0; } ote->m_oteClass = classPointer; ote->beNullTerminated(); HARDASSERT(ote->isBytes()); } return reinterpret_cast<BytesOTE*>(ote); }
OTE* ObjectMemory::CopyElements(OTE* oteObj, MWORD startingAt, MWORD count) { // Note that startingAt is expected to be a zero-based index ASSERT(startingAt >= 0); OTE* oteSlice; if (oteObj->isBytes()) { BytesOTE* oteBytes = reinterpret_cast<BytesOTE*>(oteObj); size_t elementSize = ObjectMemory::GetBytesElementSize(oteBytes); if (count == 0 || ((startingAt + count) * elementSize <= oteBytes->bytesSize())) { MWORD objectSize = elementSize * count; if (oteBytes->m_flags.m_weakOrZ) { // TODO: Allocate the correct number of null term bytes based on the encoding auto newBytes = static_cast<VariantByteObject*>(allocObject(objectSize + NULLTERMSIZE, oteSlice)); // When copying strings, the slices has the same string class (oteSlice->m_oteClass = oteBytes->m_oteClass)->countUp(); memcpy(newBytes->m_fields, oteBytes->m_location->m_fields + (startingAt * elementSize), objectSize); *reinterpret_cast<NULLTERMTYPE*>(&newBytes->m_fields[objectSize]) = 0; oteSlice->beNullTerminated(); return oteSlice; } else { VariantByteObject* newBytes = static_cast<VariantByteObject*>(allocObject(objectSize, oteSlice)); // When copying bytes, the slice is always a ByteArray oteSlice->m_oteClass = Pointers.ClassByteArray; oteSlice->beBytes(); memcpy(newBytes->m_fields, oteBytes->m_location->m_fields + (startingAt * elementSize), objectSize); return oteSlice; } } } else { // Pointers PointersOTE* otePointers = reinterpret_cast<PointersOTE*>(oteObj); BehaviorOTE* oteClass = otePointers->m_oteClass; InstanceSpecification instSpec = oteClass->m_location->m_instanceSpec; if (instSpec.m_indexable) { startingAt += instSpec.m_fixedFields; if (count == 0 || (startingAt + count) <= otePointers->pointersSize()) { MWORD objectSize = SizeOfPointers(count); auto pSlice = static_cast<VariantObject*>(allocObject(objectSize, oteSlice)); // When copying pointers, the slice is always an Array oteSlice->m_oteClass = Pointers.ClassArray; VariantObject* pSrc = otePointers->m_location; for (MWORD i = 0; i < count; i++) { countUp(pSlice->m_fields[i] = pSrc->m_fields[startingAt + i]); } return oteSlice; } } } return nullptr; }