@@ -21,7 +21,7 @@ void free_key(VM *vm) {
21 // nothing to free, we just used the VM pointer which is freed elsewhere
21 // nothing to free, we just used the VM pointer which is freed elsewhere
24−VM* init_vm(int stack_size, size_t heap_size,
24+VM* init_vm(int stack_size, size_t heap_size,
25 int max_threads // not implemented yet
25 int max_threads // not implemented yet
@@ -113,7 +113,7 @@ void idris_requireAlloc(size_t size) {
113#ifdef HAS_PTHREAD
113#ifdef HAS_PTHREAD
114 int lock = vm->processes > 0;
114 int lock = vm->processes > 0;
115 if (lock) { // We only need to lock if we're in concurrent mode
115 if (lock) { // We only need to lock if we're in concurrent mode
116− pthread_mutex_lock(&vm->alloc_lock);
116+ pthread_mutex_lock(&vm->alloc_lock);
@@ -123,7 +123,7 @@ void idris_doneAlloc() {
123 VM* vm = pthread_getspecific(vm_key);
123 VM* vm = pthread_getspecific(vm_key);
124 int lock = vm->processes > 0;
124 int lock = vm->processes > 0;
125 if (lock) { // We only need to lock if we're in concurrent mode
125 if (lock) { // We only need to lock if we're in concurrent mode
126− pthread_mutex_unlock(&vm->alloc_lock);
126+ pthread_mutex_unlock(&vm->alloc_lock);
@@ -153,7 +153,7 @@ void* allocate(size_t size, int outerlock) {
153 int lock = vm->processes > 0 && !outerlock;
153 int lock = vm->processes > 0 && !outerlock;
155 if (lock) { // not message passing
155 if (lock) { // not message passing
156− pthread_mutex_lock(&vm->alloc_lock);
156+ pthread_mutex_lock(&vm->alloc_lock);
159 VM* vm = global_vm;
159 VM* vm = global_vm;
@@ -176,7 +176,7 @@ void* allocate(size_t size, int outerlock) {
176 memset(ptr, 0, size);
176 memset(ptr, 0, size);
177#ifdef HAS_PTHREAD
177#ifdef HAS_PTHREAD
178 if (lock) { // not message passing
178 if (lock) { // not message passing
179− pthread_mutex_unlock(&vm->alloc_lock);
179+ pthread_mutex_unlock(&vm->alloc_lock);
182 return ptr;
182 return ptr;
@@ -184,7 +184,7 @@ void* allocate(size_t size, int outerlock) {
184 idris_gc(vm);
184 idris_gc(vm);
185#ifdef HAS_PTHREAD
185#ifdef HAS_PTHREAD
186 if (lock) { // not message passing
186 if (lock) { // not message passing
187− pthread_mutex_unlock(&vm->alloc_lock);
187+ pthread_mutex_unlock(&vm->alloc_lock);
190 return allocate(size, 0);
190 return allocate(size, 0);
@@ -250,7 +250,7 @@ VAL MKMPTR(VM* vm, void* ptr, size_t size) {
250 SETTY(cl, MANAGEDPTR);
250 SETTY(cl, MANAGEDPTR);
251 cl->info.mptr = (ManagedPtr*)((char*)cl + sizeof(Closure));
251 cl->info.mptr = (ManagedPtr*)((char*)cl + sizeof(Closure));
252 cl->info.mptr->data = (char*)cl + sizeof(Closure) + sizeof(ManagedPtr);
252 cl->info.mptr->data = (char*)cl + sizeof(Closure) + sizeof(ManagedPtr);
253− memcpy(cl->info.mptr->data, ptr, size);
253+ memcpy(cl->info.mptr->data, ptr, size);
254 cl->info.mptr->size = size;
254 cl->info.mptr->size = size;
255 return cl;
255 return cl;
@@ -285,7 +285,7 @@ VAL MKMPTRc(VM* vm, void* ptr, size_t size) {
285 SETTY(cl, MANAGEDPTR);
285 SETTY(cl, MANAGEDPTR);
286 cl->info.mptr = (ManagedPtr*)((char*)cl + sizeof(Closure));
286 cl->info.mptr = (ManagedPtr*)((char*)cl + sizeof(Closure));
287 cl->info.mptr->data = (char*)cl + sizeof(Closure) + sizeof(ManagedPtr);
287 cl->info.mptr->data = (char*)cl + sizeof(Closure) + sizeof(ManagedPtr);
288− memcpy(cl->info.mptr->data, ptr, size);
288+ memcpy(cl->info.mptr->data, ptr, size);
289 cl->info.mptr->size = size;
289 cl->info.mptr->size = size;
290 return cl;
290 return cl;
@@ -318,6 +318,107 @@ VAL MKB64(VM* vm, uint64_t bits64) {
318 return cl;
318 return cl;
321+VAL MKB8x16const(VM* vm,
322+ uint8_t v0, uint8_t v1, uint8_t v2, uint8_t v3,
323+ uint8_t v4, uint8_t v5, uint8_t v6, uint8_t v7,
324+ uint8_t v8, uint8_t v9, uint8_t v10, uint8_t v11,
325+ uint8_t v12, uint8_t v13, uint8_t v14, uint8_t v15) {
326+ Closure* cl = allocate(sizeof(Closure) + sizeof(__m128i), 1);
327+ SETTY(cl, BITS8X16);
329+ cl->info.bits128p = (__m128i*)ALIGN((uintptr_t)cl + sizeof(Closure), 16);
330+ assert ((uintptr_t)cl->info.bits128p % 16 == 0);
333+ data[0]=v0; data[1]=v1; data[2]=v2; data[3]=v3;
334+ data[4]=v4; data[5]=v5; data[6]=v6; data[7]=v7;
335+ data[8]=v8; data[9]=v9; data[10]=v10; data[11]=v11;
336+ data[12]=v12; data[13]=v13; data[14]=v14; data[15]=v15;
338+ *cl->info.bits128p = _mm_loadu_si128((__m128i*)&data);
344+ VAL v0, VAL v1, VAL v2, VAL v3,
345+ VAL v4, VAL v5, VAL v6, VAL v7,
346+ VAL v8, VAL v9, VAL v10, VAL v11,
347+ VAL v12, VAL v13, VAL v14, VAL v15) {
348+ return MKB8x16const(vm,
349+ v0->info.bits8, v1->info.bits8, v2->info.bits8, v3->info.bits8,
350+ v4->info.bits8, v5->info.bits8, v6->info.bits8, v7->info.bits8,
351+ v8->info.bits8, v9->info.bits8, v10->info.bits8, v11->info.bits8,
352+ v12->info.bits8, v13->info.bits8, v14->info.bits8, v15->info.bits8);
355+VAL MKB16x8const(VM* vm,
356+ uint16_t v0, uint16_t v1, uint16_t v2, uint16_t v3,
357+ uint16_t v4, uint16_t v5, uint16_t v6, uint16_t v7) {
358+ Closure* cl = allocate(sizeof(Closure) + sizeof(__m128i), 1);
359+ SETTY(cl, BITS16X8);
361+ cl->info.bits128p = (__m128i*)ALIGN((uintptr_t)cl + sizeof(Closure), 16);
362+ assert ((uintptr_t)cl->info.bits128p % 16 == 0);
365+ data[0]=v0; data[1]=v1; data[2]=v2; data[3]=v3;
366+ data[4]=v4; data[5]=v5; data[6]=v6; data[7]=v7;
368+ *cl->info.bits128p = _mm_loadu_si128((__m128i*)&data);
374+ VAL v0, VAL v1, VAL v2, VAL v3,
375+ VAL v4, VAL v5, VAL v6, VAL v7) {
376+ return MKB16x8const(vm,
377+ v0->info.bits16, v1->info.bits16, v2->info.bits16, v3->info.bits16,
378+ v4->info.bits16, v5->info.bits16, v6->info.bits16, v7->info.bits16);
381+VAL MKB32x4const(VM* vm,
382+ uint32_t v0, uint32_t v1, uint32_t v2, uint32_t v3) {
383+ Closure* cl = allocate(sizeof(Closure) + 16 + sizeof(__m128i), 1);
384+ SETTY(cl, BITS64X2);
386+ cl->info.bits128p = (__m128i*)ALIGN((uintptr_t)cl + sizeof(Closure), 16);
387+ assert ((uintptr_t)cl->info.bits128p % 16 == 0);
390+ data[0]=v0; data[1]=v1; data[2]=v2; data[3]=v3;
392+ *cl->info.bits128p = _mm_loadu_si128((__m128i*)&data);
397+ VAL v0, VAL v1, VAL v2, VAL v3) {
398+ return MKB32x4const(vm,
399+ v0->info.bits32, v1->info.bits32, v2->info.bits32, v3->info.bits32);
402+VAL MKB64x2const(VM* vm, uint64_t v0, uint64_t v1) {
403+ Closure* cl = allocate(sizeof(Closure) + 16 + sizeof(__m128i), 1);
404+ SETTY(cl, BITS64X2);
406+ cl->info.bits128p = (__m128i*)ALIGN((uintptr_t)cl + sizeof(Closure), 16);
407+ assert ((uintptr_t)cl->info.bits128p % 16 == 0);
410+ data[0]=v0; data[1]=v1;
412+ *cl->info.bits128p = _mm_loadu_si128((__m128i*)&data);
416+VAL MKB64x2(VM* vm, VAL v0, VAL v1) {
417+ return MKB64x2const(vm,
321void PROJECT(VM* vm, VAL r, int loc, int arity) {
422void PROJECT(VM* vm, VAL r, int loc, int arity) {
323 for(i = 0; i < arity; ++i) {
424 for(i = 0; i < arity; ++i) {
@@ -350,7 +451,7 @@ void dumpStack(VM* vm) {
350void dumpVal(VAL v) {
451void dumpVal(VAL v) {
351 if (v==NULL) return;
452 if (v==NULL) return;
353− if (ISINT(v)) {
454+ if (ISINT(v)) {
354 printf("%d ", (int)(GETINT(v)));
455 printf("%d ", (int)(GETINT(v)));
@@ -400,13 +501,51 @@ VAL idris_castIntStr(VM* vm, VAL i) {
400 return cl;
501 return cl;
504+VAL idris_castBitsStr(VM* vm, VAL i) {
506+ ClosureType ty = i->ty;
510+ // max length 8 bit unsigned int str 3 chars (256)
511+ cl = allocate(sizeof(Closure) + sizeof(char)*4, 0);
512+ cl->info.str = (char*)cl + sizeof(Closure);
513+ sprintf(cl->info.str, "%" PRIu8, (uint8_t)i->info.bits8);
516+ // max length 16 bit unsigned int str 5 chars (65,535)
517+ cl = allocate(sizeof(Closure) + sizeof(char)*6, 0);
518+ cl->info.str = (char*)cl + sizeof(Closure);
519+ sprintf(cl->info.str, "%" PRIu16, (uint16_t)i->info.bits16);
522+ // max length 32 bit unsigned int str 10 chars (4,294,967,295)
523+ cl = allocate(sizeof(Closure) + sizeof(char)*11, 0);
524+ cl->info.str = (char*)cl + sizeof(Closure);
525+ sprintf(cl->info.str, "%" PRIu32, (uint32_t)i->info.bits32);
528+ // max length 64 bit unsigned int str 20 chars (18,446,744,073,709,551,615)
529+ cl = allocate(sizeof(Closure) + sizeof(char)*21, 0);
530+ cl->info.str = (char*)cl + sizeof(Closure);
531+ sprintf(cl->info.str, "%" PRIu64, (uint64_t)i->info.bits64);
534+ fprintf(stderr, "Fatal Error: ClosureType %d, not an integer type", ty);
403VAL idris_castStrInt(VM* vm, VAL i) {
542VAL idris_castStrInt(VM* vm, VAL i) {
404 char *end;
543 char *end;
405 i_int v = strtol(GETSTR(i), &end, 10);
544 i_int v = strtol(GETSTR(i), &end, 10);
406− if (*end == '\0' || *end == '\n' || *end == '\r')
545+ if (*end == '\0' || *end == '\n' || *end == '\r')
407 return MKINT(v);
546 return MKINT(v);
409− return MKINT(0);
548+ return MKINT(0);
412VAL idris_castFloatStr(VM* vm, VAL i) {
551VAL idris_castFloatStr(VM* vm, VAL i) {
@@ -430,7 +569,7 @@ VAL idris_concat(VM* vm, VAL l, VAL r) {
430 SETTY(cl, STRING);
569 SETTY(cl, STRING);
431 cl -> info.str = (char*)cl + sizeof(Closure);
570 cl -> info.str = (char*)cl + sizeof(Closure);
432 strcpy(cl -> info.str, ls);
571 strcpy(cl -> info.str, ls);
433− strcat(cl -> info.str, rs);
572+ strcat(cl -> info.str, rs);
434 return cl;
573 return cl;
@@ -840,7 +979,7 @@ void* runThread(void* arg) {
842void* vmThread(VM* callvm, func f, VAL arg) {
981void* vmThread(VM* callvm, func f, VAL arg) {
843− VM* vm = init_vm(callvm->stack_max - callvm->valstack, callvm->heap.size,
982+ VM* vm = init_vm(callvm->stack_max - callvm->valstack, callvm->heap.size,
844 callvm->max_threads);
983 callvm->max_threads);
845 vm->processes=1; // since it can send and receive messages
984 vm->processes=1; // since it can send and receive messages
846 pthread_t t;
985 pthread_t t;
@@ -856,7 +995,7 @@ void* vmThread(VM* callvm, func f, VAL arg) {
856 td->callvm = callvm;
995 td->callvm = callvm;
857 td->fn = f;
996 td->fn = f;
858 td->arg = copyTo(vm, arg);
997 td->arg = copyTo(vm, arg);
860 callvm->processes++;
999 callvm->processes++;
862 pthread_create(&t, &attr, runThread, td);
1001 pthread_create(&t, &attr, runThread, td);
@@ -864,7 +1003,7 @@ void* vmThread(VM* callvm, func f, VAL arg) {
864 return vm;
1003 return vm;
867−// VM is assumed to be a different vm from the one x lives on
1006+// VM is assumed to be a different vm from the one x lives on
869VAL copyTo(VM* vm, VAL x) {
1008VAL copyTo(VM* vm, VAL x) {
870 int i, ar;
1009 int i, ar;
@@ -929,28 +1068,28 @@ void idris_sendMessage(VM* sender, VM* dest, VAL msg) {
929 // FIXME: If GC kicks in in the middle of the copy, we're in trouble.
1068 // FIXME: If GC kicks in in the middle of the copy, we're in trouble.
930 // Probably best check there is enough room in advance. (How?)
1069 // Probably best check there is enough room in advance. (How?)
932− // Also a problem if we're allocating at the same time as the
1071+ // Also a problem if we're allocating at the same time as the
933 // destination thread (which is very likely)
1072 // destination thread (which is very likely)
934 // Should the inbox be a different memory space?
1073 // Should the inbox be a different memory space?
936 // So: we try to copy, if a collection happens, we do the copy again
1075 // So: we try to copy, if a collection happens, we do the copy again
937 // under the assumption there's enough space this time.
1076 // under the assumption there's enough space this time.
939 int gcs = dest->stats.collections;
1078 int gcs = dest->stats.collections;
940− pthread_mutex_lock(&dest->alloc_lock);
1079+ pthread_mutex_lock(&dest->alloc_lock);
941 VAL dmsg = copyTo(dest, msg);
1080 VAL dmsg = copyTo(dest, msg);
942− pthread_mutex_unlock(&dest->alloc_lock);
1081+ pthread_mutex_unlock(&dest->alloc_lock);
944 if (dest->stats.collections > gcs) {
1083 if (dest->stats.collections > gcs) {
945 // a collection will have invalidated the copy
1084 // a collection will have invalidated the copy
946− pthread_mutex_lock(&dest->alloc_lock);
1085+ pthread_mutex_lock(&dest->alloc_lock);
947 dmsg = copyTo(dest, msg); // try again now there's room...
1086 dmsg = copyTo(dest, msg); // try again now there's room...
948− pthread_mutex_unlock(&dest->alloc_lock);
1087+ pthread_mutex_unlock(&dest->alloc_lock);
951 pthread_mutex_lock(&(dest->inbox_lock));
1090 pthread_mutex_lock(&(dest->inbox_lock));
952 *(dest->inbox_write) = dmsg;
1091 *(dest->inbox_write) = dmsg;
954 dest->inbox_write++;
1093 dest->inbox_write++;
955 if (dest->inbox_write >= dest->inbox_end) {
1094 if (dest->inbox_write >= dest->inbox_end) {
956 dest->inbox_write = dest->inbox;
1095 dest->inbox_write = dest->inbox;