void PriorityQueueAdd(struct VMGlobals *g, PyrObject* queueobj, PyrSlot* item, double time) { PyrObject *schedq, *newschedq; int size, maxsize; PyrSlot *schedqSlot = queueobj->slots; if (!IsObj(schedqSlot)) { size = 32; schedq = newPyrArray(g->gc, size, 0, true); schedq->size = 1; SetInt(schedq->slots + 0, 0); // stability count SetObject(schedqSlot, schedq); g->gc->GCWriteNew(queueobj, schedq); // we know schedq is white so we can use GCWriteNew } else { schedq = slotRawObject(schedqSlot); maxsize = ARRAYMAXINDEXSIZE(schedq); size = schedq->size; if (size+3 > maxsize) { newschedq = newPyrArray(g->gc, maxsize*2, 0, true); newschedq->size = size; slotCopy(newschedq->slots, schedq->slots, size); assert(IsInt(newschedq->slots)); SetObject(schedqSlot, newschedq); g->gc->GCWriteNew(queueobj, newschedq); // we know newschedq is white so we can use GCWriteNew schedq = newschedq; } } addheap(g, schedq, time, item); }
void PriorityQueueAdd(struct VMGlobals *g, PyrObject* queueobj, PyrSlot* item, double time) { PyrObject *schedq, *newschedq; int size, maxsize; PyrSlot *schedqSlot = queueobj->slots; if (!IsObj(schedqSlot)) { size = 16; schedq = newPyrArray(g->gc, size, 0, true); SetObject(schedqSlot, schedq); g->gc->GCWrite(queueobj, schedq); } else { schedq = schedqSlot->uo; maxsize = ARRAYMAXINDEXSIZE(schedq); size = schedq->size; if (size+2 > maxsize) { PyrSlot *pslot, *qslot; newschedq = newPyrArray(g->gc, maxsize*2, 0, true); newschedq->size = size; pslot = schedq->slots - 1; qslot = newschedq->slots - 1; for (int i=0; i<size; ++i) slotCopy(++qslot, ++pslot); SetObject(schedqSlot, newschedq); g->gc->GCWrite(queueobj, newschedq); schedq = newschedq; } } addheap(g, schedq, time, item); }
// extend/update the object with values from Val // this and Val should be an Object and not an array or something else void TJsonVal::MergeObj(const PJsonVal& Val) { EAssert(Val->IsObj() && IsObj()); for (int N = 0; N < Val->GetObjKeys(); N++) { const TStr Key = Val->GetObjKey(N); AddToObj(Key, Val->GetObjKey(Key)); } }
int prConnectSharedMem(VMGlobals *g, int numArgsPushed) { #if !defined(SC_IPHONE) PyrSlot *a = g->sp - 1; PyrSlot *b = g->sp; assert(IsObj(a)); PyrObject * self = slotRawObject(a); int portNumber = slotRawInt(b); int ptrIndex = 0; int finalizerIndex = 1; try { server_shared_memory_client * client = new server_shared_memory_client(portNumber); SetPtr(self->slots + ptrIndex, client); InstallFinalizer(g, self, finalizerIndex, disconnectSharedMem); postfl("Shared memory server interface initialized\n"); } catch (std::exception & e) { postfl("Cannot connect to shared memory: %s\n", e.what()); return errFailed; } #else postfl("Warning: Shared memory server interface disabled on iphone\n"); #endif return errNone; }
bool PyrGC::SanityClearObj(PyrObject *objA, int level) { if (!(objA->IsMarked())) return true; if (objA->IsPermanent()) return true; objA->ClearMark(); // unmark it if (objA->obj_format <= obj_slot) { // scan it int size = objA->size; if (size > 0) { PyrSlot *slot = objA->slots; for (int j=size; j--; ++slot) { PyrObject *objB = NULL; if (IsObj(slot) && slotRawObject(slot)) { objB = slotRawObject(slot); } if (objB) { /*if (level > 40) { fprintf(stderr, "40 levels deep!\n"); dumpBadObject(objA); //dumpObject((PyrObject*)objB); //newPyrFrame return errFailed; }*/ bool err = SanityClearObj(objB, level+1); if (!err) return false; } } } } return true; }
int prSetControlBusValue(VMGlobals *g, int numArgsPushed) { PyrSlot *a = g->sp - 2; PyrSlot *b = g->sp - 1; PyrSlot *c = g->sp; assert(IsObj(a)); PyrObject * self = slotRawObject(a); int ptrIndex = 0; PyrSlot * ptrSlot = self->slots + ptrIndex; if (NotPtr(ptrSlot)) return errFailed; if (!IsInt(b)) return errFailed; int busIndex = slotRawInt(b); if (NotPtr(ptrSlot)) return errFailed; float value; int error = slotFloatVal(c, &value); if (error != errNone) return error; server_shared_memory_client * client = (server_shared_memory_client*)slotRawPtr(ptrSlot); client->get_control_busses()[busIndex] = value; return errNone; }
int prDisconnectSharedMem(VMGlobals *g, int numArgsPushed) { PyrSlot *a = g->sp; assert(IsObj(a)); PyrObject * self = slotRawObject(a); return disconnectSharedMem(g, self); }
Ref * sysVectorAppend( Ref * pc, class MachineClass * vm ) { // Variables here would be unaffected by a GC. unsigned long N; unsigned long lhs_n; unsigned long rhs_n; if ( vm->count != 2 ) throw Ginger::Mishap( "Wrong number of arguments in vectorAppend" ); { // May need to GC so leave on the stack. Ref rhs = vm->fastPeek(); Ref lhs = vm->fastPeek( 1 ); if ( !IsObj( lhs ) || !IsObj( rhs ) ) throw Ginger::Mishap( "Invalid arguments in vectorAppend" ); Ref * lhs_K = RefToPtr4( lhs ); Ref * rhs_K = RefToPtr4( rhs ); Ref lhs_key = *lhs_K; Ref rhs_key = *rhs_K; if ( lhs_key != rhs_key || !IsSimpleKey( lhs_key ) || KindOfSimpleKey( lhs_key ) != VECTOR_KIND ) throw Ginger::Mishap( "Invalid arguments in vectorAppend" ); lhs_n = sizeAfterKeyOfVectorLayout( lhs_K ); rhs_n = sizeAfterKeyOfVectorLayout( rhs_K ); N = lhs_n + rhs_n; } XfrClass xfr( vm->heap().preflight( pc, N + 2 ) ); // No risk of GC so safe to pop. Ref * rhs_K = RefToPtr4( vm->fastPop() ); Ref * lhs_K = RefToPtr4( vm->fastPop() ); xfr.xfrRef( ULongToSmall( N ) ); xfr.setOrigin(); xfr.xfrRef( *lhs_K ); xfr.xfrCopy( lhs_K + 1, lhs_n ); xfr.xfrCopy( rhs_K + 1, rhs_n ); vm->fastPush( xfr.makeRef() ); return pc; }
void PriorityQueueClear(PyrObject *queueobj) { PyrSlot *schedqSlot = queueobj->slots; if (IsObj(schedqSlot)) { PyrObject *schedq = schedqSlot->uo; schedq->size = 0; } }
void PriorityQueueClear(PyrObject *queueobj) { PyrSlot *schedqSlot = queueobj->slots; if (IsObj(schedqSlot)) { PyrObject *schedq = slotRawObject(schedqSlot); SetInt(schedq->slots, 0); // stability count schedq->size = 1; } }
void PriorityQueuePostpone(PyrObject* queueobj, double time) { PyrSlot *schedqSlot = queueobj->slots; if (IsObj(schedqSlot)) { PyrObject *schedq = slotRawObject(schedqSlot); PyrSlot* slots = schedq->slots; for (int i=1; i < schedq->size; i+=3) { SetRaw(&slots[i], slotRawFloat(&slots[i]) + time); } } }
void PriorityQueuePostpone(PyrObject* queueobj, double time) { PyrSlot *schedqSlot = queueobj->slots; if (IsObj(schedqSlot)) { PyrObject *schedq = schedqSlot->uo; PyrSlot* slots = schedq->slots; for (int i=0; i < schedq->size; i+=2) { slots[i].uf += time; } } }
bool PriorityQueueEmpty(PyrObject *queueobj) { PyrSlot *schedqSlot = queueobj->slots; if (IsObj(schedqSlot)) { PyrObject *schedq = slotRawObject(schedqSlot); if (schedq->size > 1) { return false; } } return true; }
void PyrGC::Finalize(PyrObject *finalizer) { if (!IsPtr(finalizer->slots+0)) return; if (!IsObj(finalizer->slots+1)) return; ObjFuncPtr func = (ObjFuncPtr)finalizer->slots[0].ui; PyrObject *obj = finalizer->slots[1].uo; //post("FINALIZE %s %p\n", obj->classptr->name.us->name, obj); (func)(mVMGlobals, obj); SetNil(obj->slots+0); SetNil(obj->slots+1); }
void PyrGC::Finalize(PyrObject *finalizer) { if (!IsPtr(finalizer->slots+0)) return; if (!IsObj(finalizer->slots+1)) return; ObjFuncPtr func = (ObjFuncPtr)slotRawPtr(&finalizer->slots[0]); PyrObject *obj = slotRawObject(&finalizer->slots[1]); //post("FINALIZE %s %p\n", slotRawSymbol(&obj->classptr->name)->name, obj); (func)(mVMGlobals, obj); SetNil(obj->slots+0); SetNil(obj->slots+1); }
// // This computes obj_C = obj_Z - obj_A from obj_K // unsigned long lengthAfterObjectKey( Ref * obj_K ) { // Keys fall into the following categories: FunctionKey, SimpleKey, Pointer to Keys Ref key = *obj_K; if ( IsSimpleKey( key ) ) { switch ( LayoutOfSimpleKey( key ) ) { //switch ( KindOfSimpleKey( key ) ) { case RECORD_LAYOUT: { //case MAP_KIND: //case PAIR_KIND: //case RECORD_KIND: { assert( LayoutOfSimpleKey( key ) == RECORD_LAYOUT ); assert( KindOfSimpleKey( key ) == PAIR_KIND || KindOfSimpleKey( key ) == MAP_KIND || KindOfSimpleKey( key ) == RECORD_KIND ); return sizeAfterKeyOfRecordLayout( obj_K ); break; } case VECTOR_LAYOUT: { //case VECTOR_KIND: { assert( LayoutOfSimpleKey( key ) == VECTOR_LAYOUT ); assert( KindOfSimpleKey( key ) == VECTOR_KIND ); return sizeAfterKeyOfVectorLayout( obj_K ); break; } case MIXED_LAYOUT: { assert( LayoutOfSimpleKey( key ) == MIXED_LAYOUT ); return sizeAfterKeyOfMixedLayout( obj_K ); break; } case STRING_LAYOUT: { //case STRING_KIND: { assert( LayoutOfSimpleKey( key ) == STRING_LAYOUT ); assert( KindOfSimpleKey( key ) == STRING_KIND ); return sizeAfterKeyOfStringLayout( obj_K ); break; } case WRECORD_LAYOUT: { assert( LayoutOfSimpleKey( key ) == WRECORD_LAYOUT ); return sizeAfterKeyOfWRecordLayout( obj_K ); break; } default: throw UnreachableError(); } } else if ( IsFunctionKey( key ) ) { return sizeAfterKeyOfFn( obj_K ); } else if ( IsObj( key ) ) { return sizeAfterKeyOfInstance( obj_K ); } else { throw Ginger::Mishap( "Cannot take length of this" ); } }
void PriorityQueuePop(VMGlobals *g, PyrObject *queueobj, PyrSlot *result) { PyrSlot *schedqSlot = queueobj->slots; if (IsObj(schedqSlot)) { PyrObject *schedq = slotRawObject(schedqSlot); double time; if (!getheap(g, schedq, &time, result)) { SetNil(result); } } else { SetNil(result); } }
void PriorityQueueTop(PyrObject *queueobj, PyrSlot *result) { PyrSlot *schedqSlot = queueobj->slots; if (IsObj(schedqSlot)) { PyrObject *schedq = slotRawObject(schedqSlot); if (schedq->size > 1) { slotCopy(result,&schedq->slots[1]); } else { SetNil(result); } } else { SetNil(result); } }
imeth objrtn ObjectPool_im_gDisposeObject(object self, object obj) { ObjectPool_iv_t *iv = GetIVs(ObjectPool, self); object pobj = gNewWithPtr(Pointer, obj); object val = gFindValue(iv->iObjects, pobj); if (val) { if (IsObj(obj)) { long v1 = gObjectSerialNumber(obj); long v2 = gLongValue(gValue(val)); if (v1 == v2) gShortValue(gKey(val)) ? gDeepDispose(obj) : gDispose(obj); } gDeepDisposeObj(iv->iObjects, pobj); } gDispose(pobj); return NULL; }
// // This computes obj_K from obj_A. // Ref * findObjectKey( Ref * obj_A ) { // Cases are that 'obj_A' is pointing at // 1. FnLengthKey. // 2. NonKey* Key series if ( IsFnLength( *obj_A ) ) { // We are at the start of a function. // It has a fixed offset to the key. return obj_A + OFFSET_FROM_FN_LENGTH_TO_KEY; } else { for ( int n = 0; n < MAX_OFFSET_FROM_START_TO_KEY; n++ ) { // // Note that this function is called on objects that have been // forwarded but not yet scanned by the GC. So the test for the // key has to be capable of coping with a forwarded key. This // test is stupider and restricts values in front of the key to // simple values. // // A smarter test is // 1. Are you a simple key? Job done. A: yes // 2. Are you an object? Define K = *you // 2a. Is *K the keykey? If so job done. A: yes // 2b. Is *K forwarded? Define F = *K // 2c. Is *F the keykey? If so A: yes // 3. Otherwise done A: no // /* I think the code would look like this. if ( IsSimpleKey( *obj_A ) ) return obj_A; if ( IsObj( *obj_A ) ) { if ( *RefToPtr4( *obj_A ) == sysClassKey ) return obj_A; } if ( IsFwd( *obj_A ) ) { Ref K = *FwdToPtr4( *obj_A ); if ( IsObj( K ) ) { if ( *RefToPtr4( K ) == sysClassKey ) return obj_A; } } */ Ref * x = obj_A + n; Ref k = *x; if ( IsSimpleKey( k ) || IsObj( k ) || IsFwd( k ) ) { return x; } } throw UnreachableError(); } }
int prNetAddr_SendRaw(VMGlobals *g, int numArgsPushed) { PyrSlot* netAddrSlot = g->sp - 1; PyrSlot* arraySlot = g->sp; PyrObject* netAddrObj = netAddrSlot->uo; if (!IsObj(arraySlot) || !isKindOf(arraySlot->uo, class_rawarray)) { error("sendRaw arg must be a kind of RawArray.\n"); return errWrongType; } PyrObject *array = arraySlot->uo; char *bufptr = (char*)array->slots; int32 msglen = array->size * gFormatElemSize[array->obj_format]; return netAddrSend(netAddrObj, msglen, bufptr, false); }
HOT void PyrGC::ScanSlots(PyrSlot *inSlots, long inNumToScan) { if (inNumToScan == 0) return; unsigned char whiteColor = mWhiteColor; unsigned char greyColor = mGreyColor; mSlotsScanned += inNumToScan; int foundGreyObjects = 0; PyrObjectHdr * grey = &mGrey; PyrObjectHdr * greyNext = grey->next; PyrSlot *slot = inSlots; PyrSlot *endslot = inSlots + inNumToScan; do { if (IsObj(slot)) { PyrObject *obj = slotRawObject(slot); if (obj->gc_color == whiteColor) { /* used to be ToGrey2(obj), but rearranged for slightly better performance * * move obj from white to grey */ PyrObjectHdr * objPrev = obj->prev; PyrObjectHdr * objNext = obj->next; /* link in grey set */ greyNext->prev = obj; grey->next = obj; obj->prev = grey; obj->next = greyNext; greyNext = obj; // remove from old set objNext->prev = objPrev; objPrev->next = objNext; obj->gc_color = greyColor; foundGreyObjects++; } } ++slot; } while (slot != endslot); mNumGrey += foundGreyObjects; }
bool PyrGC::BlackToWhiteCheck(PyrObject *objA) { if (objA->obj_format > obj_slot) return true; // scan it int size = objA->size; if (size > 0) { PyrSlot *slot = objA->slots; for (int j=size; j--; ++slot) { PyrObject * objB = NULL; if (IsObj(slot) && slotRawObject(slot)) { objB = slotRawObject(slot); } if (objB && (unsigned long)objB < 100) { fprintf(stderr, "weird obj ptr\n"); return false; } if (objB) { if (objA == mStack) continue; if (objA->gc_color == mBlackColor && objA != mPartialScanObj) { if (objB->gc_color == mWhiteColor) { if (objA->classptr == class_frame) { // jmc: black stack frames pointing to white nodes can be ignore PyrFrame * frameA = (PyrFrame*)objA; PyrMethod * meth = slotRawMethod(&frameA->method); PyrMethodRaw * methraw = METHRAW(meth); if (methraw->needsHeapContext) continue; } #if DUMPINSANITY fprintf(stderr, "black frame to white ref %p %p\n", objA, objB); dumpBadObject(objA); dumpBadObject(objB); fprintf(stderr, "\n"); #endif return false; } } } } } return true; }
int prSymbol_envirGet(struct VMGlobals *g, int numArgsPushed) { PyrSlot *a, result; int objClassIndex; a = g->sp; // key PyrSlot* currentEnvironmentSlot = &g->classvars->slots[1]; PyrObject *dict = slotRawObject(currentEnvironmentSlot); if (!IsObj(currentEnvironmentSlot)) return errFailed; if (!ISKINDOF(dict, class_identdict_index, class_identdict_maxsubclassindex)) return errFailed; identDict_lookup(dict, a, calcHash(a), &result); slotCopy(a,&result); return errNone; }
int prSymbol_envirPut(struct VMGlobals *g, int numArgsPushed) { PyrSlot *a, *b; int objClassIndex; a = g->sp - 1; // key b = g->sp; // value PyrSlot* currentEnvironmentSlot = &g->classvars->slots[1]; PyrObject *dict = slotRawObject(currentEnvironmentSlot); if (!IsObj(currentEnvironmentSlot)) return errFailed; if (!ISKINDOF(dict, class_identdict_index, class_identdict_maxsubclassindex)) return errFailed; int err = identDictPut(g, dict, a, b); if (err) return err; slotCopy(a,b); return errNone; }
int prGetControlBusValues(VMGlobals *g, int numArgsPushed) { PyrSlot *a = g->sp - 2; PyrSlot *b = g->sp - 1; PyrSlot *c = g->sp; assert(IsObj(a)); PyrObject * self = slotRawObject(a); int ptrIndex = 0; PyrSlot * ptrSlot = self->slots + ptrIndex; if (NotPtr(ptrSlot)) return errFailed; if (!IsInt(b)) return errFailed; int busIndex = slotRawInt(b); if (!IsInt(c)) return errFailed; int numberOfChannels = slotRawInt(c); server_shared_memory_client * client = (server_shared_memory_client*)slotRawPtr(ptrSlot); PyrObject * ret = newPyrArray(g->gc, numberOfChannels, 0, 1); ret->size = numberOfChannels; for (int i = 0; i != numberOfChannels; ++i) { float value = client->get_control_busses()[busIndex + i]; SetFloat(ret->slots+i, value); } SetObject(a, ret); return errNone; }
inline bool IsSignal(PyrSlot* slot) { return (IsObj(slot) && slotRawObject(slot)->classptr == class_signal); }
void TJsonVal::GetObjStrV(const char *Key, TStrV& StrV) const { EAssertR(IsObj(), "Cannot get property of non-object!"); EAssertR(IsObjKey(Key), "Unknown key: " + TStr(Key)); GetObjKey(Key)->GetArrStrV(StrV); }
TStr TJsonVal::GetObjStr(const char *Key, const TStr& DefStr) const { EAssertR(IsObj(), "Cannot get property of non-object!"); return (IsObjKey(Key)) ? KeyValH.GetDat(Key)->GetStr() : DefStr; }
void TJsonVal::GetObjFltV(const TStr& Key, TFltV& FltV) const { EAssertR(IsObj(), "Cannot get property of non-object!"); EAssertR(IsObjKey(Key), "Unknown key: " + Key); GetObjKey(Key)->GetArrNumV(FltV); }