void initPatterns() { PyrSymbol *sym; ivxIdentDict_array = instVarOffset("IdentityDictionary", "array"); ivxIdentDict_size = instVarOffset("IdentityDictionary", "size"); ivxIdentDict_parent = instVarOffset("IdentityDictionary", "parent"); ivxIdentDict_proto = instVarOffset("IdentityDictionary", "proto"); ivxIdentDict_know = instVarOffset("IdentityDictionary", "know"); sym = getsym("IdentityDictionary"); class_identdict = sym ? sym->u.classobj : NULL; class_identdict_index = slotRawInt(&class_identdict->classIndex); class_identdict_maxsubclassindex = slotRawInt(&class_identdict->maxSubclassIndex); class_array_index = slotRawInt(&class_array->classIndex); class_array_maxsubclassindex = slotRawInt(&class_array->maxSubclassIndex); s_parent = getsym("parent"); s_proto = getsym("proto"); s_delta = getsym("delta"); s_dur = getsym("dur"); s_stretch = getsym("stretch"); // used in prEvent_IsRest s_type = getsym("type"); s_rest = getsym("rest"); s_empty = getsym(""); s_r = getsym("r"); s_isRest = getsym("isRest"); class_rest = getsym("Rest")->u.classobj; class_metarest = getsym("Meta_Rest")->u.classobj; }
int mathFoldInt(struct VMGlobals *g, int numArgsPushed) { PyrSlot *a, *b, *c; int err; a = g->sp - 2; b = g->sp - 1; c = g->sp; if (IsSym(b)) { *a = *b; } else if (IsSym(c)) { *a = *c; } else if (IsInt(b) && IsInt(c)) { SetRaw(a, sc_fold(slotRawInt(a), slotRawInt(b), slotRawInt(c))); } else { double x, lo, hi; x = slotRawInt(a); err = slotDoubleVal(b, &lo); if (err) return err; err = slotDoubleVal(c, &hi); if (err) return err; SetFloat(a, sc_fold(x, lo, hi)); } return errNone; }
void initPatterns() { PyrSymbol *sym; ivxIdentDict_array = instVarOffset("IdentityDictionary", "array"); ivxIdentDict_size = instVarOffset("IdentityDictionary", "size"); ivxIdentDict_parent = instVarOffset("IdentityDictionary", "parent"); ivxIdentDict_proto = instVarOffset("IdentityDictionary", "proto"); ivxIdentDict_know = instVarOffset("IdentityDictionary", "know"); sym = getsym("IdentityDictionary"); class_identdict = sym ? sym->u.classobj : NULL; class_identdict_index = slotRawInt(&class_identdict->classIndex); class_identdict_maxsubclassindex = slotRawInt(&class_identdict->maxSubclassIndex); class_array_index = slotRawInt(&class_array->classIndex); class_array_maxsubclassindex = slotRawInt(&class_array->maxSubclassIndex); s_parent = getsym("parent"); s_proto = getsym("proto"); s_delta = getsym("delta"); s_dur = getsym("dur"); s_stretch = getsym("stretch"); }
int mathWrapInt(struct VMGlobals *g, int numArgsPushed) { PyrSlot *a, *b, *c; int err; a = g->sp - 2; b = g->sp - 1; c = g->sp; if (IsSym(b)) { *a = *b; } else if (IsSym(c)) { *a = *c; } else if (IsInt(b) && IsInt(c)) { SetRaw(a, sc_mod((int)(slotRawInt(a) - slotRawInt(b)), (int)(slotRawInt(c) - slotRawInt(b) + 1)) + slotRawInt(b)); } else { double x, lo, hi; x = slotRawInt(a); err = slotDoubleVal(b, &lo); if (err) return err; err = slotDoubleVal(c, &hi); if (err) return err; SetFloat(a, sc_mod(x - lo, hi - lo) + lo); } return errNone; }
int prSetControlBusValues(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 (!IsObj(c)) return errFailed; PyrObject * values = slotRawObject(c); server_shared_memory_client * client = (server_shared_memory_client*)slotRawPtr(ptrSlot); float * control_busses = client->get_control_busses() + busIndex; for (int i = 0; i != values->size; ++i) { float value; int error = slotFloatVal(values->slots + i, &value); if (error != errNone) return error; control_busses[i] = value; } return errNone; }
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 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; }
int prIsPrime(VMGlobals *g, int numArgsPushed) { PyrSlot *a; int n, p, sqrtn, i; a = g->sp; n = slotRawInt(a); SetNil(a); if (n <= 2) { if (n == 2) { SetTrue(a); } else { SetFalse(a); } } else if (n <= nthPrime(NUMPRIMES-1)) { // do a search of the primes table i = findPrime(n); if (i >= 0) { SetTrue(a); } else { SetFalse(a); } } else { #ifdef SC_WIN32 sqrtn = (int)sqrt(static_cast<double>(n)); #else sqrtn = (int)sqrt(n); #endif for (i=0; i<NUMPRIMES; ++i) { p = nthPrime(i); if (n % p == 0) { SetFalse(a); break; } if (p >= sqrtn) { SetTrue(a); break; } } } return errNone; }
inline int prOpInt(VMGlobals *g, int numArgsPushed) { PyrSlot *a, *b; PyrSymbol *msg; a = g->sp - 1; b = g->sp; switch (GetTag(b)) { case tagInt : SetRaw(a, Functor::run(slotRawInt(a), slotRawInt(b))); break; case tagChar : case tagPtr : case tagNil : case tagFalse : case tagTrue : goto send_normal_2; case tagSym : SetSymbol(a, slotRawSymbol(b)); break; case tagObj : if (isKindOf(slotRawObject(b), class_signal)) SetObject(a, Functor::signal_fx(g, slotRawInt(a), slotRawObject(b))); else goto send_normal_2; break; default : SetFloat(a, Functor::run((double)slotRawInt(a), slotRawFloat(b))); break; } g->sp-- ; // drop g->numpop = 0; #if TAILCALLOPTIMIZE g->tailCall = 0; #endif return errNone; send_normal_2: if (numArgsPushed != -1) // special case flag meaning it is a primitive return errFailed; // arguments remain on the stack msg = gSpecialBinarySelectors[g->primitiveIndex]; sendMessage(g, msg, 2); return errNone; }
bool addheap(VMGlobals *g, PyrObject *heapArg, double schedtime, PyrSlot *task) { PyrHeap * heap = (PyrHeap*)heapArg; #ifdef GC_SANITYCHECK g->gc->SanityCheck(); #endif if (heap->size >= ARRAYMAXINDEXSIZE(heap)) return false; assert(heap->size); // post("->addheap\n"); // dumpheap(heapArg); /* parent and sibling in the heap, not in the task hierarchy */ int mom = heap->size - 1; PyrSlot * pme = heap->slots + mom; int stabilityCount = slotRawInt(&heap->count); SetRaw(&heap->count, stabilityCount + 1); for (; mom>0;) { /* percolate up heap */ int newMom = ((mom - 3) / 2); mom = newMom - newMom % 3; /// LATER: we could avoid the division by using 4 slots per element PyrSlot * pmom = heap->slots + mom; if (schedtime < slotRawFloat(pmom)) { assert(slotRawInt(pmom + 2) < stabilityCount); slotCopy(&pme[0], &pmom[0]); slotCopy(&pme[1], &pmom[1]); slotCopy(&pme[2], &pmom[2]); pme = pmom; } else break; } SetFloat(&pme[0], schedtime); slotCopy(&pme[1], task); SetInt(&pme[2], stabilityCount); g->gc->GCWrite(heap, task); heap->size += 3; #ifdef GC_SANITYCHECK g->gc->SanityCheck(); #endif // dumpheap(heapArg); // post("<-addheap %g\n", schedtime); return true; }
int prExit(VMGlobals *g, int numArgsPushed) { PyrSlot *a = g->sp; exit(slotRawInt(a)); //post("exit %d\n", slotRawInt(a)); //DumpBackTrace(g); 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 (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 prNthPrime(VMGlobals *g, int numArgsPushed) { PyrSlot *a; int n, p; a = g->sp; n = slotRawInt(a); p = nthPrime(n); if (p == 0) { SetNil(a); } else { SetInt(a, p); } 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; }
void dumpheap(PyrObject *heapArg) { PyrHeap * heap = (PyrHeap*)heapArg; double mintime = slotRawFloat(&heap->slots[0]); int count = slotRawFloat(&heap->slots[2]); int heapSize = heap->size - 1; post("SCHED QUEUE (%d)\n", heapSize); for (int i=0; i<heapSize; i+=3) { post("%3d(%3d) %9.2f %p %d\n", i/3, i, slotRawFloat(&heap->slots[i]), slotRawObject(&heap->slots[i+1]), slotRawInt(&heap->slots[i+2])); if ((slotRawFloat(&heap->slots[i]) < mintime) || (slotRawFloat(&heap->slots[i]) == mintime && slotRawInt(&heap->slots[i+2]) < count ) ) post("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"); } }
int prFileSeek(struct VMGlobals *g, int numArgsPushed) { PyrSlot *a, *b, *c; PyrFile *pfile; FILE *file; size_t offset; int origin; static int originTable[3] = { SEEK_SET, SEEK_CUR, SEEK_END }; a = g->sp - 2; b = g->sp - 1; c = g->sp; if (NotInt(b)) return errWrongType; if (NotInt(c)) return errWrongType; pfile = (PyrFile*)slotRawObject(a); file = (FILE*)slotRawPtr(&pfile->fileptr); if (file == NULL) return errFailed; offset = slotRawInt(b); origin = slotRawInt(c); if (origin < 0 || origin > 2) return errIndexOutOfRange; origin = originTable[origin]; // translate in case ANSI constants ever change.. if (fseek(file, offset, origin)) return errFailed; return errNone; }
static int addMsgSlot(big_scpacket *packet, PyrSlot *slot) { switch (GetTag(slot)) { case tagInt : packet->addi(slotRawInt(slot)); break; case tagSym : packet->adds(slotRawSymbol(slot)->name); break; case tagObj : if (isKindOf(slotRawObject(slot), class_string)) { PyrString *stringObj = slotRawString(slot); packet->adds(stringObj->s, stringObj->size); } else if (isKindOf(slotRawObject(slot), class_int8array)) { PyrInt8Array *arrayObj = slotRawInt8Array(slot); packet->addb(arrayObj->b, arrayObj->size); } else if (isKindOf(slotRawObject(slot), class_array)) { PyrObject *arrayObj = slotRawObject(slot); big_scpacket packet2; if (arrayObj->size > 1 && isKindOfSlot(arrayObj->slots+1, class_array)) { makeSynthBundle(&packet2, arrayObj->slots, arrayObj->size, true); } else { int error = makeSynthMsgWithTags(&packet2, arrayObj->slots, arrayObj->size); if (error != errNone) return error; } packet->addb((uint8*)packet2.data(), packet2.size()); } break; case tagNil : case tagTrue : case tagFalse : case tagChar : case tagPtr : break; default : if (gUseDoubles) packet->addd(slotRawFloat(slot)); else packet->addf(slotRawFloat(slot)); break; } return errNone; }
int prIndexOfPrime(VMGlobals *g, int numArgsPushed) { PyrSlot *a; int n, p; a = g->sp; n = slotRawInt(a); if (n <= 2) { if (n == 2) { SetInt(a, 0); } else { SetNil(a); } } else if (n <= nthPrime(NUMPRIMES-1)) { p = findPrime(n); if (p < 0) { SetNil(a); } else { SetInt(a, p); } } else { SetNil(a); } return errNone; }
int prPipeClose(struct VMGlobals *g, int numArgsPushed) { PyrSlot *a; PyrSlot *b; PyrFile *pfile; FILE *file; pid_t pid; a = g->sp - 1; b = g->sp; pfile = (PyrFile*)slotRawObject(a); file = (FILE*)slotRawPtr(&pfile->fileptr); if (file == NULL) return errNone; pid = (pid_t) slotRawInt(b); SetPtr(&pfile->fileptr, NULL); int perr = sc_pclose(file, pid); SetInt(a, perr); if (perr == -1) return errFailed; return errNone; }
void serialize(PyrSlot * slot) { if (IsFloat(slot)) { emitter << slotRawFloat(slot); return; } switch (GetTag(slot)) { case tagNil: emitter << YAML::Null; return; case tagInt: emitter << slotRawInt(slot); return; case tagFalse: emitter << false; return; case tagTrue: emitter << true; return; case tagObj: serialize(slotRawObject(slot)); return; case tagSym: emitter << YAML::DoubleQuoted << slotRawSymbol(slot)->name; return; default: printf ("type: %d\n", GetTag(slot)); throw std::runtime_error("YAMLSerializer: not implementation for this type"); } }
int prString_FindRegexp(struct VMGlobals *g, int numArgsPushed) { int err; PyrSlot *a = g->sp - 2; // source string PyrSlot *b = g->sp - 1; // pattern PyrSlot *c = g->sp; // offset if (!isKindOfSlot(b, class_string) || (NotInt(c))) return errWrongType; // post("prString_FindRegexp\n"); int maxfind = MAXREGEXFIND; int offset = slotRawInt(c); int stringsize = slotRawObject(a)->size + 1; int patternsize = slotRawObject(b)->size + 1; char *string = (char*)malloc(slotRawObject(a)->size + 1); err = slotStrVal(a, string, slotRawObject(a)->size + 1); if (err){ free(string); return err; } char *pattern = (char*)malloc(slotRawObject(b)->size + 1); err = slotStrVal(b, pattern, slotRawObject(b)->size + 1); if (err) return err; UParseError uerr; UErrorCode status = (UErrorCode)0; UChar *regexStr; UChar *ustring; regexStr = (UChar*)malloc((patternsize)*sizeof(UChar)); u_charsToUChars (pattern, regexStr, patternsize); ustring = (UChar*)malloc((stringsize)*sizeof(UChar)); u_charsToUChars (string+offset, ustring, stringsize-offset); unsigned flags = UREGEX_MULTILINE; int groupNumber = 0; SCRegExRegion * what; int indx = 0; int size = 0; URegularExpression *expression = uregex_open(regexStr, -1, flags, &uerr, &status); if(U_FAILURE(status)) goto nilout; if(!U_FAILURE(status)) { uregex_setText(expression, ustring, -1, &status); what = (SCRegExRegion*)malloc((maxfind)*sizeof(SCRegExRegion)); for(int i=0; i< maxfind; i++) { SCRegExRegion range; range.matched = false; what[i] = range; } int32_t groups = uregex_groupCount(expression, &status) + 1; if(U_FAILURE(status)) goto nilout; // post("groups: %i\n", groups); while (uregex_findNext(expression, &status) && size<maxfind) { if(U_FAILURE(status)) return errNone; for(int i=0; i< groups; ++i){ what[size].group = i; what[size].start = sc_clip(uregex_start(expression, i, &status), 0, stringsize) ; if(U_FAILURE(status)) goto nilout; what[size].end = sc_clip(uregex_end(expression, i, &status), 0, stringsize); what[size].matched = true; // post("index:%i, size:%i, start %i, end %i\n", i, size, what[i].start, what[i].end); size = indx++ + 1; if(U_FAILURE(status)) goto nilout; } } PyrObject *result_array = newPyrArray(g->gc, size, 0, true); result_array->size = 0; if (size>0) //(matched) { for (int i = 0; i < size; i++) { if (what[0].matched == false) { result_array->size++; SetNil(result_array->slots+i); } else { result_array->size++; int match_start = what[i].start; int match_length = what[i].end - what[i].start; // post("for i:%i, start %i, end %i\n", i, what[i].start, what[i].end); // char *match = (char*)malloc(match_length); char match[match_length]; strncpy(match, string + offset + match_start, match_length); match[match_length] = 0; PyrObject *array = newPyrArray(g->gc, 2, 0, true); array->size = 2; SetInt(array->slots, match_start + offset); PyrObject *matched_string = (PyrObject*)newPyrString(g->gc, match, 0, true); SetObject(array->slots+1, matched_string); g->gc->GCWrite(matched_string, array->slots + 1); SetObject(result_array->slots + i, array); g->gc->GCWrite(array, result_array->slots + i); } } } else { SetNil(a); } free(what); free(pattern); free(regexStr); free(ustring); free(string); SetObject(a, result_array); g->gc->GCWrite(result_array,a); //uregex_close(expression); return errNone; } nilout: free(string); free(what); free(pattern); free(regexStr); free(ustring); SetNil(a); return errNone; }
HOT void sendMessageWithKeys(VMGlobals *g, PyrSymbol *selector, long numArgsPushed, long numKeyArgsPushed) { PyrMethod *meth = NULL; PyrMethodRaw *methraw; PyrSlot *recvrSlot, *sp; PyrClass *classobj; long index; PyrObject *obj; //postfl("->sendMessage\n"); #ifdef GC_SANITYCHECK g->gc->SanityCheck(); CallStackSanity(g, "sendMessageWithKeys"); #endif recvrSlot = g->sp - numArgsPushed + 1; classobj = classOfSlot(recvrSlot); lookup_again: index = slotRawInt(&classobj->classIndex) + selector->u.index; meth = gRowTable[index]; if (slotRawSymbol(&meth->name) != selector) { doesNotUnderstandWithKeys(g, selector, numArgsPushed, numKeyArgsPushed); } else { methraw = METHRAW(meth); //postfl("methraw->methType %d\n", methraw->methType); switch (methraw->methType) { case methNormal : /* normal msg send */ executeMethodWithKeys(g, meth, numArgsPushed, numKeyArgsPushed); break; case methReturnSelf : /* return self */ g->sp -= numArgsPushed - 1; break; case methReturnLiteral : /* return literal */ sp = g->sp -= numArgsPushed - 1; slotCopy(sp, &meth->selectors); /* in this case selectors is just a single value */ break; case methReturnArg : /* return an argument */ numArgsPushed = keywordFixStack(g, meth, methraw, numArgsPushed, numKeyArgsPushed); numKeyArgsPushed = 0; g->sp -= numArgsPushed - 1; sp = g->sp; index = methraw->specialIndex; // zero is index of the first argument if (index < numArgsPushed) { slotCopy(sp, sp + index); } else { slotCopy(sp, &slotRawObject(&meth->prototypeFrame)->slots[index]); } break; case methReturnInstVar : /* return inst var */ sp = g->sp -= numArgsPushed - 1; index = methraw->specialIndex; slotCopy(sp, &slotRawObject(recvrSlot)->slots[index]); break; case methAssignInstVar : /* assign inst var */ sp = g->sp -= numArgsPushed - 1; index = methraw->specialIndex; obj = slotRawObject(recvrSlot); if (obj->IsImmutable()) { StoreToImmutableB(g, sp, g->ip); } else { if (numArgsPushed >= 2) { slotCopy(&obj->slots[index], sp + 1); g->gc->GCWrite(obj, sp + 1); } else { SetNil(&obj->slots[index]); } slotCopy(sp, recvrSlot); } break; case methReturnClassVar : /* return class var */ sp = g->sp -= numArgsPushed - 1; slotCopy(sp, &g->classvars->slots[methraw->specialIndex]); break; case methAssignClassVar : /* assign class var */ sp = g->sp -= numArgsPushed - 1; if (numArgsPushed >= 2) { slotCopy(&g->classvars->slots[methraw->specialIndex], sp + 1); g->gc->GCWrite(g->classvars, sp + 1); } else { SetNil(&g->classvars->slots[methraw->specialIndex]); } slotCopy(sp, recvrSlot); break; case methRedirect : /* send a different selector to self, e.g. this.subclassResponsibility */ numArgsPushed = keywordFixStack(g, meth, methraw, numArgsPushed, numKeyArgsPushed); numKeyArgsPushed = 0; selector = slotRawSymbol(&meth->selectors); goto lookup_again; case methRedirectSuper : /* send a different selector to self, e.g. this.subclassResponsibility */ numArgsPushed = keywordFixStack(g, meth, methraw, numArgsPushed, numKeyArgsPushed); numKeyArgsPushed = 0; selector = slotRawSymbol(&meth->selectors); classobj = slotRawSymbol(&slotRawClass(&meth->ownerclass)->superclass)->u.classobj; goto lookup_again; case methForwardInstVar : /* forward to an instance variable */ numArgsPushed = keywordFixStack(g, meth, methraw, numArgsPushed, numKeyArgsPushed); numKeyArgsPushed = 0; selector = slotRawSymbol(&meth->selectors); index = methraw->specialIndex; slotCopy(recvrSlot, &slotRawObject(recvrSlot)->slots[index]); classobj = classOfSlot(recvrSlot); goto lookup_again; case methForwardClassVar : /* forward to a class variable */ numArgsPushed = keywordFixStack(g, meth, methraw, numArgsPushed, numKeyArgsPushed); numKeyArgsPushed = 0; selector = slotRawSymbol(&meth->selectors); slotCopy(recvrSlot, &g->classvars->slots[methraw->specialIndex]); classobj = classOfSlot(recvrSlot); goto lookup_again; case methPrimitive : /* primitive */ doPrimitiveWithKeys(g, meth, (int)numArgsPushed, (int)numKeyArgsPushed); #ifdef GC_SANITYCHECK g->gc->SanityCheck(); #endif break; } } #if TAILCALLOPTIMIZE g->tailCall = 0; #endif #ifdef GC_SANITYCHECK g->gc->SanityCheck(); CallStackSanity(g, "<sendMessageWithKeys"); #endif //postfl("<-sendMessage\n"); }
HOT void sendSuperMessage(VMGlobals *g, PyrSymbol *selector, long numArgsPushed) { PyrMethod *meth = NULL; PyrMethodRaw *methraw; PyrSlot *recvrSlot, *sp; PyrClass *classobj; long index; PyrObject *obj; //postfl("->sendMessage\n"); #ifdef GC_SANITYCHECK g->gc->SanityCheck(); CallStackSanity(g, "sendSuperMessage"); #endif recvrSlot = g->sp - numArgsPushed + 1; classobj = slotRawSymbol(&slotRawClass(&g->method->ownerclass)->superclass)->u.classobj; //assert(isKindOfSlot(recvrSlot, classobj)); lookup_again: index = slotRawInt(&classobj->classIndex) + selector->u.index; meth = gRowTable[index]; if (slotRawSymbol(&meth->name) != selector) { doesNotUnderstand(g, selector, numArgsPushed); } else { methraw = METHRAW(meth); //postfl("methraw->methType %d\n", methraw->methType); switch (methraw->methType) { case methNormal : /* normal msg send */ executeMethod(g, meth, numArgsPushed); break; case methReturnSelf : /* return self */ g->sp -= numArgsPushed - 1; break; case methReturnLiteral : /* return literal */ sp = g->sp -= numArgsPushed - 1; slotCopy(sp, &meth->selectors); /* in this case selectors is just a single value */ break; case methReturnArg : /* return an argument */ sp = g->sp -= numArgsPushed - 1; index = methraw->specialIndex; // zero is index of the first argument if (index < numArgsPushed) { slotCopy(sp, sp + index); } else { slotCopy(sp, &slotRawObject(&meth->prototypeFrame)->slots[index]); } break; case methReturnInstVar : /* return inst var */ sp = g->sp -= numArgsPushed - 1; index = methraw->specialIndex; slotCopy(sp, &slotRawObject(recvrSlot)->slots[index]); break; case methAssignInstVar : /* assign inst var */ sp = g->sp -= numArgsPushed - 1; index = methraw->specialIndex; obj = slotRawObject(recvrSlot); if (obj->IsImmutable()) { StoreToImmutableB(g, sp, g->ip); } else { if (numArgsPushed >= 2) { slotCopy(&obj->slots[index], sp + 1); g->gc->GCWrite(obj, sp + 1); } else { SetNil(&obj->slots[index]); } slotCopy(sp, recvrSlot); } break; case methReturnClassVar : /* return class var */ sp = g->sp -= numArgsPushed - 1; slotCopy(sp, &g->classvars->slots[methraw->specialIndex]); break; case methAssignClassVar : /* assign class var */ sp = g->sp -= numArgsPushed - 1; if (numArgsPushed >= 2) { slotCopy(&g->classvars->slots[methraw->specialIndex], sp + 1); g->gc->GCWrite(g->classvars, sp + 1); } else { SetNil(&g->classvars->slots[methraw->specialIndex]); } slotCopy(sp, recvrSlot); break; case methRedirect : /* send a different selector to self, e.g. this.subclassResponsibility */ if (numArgsPushed < methraw->numargs) { // not enough args pushed /* push default arg values */ PyrSlot *pslot, *qslot; long m, mmax; pslot = g->sp; qslot = slotRawObject(&meth->prototypeFrame)->slots + numArgsPushed - 1; for (m=0, mmax=methraw->numargs - numArgsPushed; m<mmax; ++m) slotCopy(++pslot, ++qslot); numArgsPushed = methraw->numargs; g->sp += mmax; } selector = slotRawSymbol(&meth->selectors); goto lookup_again; case methRedirectSuper : /* send a different selector to self, e.g. this.subclassResponsibility */ if (numArgsPushed < methraw->numargs) { // not enough args pushed /* push default arg values */ PyrSlot *pslot, *qslot; long m, mmax; pslot = g->sp; qslot = slotRawObject(&meth->prototypeFrame)->slots + numArgsPushed - 1; for (m=0, mmax=methraw->numargs - numArgsPushed; m<mmax; ++m) slotCopy(++pslot, ++qslot); numArgsPushed = methraw->numargs; g->sp += mmax; } selector = slotRawSymbol(&meth->selectors); classobj = slotRawSymbol(&slotRawClass(&meth->ownerclass)->superclass)->u.classobj; goto lookup_again; case methForwardInstVar : /* forward to an instance variable */ if (numArgsPushed < methraw->numargs) { // not enough args pushed /* push default arg values */ PyrSlot *pslot, *qslot; long m, mmax; pslot = g->sp; qslot = slotRawObject(&meth->prototypeFrame)->slots + numArgsPushed - 1; for (m=0, mmax=methraw->numargs - numArgsPushed; m<mmax; ++m) slotCopy(++pslot, ++qslot); numArgsPushed = methraw->numargs; g->sp += mmax; } selector = slotRawSymbol(&meth->selectors); index = methraw->specialIndex; slotCopy(recvrSlot, &slotRawObject(recvrSlot)->slots[index]); classobj = classOfSlot(recvrSlot); goto lookup_again; case methForwardClassVar : /* forward to a class variable */ if (numArgsPushed < methraw->numargs) { // not enough args pushed /* push default arg values */ PyrSlot *pslot, *qslot; long m, mmax; pslot = g->sp; qslot = slotRawObject(&meth->prototypeFrame)->slots + numArgsPushed - 1; for (m=0, mmax=methraw->numargs - numArgsPushed; m<mmax; ++m) slotCopy(++pslot, ++qslot); numArgsPushed = methraw->numargs; g->sp += mmax; } selector = slotRawSymbol(&meth->selectors); slotCopy(recvrSlot, &g->classvars->slots[methraw->specialIndex]); classobj = classOfSlot(recvrSlot); goto lookup_again; case methPrimitive : /* primitive */ doPrimitive(g, meth, (int)numArgsPushed); #ifdef GC_SANITYCHECK g->gc->SanityCheck(); #endif break; /* case methMultDispatchByClass : { index = methraw->specialIndex; if (index < numArgsPushed) { classobj = slotRawObject(sp + index)->classptr; selector = slotRawSymbol(&meth->selectors); goto lookup_again; } else { doesNotUnderstand(g, selector, numArgsPushed); } } break; case methMultDispatchByValue : { index = methraw->specialIndex; if (index < numArgsPushed) { index = arrayAtIdentityHashInPairs(array, b); meth = slotRawObject(&meth->selectors)->slots[index + 1].uom; goto meth_select_again; } else { doesNotUnderstand(g, selector, numArgsPushed); } } break; */ } } #if TAILCALLOPTIMIZE g->tailCall = 0; #endif #ifdef GC_SANITYCHECK g->gc->SanityCheck(); CallStackSanity(g, "<sendSuperMessage"); #endif //postfl("<-sendMessage\n"); }
int prFileWriteLE(struct VMGlobals *g, int numArgsPushed) { PyrSlot *a, *b, *ptr; PyrFile *pfile; FILE *file; PyrObject *obj; char chr; a = g->sp - 1; b = g->sp; pfile = (PyrFile*)slotRawObject(a); file = (FILE*)slotRawPtr(&pfile->fileptr); if (file == NULL) return errFailed; switch (GetTag(b)) { case tagInt : { SC_IOStream<FILE*> scio(file); scio.writeInt32_le(slotRawInt(b)); break; } case tagSym : fwrite(slotRawSymbol(b)->name, sizeof(char), slotRawSymbol(b)->length, file); break; case tagChar : chr = slotRawInt(b); fwrite(&chr, sizeof(char), 1, file); break; case tagNil : case tagFalse : case tagTrue : case tagPtr : return errWrongType; case tagObj : { // writes the indexable part of any non obj_slot format object obj = slotRawObject(b); if (!isKindOf(obj, class_rawarray) || isKindOf(obj, class_symbolarray)) return errWrongType; if (obj->size) { ptr = obj->slots; int elemSize = gFormatElemSize[obj->obj_format]; int numElems = obj->size; #if BYTE_ORDER == BIG_ENDIAN switch (elemSize) { case 1: fwrite(ptr, elemSize, numElems, file); break; case 2: { char *ptr = slotRawString(b)->s; char *ptrend = ptr + numElems*2; for (; ptr < ptrend; ptr+=2) { fputc(ptr[1], file); fputc(ptr[0], file); } break; } case 4: { char *ptr = slotRawString(b)->s; char *ptrend = ptr + numElems*4; for (; ptr < ptrend; ptr+=4) { fputc(ptr[3], file); fputc(ptr[2], file); fputc(ptr[1], file); fputc(ptr[0], file); } break; } case 8: { char *ptr = slotRawString(b)->s; char *ptrend = ptr + numElems*8; for (; ptr < ptrend; ptr+=8) { fputc(ptr[7], file); fputc(ptr[6], file); fputc(ptr[5], file); fputc(ptr[4], file); fputc(ptr[3], file); fputc(ptr[2], file); fputc(ptr[1], file); fputc(ptr[0], file); } break; } } #else fwrite(ptr, elemSize, numElems, file); #endif } break; } default : // double { SC_IOStream<FILE*> scio(file); scio.writeDouble_le(slotRawFloat(b)); break; } } 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 }
HOT void executeMethod(VMGlobals *g, PyrMethod *meth, long numArgsPushed) { PyrMethodRaw *methraw; PyrFrame *frame; PyrFrame *caller; PyrSlot *pslot, *qslot; PyrSlot *rslot; PyrSlot *vars; PyrObject *proto; long i, m, mmax, numtemps, numargs; #ifdef GC_SANITYCHECK g->gc->SanityCheck(); CallStackSanity(g, "executeMethod"); #endif #if DEBUGMETHODS if (gTraceInterpreter) { if (g->method) { postfl(" %s:%s -> %s:%s\n", slotRawSymbol(&slotRawClass(&g->method->ownerclass)->name)->name, slotRawSymbol(&g->method->name)->name, slotRawSymbol(&slotRawClass(&meth->ownerclass)->name)->name, slotRawSymbol(&meth->name)->name); } else { postfl(" top -> %s:%s\n", slotRawSymbol(&slotRawClass(&meth->ownerclass)->name)->name, slotRawSymbol(&meth->name)->name); } } #endif #if METHODMETER if (gTraceInterpreter) { slotRawInt(&meth->callMeter)++; } #endif #if TAILCALLOPTIMIZE int tailCall = g->tailCall; if (tailCall) { if (tailCall == 1) { returnFromMethod(g); } else { returnFromBlock(g); } } #endif g->execMethod = 20; proto = slotRawObject(&meth->prototypeFrame); methraw = METHRAW(meth); numtemps = methraw->numtemps; numargs = methraw->numargs; caller = g->frame; //postfl("executeMethod allArgsPushed %d numKeyArgsPushed %d\n", allArgsPushed, numKeyArgsPushed); frame = (PyrFrame*)g->gc->NewFrame(methraw->frameSize, 0, obj_slot, methraw->needsHeapContext); vars = frame->vars - 1; frame->classptr = class_frame; frame->size = FRAMESIZE + proto->size; SetObject(&frame->method, meth); SetObject(&frame->homeContext, frame); SetObject(&frame->context, frame); if (caller) { SetPtr(&caller->ip, g->ip); SetObject(&frame->caller, caller); } else { SetInt(&frame->caller, 0); } SetPtr(&frame->ip, 0); g->method = meth; g->ip = slotRawInt8Array(&meth->code)->b - 1; g->frame = frame; g->block = (PyrBlock*)meth; g->sp -= numArgsPushed; qslot = g->sp; pslot = vars; if (numArgsPushed <= numargs) { /* not enough args pushed */ /* push all args to frame */ for (m=0,mmax=numArgsPushed; m<mmax; ++m) slotCopy(++pslot, ++qslot); /* push default arg & var values */ pslot = vars + numArgsPushed; qslot = proto->slots + numArgsPushed - 1; for (m=0, mmax=numtemps - numArgsPushed; m<mmax; ++m) slotCopy(++pslot, ++qslot); } else if (methraw->varargs) { PyrObject *list; PyrSlot *lslot; /* push all normal args to frame */ for (m=0,mmax=numargs; m<mmax; ++m) slotCopy(++pslot, ++qslot); /* push list */ i = numArgsPushed - numargs; list = newPyrArray(g->gc, (int)i, 0, false); list->size = (int)i; rslot = pslot+1; SetObject(rslot, list); //SetObject(vars + numargs + 1, list); /* put extra args into list */ lslot = (list->slots - 1); // fixed and raw sizes are zero for (m=0,mmax=i; m<mmax; ++m) slotCopy(++lslot, ++qslot); if (methraw->numvars) { /* push default keyword and var values */ pslot = vars + numargs + 1; qslot = proto->slots + numargs; for (m=0,mmax=methraw->numvars; m<mmax; ++m) slotCopy(++pslot, ++qslot); } } else { /* push all args to frame */ for (m=0,mmax=numargs; m<mmax; ++m) slotCopy(++pslot, ++qslot); if (methraw->numvars) { /* push default keyword and var values */ pslot = vars + numargs; qslot = proto->slots + numargs - 1; for (m=0,mmax=methraw->numvars; m<mmax; ++m) slotCopy(++pslot, ++qslot); } } slotCopy(&g->receiver, &vars[1]); #ifdef GC_SANITYCHECK g->gc->SanityCheck(); CallStackSanity(g, "<executeMethod"); #endif }
bool getheap(VMGlobals *g, PyrObject *heapArg, double *schedtime, PyrSlot *task) { PyrHeap * heap = (PyrHeap*)heapArg; PyrGC* gc = g->gc; bool isPartialScanObj = gc->IsPartialScanObject(heapArg); assert(heap->size); // post("->getheap\n"); // dumpheap(heapArg); if (heap->size>1) { *schedtime = slotRawFloat(&heap->slots[0]); slotCopy(task, &heap->slots[1]); heap->size -= 3; int size = heap->size - 1; slotCopy(&heap->slots[0], &heap->slots[size]); slotCopy(&heap->slots[1], &heap->slots[size+1]); slotCopy(&heap->slots[2], &heap->slots[size+2]); /* parent and sibling in the heap, not in the task hierarchy */ int mom = 0; int me = 3; PyrSlot * pmom = heap->slots + mom; PyrSlot * pme = heap->slots + me; PyrSlot * pend = heap->slots + size; double timetemp = slotRawFloat(&pmom[0]); int stabilityCountTemp = slotRawInt(&pmom[2]); PyrSlot tasktemp; slotCopy(&tasktemp, &pmom[1]); for (;pme < pend;) { /* demote heap */ if (pme+3 < pend && ((slotRawFloat(&pme[0]) > slotRawFloat(&pme[3])) || ((slotRawFloat(&pme[0]) == slotRawFloat(&pme[3])) && (slotRawInt(&pme[2]) > slotRawInt(&pme[5])) ))) { me += 3; pme += 3; } if (timetemp > slotRawFloat(&pme[0]) || (timetemp == slotRawFloat(&pme[0]) && stabilityCountTemp > slotRawInt(&pme[2]))) { slotCopy(&pmom[0], &pme[0]); slotCopy(&pmom[1], &pme[1]); slotCopy(&pmom[2], &pme[2]); if (isPartialScanObj) { gc->GCWriteBlack(pmom+1); } pmom = pme; me = ((mom = me) * 2) + 3; pme = heap->slots + me; } else break; } SetRaw(&pmom[0], timetemp); slotCopy(&pmom[1], &tasktemp); SetRaw(&pmom[2], stabilityCountTemp); if (isPartialScanObj) gc->GCWriteBlack(pmom+1); if (size == 0) SetInt(&heap->count, 0); // dumpheap(heapArg); // post("<-getheap true\n"); return true; } else { // post("<-getheap false\n"); return false; } }
int prSimpleNumberSeries(struct VMGlobals *g, int numArgsPushed) { PyrSlot *a = g->sp - 2; PyrSlot *b = g->sp - 1; PyrSlot *c = g->sp; int err, size; if (IsInt(a) && (IsInt(b) || IsNil(b)) && IsInt(c)) { int first, second, last, step; first = slotRawInt(a); last = slotRawInt(c); second = IsInt(b) ? slotRawInt(b) : (first < last ? first + 1 : first - 1); step = second - first; if ( step == 0 ) size = 1; else size = ((last - first) / step) + 1; if(size<1 || size > INT_MAX_BY_PyrSlot){ post("prSimpleNumberSeries: array size %i exceeds limit (%i)\n", size, INT_MAX_BY_PyrSlot); return errFailed; } PyrObject *obj = newPyrArray(g->gc, size, 0, true); obj->size = size; PyrSlot *slots = obj->slots; if(step==1){ // Faster iteration for common case if(first==0){ for (int i=0; i<size; ++i) { SetInt(slots+i, i); } }else{ for (int i=0; i<size; ++i) { SetInt(slots+i, first++); } } }else{ int val = first; for (int i=0; i<size; ++i) { SetInt(slots+i, val); val += step; } } SetObject(a, obj); } else { double first, second, last, step; err = slotDoubleVal(a, &first); if (err) return err; err = slotDoubleVal(c, &last); if (err) return err; err = slotDoubleVal(b, &second); if (err) { if (first < last) second = first + 1.; else second = first - 1.; } step = second - first; size = (int)floor((last - first) / step + 0.001) + 1; if(size<1 || size > INT_MAX_BY_PyrSlot){ post("prSimpleNumberSeries: array size %i exceeds limit (%i)\n", size, INT_MAX_BY_PyrSlot); return errFailed; } PyrObject *obj = newPyrArray(g->gc, size, 0, true); obj->size = size; PyrSlot *slots = obj->slots; if(first==0. && step==1.){ // Faster iteration for common case for (long i=0; i<size; ++i) { SetFloat(slots+i, i); } }else{ double val = first; for (long i=0; i<size; ++i) { val = first + step * i; SetFloat(slots+i, val); } } SetObject(a, obj); } return errNone; }
static int read( PyrSlot *slot ) { return slotRawInt(slot); }