int identDictPut(struct VMGlobals *g, PyrObject *dict, PyrSlot *key, PyrSlot *value) { PyrSlot *slot, *newslot; int i, index, size; PyrObject *array; bool knows = IsTrue(dict->slots + ivxIdentDict_know); if (knows && IsSym(key)) { if (slotRawSymbol(key) == s_parent) { slotCopy(&dict->slots[ivxIdentDict_parent],value); g->gc->GCWrite(dict, value); return errNone; } if (slotRawSymbol(key) == s_proto) { slotCopy(&dict->slots[ivxIdentDict_proto],value); g->gc->GCWrite(dict, value); return errNone; } } array = slotRawObject(&dict->slots[ivxIdentDict_array]); if (array->IsImmutable()) return errImmutableObject; if (!isKindOf((PyrObject*)array, class_array)) return errFailed; index = arrayAtIdentityHashInPairs(array, key); slot = array->slots + index; slotCopy(&slot[1],value); g->gc->GCWrite(array, value); if (IsNil(slot)) { slotCopy(slot,key); g->gc->GCWrite(array, key); size = slotRawInt(&dict->slots[ivxIdentDict_size]) + 1; SetRaw(&dict->slots[ivxIdentDict_size], size); if (array->size < size*3) { PyrObject *newarray; newarray = newPyrArray(g->gc, size*3, 0, false); newarray->size = ARRAYMAXINDEXSIZE(newarray); nilSlots(newarray->slots, newarray->size); slot = array->slots; for (i=0; i<array->size; i+=2, slot+=2) { if (NotNil(slot)) { index = arrayAtIdentityHashInPairs(newarray, slot); newslot = newarray->slots + index; slotCopy(&newslot[0],&slot[0]); slotCopy(&newslot[1],&slot[1]); } } SetRaw(&dict->slots[ivxIdentDict_array], newarray); g->gc->GCWriteNew(dict, newarray); // we know newarray is white so we can use GCWriteNew } } return errNone; }
int prIdentDict_PutGet(struct VMGlobals *g, int numArgsPushed) { PyrSlot *a, *b, *c, *d, *slot, *newslot; int i, index, size; PyrObject *dict; PyrObject *array; a = g->sp - 2; // dict b = g->sp - 1; // key c = g->sp; // value d = ++g->sp; // push the stack to save the receiver slotCopy(d,a); dict = slotRawObject(d); array = slotRawObject(&dict->slots[ivxIdentDict_array]); if (!isKindOf((PyrObject*)array, class_array)) { SetNil(a); --g->sp; return errFailed; } index = arrayAtIdentityHashInPairs(array, b); slot = array->slots + index; slotCopy(a,&slot[1]); slotCopy(&slot[1],c); g->gc->GCWrite(array, c); if (IsNil(slot)) { slotCopy(slot,b); g->gc->GCWrite(array, b); size = slotRawInt(&dict->slots[ivxIdentDict_size]) + 1; SetRaw(&dict->slots[ivxIdentDict_size], size); if (array->size < size*3) { PyrObject *newarray; newarray = newPyrArray(g->gc, size*3, 0, true); newarray->size = ARRAYMAXINDEXSIZE(newarray); nilSlots(newarray->slots, newarray->size); slot = array->slots; for (i=0; i<array->size; i+=2, slot+=2) { if (NotNil(slot)) { index = arrayAtIdentityHashInPairs(newarray, slot); newslot = newarray->slots + index; slotCopy(&newslot[0],&slot[0]); slotCopy(&newslot[1],&slot[1]); } } SetRaw(&dict->slots[ivxIdentDict_array], newarray); g->gc->GCWriteNew(dict, newarray); // we know newarray is white so we can use GCWriteNew } } --g->sp; return errNone; }
int identDictPut(struct VMGlobals *g, PyrObject *dict, PyrSlot *key, PyrSlot *value) { PyrSlot *slot, *newslot; int i, index, size; PyrObject *array; bool knows = IsTrue(dict->slots + ivxIdentDict_know); if (knows && IsSym(key)) { if (key->us == s_parent) { slotCopy(&dict->slots[ivxIdentDict_parent],value); g->gc->GCWrite(dict, value); return errNone; } if (key->us == s_proto) { slotCopy(&dict->slots[ivxIdentDict_proto],value); g->gc->GCWrite(dict, value); return errNone; } } array = dict->slots[ivxIdentDict_array].uo; if (!isKindOf((PyrObject*)array, class_array)) return errFailed; index = arrayAtIdentityHashInPairs(array, key); slot = array->slots + index; slotCopy(&slot[1],value); g->gc->GCWrite(array, value); if (IsNil(slot)) { slotCopy(slot,key); g->gc->GCWrite(array, key); size = ++dict->slots[ivxIdentDict_size].ui; if (array->size < size*3) { PyrObject *newarray; newarray = newPyrArray(g->gc, size*3, 0, false); newarray->size = ARRAYMAXINDEXSIZE(newarray); nilSlots(newarray->slots, newarray->size); slot = array->slots; for (i=0; i<array->size; i+=2, slot+=2) { if (NotNil(slot)) { index = arrayAtIdentityHashInPairs(newarray, slot); newslot = newarray->slots + index; slotCopy(&newslot[0],&slot[0]); slotCopy(&newslot[1],&slot[1]); } } dict->slots[ivxIdentDict_array].uo = newarray; g->gc->GCWrite(dict, newarray); } } return errNone; }
int prArray_AtIdentityHashInPairs(struct VMGlobals *g, int numArgsPushed) { PyrSlot *a, *b; unsigned int i; a = g->sp - 1; // array b = g->sp; // key if(slotRawObject(a)->size < 2) return errFailed; i = arrayAtIdentityHashInPairs(slotRawObject(a), b); SetInt(a, i); return errNone; }
void doesNotUnderstand(VMGlobals *g, PyrSymbol *selector, long numArgsPushed) { PyrSlot *qslot, *pslot, *pend; long i, index; PyrSlot *uniqueMethodSlot, *arraySlot, *recvrSlot, *selSlot, *slot; PyrClass *classobj; PyrMethod *meth; PyrObject *array; #ifdef GC_SANITYCHECK g->gc->SanityCheck(); #endif // move args up by one to make room for selector qslot = g->sp + 1; pslot = g->sp + 2; pend = pslot - numArgsPushed + 1; while (pslot > pend) *--pslot = *--qslot; selSlot = g->sp - numArgsPushed + 2; SetSymbol(selSlot, selector); g->sp++; recvrSlot = selSlot - 1; classobj = classOfSlot(recvrSlot); index = slotRawInt(&classobj->classIndex) + s_nocomprendo->u.index; meth = gRowTable[index]; if (slotRawClass(&meth->ownerclass) == class_object) { // lookup instance specific method uniqueMethodSlot = &g->classvars->slots[cvxUniqueMethods]; if (isKindOfSlot(uniqueMethodSlot, class_identdict)) { arraySlot = slotRawObject(uniqueMethodSlot)->slots + ivxIdentDict_array; if ((IsObj(arraySlot) && (array = slotRawObject(arraySlot))->classptr == class_array)) { i = arrayAtIdentityHashInPairs(array, recvrSlot); if (i >= 0) { slot = array->slots + i; if (NotNil(slot)) { ++slot; if (isKindOfSlot(slot, class_identdict)) { arraySlot = slotRawObject(slot)->slots + ivxIdentDict_array; if ((IsObj(arraySlot) && (array = slotRawObject(arraySlot))->classptr == class_array)) { i = arrayAtIdentityHashInPairs(array, selSlot); if (i >= 0) { slot = array->slots + i; if (NotNil(slot)) { ++slot; slotCopy(selSlot, recvrSlot); slotCopy(recvrSlot, slot); blockValue(g, (int)numArgsPushed+1); return; } } } } } } } } } executeMethod(g, meth, numArgsPushed+1); #ifdef GC_SANITYCHECK g->gc->SanityCheck(); #endif }