GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/vm/vm.c Lines: 528 569 92.8 %
Date: 2020-09-14 09:03:05 Branches: 84 128 65.6 %

Line Branch Exec Source
1
#include <time.h>
2
#include "gwion_util.h"
3
#include "gwion_ast.h"
4
#include "gwion_env.h"
5
#include "vm.h"
6
#include "instr.h"
7
#include "object.h"
8
#include "ugen.h"
9
#include "shreduler_private.h"
10
#include "emit.h"
11
#include "gwion.h"
12
#include "operator.h"
13
#include "import.h"
14
#include "gack.h"
15
#include "array.h"
16
17
721
static inline uint64_t splitmix64_stateless(uint64_t index) {
18
721
  uint64_t z = (index + UINT64_C(0x9E3779B97F4A7C15));
19
721
  z = (z ^ (z >> 30)) * UINT64_C(0xBF58476D1CE4E5B9);
20
721
  z = (z ^ (z >> 27)) * UINT64_C(0x94D049BB133111EB);
21
721
  return z ^ (z >> 31);
22
}
23
24
93
static inline uint32_t rotl(const uint32_t x, int k) {
25
93
  return (x << k) | (x >> (32 -k));
26
}
27
28
721
void gw_seed(uint32_t rnd[2], const uint64_t s) {
29
721
  uint64_t seed = splitmix64_stateless(s);
30
721
  memcpy(rnd, &seed, sizeof(uint64_t));
31
721
}
32
33
/*xoroshiro32** */
34
31
uint32_t gw_rand(uint32_t s[2]) {
35
31
  const uint32_t s0 = s[0];
36
31
  const uint32_t s1 = s[1] ^ s0;
37
31
  const uint32_t ret = rotl(s0 * 0x9E3779BB, 5) * 5;
38
31
  s[0] = rotl(s0, 26) ^ s1 ^ (s1 << 9);
39
31
  s[1] = rotl(s1, 13);
40
31
  return ret;
41
}
42
43
2
void vm_remove(const VM* vm, const m_uint index) {
44
2
  const Vector v = (Vector)&vm->shreduler->shreds;
45
  LOOP_OPTIM
46
5
  for(m_uint i = vector_size(v) + 1; --i;) {
47
2
    const VM_Shred sh = (VM_Shred)vector_at(v, i - 1);
48

2
    if(sh && sh->tick->xid == index)
49
1
       Except(sh, "MsgRemove");
50
  }
51
}
52
53
717
ANN void free_vm(VM* vm) {
54
717
  vector_release(&vm->shreduler->shreds);
55
717
  vector_release(&vm->ugen);
56
717
  if(vm->bbq)
57
717
    free_driver(vm->bbq, vm);
58
717
  MUTEX_CLEANUP(vm->shreduler->mutex);
59
717
  mp_free(vm->gwion->mp, Shreduler, vm->shreduler);
60
717
  mp_free(vm->gwion->mp, VM, vm);
61
717
}
62
63
487
ANN void vm_add_shred(const VM* vm, const VM_Shred shred) {
64
487
  shred->info->vm = (VM*)vm;
65
487
  shred->info->me = new_shred(shred);
66
487
  shreduler_add(vm->shreduler, shred);
67
487
}
68
69
711
ANN void vm_ini_shred(const VM* vm, const VM_Shred shred) {
70
711
  shred->info->vm = (VM*)vm;
71
711
  shred->info->me = new_shred(shred);
72
711
  shreduler_ini(vm->shreduler, shred);
73
711
}
74
75
ANN void vm_lock(VM const *vm) {
76
  if(vm->parent)
77
    vm_lock(vm->parent);
78
  MUTEX_LOCK(vm->shreduler->mutex);
79
}
80
81
ANN void vm_unlock(VM const *vm) {
82
  do MUTEX_UNLOCK(vm->shreduler->mutex);
83
  while((vm = vm->parent));
84
}
85
86
ANN m_bool vm_running(VM const *vm) {
87
  if(!vm->shreduler->bbq->is_running)
88
    return 0;
89
  if(!vm->parent)
90
    return 1;
91
  return vm->shreduler->bbq->is_running = vm_running(vm->parent);
92
}
93
94
__attribute__((hot))
95
2921266
ANN static inline void vm_ugen_init(const VM* vm) {
96
2921266
  const Vector v = (Vector)&vm->ugen;
97
  LOOP_OPTIM
98
15086355
  for(m_uint i = vector_size(v) + 1; --i;) {
99
9243823
    const UGen u = (UGen)vector_at(v, i - 1);
100
9243823
    u->done = 0;
101
9243823
    if(u->multi) {
102
5842533
      struct ugen_multi_* m = u->connect.multi;
103
      LOOP_OPTIM
104
23370132
      for(m_uint j = m->n_chan + 1; --j;)
105
11685066
        UGEN(m->channel[j - 1])->done = 0;
106
    }
107
  }
108
2921266
  const UGen hole = (UGen)vector_at(v, 0);
109
2921266
  hole->compute(hole);
110
2921265
}
111
112
#ifdef DEBUG_STACK
113
#define VM_INFO                                                              \
114
  gw_err("shred[%" UINT_F "] mem[%" INT_F"] reg[%" INT_F"]\n", \
115
  shred->tick->xid, \
116
  mem - ((m_bit*)shred + sizeof(struct VM_Shred_) + SIZEOF_REG), reg - ((m_bit*)shred + sizeof(struct VM_Shred_)));
117
#else
118
#define VM_INFO
119
#endif
120
121
2929
ANN static inline m_bool overflow_(const m_bit* mem, const VM_Shred c) {
122
2929
  return mem > (((m_bit*)c + sizeof(struct VM_Shred_) + SIZEOF_REG) + (SIZEOF_MEM) - (MEM_STEP*16));
123
}
124
125
75
ANN static inline VM_Shred init_spork_shred(const VM_Shred shred, const VM_Code code) {
126
75
  const VM_Shred sh = new_shred_base(shred, code);
127
75
  vm_add_shred(shred->info->vm, sh);
128
75
  sh->tick->parent = shred->tick;
129
75
  if(!shred->tick->child.ptr)
130
32
    vector_init(&shred->tick->child);
131
75
  vector_add(&shred->tick->child, (vtype)sh);
132
75
  return sh;
133
}
134
135
ANN M_Object new_fork(const VM_Shred, const VM_Code code, const Type);
136
7
ANN static VM_Shred init_fork_shred(const VM_Shred shred, const VM_Code code, const Type t, const m_uint retsz) {
137
7
  const M_Object o = new_fork(shred, code, t);
138
7
  VM* vm = shred->info->vm;
139
7
  if(!vm->gwion->data->child.ptr)
140
7
    vector_init(&vm->gwion->data->child);
141
7
  vector_add(&vm->gwion->data->child, (vtype)o);
142
7
  fork_launch(o, retsz);
143
7
  return ME(o);
144
}
145
146
#define TEST0(t, pos) if(!*(t*)(reg-pos)){ shred->pc = PC; exception(shred, "ZeroDivideException"); break; }
147
148
#define ADVANCE() byte += BYTECODE_SZ;
149
150
#define SDISPATCH() goto *dispatch[*(m_bit*)byte];
151
#define IDISPATCH() { VM_INFO; SDISPATCH(); }
152
153
#define SET_BYTE(pc)	(byte = bytecode + (pc) * BYTECODE_SZ)
154
155
#define PC_DISPATCH(pc)\
156
  SET_BYTE((pc));\
157
  IDISPATCH();
158
159
#define DISPATCH()\
160
  ADVANCE();\
161
  IDISPATCH();
162
163
164
#define ADVANCE() byte += BYTECODE_SZ;
165
166
#define ADISPATCH() { ADVANCE(); SDISPATCH(); }
167
168
#define PC ((*(unsigned short*)(byte + 2)) + 1)
169
170
#define OP(t, sz, op, ...) \
171
  reg -= sz;\
172
  __VA_ARGS__\
173
  *(t*)(reg - sz) op##= *(t*)reg;\
174
  DISPATCH();
175
176
#define INT_OP(op, ...) OP(m_int, SZ_INT, op, __VA_ARGS__)
177
#define FLOAT_OP(op, ...) OP(m_float, SZ_FLOAT, op, __VA_ARGS__)
178
179
#define LOGICAL(t, sz0, sz, op)\
180
reg -= sz0;\
181
*(m_int*)(reg-SZ_INT) = (*(t*)(reg - SZ_INT) op *(t*)(reg+sz));\
182
DISPATCH()
183
184
#define INT_LOGICAL(op) LOGICAL(m_int, SZ_INT, 0, op)
185
186
#define FLOAT_LOGICAL(op) LOGICAL(m_float, SZ_FLOAT * 2 - SZ_INT, \
187
  SZ_FLOAT - SZ_INT, op)
188
189
#define SELF(t, sz,op) \
190
  *(t*)(reg - sz) = op*(t*)(reg - sz);\
191
  DISPATCH();
192
193
// check me
194
#define R(t, sz, op, ...) \
195
reg -= SZ_INT;\
196
__VA_ARGS__\
197
*(t*)(reg-sz) = (**(t**)reg op##= (*(t*)(reg-sz)));\
198
DISPATCH()
199
#define INT_R(op, ...) R(m_int, SZ_INT, op, __VA_ARGS__)
200
#define FLOAT_R(op, ...) R(m_float, SZ_FLOAT, op)
201
202
#define INT_PRE(op) \
203
/*assert(*(m_int**)(reg-SZ_INT));*/\
204
*(m_int*)(reg- SZ_INT) = op(**(m_int**)(reg-SZ_INT));\
205
DISPATCH()
206
207
#define INT_POST(op) \
208
/*assert(*(m_int**)(reg-SZ_INT));*/\
209
*(m_int*)(reg- SZ_INT) = (**(m_int**)(reg-SZ_INT))op;\
210
DISPATCH()
211
212
#define IF_OP(op) \
213
  reg -=SZ_INT;\
214
    *(m_float*)(reg-SZ_FLOAT) = (m_float)*(m_int*)(reg-SZ_FLOAT) op \
215
    *(m_float*)(reg + SZ_INT - SZ_FLOAT); \
216
  DISPATCH()
217
218
#define IF_LOGICAL(op)\
219
  reg -= SZ_FLOAT; \
220
  *(m_int*)(reg-SZ_INT) = (m_int)(*(m_int*)(reg-SZ_INT) op *(m_float*)reg); \
221
  DISPATCH()
222
__attribute__((hot))
223
224
#define IF_R(op) \
225
  reg -= SZ_INT * 2 - SZ_FLOAT; \
226
  *(m_float*)(reg-SZ_FLOAT) = (**(m_float**)(reg +SZ_INT - SZ_FLOAT) op##= \
227
    (m_float)*(m_int*)(reg-SZ_FLOAT)); \
228
  DISPATCH()
229
230
#define FI_OP(op)\
231
  reg -= SZ_INT; \
232
  *(m_float*)(reg-SZ_FLOAT) op##= (m_float)*(m_int*)reg; \
233
  DISPATCH()
234
235
#define FI_LOGICAL(op) \
236
  reg -= SZ_FLOAT; \
237
  *(m_int*)(reg-SZ_INT) = (m_int)(*(m_float*)(reg-SZ_INT) op\
238
    *(m_int*)(reg + SZ_FLOAT-SZ_INT)); \
239
  DISPATCH()
240
241
#define FI_R(op, ...) \
242
  reg -= SZ_FLOAT; \
243
  __VA_ARGS__ \
244
  *(m_int*)(reg-SZ_INT) = (**(m_int**)(reg+SZ_FLOAT -SZ_INT) op##= \
245
    /*(m_int)*/(*(m_float*)(reg-SZ_INT))); \
246
  DISPATCH()
247
248
249
#define STRINGIFY_NX(a) #a
250
#define STRINGIFY(a) STRINGIFY_NX(a)
251
#define PPCAT_NX(A, B) A ## B
252
#define PPCAT(A, B) PPCAT_NX(A, B)
253
254
#if defined(__clang__)
255
#define COMPILER clang
256
#define UNINITIALIZED "-Wuninitialized")
257
#elif defined(__GNUC__) || defined(__GNUG__)
258
#define COMPILER GCC
259
#define UNINITIALIZED "-Wmaybe-uninitialized")
260
#endif
261
262
#define PRAGMA_PUSH() \
263
_Pragma(STRINGIFY(COMPILER diagnostic push)) \
264
_Pragma(STRINGIFY(COMPILER diagnostic ignored UNINITIALIZED)
265
#define PRAGMA_POP() _Pragma(STRINGIFY(COMPILER diagnostic pop)) \
266
267
#define VAL (*(m_uint*)(byte + SZ_INT))
268
#define FVAL (*(m_float*)(byte + SZ_INT))
269
#define VAL2 (*(m_uint*)(byte + SZ_INT*2))
270
271
#define BRANCH_DISPATCH(check) \
272
  if(check) SET_BYTE(VAL);\
273
  else ADVANCE(); \
274
  IDISPATCH();
275
276
#define VM_OUT shred->code = code; shred->reg = reg; shred->mem = mem; shred->pc = PC;
277
278
__attribute__ ((hot, optimize("-O2")))
279
4828537
ANN void vm_run(const VM* vm) { // lgtm [cpp/use-of-goto]
280
  static const void* dispatch[] = {
281
    &&regsetimm,
282
    &&regpushimm, &&regpushfloat, &&regpushother, &&regpushaddr,
283
    &&regpushmem, &&regpushmemfloat, &&regpushmemother, &&regpushmemaddr, &&regpushmemderef,
284
    &&pushnow,
285
    &&baseint, &&basefloat, &&baseother, &&baseaddr,
286
    &&regtoreg, &&regtoregaddr, &&regtoregderef,
287
    &&structmember, &&structmemberfloat, &&structmemberother, &&structmemberaddr,
288
    &&memsetimm,
289
    &&regpushme, &&regpushmaybe,
290
    &&funcreturn,
291
    &&_goto,
292
    &&allocint, &&allocfloat, &&allocother,
293
    &&intplus, &&intminus, && intmul, &&intdiv, &&intmod,
294
    // int relationnal
295
    &&inteq, &&intne, &&intand, &&intor,
296
    &&intgt, &&intge, &&intlt, &&intle,
297
    &&intsl, &&intsr, &&intsand, &&intsor, &&intxor,
298
    &&intnegate, &&intnot, &&intcmp,
299
    &&intrassign,
300
    &&intradd, &&intrsub, &&intrmul, &&intrdiv, &&intrmod,
301
    &&intrsl, &&intrsr, &&intrsand, &&intrsor, &&intrxor,
302
    &&preinc, &&predec,
303
    &&postinc, &&postdec,
304
    &&floatadd, &&floatsub, &&floatmul, &&floatdiv,
305
// logical
306
    &&floatand, &&floator, &&floateq, &&floatne,
307
    &&floatgt, &&floatge, &&floatlt, &&floatle,
308
    &&floatneg, &&floatnot,
309
    &&floatrassign, &&floatradd, &&floatrsub, &&floatrmul, &&floatrdiv,
310
    &&ifadd, &&ifsub, &&ifmul, &&ifdiv,
311
    &&ifand, &&ifor, &&ifeq, &&ifne, &&ifgt, &&ifge, &&iflt, &&ifle,
312
    &&ifrassign, &&ifradd, &&ifrsub, &&ifrmul, &&ifrdiv,
313
    &&fiadd, &&fisub, &&fimul, &&fidiv,
314
    &&fiand, &&fior, &&fieq, &&fine, &&figt, &&fige, &&filt, &&file,
315
    &&firassign, &&firadd, &&firsub, &&firmul, &&firdiv,
316
    &&itof, &&ftoi,
317
    &&timeadv,
318
    &&setcode,
319
    &&regpop, &&regpush, &&regtomem, &&regtomemother, &&overflow, &&funcusrend, &&funcmemberend,
320
    &&sporkini, &&forkini, &&sporkfunc, &&sporkmemberfptr, &&sporkexp, &&sporkend,
321
    &&brancheqint, &&branchneint, &&brancheqfloat, &&branchnefloat,
322
    &&arrayappend, &&autoloop, &&autoloopptr, &&autoloopcount, &&arraytop, &&arrayaccess, &&arrayget, &&arrayaddr, &&arrayvalid,
323
    &&newobj, &&addref, &&addrefaddr, &&objassign, &&assign, &&remref,
324
    &&except, &&allocmemberaddr, &&dotmember, &&dotfloat, &&dotother, &&dotaddr,
325
    &&staticint, &&staticfloat, &&staticother,
326
    &&dotfunc, &&dotstaticfunc,
327
    &&gcini, &&gcadd, &&gcend,
328
    &&gacktype, &&gackend, &&gack, &&noop, &&eoc, &&other, &&regpushimm
329
  };
330
4828537
  const Shreduler s = vm->shreduler;
331
  register VM_Shred shred;
332
  register m_bit next;
333
334
9657707
  while((shred = shreduler_get(s))) {
335
633
    register VM_Code code = shred->code;
336
633
    register m_bit* bytecode = code->bytecode;
337
633
    register m_bit* byte = bytecode + shred->pc * BYTECODE_SZ;
338
633
    register m_bit* reg = shred->reg;
339
633
    register m_bit* mem = shred->mem;
340
    register union {
341
      M_Object obj;
342
      VM_Code code;
343
    } a;
344
PRAGMA_PUSH()
345
    register VM_Shred child;
346
PRAGMA_POP()
347
633
  MUTEX_LOCK(s->mutex);
348
  do {
349
633
    SDISPATCH();
350
6028
regsetimm:
351
6028
  *(m_uint*)(reg + (m_int)VAL2) = VAL;
352
6028
  DISPATCH();
353
2835
regpushimm:
354
2835
  *(m_uint*)reg = VAL;
355
2835
  reg += SZ_INT;
356
2835
  DISPATCH();
357
452
regpushfloat:
358
452
  *(m_float*)reg = FVAL;
359
452
  reg += SZ_FLOAT;
360
452
  DISPATCH();
361
regpushother:
362
//  LOOP_OPTIM
363
  for(m_uint i = 0; i <= VAL2; i+= SZ_INT)
364
    *(m_bit**)(reg+i) = (m_bit*)(VAL + i);
365
  reg += VAL2;
366
  DISPATCH();
367
1
regpushaddr:
368
1
  *(m_uint**)reg =  &VAL;
369
1
  reg += SZ_INT;
370
1
  DISPATCH()
371
938
regpushmem:
372
938
  *(m_uint*)reg = *(m_uint*)(mem + (m_int)VAL);
373
938
  reg += SZ_INT;
374
938
  DISPATCH();
375
151
regpushmemfloat:
376
151
  *(m_float*)reg = *(m_float*)(mem + (m_int)VAL);
377
151
  reg += SZ_FLOAT;
378
151
  DISPATCH();
379
2
regpushmemother:
380
6
  for(m_uint i = 0; i <= VAL2; i+= SZ_INT)
381
4
    *(m_uint*)(reg+i) = *(m_uint*)((m_bit*)(mem + (m_int)VAL) + i);
382
2
  reg += VAL2;
383
2
  DISPATCH();
384
372
regpushmemaddr:
385
372
  *(m_bit**)reg = &*(m_bit*)(mem + (m_int)VAL);
386
372
  reg += SZ_INT;
387
372
  DISPATCH()
388
1
regpushmemderef:
389
1
  memcpy(reg, *(m_uint**)(mem+(m_int)VAL), VAL2);
390
1
  reg += VAL2;
391
1
  DISPATCH()
392
144
pushnow:
393
144
  *(m_float*)reg = vm->bbq->pos;
394
144
  reg += SZ_FLOAT;
395
144
  DISPATCH();
396
2775
baseint:
397
2775
  *(m_uint*)reg = *(m_uint*)(shred->base + VAL);
398
2775
  reg += SZ_INT;
399
2775
  DISPATCH();
400
36
basefloat:
401
36
  *(m_float*)reg = *(m_float*)(shred->base + VAL);
402
36
  reg += SZ_FLOAT;
403
36
  DISPATCH();
404
baseother:
405
//  LOOP_OPTIM
406
  for(m_uint i = 0; i <= VAL2; i+= SZ_INT)
407
    *(m_uint*)(reg+i) = *(m_uint*)((shred->base + VAL) + i);
408
  reg += VAL2;
409
  DISPATCH();
410
96
baseaddr:
411
96
  *(m_uint**)reg = &*(m_uint*)(shred->base + (m_int)VAL);
412
96
  reg += SZ_INT;
413
96
  DISPATCH();
414
240
regtoreg:
415
240
  *(m_uint*)(reg + (m_int)VAL) = *(m_uint*)(reg + (m_int)VAL2);
416
240
  DISPATCH()
417
2
regtoregaddr:
418
2
  *(m_uint**)(reg + (m_int)VAL) = &*(m_uint*)(reg + (m_int)VAL2);
419
2
  DISPATCH()
420
11
regtoregderef:
421
11
  memcpy(*(m_bit**)(reg - SZ_INT), *(m_bit**)(reg + (m_int)VAL), VAL2);
422
11
  DISPATCH()
423
15
structmember:
424
15
  *(m_bit**)(reg-SZ_INT) =  *(m_bit**)(*(m_bit**)(reg-SZ_INT) + (m_int)VAL);
425
15
  DISPATCH()
426
8
structmemberfloat:
427
8
  *(m_bit**)(reg-SZ_INT) =  *(m_bit**)(*(m_bit**)(reg-SZ_INT) + (m_int)VAL);
428
8
  DISPATCH()
429
structmemberother:
430
  *(m_bit**)(reg-SZ_INT) =  *(m_bit**)(*(m_bit**)(reg-SZ_INT) + (m_int)VAL);
431
  DISPATCH()
432
17
structmemberaddr:
433
17
  *(m_bit**)(reg-SZ_INT) =  &*(*(m_bit**)(reg-SZ_INT) + (m_int)VAL);
434
17
  DISPATCH()
435
213
memsetimm:
436
213
  *(m_uint*)(mem+VAL) = VAL2;
437
213
  DISPATCH();
438
71
regpushme:
439
71
  *(M_Object*)reg = shred->info->me;
440
71
  reg += SZ_INT;
441
71
  DISPATCH()
442
31
regpushmaybe:
443
31
  *(m_uint*)reg = gw_rand((uint32_t*)vm->rand) > (UINT32_MAX / 2);
444
31
  reg += SZ_INT;
445
31
  DISPATCH();
446
543
funcreturn:
447
{
448
543
  register const m_uint pc = *(m_uint*)(mem-SZ_INT*2);
449
543
  bytecode = (code = *(VM_Code*)(mem-SZ_INT*3))->bytecode;
450
543
  mem -= (*(m_uint*)(mem-SZ_INT*4) + SZ_INT*4);
451
543
  PC_DISPATCH(pc);
452
}
453
12
_goto:
454
2368
  PC_DISPATCH(VAL);
455
174
allocint:
456
174
  *(m_uint*)reg = *(m_uint*)(mem+VAL) = 0;
457
174
  reg += SZ_INT;
458
174
  DISPATCH()
459
87
allocfloat:
460
87
  *(m_float*)reg = *(m_float*)(mem+VAL) = 0;
461
87
  reg += SZ_FLOAT;
462
87
  DISPATCH()
463
allocother:
464
//  LOOP_OPTIM
465
  for(m_uint i = 0; i <= VAL2; i += SZ_INT)
466
    *(m_uint*)(reg+i) = (*(m_uint*)(mem+VAL+i) = 0);
467
  reg += VAL2;
468
  DISPATCH()
469
470
22
intplus:  INT_OP(+)
471
55
intminus: INT_OP(-)
472
2
intmul:   INT_OP(*)
473
2
intdiv:   INT_OP(/, TEST0(m_int, 0))
474
2
intmod:   INT_OP(%, TEST0(m_int, 0))
475
476
71
inteq:   INT_LOGICAL(==)
477
5
intne:   INT_LOGICAL(!=)
478

1
intand:  INT_LOGICAL(&&)
479

1
intor:   INT_LOGICAL(||)
480
26
intgt:   INT_LOGICAL(>)
481
1
intge:   INT_LOGICAL(>=)
482
51
intlt:   INT_LOGICAL(<)
483
1
intle:   INT_LOGICAL(<=)
484
1
intsl:   INT_LOGICAL(<<)
485
1
intsr:   INT_LOGICAL(>>)
486
1
intsand: INT_LOGICAL(&)
487
1
intsor:  INT_LOGICAL(|)
488
1
intxor:  INT_LOGICAL(^)
489
490
20
intnegate:
491
20
  *(m_int*)(reg - SZ_INT) *= -1;
492
20
  DISPATCH()
493
25
intnot: SELF(m_int, SZ_INT, !)
494
intcmp: SELF(m_int, SZ_INT, ~)
495
496
118
intrassign:
497
118
  reg -= SZ_INT;
498
118
  **(m_int**)reg = *(m_int*)(reg-SZ_INT);
499
118
  DISPATCH()
500
501
3
intradd: INT_R(+)
502
1
intrsub: INT_R(-)
503
1
intrmul: INT_R(*)
504
//intrdiv: INT_R(/, TEST0(m_int, -SZ_INT))
505
//intrmod: INT_R(%, TEST0(m_int, -SZ_INT))
506
1
intrdiv: INT_R(/, TEST0(m_int, SZ_INT))
507
1
intrmod: INT_R(%, TEST0(m_int, SZ_INT))
508
1
intrsl: INT_R(<<)
509
1
intrsr: INT_R(>>)
510
1
intrsand: INT_R(&)
511
1
intrsor: INT_R(|)
512
1
intrxor: INT_R(^)
513
514
41
preinc: INT_PRE(++)
515
26
predec: INT_PRE(--)
516
517
45
postinc: INT_POST(++)
518
43
postdec: INT_POST(--)
519
520
3
floatadd: FLOAT_OP(+)
521
1
floatsub: FLOAT_OP(-)
522
72
floatmul: FLOAT_OP(*)
523
1
floatdiv: FLOAT_OP(/)
524
525

1
floatand: FLOAT_LOGICAL(&&)
526

1
floator: FLOAT_LOGICAL(||)
527
68
floateq: FLOAT_LOGICAL(==)
528
1
floatne: FLOAT_LOGICAL(!=)
529
6
floatgt: FLOAT_LOGICAL(>)
530
3
floatge: FLOAT_LOGICAL(>=)
531
5
floatlt: FLOAT_LOGICAL(<)
532
1
floatle: FLOAT_LOGICAL(<=)
533
534
1
floatneg: SELF(m_float, SZ_FLOAT, -)
535
536
3
floatnot:
537
3
  reg -= SZ_FLOAT - SZ_INT;
538
3
  *(m_int*)(reg - SZ_INT) = !*(m_float*)(reg - SZ_INT);
539
3
  DISPATCH()
540
541
19
floatrassign:
542
19
  reg -= SZ_INT;
543
19
  **(m_float**)reg = *(m_float*)(reg-SZ_FLOAT);
544
19
  DISPATCH()
545
546
1
floatradd: FLOAT_R(+)
547
11
floatrsub: FLOAT_R(-)
548
1
floatrmul: FLOAT_R(*)
549
1
floatrdiv: FLOAT_R(/)
550
551
1
ifadd: IF_OP(+)
552
4
ifsub: IF_OP(-)
553
21
ifmul: IF_OP(*)
554
1
ifdiv: IF_OP(/)
555
556

1
ifand: IF_LOGICAL(&&)
557

1
ifor: IF_LOGICAL(||)
558
1
ifeq: IF_LOGICAL(==)
559
1
ifne: IF_LOGICAL(!=)
560
1
ifgt: IF_LOGICAL(>)
561
1
ifge: IF_LOGICAL(>=)
562
1
iflt: IF_LOGICAL(<)
563
1
ifle: IF_LOGICAL(<=)
564
565
20
ifrassign: IF_R()
566
3
ifradd: IF_R(+)
567
18
ifrsub: IF_R(-)
568
1
ifrmul: IF_R(*)
569
1
ifrdiv: IF_R(/)
570
571
1
fiadd: FI_OP(+)
572
1
fisub: FI_OP(-)
573
1
fimul: FI_OP(*)
574
1
fidiv: FI_OP(/)
575
576

1
fiand: FI_LOGICAL(&&)
577

1
fior: FI_LOGICAL(||)
578
6
fieq: FI_LOGICAL(==)
579
1
fine: FI_LOGICAL(!=)
580
25
figt: FI_LOGICAL( >)
581
1
fige: FI_LOGICAL(>=)
582
1
filt: FI_LOGICAL( <)
583
1
file: FI_LOGICAL(<=)
584
585
2
firassign:
586
2
  reg -=SZ_FLOAT;
587
4
  *(m_int*)(reg-SZ_INT) = **(m_int**)(reg + SZ_FLOAT-SZ_INT) =
588
4
    (m_int)*(m_float*)(reg-SZ_INT);
589
2
  DISPATCH()
590
591
1
firadd: FI_R(+)
592
2
firsub: FI_R(-)
593
1
firmul: FI_R(*)
594
1
firdiv: FI_R(/, TEST0(m_float, SZ_INT))
595
596
82
itof:
597
82
  reg -= SZ_INT - SZ_FLOAT;
598
82
  *(m_float*)(reg-SZ_FLOAT) = (m_float)*(m_int*)(reg-SZ_FLOAT);
599
82
  DISPATCH()
600
2
ftoi:
601
2
  reg -= SZ_FLOAT - SZ_INT;
602
2
  *(m_int*)(reg-SZ_INT) = (m_int)*(m_float*)(reg-SZ_INT);
603
2
  DISPATCH()
604
131
timeadv:
605
131
  reg -= SZ_FLOAT;
606
131
  shredule(s, shred, *(m_float*)(reg-SZ_FLOAT));
607
131
  *(m_float*)(reg-SZ_FLOAT) += vm->bbq->pos;
608
131
  VM_OUT
609
131
  break;
610
2929
setcode:
611
PRAGMA_PUSH()
612
2929
  reg -= SZ_INT;
613
2929
  a.code = *(VM_Code*)reg;
614
2929
  if(!GET_FLAG((VM_Code)a.code, builtin)) {
615
2585
    register const m_uint push = *(m_uint*)(reg + SZ_INT) + *(m_uint*)(mem-SZ_INT);
616
2585
    mem += push;
617
2585
    *(m_uint*)  mem = push;mem += SZ_INT;
618
2585
    *(VM_Code*) mem = code; mem += SZ_INT;
619
2585
    *(m_uint*)  mem = PC + VAL2; mem += SZ_INT;
620
2585
    *(m_uint*) mem = a.code->stack_depth; mem += SZ_INT;
621
    next = eFuncUsrEnd;
622
  } else {
623
344
    mem += *(m_uint*)(reg + SZ_INT);
624
    next = eFuncMemberEnd;
625
  }
626
PRAGMA_POP()
627
6979
regpop:
628
6979
  reg -= VAL;
629
6979
  DISPATCH();
630
286
regpush:
631
286
  reg += VAL;
632
286
  DISPATCH();
633
853
regtomem:
634
853
  *(m_uint*)(mem+VAL) = *(m_uint*)(reg+(m_int)VAL2);
635
853
  DISPATCH()
636
167
regtomemother:
637
167
  memcpy(mem+VAL, reg, VAL2);
638
167
  DISPATCH()
639
2929
overflow:
640
2929
  if(overflow_(mem + VAL2, shred)) {
641
1
    shred->pc = PC;
642
1
    exception(shred, "StackOverflow");
643
1
    continue;
644
  }
645
PRAGMA_PUSH()
646
2928
  goto *dispatch[next];
647
PRAGMA_POP()
648
2584
funcusrend:
649
PRAGMA_PUSH()
650
2584
  byte = bytecode = (code = a.code)->bytecode;
651
PRAGMA_POP()
652
2584
  SDISPATCH();
653
344
funcmemberend:
654
344
  VM_OUT
655
  {
656
344
    register const m_uint val = VAL;
657
344
    register const m_uint val2 = VAL2;
658
344
    ((f_mfun)a.code->native_func)((*(M_Object*)mem), reg, shred);
659
344
    reg += val;
660
344
    shred->mem = (mem -= val2);
661
344
    if(!s->curr)break;
662
  }
663
315
  PC_DISPATCH(shred->pc)
664
75
sporkini:
665
75
  child = init_spork_shred(shred, (VM_Code)VAL);
666
75
  DISPATCH()
667
7
forkini:
668
7
  reg -= SZ_INT;
669
7
  child = init_fork_shred(shred, (VM_Code)VAL, *(Type*)reg, VAL2),
670
7
  DISPATCH()
671
50
sporkfunc:
672
//  LOOP_OPTIM
673
PRAGMA_PUSH()
674
147
  for(m_uint i = 0; i < VAL; i+= SZ_INT)
675
97
    *(m_uint*)(child->reg + i) = *(m_uint*)(reg + i + (m_int)VAL2);
676
50
  child->reg += VAL;
677
50
  DISPATCH()
678
PRAGMA_POP()
679
3
sporkmemberfptr:
680
6
  for(m_uint i = SZ_INT; i < VAL; i+= SZ_INT)
681
3
    *(m_uint*)(child->reg + i) = *(m_uint*)(reg - VAL + i);
682
3
  *(M_Object*)(child->reg + VAL) = *(M_Object*)(reg + VAL + SZ_INT);
683
3
  *(m_uint*)(child->reg + VAL + SZ_INT) = *(m_uint*)(reg + VAL - SZ_INT*2);
684
3
  child->reg += VAL + SZ_INT*2;
685
3
  DISPATCH()
686
29
sporkexp:
687
//  LOOP_OPTIM
688
40
  for(m_uint i = 0; i < VAL; i+= SZ_INT)
689
11
    *(m_uint*)(child->mem + i) = *(m_uint*)(mem+i);
690
29
  DISPATCH()
691
82
sporkend:
692
  assert(!VAL); // spork are not mutable
693
82
  *(M_Object*)(reg-SZ_INT) = child->info->me;
694
82
  DISPATCH()
695
369
brancheqint:
696
369
  reg -= SZ_INT;
697
369
  BRANCH_DISPATCH(!*(m_uint*)reg);
698
35
branchneint:
699
35
  reg -= SZ_INT;
700
35
  BRANCH_DISPATCH(*(m_uint*)reg);
701
74
brancheqfloat:
702
74
  reg -= SZ_FLOAT;
703
74
  BRANCH_DISPATCH(!*(m_float*)reg);
704
8
branchnefloat:
705
8
  reg -= SZ_FLOAT;
706
8
  BRANCH_DISPATCH(*(m_float*)reg);
707
2
arrayappend:
708
2
  m_vector_add(ARRAY(*(M_Object*)(reg-SZ_INT)), reg);
709
2
  release(*(M_Object*)(reg-SZ_INT), shred);
710
2
  DISPATCH()
711
20
autoloop:
712
20
  m_vector_get(ARRAY(*(M_Object*)(reg-SZ_INT)), *(m_uint*)(mem + VAL), mem + VAL + SZ_INT);
713
20
  goto autoloopcount;
714
14
autoloopptr:
715
14
  *(m_bit**)(*(M_Object*)(mem + VAL + SZ_INT))->data = m_vector_addr(ARRAY(*(M_Object*)(reg-SZ_INT)), *(m_uint*)(mem + VAL));
716
34
autoloopcount:
717
34
  *(m_uint*)reg = m_vector_size(ARRAY(*(M_Object*)(reg-SZ_INT))) - (*(m_uint*)(mem + VAL))++;
718
34
  reg += SZ_INT;
719
34
  DISPATCH()
720
1631
arraytop:
721
1631
  if(*(m_uint*)(reg - SZ_INT * 2) < *(m_uint*)(reg-SZ_INT))
722
    goto newobj;
723
  else
724
    goto _goto;
725
35
arrayaccess:
726
{
727
35
  register const m_int idx = *(m_int*)(reg + VAL);
728
35
  a.obj = *(M_Object*)(reg-VAL2);
729

35
  if(idx < 0 || (m_uint)idx >= m_vector_size(ARRAY(a.obj))) {
730
4
    gw_err(_("  ... at index [%" INT_F "]\n"), idx);
731
4
    gw_err(_("  ... at dimension [%" INT_F "]\n"), VAL);
732
4
    VM_OUT
733
4
    exception(shred, "ArrayOutofBounds");
734
4
    continue; // or break ?
735
  }
736
31
  DISPATCH()
737
}
738
25
arrayget:
739
25
  m_vector_get(ARRAY(a.obj), *(m_int*)(reg + VAL), (reg + (m_int)VAL2));
740
25
  DISPATCH()
741
6
arrayaddr:
742
6
  *(m_bit**)(reg + (m_int)VAL2) = m_vector_addr(ARRAY(a.obj), *(m_int*)(reg + VAL));
743
6
  DISPATCH()
744
22
arrayvalid:
745
// are we sure it is the array ?
746
// rather increase ref
747
22
  vector_pop(&shred->gc);
748
22
  goto regpush;
749
1619
newobj:
750
1813
  *(M_Object*)reg = new_object(vm->gwion->mp, shred, (Type)VAL2);
751
1813
  reg += SZ_INT;
752
1813
  DISPATCH()
753
681
addref:
754
  {
755
681
    const M_Object o = *((M_Object*)(reg+(m_int)VAL) + (m_int)VAL2);
756
681
    if(o)
757
665
      ++o->ref;
758
  }
759
681
  DISPATCH()
760
36
addrefaddr:
761
  {
762
36
    const M_Object o = *(*(M_Object**)(reg+(m_int)VAL) + (m_int)VAL2);
763
36
    if(o)
764
9
      ++o->ref;
765
  }
766
36
  DISPATCH()
767
33
objassign:
768
{
769
33
  const M_Object o = **(M_Object**)(reg -SZ_INT);
770
33
  if(o) {
771
8
    --o->ref;
772
8
    _release(o, shred);
773
  }
774
}
775
232
assign:
776
232
  reg -= SZ_INT;
777
232
  **(M_Object**)reg = *(M_Object*)(reg-SZ_INT);
778
232
  DISPATCH()
779
273
remref:
780
273
  release(*(M_Object*)(mem + VAL), shred);
781
273
  DISPATCH()
782
873
except:
783
/* TODO: Refactor except instruction             *
784
 * so that                                       *
785
 *  VAL = offset (no default SZ_INT)             *
786
 *  VAL2 = error message                         *
787
 * grep for GWOP_EXCEPT and Except, exception... */
788
873
  if(!*(M_Object*)(reg-SZ_INT-VAL)) {
789
21
    shred->pc = PC;
790
21
    exception(shred, "NullPtrException");
791
21
    continue;
792
  }
793
852
  DISPATCH();
794
36
allocmemberaddr:
795
36
  *(m_bit**)reg = (*(M_Object*)mem)->data + VAL;
796
36
  reg += SZ_INT;
797
36
  DISPATCH()
798
141
dotmember:
799
141
  *(m_uint*)(reg-SZ_INT) = *(m_uint*)((*(M_Object*)(reg-SZ_INT))->data + VAL);
800
141
  DISPATCH()
801
14
dotfloat:
802
14
  *(m_float*)(reg-SZ_INT) = *(m_float*)((*(M_Object*)(reg-SZ_INT))->data + VAL);
803
14
  reg += SZ_FLOAT - SZ_INT;
804
14
  DISPATCH()
805
dotother:
806
//  LOOP_OPTIM
807
PRAGMA_PUSH()
808
  for(m_uint i = 0; i <= VAL2; i += SZ_INT)
809
    *(m_uint*)(reg+i-SZ_INT) = *(m_uint*)(((*(M_Object*)(reg-SZ_INT))->data + VAL) + i);
810
PRAGMA_POP()
811
  reg += VAL2 - SZ_INT;
812
  DISPATCH()
813
87
dotaddr:
814
87
  *(m_bit**)(reg-SZ_INT) = ((*(M_Object*)(reg-SZ_INT))->data + VAL);
815
87
  DISPATCH()
816
44
staticint:
817
44
  *(m_uint*)reg = *(m_uint*)VAL;
818
44
  reg += SZ_INT;
819
44
  DISPATCH()
820
4
staticfloat:
821
4
  *(m_float*)reg = *(m_float*)VAL;
822
4
  reg += SZ_FLOAT;
823
4
  DISPATCH()
824
staticother:
825
//  LOOP_OPTIM
826
//  for(m_uint i = 0; i <= VAL2; i += SZ_INT)
827
//    *(m_uint*)(reg+i) = *(m_uint*)((m_bit*)VAL + i);
828
  memcpy(reg, (m_bit*)VAL, VAL2);
829
  reg += VAL2;
830
  DISPATCH()
831
370
dotfunc:
832
370
  reg += SZ_INT;
833
370
  VAL2 = SZ_INT;
834
376
dotstaticfunc:
835
PRAGMA_PUSH()
836
376
  *(VM_Code*)(reg-SZ_INT) = ((Func)vector_at((*(M_Object*)(reg-SZ_INT-VAL2))->vtable, VAL))->code;
837
PRAGMA_POP()
838
376
  DISPATCH()
839
6
gcini:
840
6
  vector_add(&shred->gc, 0);
841
6
  DISPATCH();
842
63
gcadd:
843
63
  vector_add(&shred->gc, *(vtype*)(reg-SZ_INT));
844
63
  DISPATCH();
845
6
gcend:
846
{
847
  M_Object o;
848
6
  while((o = (M_Object)vector_pop(&shred->gc)))
849
3
    _release(o, shred);
850
}
851
3
  DISPATCH()
852
643
gacktype:
853
{
854
643
  const M_Object o = *(M_Object*)(reg - SZ_INT);
855
643
  if(o)
856
625
    *(Type*)reg = o->type_ref;
857
}
858
643
  DISPATCH()
859
1064
gackend:
860
{
861
1064
  m_str str = *(m_str*)(reg - SZ_INT);
862
1064
  if(!VAL)
863
1059
    gw_out("%s\n", str);
864
  else
865
5
    *(M_Object*)(reg - SZ_INT)= new_string(vm->gwion->mp, shred, str);
866
1064
  if(str)
867
1064
    mp_free2(vm->gwion->mp, strlen(str), str);
868
1064
  DISPATCH();
869
}
870
1442
gack:
871
1442
  VM_OUT
872
1442
  gack(shred, VAL);
873
1442
  goto in;
874
2756
noop:
875
2756
  DISPATCH();
876
1997
other:
877
1997
  VM_OUT
878
1997
  ((f_instr)VAL2)(shred, (Instr)VAL);
879
3439
in:
880
3439
  if(!s->curr)
881
    break;
882
3413
  bytecode = (code = shred->code)->bytecode;
883
3413
  reg = shred->reg;
884
3413
  mem = shred->mem;
885
3413
  PC_DISPATCH(shred->pc)
886
419
eoc:
887
419
  VM_OUT
888
419
  vm_shred_exit(shred);
889
445
    } while(s->curr);
890
633
  MUTEX_UNLOCK(s->mutex);
891
  }
892
4791545
}
893
894
2921266
static void vm_run_audio(const VM *vm) {
895
2921266
  vm_run(vm);
896
2921266
  vm_ugen_init(vm);
897
2921265
}
898
899
721
VM* new_vm(MemPool p, const m_bool audio) {
900
721
  VM* vm = (VM*)mp_calloc(p, VM);
901
721
  vector_init(&vm->ugen);
902
721
  vm->bbq = new_driver(p);
903
721
  vm->bbq->run = audio ? vm_run_audio : vm_run;
904
721
  vm->shreduler  = (Shreduler)mp_calloc(p, Shreduler);
905
721
  vector_init(&vm->shreduler->shreds);
906
721
  MUTEX_SETUP(vm->shreduler->mutex);
907
721
  vm->shreduler->bbq = vm->bbq;
908
#ifndef __AFL_COMPILER
909
721
  gw_seed(vm->rand, (uint64_t)time(NULL));
910
#else
911
  gw_seed(vm->rand, 0);
912
#endif
913
721
  return vm;
914
}