public
Description: Rubinius, the Ruby VM
Homepage: http://rubini.us
Clone URL: git://github.com/evanphx/rubinius.git
Search Repo:
Working on macro threaded ops
evanphx (author)
Wed Feb 13 11:50:35 -0800 2008
commit  142b22e149f4b48bb090969e574b20809b91d3c9
tree    78ebdbc0885dac8d03d29481dcd7bdcf82446ea0
parent  886c3fe5ade6e62a1d073aa3b45aa8a182197851
...
63
64
65
66
 
67
68
69
70
71
 
72
73
74
...
288
289
290
 
 
 
 
 
 
 
 
 
 
 
 
291
292
293
...
63
64
65
 
66
67
68
69
70
 
71
72
73
74
...
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
0
@@ -63,12 +63,12 @@ class InstructionSet
0
     {:opcode => :push_ivar, :args => [:literal], :stack => [0,1]},
0
     {:opcode => :goto_if_defined, :args => [:ip], :stack => [1,0],
0
       :flow => :goto},
0
- {:opcode => :push_const, :args => [:literal], :stack => [0,1]},
0
+ {:opcode => :push_const, :args => [:literal], :stack => [0,1], :flow => :send},
0
     {:opcode => :set_const, :args => [:literal], :stack => [1,1],
0
       :vm_flags => []},
0
     {:opcode => :set_const_at, :args => [:literal], :stack => [2,0],
0
       :vm_flags => []},
0
- {:opcode => :find_const, :args => [:literal], :stack => [1,1]},
0
+ {:opcode => :find_const, :args => [:literal], :stack => [1,1], :flow => :send},
0
     {:opcode => :attach_method, :args => [:literal], :stack => [2,1],
0
       :vm_flags => [:check_interrupts]},
0
     {:opcode => :add_method, :args => [:literal], :stack => [2,1],
0
@@ -288,6 +288,18 @@ class InstructionSet
0
       @opcode_info[:flow] || :sequential
0
     end
0
 
0
+ # Indicates if this instruction terminates a basic block. Used
0
+ # for translating the bytecode into macro ops.
0
+ def final?
0
+ [:send, :return].include? @opcode_info[:flow]
0
+ end
0
+
0
+ # Indicates that this is a goto, and thus the target must be
0
+ # the first instruction in a basic block.
0
+ def goto?
0
+ @opcode_info[:flow] == :goto
0
+ end
0
+
0
     def to_s
0
       @opcode_info[:opcode].to_s
0
     end
...
159
160
161
 
 
 
 
162
163
164
...
159
160
161
162
163
164
165
166
167
168
0
@@ -159,6 +159,10 @@ int cpu_simple_return(STATE, cpu c, OBJECT val);
0
 void cpu_save_registers(STATE, cpu c, int offset);
0
 void cpu_yield_debugger_check(STATE, cpu c);
0
 
0
+void cpu_activate_method(STATE, cpu c, struct message *msg);
0
+OBJECT cpu_open_module(STATE, cpu c, OBJECT under, OBJECT sym);
0
+void cpu_send_message(STATE, cpu c, struct message *msg);
0
+
0
 OBJECT cpu_const_get_in_context(STATE, cpu c, OBJECT sym);
0
 OBJECT cpu_const_get_from(STATE, cpu c, OBJECT sym, OBJECT under);
0
 
...
66
67
68
69
70
71
72
...
407
408
409
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
410
411
412
...
428
429
430
 
 
 
 
431
 
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
...
484
485
486
487
 
 
488
489
490
...
1022
1023
1024
1025
 
1026
1027
1028
...
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
 
 
 
 
1472
1473
 
1474
 
 
1475
 
 
 
1476
1477
1478
1479
1480
1481
1482
1483
 
1484
1485
1486
...
1544
1545
1546
 
1547
 
 
 
1548
 
 
1549
1550
1551
...
66
67
68
 
69
70
71
...
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
...
626
627
628
629
630
631
632
633
634
635
636
 
 
 
 
 
 
 
 
 
 
 
 
 
637
638
639
...
674
675
676
 
677
678
679
680
681
...
1213
1214
1215
 
1216
1217
1218
1219
...
1651
1652
1653
 
 
 
 
 
1654
1655
1656
1657
1658
1659
1660
1661
1662
 
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
 
1673
1674
1675
1676
1677
1678
1679
1680
1681
...
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
0
@@ -66,7 +66,6 @@ void cpu_show_lookup_time(STATE) {
0
 
0
 #if DIRECT_THREADED
0
 #include "shotgun/lib/instruction_funcs.gen"
0
-DT_ADDRESSES;
0
 
0
 #ifdef SHOW_OPS
0
 #define NEXT_OP printf(" => %p\n", *ip_ptr); sassert(*ip_ptr); goto **ip_ptr++
0
@@ -407,6 +406,205 @@ static inline OBJECT cpu_check_serial(STATE, cpu c, OBJECT obj, OBJECT sym, int
0
   return Qfalse;
0
 }
0
 
0
+const char *cpu_op_to_name(STATE, uint32_t op) {
0
+#include "shotgun/lib/instruction_names.h"
0
+ return get_instruction_name(op);
0
+}
0
+
0
+
0
+/* Functions to translating the bytecode into a macro op series. */
0
+#if DIRECT_THREADED
0
+
0
+struct ins2block {
0
+ int block;
0
+ int jump_target;
0
+ int first;
0
+};
0
+
0
+/* the noop instruction contains NEXT_OP(), so we used it to copy
0
+ * the code to just move to the next instruction. */
0
+#define INS_NEXT 0
0
+
0
+void calculate_macro_size(STATE, OBJECT comp, OBJECT exc_table,
0
+ int *out, struct ins2block *tbl) {
0
+ OBJECT ent;
0
+ uint32_t *bytecode;
0
+ uint32_t op;
0
+ int args, total, i, size, cur_block;
0
+ int block_size;
0
+
0
+ /* Pull in jump targets from the exception table */
0
+ total = NUM_FIELDS(exc_table);
0
+ for(i = 0; i < total; i++) {
0
+ ent = tuple_at(state, exc_table, i);
0
+ native_int target = N2I(tuple_at(state, ent, 2));
0
+ tbl[target].jump_target = TRUE;
0
+ }
0
+
0
+ bytecode = (uint32_t*)BYTES_OF(comp);
0
+ total = NUM_FIELDS(comp);
0
+
0
+ size = 0;
0
+
0
+ /* Step 1: find all the jump targets and mark them. */
0
+
0
+ for(i = 0; i < total; i++) {
0
+ op = *bytecode++;
0
+ if(!op) continue;
0
+ args = _ip_size(op) - 1;
0
+
0
+ if(ins_info[op].jump) {
0
+ uint32_t target = *bytecode;
0
+ tbl[target].jump_target = TRUE;
0
+ }
0
+
0
+ i += args;
0
+ bytecode += args;
0
+ }
0
+
0
+ /* Step 2: calculate the block for each op */
0
+ bytecode = (uint32_t*)BYTES_OF(comp);
0
+
0
+ cur_block = 0;
0
+ block_size = 0;
0
+
0
+ for(i = 0; i < total; i++) {
0
+ op = *bytecode++;
0
+ if(!op) continue;
0
+ args = _ip_size(op) - 1;
0
+ size += ins_info[op].size;
0
+
0
+ if(tbl[i].jump_target) {
0
+ if(block_size > 1) {
0
+ cur_block++;
0
+ block_size = 0;
0
+ }
0
+ }
0
+
0
+ if(i > 0 && block_size == 0) tbl[i].first = TRUE;
0
+
0
+ block_size++;
0
+
0
+ tbl[i].block = cur_block;
0
+
0
+ if(ins_info[op].final) {
0
+ size += ins_info[INS_NEXT].size;
0
+ cur_block++;
0
+ block_size = 0;
0
+ }
0
+
0
+ i += args;
0
+ bytecode += args;
0
+ }
0
+
0
+ *out = size;
0
+}
0
+
0
+OBJECT create_macro(STATE, OBJECT exc_tbl, OBJECT in) {
0
+ OBJECT bc;
0
+ int macro_size;
0
+ int cur_block, total, i;
0
+
0
+ void *macro;
0
+ uint8_t *macro_ptr;
0
+ struct ins2block *tbl;
0
+ uint32_t *bytecode;
0
+ uint32_t op;
0
+ uintptr_t *macro_bc, *bc_ptr;
0
+
0
+ int bc_offset = 0;
0
+
0
+#if !CONFIG_BIG_ENDIAN
0
+ int target_size = BYTEARRAY_SIZE(in) * sizeof(uintptr_t);
0
+ bc = bytearray_new(state, target_size);
0
+ iseq_flip(state, in, bc);
0
+#else
0
+ bc = in;
0
+#endif
0
+
0
+ bytecode = (uint32_t*)BYTES_OF(bc);
0
+ total = NUM_FIELDS(bc);
0
+
0
+ tbl = (struct ins2block*)calloc(NUM_FIELDS(bc), sizeof(struct ins2block));
0
+
0
+ calculate_macro_size(state, bc, exc_tbl, &macro_size, tbl);
0
+
0
+ /* we use one chunk of memory for both the new bytecode stream and the
0
+ * code for each macro. */
0
+
0
+ macro_size += sizeof(uintptr_t) * total;
0
+
0
+ macro_bc = (uintptr_t*)malloc(macro_size);
0
+ memset(macro_bc, 0, macro_size);
0
+
0
+ macro = (void*)(macro_bc + total);
0
+
0
+ cur_block = 0;
0
+
0
+ /* macro_bc is the converted instruction sequence. It's a mix of addresses and
0
+ * ints. The addresses are the start of a basic block, then ints are argumens
0
+ * to the instructions that make up the basic block. */
0
+
0
+ bc_ptr = macro_bc;
0
+ macro_ptr = (uint8_t*)macro;
0
+
0
+ /* Initialize the first block. */
0
+ *bc_ptr++ = (uintptr_t)macro;
0
+ bc_offset++;
0
+
0
+ printf("macro size: %d\n", macro_size);
0
+ printf("block 0: %p\n", macro_ptr);
0
+
0
+ for(i = 0; i < total; i++) {
0
+ op = *bytecode++;
0
+ if(!op) continue;
0
+
0
+ printf("[%3d] %3d (%20s), block %d (%d)\n", i, op, cpu_op_to_name(state, op), tbl[i].block, ins_info[op].size);
0
+
0
+ /* We've hit an instruction that must be the first instruction
0
+ * in a block. We fix up the current block and start a new one. */
0
+ if(tbl[i].first) {
0
+ /* Copy NEXT_OP into the end of the current block */
0
+ memcpy(macro_ptr, ins_info[INS_NEXT].start, ins_info[INS_NEXT].size);
0
+ macro_ptr += ins_info[INS_NEXT].size;
0
+
0
+ /* Stick the block number into instruction sequence. */
0
+ bc_offset += 2;
0
+ *bc_ptr++ = bc_offset;
0
+ *bc_ptr++ = (uintptr_t)macro_ptr;
0
+
0
+ printf("block %d: %p\n", tbl[i].block, macro_ptr);
0
+ }
0
+
0
+ /* Copy the code for this operation into the macro */
0
+ memcpy(macro_ptr, ins_info[op].start, ins_info[op].size);
0
+ macro_ptr += ins_info[op].size;
0
+
0
+ /* Copy the args to this op into the instruction stream */
0
+
0
+ switch(_ip_size(op) - 1) {
0
+ case 2:
0
+ printf(" arg: %d\n", *bytecode);
0
+ *bc_ptr++ = (uintptr_t)(*bytecode++);
0
+ bc_offset++;
0
+ i++;
0
+ /* fallow through */
0
+ case 1:
0
+ printf(" arg: %d\n", *bytecode);
0
+ *bc_ptr++ = (uintptr_t)(*bytecode++);
0
+ bc_offset++;
0
+ i++;
0
+ break;
0
+ }
0
+ }
0
+
0
+ OBJECT ptr = ffi_new_pointer(state, macro_bc);
0
+ ffi_autorelease(ptr, 1);
0
+ return ptr;
0
+}
0
+
0
+#endif
0
+
0
 OBJECT cpu_compile_method(STATE, OBJECT cm) {
0
   OBJECT ba, bc;
0
   int target_size;
0
@@ -428,22 +626,14 @@ OBJECT cpu_compile_method(STATE, OBJECT cm) {
0
     ba = bytearray_new(state, target_size);
0
   }
0
 
0
+#if DIRECT_THREADED
0
+ ba = create_macro(state, cmethod_get_exceptions(cm), bc);
0
+ cmethod_set_compiled(cm, ba);
0
+#else
0
   cpu_compile_instructions(state, bc, ba);
0
+#endif
0
   cmethod_set_compiled(cm, ba);
0
 
0
- /* Allocate a tuple to hold the cache entries for method calls */
0
- OBJECT cs;
0
- cs = cmethod_get_cache(cm);
0
- if(FIXNUM_P(cs)) {
0
- native_int sz = N2I(cs);
0
- if(sz > 0) {
0
- cs = tuple_new(state, sz);
0
- // Reserve field 0 for call sites that are not cached
0
- fast_unsafe_set(cs, 0, Qfalse);
0
- cmethod_set_cache(cm, cs);
0
- }
0
- }
0
-
0
   return ba;
0
 }
0
 
0
@@ -484,7 +674,8 @@ static inline OBJECT _allocate_context(STATE, cpu c, OBJECT meth, int locals) {
0
   fc->sender = c->active_context;
0
 
0
   fc->method = meth;
0
- fc->data = bytearray_byte_address(state, ins);
0
+ fc->data = *DATA_STRUCT(ins, void**);
0
+ // fc->data = bytearray_byte_address(state, ins);
0
   fc->literals = fast_fetch(meth, CMETHOD_f_LITERALS);
0
 
0
   if(locals > 0) {
0
@@ -1022,7 +1213,7 @@ inline void cpu_perform_hook(STATE, cpu c, OBJECT recv, OBJECT meth, OBJECT arg)
0
 
0
 /* Layer 4: direct activation. Used for calling a method thats already
0
    been looked up. */
0
-static inline void cpu_activate_method(STATE, cpu c, struct message *msg) {
0
+inline void cpu_activate_method(STATE, cpu c, struct message *msg) {
0
   OBJECT ctx;
0
 
0
   c->depth++;
0
@@ -1460,27 +1651,31 @@ void cpu_yield_debugger(STATE, cpu c) {
0
   }
0
 }
0
 
0
-const char *cpu_op_to_name(STATE, char op) {
0
-#include "shotgun/lib/instruction_names.h"
0
- return get_instruction_name(op);
0
-}
0
-
0
 void state_collect(STATE, cpu c);
0
 void state_major_collect(STATE, cpu c);
0
 
0
 void cpu_run(STATE, cpu c, int setup) {
0
+ uint32_t _int;
0
+ native_int j, k, m;
0
+ OBJECT _lit, t1, t2, t3, t4, t5;
0
+ struct message msg;
0
   IP_TYPE op;
0
- IP_TYPE *ip_ptr = NULL;
0
+ IP_TYPE *ip_ptr;
0
   const char *firesuit_arg;
0
+ struct rubinius_globals *global;
0
+ struct inter_proxy *proxy;
0
 
0
+ ip_ptr = NULL;
0
+ proxy = state->proxy;
0
+ global = state->global;
0
   c->ip_ptr = &ip_ptr;
0
 
0
- struct rubinius_globals *global = state->global;
0
 
0
   if(setup) {
0
     (void)op;
0
 #if DIRECT_THREADED
0
     SETUP_DT_ADDRESSES;
0
+ _populate_ins_info();
0
     return;
0
 #else
0
     return;
0
@@ -1544,8 +1739,14 @@ insn_start:
0
         rbs_symbol_to_cstring(state, cmethod_get_name(cpu_current_method(state, c))),
0
         (void*)*ip_ptr);
0
     }
0
+jump_next:
0
     NEXT_OP;
0
+jump_next_end:
0
+ #undef WB_FUNC
0
+ #define WB_FUNC proxy->write_barrier
0
     #include "shotgun/lib/instruction_dt.gen"
0
+ #undef WB_FUNC
0
+ #define WB_FUNC object_memory_write_barrier
0
 #else
0
 
0
 next_op:
...
32
33
34
 
35
36
37
...
66
67
68
69
 
 
 
 
 
70
71
72
73
 
 
 
 
 
 
 
74
75
76
 
 
 
 
 
 
 
 
 
 
 
 
 
77
78
79
...
131
132
133
134
 
135
136
137
...
145
146
147
148
 
149
150
151
152
153
154
155
 
156
157
158
...
179
180
181
182
 
 
183
184
185
...
205
206
207
208
 
 
 
 
 
 
 
 
209
210
211
...
226
227
228
229
 
230
231
232
...
247
248
249
250
 
251
252
253
...
268
269
270
271
 
272
273
274
...
289
290
291
292
 
293
294
295
...
356
357
358
359
 
360
361
362
...
379
380
381
382
383
384
385
 
 
386
387
388
...
410
411
412
413
 
414
415
416
...
483
484
485
486
 
487
488
489
...
572
573
574
575
 
576
577
578
...
594
595
596
597
598
 
599
600
601
...
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
 
768
769
770
...
1568
1569
1570
1571
 
1572
1573
1574
...
1596
1597
1598
1599
 
1600
1601
1602
...
1743
1744
1745
1746
 
 
1747
1748
1749
...
1805
1806
1807
1808
 
1809
1810
 
1811
1812
1813
...
1839
1840
1841
1842
 
1843
1844
 
1845
1846
1847
...
1891
1892
1893
1894
 
1895
1896
1897
...
1928
1929
1930
1931
 
1932
1933
1934
 
 
 
 
 
 
 
 
 
 
 
1935
1936
1937
...
2752
2753
2754
2755
 
2756
2757
2758
...
3085
3086
3087
3088
 
3089
3090
3091
...
3697
3698
3699
3700
3701
3702
3703
...
3713
3714
3715
3716
3717
3718
3719
...
32
33
34
35
36
37
38
...
67
68
69
 
70
71
72
73
74
75
76
77
 
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
...
155
156
157
 
158
159
160
161
...
169
170
171
 
172
173
174
175
176
177
178
 
179
180
181
182
...
203
204
205
 
206
207
208
209
210
...
230
231
232
 
233
234
235
236
237
238
239
240
241
242
243
...
258
259
260
 
261
262
263
264
...
279
280
281
 
282
283
284
285
...
300
301
302
 
303
304
305
306
...
321
322
323
 
324
325
326
327
...
388
389
390
 
391
392
393
394
...
411
412
413
 
 
 
 
414
415
416
417
418
...
440
441
442
 
443
444
445
446
...
513
514
515
 
516
517
518
519
...
602
603
604
 
605
606
607
608
...
624
625
626
 
 
627
628
629
630
...
776
777
778
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
779
780
781
782
...
1580
1581
1582
 
1583
1584
1585
1586
...
1608
1609
1610
 
1611
1612
1613
1614
...
1755
1756
1757
 
1758
1759
1760
1761
1762
...
1818
1819
1820
 
1821
1822
 
1823
1824
1825
1826
...
1852
1853
1854
 
1855
1856
 
1857
1858
1859
1860
...
1904
1905
1906
 
1907
1908
1909
1910
...
1941
1942
1943
 
1944
1945
1946
 
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
...
2775
2776
2777
 
2778
2779
2780
2781
...
3108
3109
3110
 
3111
3112
3113
3114
...
3720
3721
3722
 
3723
3724
3725
...
3735
3736
3737
 
3738
3739
3740
0
@@ -32,6 +32,7 @@ class ShotgunInstructions
0
       if code
0
         fd.puts " insn_#{ins.bytecode}: {"
0
         fd.puts code
0
+ fd.puts " insn_#{ins.bytecode}_end:"
0
         if ins.check_interrupts?
0
           fd.puts " goto check_interrupts;"
0
         elsif ins.terminator?
0
@@ -66,14 +67,37 @@ class ShotgunInstructions
0
 
0
     code << "}\nreturn 1;\n}\n\n"
0
 
0
- code << "#define DT_ADDRESSES static void* _dt_addresses[#{InstructionSet::OpCodes.size + 1}]; static int _dt_size = #{InstructionSet::OpCodes.size};\n"
0
+ code << "struct ins_info_t { int bytecode; uintptr_t size; void *start; int final; int jump; };\n"
0
+ code << "static void* _dt_addresses[#{InstructionSet::OpCodes.size + 1}];\n"
0
+ code << "static int _dt_size = #{InstructionSet::OpCodes.size};\n"
0
+ code << "static void *_dt_ends[#{InstructionSet::OpCodes.size + 1}];\n"
0
+ code << "static struct ins_info_t ins_info[#{InstructionSet::OpCodes.size + 1}];\n"
0
     code << "#define SETUP_DT_ADDRESSES "
0
 
0
     InstructionSet::OpCodes.each do |ins|
0
- code << "_dt_addresses[#{ins.bytecode}] = &&insn_#{ins.bytecode}; "
0
+ if ins.bytecode == 0
0
+ code << "_dt_addresses[0] = &&jump_next; "
0
+ code << "_dt_ends[0] = &&jump_next_end; "
0
+ else
0
+ code << "_dt_addresses[#{ins.bytecode}] = &&insn_#{ins.bytecode}; "
0
+ code << "_dt_ends[#{ins.bytecode}] = &&insn_#{ins.bytecode}_end; "
0
+ end
0
     end
0
     code << "\n"
0
 
0
+ code << "static void _populate_ins_info() {\n"
0
+ InstructionSet::OpCodes.each do |ins|
0
+ idx = ins.bytecode
0
+
0
+ code << "ins_info[#{idx}].bytecode = #{idx};\n"
0
+ code << "ins_info[#{idx}].size = (uintptr_t)_dt_ends[#{idx}] - (uintptr_t)_dt_addresses[#{idx}];\n"
0
+ code << "ins_info[#{idx}].start = _dt_addresses[#{idx}];\n"
0
+ code << "ins_info[#{idx}].final = #{ins.final? ? 'TRUE' : 'FALSE'};\n"
0
+ code << "ins_info[#{idx}].jump = #{ins.goto? ? 'TRUE' : 'FALSE'};\n"
0
+ end
0
+
0
+ code << "}\n"
0
+
0
     code << <<-CODE
0
 
0
     static inline uint32_t read_int_from_be(uint8_t *str) {
0
@@ -131,7 +155,7 @@ class ShotgunInstructions
0
   end
0
 
0
   def generate_names
0
- str = "static const char instruction_names[] = {\n"
0
+ str = "#include <stdint.h>\nstatic const char instruction_names[] = {\n"
0
     InstructionSet::OpCodes.each do |ins|
0
       str << " \"#{ins.opcode.to_s}\\0\"\n"
0
     end
0
@@ -145,14 +169,14 @@ class ShotgunInstructions
0
     end
0
     str << "\n};\n\n"
0
     str << <<CODE
0
-const char *get_instruction_name(int op) {
0
+const char *get_instruction_name(uint32_t op) {
0
   return instruction_names + instruction_name_offsets[op];
0
 }
0
 CODE
0
   end
0
 
0
   def generate_names_header
0
- str = "const char *get_instruction_name(int op);\n"
0
+ str = "const char *get_instruction_name(uint32_t op);\n"
0
 
0
     InstructionSet::OpCodes.each do |ins|
0
       str << "#define CPU_INSTRUCTION_#{ins.opcode.to_s.upcase} #{ins.bytecode}\n"
0
@@ -179,7 +203,8 @@ CODE
0
   # * pop
0
 
0
   def noop
0
- ""
0
+ <<-CODE
0
+ CODE
0
   end
0
 
0
   # [Operation]
0
@@ -205,7 +230,14 @@ CODE
0
   def push_int
0
     <<-CODE
0
     next_int;
0
- stack_push(I2N(_int));
0
+ /* hand inlined version of rbs_int_numeric. Don't remove this. */
0
+ t1 = APPLY_TAG((native_int)_int, TAG_FIXNUM);
0
+
0
+ if((native_int)STRIP_TAG(t1) != (native_int)_int) {
0
+ t1 = proxy->bignum_new(state, (native_int)_int);
0
+ }
0
+
0
+ stack_push(t1);
0
     CODE
0
   end
0
 
0
@@ -226,7 +258,7 @@ CODE
0
 
0
   def meta_push_neg_1
0
     <<-CODE
0
- stack_push(I2N(-1));
0
+ stack_push(APPLY_TAG(-1, TAG_FIXNUM));
0
     CODE
0
   end
0
 
0
@@ -247,7 +279,7 @@ CODE
0
 
0
   def meta_push_0
0
     <<-CODE
0
- stack_push(I2N(0));
0
+ stack_push(APPLY_TAG(0, TAG_FIXNUM));
0
     CODE
0
   end
0
 
0
@@ -268,7 +300,7 @@ CODE
0
 
0
   def meta_push_1
0
     <<-CODE
0
- stack_push(I2N(1));
0
+ stack_push(APPLY_TAG(1, TAG_FIXNUM));
0
     CODE
0
   end
0
 
0
@@ -289,7 +321,7 @@ CODE
0
 
0
   def meta_push_2
0
     <<-CODE
0
- stack_push(I2N(2));
0
+ stack_push(APPLY_TAG(2, TAG_FIXNUM));
0
     CODE
0
   end
0
 
0
@@ -356,7 +388,7 @@ CODE
0
 
0
   def push_context
0
     <<-CODE
0
- methctx_reference(state, c->active_context);
0
+ proxy->methctx_reference(state, c->active_context);
0
     stack_push(c->active_context);
0
     CODE
0
   end
0
@@ -379,10 +411,8 @@ CODE
0
 
0
   def push_literal
0
     <<-CODE
0
- next_int;
0
- t1 = cpu_current_literals(state, c);
0
- t2 = fast_fetch(t1, _int);
0
- stack_push(t2);
0
+ next_literal;
0
+ stack_push(_lit);
0
     CODE
0
   end
0
 
0
@@ -410,7 +440,7 @@ CODE
0
   def set_literal
0
     <<-CODE
0
     next_int;
0
- tuple_put(state, cpu_current_literals(state, c), _int, stack_top());
0
+ SET_FIELD_DIRECT(cpu_current_literals(state, c), _int, stack_top());
0
     CODE
0
   end
0
 
0
@@ -483,7 +513,7 @@ CODE
0
       t2 = blokctx_env(state, t1);
0
       t1 = blokenv_get_home_block(t2);
0
     }
0
- stack_push(tuple_at(state, blokctx_locals(state, t1), _int));
0
+ stack_push(fast_fetch(blokctx_locals(state, t1), _int));
0
     CODE
0
   end
0
 
0
@@ -572,7 +602,7 @@ CODE
0
   def push_ivar
0
     <<-CODE
0
     next_literal;
0
- stack_push(object_get_ivar(state, c->self, _lit));
0
+ stack_push(proxy->get_ivar(state, c->self, _lit));
0
     CODE
0
   end
0
 
0
@@ -594,8 +624,7 @@ CODE
0
 
0
   def allocate
0
     <<-CODE
0
- _lit = stack_pop();
0
- stack_push(NEW_OBJECT(Qnil, N2I(_lit)));
0
+ sassert(0);
0
     CODE
0
   end
0
 
0
@@ -747,24 +776,7 @@ CODE
0
 
0
   def send_primitive
0
     <<-CODE
0
- next_int;
0
- j = (native_int)_int; // primitive index
0
- next_int;
0
- k = (native_int)_int; // num_args
0
-
0
- // Should the OBJECT parameter be removed since a primitive is not necesarily
0
- // performed on an object? Or should we state that the semantics of a primitive
0
- // will always have an object or else it needs to be an opcode... ?
0
- // If the primitive fails raise an exception
0
-
0
- msg.name = Qnil;
0
- msg.args = k;
0
- msg.method = Qnil;
0
- msg.module = Qnil;
0
- if(!cpu_perform_system_primitive(state, c, j, &msg))
0
- {
0
- cpu_raise_primitive_failure(state, c, j);
0
- }
0
+ sassert(0);
0
     CODE
0
   end
0
 
0
@@ -1568,7 +1580,7 @@ CODE
0
   def set_encloser
0
     <<-CODE
0
     t1 = stack_pop();
0
- cpu_set_encloser_path(state, c, t1);
0
+ proxy->set_encloser(state, c, t1);
0
     CODE
0
   end
0
 
0
@@ -1596,7 +1608,7 @@ CODE
0
 
0
   def push_encloser
0
     <<-CODE
0
- cpu_push_encloser(state, c);
0
+ proxy->push_encloser(state, c);
0
     CODE
0
   end
0
 
0
@@ -1743,7 +1755,8 @@ CODE
0
   def open_module
0
     <<-CODE
0
     next_literal;
0
- stack_push(cpu_open_module(state, c, c->enclosing_class, _lit));
0
+ t1 = proxy->open_module(state, c, c->enclosing_class, _lit);
0
+ stack_push(t1);
0
     CODE
0
   end
0
 
0
@@ -1805,9 +1818,9 @@ CODE
0
     next_literal;
0
     t1 = stack_pop();
0
     t2 = stack_pop();
0
- cpu_attach_method(state, c, t1, _lit, t2);
0
+ proxy->attach_method(state, c, t1, _lit, t2);
0
     stack_push(t2);
0
- cpu_perform_hook(state, c, t1, global->sym_s_method_added, _lit);
0
+ proxy->perform_hook(state, c, t1, global->sym_s_method_added, _lit);
0
     CODE
0
   end
0
 
0
@@ -1839,9 +1852,9 @@ CODE
0
     next_literal;
0
     t1 = stack_pop();
0
     t2 = stack_pop();
0
- cpu_add_method(state, c, t1, _lit, t2);
0
+ proxy->add_method(state, c, t1, _lit, t2);
0
     stack_push(t2);
0
- cpu_perform_hook(state, c, t1, global->sym_method_added, _lit);
0
+ proxy->perform_hook(state, c, t1, global->sym_method_added, _lit);
0
     CODE
0
   end
0
 
0
@@ -1891,7 +1904,7 @@ CODE
0
     t3 = stack_pop(); /* locals */
0
     msg.block = stack_pop();
0
 
0
- cpu_activate_method(state, c, &msg);
0
+ proxy->activate_method(state, c, &msg);
0
     if(RTEST(t3)) {
0
       if(NIL_P(cpu_current_locals(state, c)) || NUM_FIELDS(t3) >= NUM_FIELDS(cpu_current_locals(state, c))) {
0
         cpu_set_locals(state, c, t3);
0
@@ -1928,10 +1941,20 @@ CODE
0
   def send_method
0
     <<-CODE
0
     next_literal_into(msg.send_site);
0
- msg.recv = stack_pop();
0
+ t1 = msg.recv = stack_pop();
0
     msg.block = Qnil;
0
     msg.args = 0;
0
- goto perform_send;
0