size_t getMemSize(const APCHandle* handle) { auto t = handle->getType(); if (!IS_REFCOUNTED_TYPE(t)) { return sizeof(APCHandle); } if (t == KindOfString) { if (handle->isUncounted()) { return sizeof(APCTypedValue) + getMemSize(APCTypedValue::fromHandle(handle)->getStringData()); } return getMemSize(APCString::fromHandle(handle)); } if (t == KindOfArray) { if (handle->isSerializedArray()) { return getMemSize(APCString::fromHandle(handle)); } if (handle->isUncounted()) { return sizeof(APCTypedValue) + getMemSize(APCTypedValue::fromHandle(handle)->getArrayData()); } return getMemSize(APCArray::fromHandle(handle)); } if (t == KindOfObject) { if (handle->isCollection()) { return getMemSize(APCCollection::fromHandle(handle)); } if (handle->isObj()) { return getMemSize(APCObject::fromHandle(handle)); } return getMemSize(APCString::fromHandle(handle)); } assert(!"Unsupported APCHandle Type in getMemSize"); return 0; }
// 0x5D // Branch if Less than A void R34HC22::branchIfLessThanA(int address) { if((address + 4) < getMemSize()) { // get the value to compare to A unsigned char compareValue = getMemoryValueAtLocation(address + 1); if(compareValue < getA()) { if(getLocation(address,2,3) != -1) { // set the program counter to the new address setProgCounter(getLocation(address,2,3)); executeFromLocation(getLocation(address,2,3)); cout << complete_mess << endl; } else { cout << invalid_mem << endl; haltOpcode(); } } else { // set the program counter to the the fourth byte after the opcode setProgCounter(address + 4); executeFromLocation(address + 4); cout << complete_mess << endl; } } else { cerr << error_mess << endl; haltOpcode(); } }
// 0x5B // Branch if A < B void R34HC22::branchIfALessThanB(int address) { if((address + 3) < getMemSize()) { // compare the value of A and B if(getA() < getB()) { if(getLocation(address,1,2) != -1) { // set the program counter to the new address setProgCounter(getLocation(address,1,2)); executeFromLocation(getLocation(address,1,2)); cout << complete_mess << endl; } else { cout << invalid_mem << endl; haltOpcode(); } } else { // set the program counter to the third byte after the opcode setProgCounter(address + 3); executeFromLocation(address + 3); cout << complete_mess << endl; } } else { cerr << error_mess << endl; haltOpcode(); } }
APCHandle* APCArray::MakeShared(ArrayData* arr, size_t& size, bool inner, bool unserializeObj) { if (!inner) { // only need to call traverseData() on the toplevel array DataWalker walker(DataWalker::LookupFeature::HasObjectOrResource); DataWalker::DataFeature features = walker.traverseData(arr); if (features.isCircular() || features.hasCollection()) { String s = apc_serialize(arr); APCHandle* handle = APCString::MakeShared(KindOfArray, s.get(), size); handle->setSerializedArray(); return handle; } if (apcExtension::UseUncounted && !features.hasObjectOrResource() && !arr->empty()) { size = getMemSize(arr) + sizeof(APCTypedValue); return APCTypedValue::MakeSharedArray(arr); } } if (arr->isVectorData()) { return APCArray::MakePackedShared(arr, size, unserializeObj); } return APCArray::MakeShared(arr, size, unserializeObj); }
int GFFFile::endwrite(uint8 **mem, uint32 *size) { if((datas.size() != datac.size()) || (datas.size() != dataoffs.size()) || (datas.size() != datasizes.size())) return errcode = 25; for(uint32 i=0;i<structs.size();i++) { if((structs[i].fieldcount = structs[i].values.size()) > 1) fieldidxsize += structs[i].fieldcount*4; // Yeah, I know this is kind of a bad hack, but I need it that way... for(uint32 j=0;j<structs[i].labels.size();j++) if(structs[i].labels[j] == (std::string *) -1) structs[i].labels[j] = (std::string *) (uint64) addLabel(""); } for(uint32 i=0;i<lists.size();i++) listidxsize += lists[i].size()*4 + 4; structcount = structs.size(); labelcount = labels.size(); offstruct = 56; offfield = offstruct + structcount*12; offlabel = offfield + fieldcount*12; offfielddata = offlabel + labelcount*16; offfieldidx = offfielddata + fielddatasize; offlistidx = offfieldidx + fieldidxsize; if(finalWriteHeader()) return errcode; if(finalWriteData()) return errcode; if(finalWriteLists()) return errcode; if(finalWriteLabels()) return errcode; if(finalWriteStructs()) return errcode; deInit(); if(mem) *mem = getMem(); if(size) *size = getMemSize(); return 0; }
size_t getMemSize(const ArrayData* arr) { switch (arr->kind()) { case ArrayData::ArrayKind::kPackedKind: { auto size = sizeof(ArrayData) + sizeof(TypedValue) * (arr->m_cap.decode() - arr->m_size); auto const values = reinterpret_cast<const TypedValue*>(arr + 1); auto const last = values + arr->m_size; for (auto ptr = values; ptr != last; ++ptr) { size += getMemSize(ptr); } return size; } case ArrayData::ArrayKind::kStructKind: { auto structArray = StructArray::asStructArray(arr); auto size = sizeof(StructArray) + (structArray->shape()->capacity() - structArray->size()) * sizeof(TypedValue); auto const values = structArray->data(); auto const last = values + structArray->size(); for (auto ptr = values; ptr != last; ++ptr) { size += getMemSize(ptr); } return size; } case ArrayData::ArrayKind::kMixedKind: { auto const mixed = MixedArray::asMixed(arr); auto size = sizeof(MixedArray) + sizeof(MixedArray::Elm) * (mixed->capacity() - mixed->m_used); auto elms = mixed->data(); auto last = elms + mixed->m_used; for (auto ptr = elms; ptr != last; ++ptr) { if (MixedArray::isTombstone(ptr->data.m_type)) { size += sizeof(MixedArray::Elm); continue; } size += ptr->hasStrKey() ? getMemSize(ptr->skey) : sizeof(int64_t); size += getMemSize(&ptr->data); } return size; } case ArrayData::ArrayKind::kEmptyKind: return sizeof(ArrayData); default: assert(!"Unsupported Array type in getMemSize"); } return 0; }
void TestHeapLimit() { if(!isMallocInitialized()) doInitialization(); // tiny limit to stop caching int res = scalable_allocation_mode(TBBMALLOC_SET_SOFT_HEAP_LIMIT, 1); ASSERT(res == TBBMALLOC_OK, NULL); // provoke bootstrap heap initialization before recording memory size scalable_free(scalable_malloc(8)); size_t n, sizeBefore = getMemSize(); // Try to provoke call to OS for memory to check that // requests are not fulfilled from caches. // Single call is not enough here because of backend fragmentation. for (n = minLargeObjectSize; n < 10*1024*1024; n += 16*1024) { void *p = scalable_malloc(n); bool leave = (sizeBefore != getMemSize()); scalable_free(p); if (leave) break; ASSERT(sizeBefore == getMemSize(), "No caching expected"); } ASSERT(n < 10*1024*1024, "scalable_malloc doesn't provoke OS request for memory, " "is some internal cache still used?"); // estimate number of objects in single bootstrap block int objInBootstrapHeapBlock = (slabSize-2*estimatedCacheLineSize)/sizeof(TLSData); // When we have more threads than objects in bootstrap heap block, // additional block can be allocated from a region that is different // from the original region. Thus even after all caches cleaned, // we unable to reach sizeBefore. ASSERT_WARNING(MaxThread<=objInBootstrapHeapBlock, "The test might fail for larger thread number, " "as bootstrap heap is not released till size checking."); for( int p=MaxThread; p>=MinThread; --p ) { RunTestHeapLimit::initBarrier( p ); NativeParallelFor( p, RunTestHeapLimit(sizeBefore) ); } // it's try to match limit as well as set limit, so call here res = scalable_allocation_mode(TBBMALLOC_SET_SOFT_HEAP_LIMIT, 1); ASSERT(res == TBBMALLOC_OK, NULL); size_t m = getMemSize(); ASSERT(sizeBefore == m, NULL); // restore default res = scalable_allocation_mode(TBBMALLOC_SET_SOFT_HEAP_LIMIT, 0); ASSERT(res == TBBMALLOC_OK, NULL); }
int TLKFile::write(uint8 **mem, uint32 *size) { if(openWrite()) return errcode; if(finalWrite()) return errcode; if(mem) *mem = getMem(); if(size) *size = getMemSize(); close(); return errcode = 0; }
size_t getMemSize(const APCArray* arr) { auto memSize = sizeof(APCArray); auto size = arr->size(); if (arr->isPacked()) { memSize += sizeof(APCHandle*) * size; for (auto i = 0; i < size; i++) { memSize += getMemSize(arr->getValue(i)); } } else { memSize += sizeof(int) * (arr->m.m_capacity_mask + 1) + sizeof(APCArray::Bucket) * size; auto b = arr->buckets(); for (auto i = 0; i < size; i++) { memSize += getMemSize(b[i].key); memSize += getMemSize(b[i].val); } } return memSize; }
// return the location of given memory address int R34HC22::getLocation(int address, int highNo, int lowNo) { unsigned char highByte = getMemoryValueAtLocation(address + highNo); unsigned char lowByte = getMemoryValueAtLocation(address + lowNo); if(((highByte << 8) | lowByte) >= 0 && ((highByte << 8) | lowByte) < getMemSize()) { return ((highByte << 8) | lowByte); } return -1; }
size_t getMemSize(const APCObject* obj) { auto size = sizeof(APCObject) + sizeof(APCObject::Prop) * obj->m_propCount; auto prop = obj->props(); auto const propEnd = prop + obj->m_propCount; // we don't add property names and class names (or Class*) in Prop // assuming that is static data not owned or accounted by the APCObject for (; prop != propEnd; ++prop) { if (prop->val) size += getMemSize(prop->val); } return size; }
// The idea is to allocate a set of objects and then deallocate them in random // order in parallel to force occuring conflicts in backend during coalescing. // Thus if the backend does not check the queue of postponed coalescing // requests it will not be able to unmap all memory and a memory leak will be // observed. void TestCleanAllBuffers() { const int num_threads = 8; // Clean up if something was allocated before the test scalable_allocation_command(TBBMALLOC_CLEAN_ALL_BUFFERS,0); size_t memory_in_use_before = getMemSize(); for ( int i=0; i<num_allocs; ++i ) { ptrs[i] = scalable_malloc( alloc_size ); ASSERT( ptrs[i] != NULL, "scalable_malloc has return zero." ); } deallocs_counter = 0; TestCleanAllBuffersDeallocate::initBarrier(num_threads); NativeParallelFor(num_threads, TestCleanAllBuffersDeallocate()); if ( defaultMemPool->extMemPool.backend.coalescQ.blocksToFree == NULL ) REPORT( "Warning: The queue of postponed coalescing requests is empty. Unable to create the condition for bug reproduction.\n" ); ASSERT( scalable_allocation_command(TBBMALLOC_CLEAN_ALL_BUFFERS,0) == TBBMALLOC_OK, "The cleanup request has not cleaned anithing." ); size_t memory_in_use_after = getMemSize(); REMARK( "memory_in_use_before = %ld\nmemory_in_use_after = %ld\n", memory_in_use_before, memory_in_use_after ); size_t memory_leak = memory_in_use_after - memory_in_use_before; ASSERT( memory_leak == 0, "The backend has not processed the queue of postponed coalescing requests during cleanup." ); }
// 0x53 // Increment Register A void R34HC22::incrementRegisterA(int address){ if((address + 1) < getMemSize()){ // increare the value of A setA(getA() + 1); // move the program counter to the next byte setProgCounter(address + 1); executeFromLocation(address + 1); cout << complete_mess << endl; } else { cerr << error_mess << endl; haltOpcode(); } }
int ERFFile::endwrite(uint8 **mem, uint32 *size) { if(pronto && (prontowritten < entrycount)) return errcode = 32; if(!pronto) { if(finalWriteCalc()) return errcode; if(finalWriteHeader()) return errcode; if(finalWriteDescription()) return errcode; } if(finalWriteKeyList()) return errcode; if(finalWriteResList()) return errcode; if(!pronto && finalWriteEntries()) return errcode; deInit(); if(mem) *mem = getMem(); if(size) *size = getMemSize(); return errcode = 0; }
APCHandle::Pair APCCollection::Make(const ObjectData* obj, APCHandleLevel level, bool unserializeObj) { auto bail = [&] { return APCString::MakeSerializedObject( apc_serialize(Variant(const_cast<ObjectData*>(obj))) ); }; auto const array = collections::asArray(obj); if (!array) return bail(); /* * Create an uncounted array if we can. * * If this collection is an OuterHandle, then we need to do a full check on * this array for things like circularity. If we're an InnerHandle, someone * already checked that, but we want to check for whether it's uncounted to * use a better representation. For the OuterHandle case, we just delegate * to APCArray below (which will do the full DataWalker pass). */ if (level == APCHandleLevel::Inner && apcExtension::UseUncounted && !array->empty()) { DataWalker walker(DataWalker::LookupFeature::HasObjectOrResource); auto const features = walker.traverseData(const_cast<ArrayData*>(array)); assert(!features.isCircular); if (!features.hasObjectOrResource) { return WrapArray( { APCArray::MakeUncountedArray(const_cast<ArrayData*>(array)), getMemSize(array) + sizeof(APCTypedValue) }, obj->collectionType() ); } } return WrapArray( APCArray::MakeSharedArray(const_cast<ArrayData*>(array), level, unserializeObj), obj->collectionType() ); }
// 0x5A // Branch Always void R34HC22::branchAlways(int address) { if((address + 2) < getMemSize()) { if(getLocation(address,1,2) != -1) { // set the program counter to the new address setProgCounter(getLocation(address,1,2)); executeFromLocation(getLocation(address,1,2)); cout << complete_mess << endl; } else { cerr << invalid_mem << endl; haltOpcode(); } } else { cerr << error_mess << endl; haltOpcode(); } }
APCHandle::Pair APCArray::MakeSharedArray(ArrayData* arr, APCHandleLevel level, bool unserializeObj) { if (level == APCHandleLevel::Outer) { // only need to call traverseData() on the toplevel array DataWalker walker(DataWalker::LookupFeature::HasObjectOrResource); DataWalker::DataFeature features = walker.traverseData(arr); if (features.isCircular) { String s = apc_serialize(Variant{arr}); return APCString::MakeSerializedArray(s.get()); } if (apcExtension::UseUncounted && !features.hasObjectOrResource && !arr->empty()) { return {MakeUncountedArray(arr), getMemSize(arr) + sizeof(APCTypedValue)}; } } return arr->isVectorData() ? MakePacked(arr, unserializeObj) : MakeHash(arr, unserializeObj); }
// 0x0C // Move A to memory void R34HC22::moveAToMemory(int address) { if((address + 3) < getMemSize()) { if(getLocation(address,1,2) != -1) { // move the content of A to the destination address in memory setMemoryValueAtLocation(getLocation(address,1,2), getA()); // set the program counter to the third byte after the opcode setProgCounter(address + 3); executeFromLocation(address + 3); cout << complete_mess << endl; } else { cerr << invalid_mem << endl; haltOpcode(); } } else { cerr << error_mess << endl; haltOpcode(); } }
// 0x37 // Load A with Value void R34HC22::loadRegisterWithValue(int address, string r) { if((address + 2) < getMemSize()) { if(r.compare("A") == 0) { // load value from the first byte after the opcode to A setA(getMemoryValueAtLocation(address + 1)); } else if(r.compare("B") == 0) { // load value from the first byte after the opcode to B setB(getMemoryValueAtLocation(address + 1)); } // set the program counter the the second byte after opcode setProgCounter(address + 2); executeFromLocation(address + 2); cout << complete_mess << endl; } else { cerr << error_mess << endl; haltOpcode(); } }
/************************************************************** * * dataCreate - create the DATA Object Data Structure & Semaphore, etc.. * * * RETURNS: * DATAOBJ_ID - if no error, NULL - if mallocing or semaphore creation failed * */ DATAOBJ_ID dataCreate(int dataChannel,char *idStr) /* int dataChannel - STM channel = 0 - 3, for the 4 four possible stm's in system */ { char tmpstr[80]; DATAOBJ_ID pDataObj; int tDRid, tMTid, tDEid; short sr; long memval; int cnt,slen; unsigned long maxNumOfEntries; unsigned long memAddr; if (idStr == NULL) { slen = 16; } else { slen = strlen(idStr); } /* ------- malloc space for STM Object --------- */ if ( (pDataObj = (DATA_OBJ *) malloc( sizeof(DATA_OBJ)) ) == NULL ) { errLogSysRet(LOGIT,debugInfo,"dataCreate: "); return(NULL); } /* zero out structure so we don't free something by mistake */ memset(pDataObj,0,sizeof(DATA_OBJ)); pDataObj->dspAppVersion = getDspAppVer(); pDataObj->dspMemSize = getMemSize(); /* -------------- setup given or default ID string ---------------- */ pDataObj->pIdStr = (char *) malloc(slen+2); if (pDataObj->pIdStr == NULL) { dataDelete(pDataObj); return(NULL); } if (idStr != NULL) strcpy(pDataObj->pIdStr,idStr); else strcpy(pDataObj->pIdStr,"dataObj"); /* -------------------------------------------------------------------*/ pDataObj->dataState = OK; /* create the STM State sync semaphore */ pDataObj->pSemStateChg = semBCreate(SEM_Q_FIFO,SEM_EMPTY); /* create the STM Object Mutual Exclusion semaphore */ pDataObj->pStmMutex = semMCreate(SEM_Q_PRIORITY | SEM_INVERSION_SAFE | SEM_DELETE_SAFE); if ( (pDataObj->pSemStateChg == NULL) || (pDataObj->pStmMutex == NULL) ) { errLogSysRet(LOGIT,debugInfo,"dataCreate: Could not create semaphore "); dataDelete(pDataObj); return(NULL); } /* Make initial buffer, msgQ, freelist, may expand */ maxNumOfEntries = MAX_BUFFER_ALLOCATION / ( sizeof(FID_STAT_BLOCK) + sizeof(ITR_MSG) + sizeof(long)); pDataObj->maxFidBlkBuffered = pDataObj->maxFreeList = maxNumOfEntries; pDataObj->pStatBlkArray = (FID_STAT_BLOCK*) malloc(sizeof(FID_STAT_BLOCK) * maxNumOfEntries); /* Free List of Tags, typically 0 - maxNumFidBlkToAlloc */ pDataObj->pTagFreeList = rngXBlkCreate(maxNumOfEntries, "Data Addr Free Pool ",EVENT_STM_ALLOC_BLKS,1); DPRINT1(-1," %lu MBytes of Memory.\n",(pDataObj->dspMemSize/1048576L)); pDataId = pDataObj; /* set internal static pointer */ return( pDataObj ); }
void nsPluginInstance::threadMain(void) { DBG("nsPluginInstance::threadMain started\n"); DBG("URL: %s\n", _url.c_str()); PR_Lock(playerLock); // Initialize Gnash core library. DBG("Gnash core initialized.\n"); // Init logfile. gnash::RcInitFile& rcinit = gnash::RcInitFile::getDefaultInstance(); std::string logfilename = std::string("T:npgnash.log"); rcinit.setDebugLog(logfilename); gnash::LogFile& dbglogfile = gnash::LogFile::getDefaultInstance(); dbglogfile.setWriteDisk(true); dbglogfile.setVerbosity(GNASH_DEBUG_LEVEL); DBG("Gnash logging initialized: %s\n", logfilename.c_str()); // Init sound. //_sound_handler.reset(gnash::sound::create_sound_handler_sdl()); //gnash::set_sound_handler(_sound_handler.get()); DBG("Gnash sound initialized.\n"); // Init GUI. int old_mouse_x = 0, old_mouse_y = 0, old_mouse_buttons = 0; _render_handler = (gnash::render_handler *) gnash::create_render_handler_agg("BGR24"); // _memaddr = (unsigned char *) malloc(getMemSize()); static_cast<gnash::render_handler_agg_base *>(_render_handler)->init_buffer( getMemAddr(), getMemSize(), _width, _height, _rowstride); gnash::set_render_handler(_render_handler); DBG("Gnash GUI initialized: %ux%u\n", _width, _height); gnash::URL url(_url); VariableMap vars; gnash::URL::parse_querystring(url.querystring(), vars); for (VariableMap::iterator i = vars.begin(), ie = vars.end(); i != ie; i++) { _flashVars[i->first] = i->second; } gnash::set_base_url(url); gnash::movie_definition* md = NULL; try { md = gnash::createMovie(url, _url.c_str(), false); } catch (const gnash::GnashException& err) { md = NULL; } if (!md) { /* * N.B. Can't use the goto here, as C++ complains about "jump to * label 'done' from here crosses initialization of ..." a bunch * of things. Sigh. So, instead, I duplicate the cleanup code * here. TODO: Remove this duplication. */ // goto done; PR_Unlock(playerLock); DBG("Clean up Gnash.\n"); //gnash::clear(); DBG("nsPluginInstance::threadMain exiting\n"); return; } DBG("Movie created: %s\n", _url.c_str()); int movie_width = static_cast<int>(md->get_width_pixels()); int movie_height = static_cast<int>(md->get_height_pixels()); float movie_fps = md->get_frame_rate(); DBG("Movie dimensions: %ux%u (%.2f fps)\n", movie_width, movie_height, movie_fps); gnash::SystemClock clock; // use system clock here... gnash::movie_root& root = gnash::VM::init(*md, clock).getRoot(); DBG("Gnash VM initialized.\n"); // Register this plugin as listener for FsCommands from the core // (movie_root) #if 0 /* Commenting out for now as registerFSCommandCallback() has changed. */ root.registerFSCommandCallback(FSCommand_callback); #endif // Register a static function to handle ActionScript events such // as Mouse.hide, Stage.align etc. // root.registerEventCallback(&staticEventHandlingFunction); md->completeLoad(); DBG("Movie loaded.\n"); std::auto_ptr<gnash::Movie> mr(md->createMovie()); mr->setVariables(_flashVars); root.setRootMovie(mr.release()); //root.set_display_viewport(0, 0, _width, _height); root.set_background_alpha(1.0f); gnash::Movie* mi = root.getRootMovie(); DBG("Movie instance created.\n"); //ShowWindow(_window, SW_SHOW); IIntuition->ShowWindow(_window,NULL); for (;;) { // DBG("Inside main thread loop.\n"); if (_shutdown) { DBG("Main thread shutting down.\n"); break; } size_t cur_frame = mi->get_current_frame(); // DBG("Got current frame number: %d.\n", cur_frame); size_t tot_frames = mi->get_frame_count(); // DBG("Got total frame count: %d.\n", tot_frames); // DBG("Advancing one frame.\n"); root.advance(); // DBG("Going to next frame.\n"); root.goto_frame(cur_frame + 1); // DBG("Ensuring frame is loaded.\n"); //root.get_movie_definition()->ensure_frame_loaded(tot_frames); // DBG("Setting play state to PLAY.\n"); root.set_play_state(gnash::MovieClip::PLAYSTATE_PLAY); if (old_mouse_x != mouse_x || old_mouse_y != mouse_y) { old_mouse_x = mouse_x; old_mouse_y = mouse_y; //root.notify_mouse_moved(mouse_x, mouse_y); } if (old_mouse_buttons != mouse_buttons) { old_mouse_buttons = mouse_buttons; int mask = 1; //root.notify_mouse_clicked(mouse_buttons > 0, mask); } root.display(); #if 0 RECT rt; GetClientRect(_window, &rt); InvalidateRect(_window, &rt, FALSE); InvalidatedRanges ranges; ranges.setSnapFactor(1.3f); ranges.setSingleMode(false); root.add_invalidated_bounds(ranges, false); ranges.growBy(40.0f); ranges.combine_ranges(); if (!ranges.isNull()) { InvalidateRect(_window, &rt, FALSE); } root.display(); #endif // DBG("Unlocking playerLock mutex.\n"); PR_Unlock(playerLock); // DBG("Sleeping.\n"); PR_Sleep(PR_INTERVAL_MIN); // DBG("Acquiring playerLock mutex.\n"); PR_Lock(playerLock); } done: PR_Unlock(playerLock); DBG("Clean up Gnash.\n"); /* * N.B. As per server/impl.cpp:clear(), all of Gnash's threads aren't * guaranteed to be terminated by this, yet. Therefore, when Firefox * unloads npgnash.dll after calling NS_PluginShutdown(), and there are * still Gnash threads running, they will try and access memory that was * freed as part of the unloading of npgnash.dll, resulting in a process * abend. */ //gnash::clear(); DBG("nsPluginInstance::threadMain exiting\n"); }
void operator() () const { int res = scalable_allocation_mode(TBBMALLOC_SET_SOFT_HEAP_LIMIT, 1); ASSERT(res == TBBMALLOC_OK, NULL); ASSERT(getMemSize() == memSize, NULL); }