GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/vm/vm.c Lines: 528 569 92.8 %
Date: 2020-10-03 10:30:04 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
724
static inline uint64_t splitmix64_stateless(uint64_t index) {
18
724
  uint64_t z = (index + UINT64_C(0x9E3779B97F4A7C15));
19
724
  z = (z ^ (z >> 30)) * UINT64_C(0xBF58476D1CE4E5B9);
20
724
  z = (z ^ (z >> 27)) * UINT64_C(0x94D049BB133111EB);
21
724
  return z ^ (z >> 31);
22
}
23
24
108
static inline uint32_t rotl(const uint32_t x, int k) {
25
108
  return (x << k) | (x >> (32 -k));
26
}
27
28
724
void gw_seed(uint32_t rnd[2], const uint64_t s) {
29
724
  uint64_t seed = splitmix64_stateless(s);
30
724
  memcpy(rnd, &seed, sizeof(uint64_t));
31
724
}
32
33
/*xoroshiro32** */
34
36
uint32_t gw_rand(uint32_t s[2]) {
35
36
  const uint32_t s0 = s[0];
36
36
  const uint32_t s1 = s[1] ^ s0;
37
36
  const uint32_t ret = rotl(s0 * 0x9E3779BB, 5) * 5;
38
36
  s[0] = rotl(s0, 26) ^ s1 ^ (s1 << 9);
39
36
  s[1] = rotl(s1, 13);
40
36
  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
721
ANN void free_vm(VM* vm) {
54
721
  vector_release(&vm->shreduler->shreds);
55
721
  vector_release(&vm->ugen);
56
721
  if(vm->bbq)
57
721
    free_driver(vm->bbq, vm);
58
721
  MUTEX_CLEANUP(vm->shreduler->mutex);
59
721
  mp_free(vm->gwion->mp, Shreduler, vm->shreduler);
60
721
  mp_free(vm->gwion->mp, VM, vm);
61
721
}
62
63
496
ANN void vm_add_shred(const VM* vm, const VM_Shred shred) {
64
496
  shred->info->vm = (VM*)vm;
65
496
  shred->info->me = new_shred(shred);
66
496
  shreduler_add(vm->shreduler, shred);
67
496
}
68
69
713
ANN void vm_ini_shred(const VM* vm, const VM_Shred shred) {
70
713
  shred->info->vm = (VM*)vm;
71
713
  shred->info->me = new_shred(shred);
72
713
  shreduler_ini(vm->shreduler, shred);
73
713
}
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
2877274
ANN static inline void vm_ugen_init(const VM* vm) {
96
2877274
  const Vector v = (Vector)&vm->ugen;
97
  LOOP_OPTIM
98
14866395
  for(m_uint i = vector_size(v) + 1; --i;) {
99
9111847
    const UGen u = (UGen)vector_at(v, i - 1);
100
9111847
    u->done = 0;
101
9111847
    if(u->multi) {
102
5754549
      struct ugen_multi_* m = u->connect.multi;
103
      LOOP_OPTIM
104
23018196
      for(m_uint j = m->n_chan + 1; --j;)
105
11509098
        UGEN(m->channel[j - 1])->done = 0;
106
    }
107
  }
108
2877274
  const UGen hole = (UGen)vector_at(v, 0);
109
2877274
  hole->compute(hole);
110
2877274
}
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
2932
ANN static inline m_bool overflow_(const m_bit* mem, const VM_Shred c) {
122
2932
  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
8
ANN static VM_Shred init_fork_shred(const VM_Shred shred, const VM_Code code, const Type t, const m_uint retsz) {
137
8
  const M_Object o = new_fork(shred, code, t);
138
8
  VM* vm = shred->info->vm;
139
8
  if(!vm->gwion->data->child.ptr)
140
8
    vector_init(&vm->gwion->data->child);
141
8
  vector_add(&vm->gwion->data->child, (vtype)o);
142
8
  fork_launch(o, retsz);
143
8
  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))
279
CC_OPTIM(-O2)
280
4932265
ANN void vm_run(const VM* vm) { // lgtm [cpp/use-of-goto]
281
  static const void* dispatch[] = {
282
    &&regsetimm,
283
    &&regpushimm, &&regpushfloat, &&regpushother, &&regpushaddr,
284
    &&regpushmem, &&regpushmemfloat, &&regpushmemother, &&regpushmemaddr, &&regpushmemderef,
285
    &&pushnow,
286
    &&baseint, &&basefloat, &&baseother, &&baseaddr,
287
    &&regtoreg, &&regtoregaddr, &&regtoregderef,
288
    &&structmember, &&structmemberfloat, &&structmemberother, &&structmemberaddr,
289
    &&memsetimm,
290
    &&regpushme, &&regpushmaybe,
291
    &&funcreturn,
292
    &&_goto,
293
    &&allocint, &&allocfloat, &&allocother,
294
    &&intplus, &&intminus, && intmul, &&intdiv, &&intmod,
295
    // int relationnal
296
    &&inteq, &&intne, &&intand, &&intor,
297
    &&intgt, &&intge, &&intlt, &&intle,
298
    &&intsl, &&intsr, &&intsand, &&intsor, &&intxor,
299
    &&intnegate, &&intnot, &&intcmp,
300
    &&intrassign,
301
    &&intradd, &&intrsub, &&intrmul, &&intrdiv, &&intrmod,
302
    &&intrsl, &&intrsr, &&intrsand, &&intrsor, &&intrxor,
303
    &&preinc, &&predec,
304
    &&postinc, &&postdec,
305
    &&floatadd, &&floatsub, &&floatmul, &&floatdiv,
306
// logical
307
    &&floatand, &&floator, &&floateq, &&floatne,
308
    &&floatgt, &&floatge, &&floatlt, &&floatle,
309
    &&floatneg, &&floatnot,
310
    &&floatrassign, &&floatradd, &&floatrsub, &&floatrmul, &&floatrdiv,
311
    &&ifadd, &&ifsub, &&ifmul, &&ifdiv,
312
    &&ifand, &&ifor, &&ifeq, &&ifne, &&ifgt, &&ifge, &&iflt, &&ifle,
313
    &&ifrassign, &&ifradd, &&ifrsub, &&ifrmul, &&ifrdiv,
314
    &&fiadd, &&fisub, &&fimul, &&fidiv,
315
    &&fiand, &&fior, &&fieq, &&fine, &&figt, &&fige, &&filt, &&file,
316
    &&firassign, &&firadd, &&firsub, &&firmul, &&firdiv,
317
    &&itof, &&ftoi,
318
    &&timeadv,
319
    &&setcode,
320
    &&regpop, &&regpush, &&regtomem, &&regtomemother, &&overflow, &&funcusrend, &&funcmemberend,
321
    &&sporkini, &&forkini, &&sporkfunc, &&sporkmemberfptr, &&sporkexp, &&sporkend,
322
    &&brancheqint, &&branchneint, &&brancheqfloat, &&branchnefloat,
323
    &&arrayappend, &&autoloop, &&autoloopptr, &&autoloopcount, &&arraytop, &&arrayaccess, &&arrayget, &&arrayaddr, &&arrayvalid,
324
    &&newobj, &&addref, &&addrefaddr, &&objassign, &&assign, &&remref,
325
    &&except, &&allocmemberaddr, &&dotmember, &&dotfloat, &&dotother, &&dotaddr,
326
    &&staticint, &&staticfloat, &&staticother,
327
    &&dotfunc, &&dotstaticfunc,
328
    &&gcini, &&gcadd, &&gcend,
329
    &&gacktype, &&gackend, &&gack, &&noop, &&eoc, &&other, &&regpushimm
330
  };
331
4932265
  const Shreduler s = vm->shreduler;
332
  register VM_Shred shred;
333
  register m_bit next;
334
335
9865177
  while((shred = shreduler_get(s))) {
336
647
    register VM_Code code = shred->code;
337
647
    register m_bit* bytecode = code->bytecode;
338
647
    register m_bit* byte = bytecode + shred->pc * BYTECODE_SZ;
339
647
    register m_bit* reg = shred->reg;
340
647
    register m_bit* mem = shred->mem;
341
    register union {
342
      M_Object obj;
343
      VM_Code code;
344
    } a;
345
PRAGMA_PUSH()
346
    register VM_Shred child;
347
PRAGMA_POP()
348
647
  MUTEX_LOCK(s->mutex);
349
  do {
350
647
    SDISPATCH();
351
6056
regsetimm:
352
6056
  *(m_uint*)(reg + (m_int)VAL2) = VAL;
353
6056
  DISPATCH();
354
2854
regpushimm:
355
2854
  *(m_uint*)reg = VAL;
356
2854
  reg += SZ_INT;
357
2854
  DISPATCH();
358
456
regpushfloat:
359
456
  *(m_float*)reg = FVAL;
360
456
  reg += SZ_FLOAT;
361
456
  DISPATCH();
362
regpushother:
363
//  LOOP_OPTIM
364
  for(m_uint i = 0; i <= VAL2; i+= SZ_INT)
365
    *(m_bit**)(reg+i) = (m_bit*)(VAL + i);
366
  reg += VAL2;
367
  DISPATCH();
368
1
regpushaddr:
369
1
  *(m_uint**)reg =  &VAL;
370
1
  reg += SZ_INT;
371
1
  DISPATCH()
372
941
regpushmem:
373
941
  *(m_uint*)reg = *(m_uint*)(mem + (m_int)VAL);
374
941
  reg += SZ_INT;
375
941
  DISPATCH();
376
152
regpushmemfloat:
377
152
  *(m_float*)reg = *(m_float*)(mem + (m_int)VAL);
378
152
  reg += SZ_FLOAT;
379
152
  DISPATCH();
380
2
regpushmemother:
381
6
  for(m_uint i = 0; i <= VAL2; i+= SZ_INT)
382
4
    *(m_uint*)(reg+i) = *(m_uint*)((m_bit*)(mem + (m_int)VAL) + i);
383
2
  reg += VAL2;
384
2
  DISPATCH();
385
376
regpushmemaddr:
386
376
  *(m_bit**)reg = &*(m_bit*)(mem + (m_int)VAL);
387
376
  reg += SZ_INT;
388
376
  DISPATCH()
389
1
regpushmemderef:
390
1
  memcpy(reg, *(m_uint**)(mem+(m_int)VAL), VAL2);
391
1
  reg += VAL2;
392
1
  DISPATCH()
393
147
pushnow:
394
147
  *(m_float*)reg = vm->bbq->pos;
395
147
  reg += SZ_FLOAT;
396
147
  DISPATCH();
397
2788
baseint:
398
2788
  *(m_uint*)reg = *(m_uint*)(shred->base + VAL);
399
2788
  reg += SZ_INT;
400
2788
  DISPATCH();
401
36
basefloat:
402
36
  *(m_float*)reg = *(m_float*)(shred->base + VAL);
403
36
  reg += SZ_FLOAT;
404
36
  DISPATCH();
405
baseother:
406
//  LOOP_OPTIM
407
  for(m_uint i = 0; i <= VAL2; i+= SZ_INT)
408
    *(m_uint*)(reg+i) = *(m_uint*)((shred->base + VAL) + i);
409
  reg += VAL2;
410
  DISPATCH();
411
98
baseaddr:
412
98
  *(m_uint**)reg = &*(m_uint*)(shred->base + (m_int)VAL);
413
98
  reg += SZ_INT;
414
98
  DISPATCH();
415
240
regtoreg:
416
240
  *(m_uint*)(reg + (m_int)VAL) = *(m_uint*)(reg + (m_int)VAL2);
417
240
  DISPATCH()
418
2
regtoregaddr:
419
2
  *(m_uint**)(reg + (m_int)VAL) = &*(m_uint*)(reg + (m_int)VAL2);
420
2
  DISPATCH()
421
11
regtoregderef:
422
11
  memcpy(*(m_bit**)(reg - SZ_INT), *(m_bit**)(reg + (m_int)VAL), VAL2);
423
11
  DISPATCH()
424
15
structmember:
425
15
  *(m_bit**)(reg-SZ_INT) =  *(m_bit**)(*(m_bit**)(reg-SZ_INT) + (m_int)VAL);
426
15
  DISPATCH()
427
8
structmemberfloat:
428
8
  *(m_bit**)(reg-SZ_INT) =  *(m_bit**)(*(m_bit**)(reg-SZ_INT) + (m_int)VAL);
429
8
  DISPATCH()
430
structmemberother:
431
  *(m_bit**)(reg-SZ_INT) =  *(m_bit**)(*(m_bit**)(reg-SZ_INT) + (m_int)VAL);
432
  DISPATCH()
433
17
structmemberaddr:
434
17
  *(m_bit**)(reg-SZ_INT) =  &*(*(m_bit**)(reg-SZ_INT) + (m_int)VAL);
435
17
  DISPATCH()
436
214
memsetimm:
437
214
  *(m_uint*)(mem+VAL) = VAL2;
438
214
  DISPATCH();
439
72
regpushme:
440
72
  *(M_Object*)reg = shred->info->me;
441
72
  reg += SZ_INT;
442
72
  DISPATCH()
443
36
regpushmaybe:
444
36
  *(m_uint*)reg = gw_rand((uint32_t*)vm->rand) > (UINT32_MAX / 2);
445
36
  reg += SZ_INT;
446
36
  DISPATCH();
447
545
funcreturn:
448
{
449
545
  register const m_uint pc = *(m_uint*)(mem-SZ_INT*2);
450
545
  bytecode = (code = *(VM_Code*)(mem-SZ_INT*3))->bytecode;
451
545
  mem -= (*(m_uint*)(mem-SZ_INT*4) + SZ_INT*4);
452
545
  PC_DISPATCH(pc);
453
}
454
12
_goto:
455
2377
  PC_DISPATCH(VAL);
456
179
allocint:
457
179
  *(m_uint*)reg = *(m_uint*)(mem+VAL) = 0;
458
179
  reg += SZ_INT;
459
179
  DISPATCH()
460
87
allocfloat:
461
87
  *(m_float*)reg = *(m_float*)(mem+VAL) = 0;
462
87
  reg += SZ_FLOAT;
463
87
  DISPATCH()
464
allocother:
465
//  LOOP_OPTIM
466
  for(m_uint i = 0; i <= VAL2; i += SZ_INT)
467
    *(m_uint*)(reg+i) = (*(m_uint*)(mem+VAL+i) = 0);
468
  reg += VAL2;
469
  DISPATCH()
470
471
22
intplus:  INT_OP(+)
472
55
intminus: INT_OP(-)
473
2
intmul:   INT_OP(*)
474
2
intdiv:   INT_OP(/, TEST0(m_int, 0))
475
2
intmod:   INT_OP(%, TEST0(m_int, 0))
476
477
71
inteq:   INT_LOGICAL(==)
478
5
intne:   INT_LOGICAL(!=)
479

1
intand:  INT_LOGICAL(&&)
480

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

1
floatand: FLOAT_LOGICAL(&&)
527

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

1
ifand: IF_LOGICAL(&&)
558

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

1
fiand: FI_LOGICAL(&&)
578

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

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