cast_off 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. data/README +578 -0
  2. data/README.en +256 -0
  3. data/bin/CastOff +145 -0
  4. data/cast_off.gemspec +25 -0
  5. data/ext/cast_off/cast_off.c.rb +1386 -0
  6. data/ext/cast_off/cast_off.h +24 -0
  7. data/ext/cast_off/depend +70 -0
  8. data/ext/cast_off/extconf.rb +19 -0
  9. data/ext/cast_off/generated_c_include/inline_api.h +507 -0
  10. data/ext/cast_off/generated_c_include/iter_api.h +595 -0
  11. data/ext/cast_off/generated_c_include/unbox_api.h.rb +76 -0
  12. data/ext/cast_off/generated_c_include/vm_api.h +751 -0
  13. data/ext/cast_off/ruby_source/atomic.h +56 -0
  14. data/ext/cast_off/ruby_source/constant.h +34 -0
  15. data/ext/cast_off/ruby_source/debug.h +41 -0
  16. data/ext/cast_off/ruby_source/eval_intern.h +234 -0
  17. data/ext/cast_off/ruby_source/gc.h +98 -0
  18. data/ext/cast_off/ruby_source/id.h +175 -0
  19. data/ext/cast_off/ruby_source/insns.inc +179 -0
  20. data/ext/cast_off/ruby_source/insns_info.inc +695 -0
  21. data/ext/cast_off/ruby_source/internal.h +227 -0
  22. data/ext/cast_off/ruby_source/iseq.h +125 -0
  23. data/ext/cast_off/ruby_source/manual_update.h +135 -0
  24. data/ext/cast_off/ruby_source/method.h +105 -0
  25. data/ext/cast_off/ruby_source/node.h +503 -0
  26. data/ext/cast_off/ruby_source/thread_pthread.h +51 -0
  27. data/ext/cast_off/ruby_source/thread_win32.h +40 -0
  28. data/ext/cast_off/ruby_source/vm_core.h +756 -0
  29. data/ext/cast_off/ruby_source/vm_exec.h +184 -0
  30. data/ext/cast_off/ruby_source/vm_insnhelper.c +1748 -0
  31. data/ext/cast_off/ruby_source/vm_insnhelper.h +220 -0
  32. data/ext/cast_off/ruby_source/vm_opts.h +51 -0
  33. data/lib/cast_off.rb +15 -0
  34. data/lib/cast_off/compile.rb +629 -0
  35. data/lib/cast_off/compile/basicblock.rb +144 -0
  36. data/lib/cast_off/compile/cfg.rb +391 -0
  37. data/lib/cast_off/compile/code_manager.rb +284 -0
  38. data/lib/cast_off/compile/configuration.rb +2368 -0
  39. data/lib/cast_off/compile/dependency.rb +240 -0
  40. data/lib/cast_off/compile/information.rb +775 -0
  41. data/lib/cast_off/compile/instruction.rb +446 -0
  42. data/lib/cast_off/compile/ir/call_ir.rb +2348 -0
  43. data/lib/cast_off/compile/ir/guard_ir.rb +423 -0
  44. data/lib/cast_off/compile/ir/jump_ir.rb +223 -0
  45. data/lib/cast_off/compile/ir/operand.rb +934 -0
  46. data/lib/cast_off/compile/ir/param_ir.rb +98 -0
  47. data/lib/cast_off/compile/ir/return_ir.rb +92 -0
  48. data/lib/cast_off/compile/ir/simple_ir.rb +808 -0
  49. data/lib/cast_off/compile/ir/sub_ir.rb +212 -0
  50. data/lib/cast_off/compile/iseq.rb +454 -0
  51. data/lib/cast_off/compile/method_information.rb +1384 -0
  52. data/lib/cast_off/compile/namespace/namespace.rb +556 -0
  53. data/lib/cast_off/compile/namespace/uuid.rb +323 -0
  54. data/lib/cast_off/compile/stack.rb +65 -0
  55. data/lib/cast_off/compile/translator.rb +1562 -0
  56. data/lib/cast_off/suggestion.rb +98 -0
  57. data/lib/cast_off/util.rb +58 -0
  58. metadata +107 -0
@@ -0,0 +1,595 @@
1
+ static rb_iseq_t *construct_iter_api_iseq(VALUE (*fptr)(ANYARGS), ID mid)
2
+ {
3
+ VALUE putnil = rb_ary_new();
4
+ VALUE pop = rb_ary_new();
5
+ VALUE send = rb_ary_new();
6
+ VALUE getlocal0 = rb_ary_new();
7
+ VALUE getlocal1 = rb_ary_new();
8
+ VALUE getlocal2 = rb_ary_new();
9
+ VALUE leave = rb_ary_new();
10
+ VALUE val = rb_ary_new();
11
+ VALUE misc = rb_hash_new();
12
+ VALUE locals = rb_ary_new();
13
+ VALUE exception = rb_ary_new();
14
+ VALUE body = rb_ary_new();
15
+ VALUE iseqval;
16
+ rb_iseq_t *iseq;
17
+
18
+ /* create putnil instruction */
19
+ rb_ary_push(putnil, ID2SYM(rb_intern("putnil")));
20
+
21
+ /* create pop instruction */
22
+ rb_ary_push(pop, ID2SYM(rb_intern("pop")));
23
+
24
+ /* create send instruction */
25
+ rb_ary_push(send, ID2SYM(rb_intern("send")));
26
+ rb_ary_push(send, ID2SYM(mid)); /* mid */
27
+ rb_ary_push(send, INT2FIX(2)); /* argc */
28
+ rb_ary_push(send, Qnil); /* blockiseq */
29
+ rb_ary_push(send, LONG2FIX(0)); /* flag */
30
+ rb_ary_push(send, LONG2FIX(0)); /* */
31
+
32
+ /* create getlocal instruction */
33
+ rb_ary_push(getlocal0, ID2SYM(rb_intern("getlocal")));
34
+ rb_ary_push(getlocal0, INT2FIX(4));
35
+ rb_ary_push(getlocal1, ID2SYM(rb_intern("getlocal")));
36
+ rb_ary_push(getlocal1, INT2FIX(3));
37
+ rb_ary_push(getlocal2, ID2SYM(rb_intern("getlocal")));
38
+ rb_ary_push(getlocal2, INT2FIX(2));
39
+
40
+ /* create leave instruction */
41
+ rb_ary_push(leave, ID2SYM(rb_intern("leave")));
42
+
43
+ /*
44
+ * [:magic, :major_version, :minor_version, :format_type, :misc,
45
+ * :name, :filename, :filepath, :line_no, :type, :locals, :args,
46
+ * :catch_table, :bytecode]
47
+ */
48
+
49
+ #define ISEQ_MAJOR_VERSION 1
50
+ #define ISEQ_MINOR_VERSION 2
51
+ rb_ary_push(val, rb_str_new2("YARVInstructionSequence/SimpleDataFormat")); /* magic */
52
+ rb_ary_push(val, INT2FIX(ISEQ_MAJOR_VERSION)); /* major version */
53
+ rb_ary_push(val, INT2FIX(ISEQ_MINOR_VERSION)); /* minor version */
54
+ rb_ary_push(val, INT2FIX(1)); /* format type */
55
+
56
+ /* misc */
57
+ rb_hash_aset(misc, ID2SYM(rb_intern("arg_size")), INT2FIX(0));
58
+ rb_hash_aset(misc, ID2SYM(rb_intern("local_size")), INT2FIX(4));
59
+ rb_hash_aset(misc, ID2SYM(rb_intern("stack_max")), INT2FIX(3));
60
+ rb_ary_push(val, misc);
61
+
62
+ rb_ary_push(val, rb_str_new2("<compiled>")); /* name */
63
+ rb_ary_push(val, rb_str_new2("<compiled>")); /* filename */
64
+ rb_ary_push(val, rb_str_new2("<compiled>")); /* filepath */
65
+ rb_ary_push(val, INT2FIX(-1)); /* line_no */
66
+ rb_ary_push(val, ID2SYM(rb_intern("method"))); /* type */
67
+
68
+ /* locals */
69
+ rb_ary_push(locals, ID2SYM(rb_intern("recv")));
70
+ rb_ary_push(locals, ID2SYM(rb_intern("key")));
71
+ rb_ary_push(locals, ID2SYM(rb_intern("blockptr")));
72
+ rb_ary_push(val, locals);
73
+
74
+ /* args */
75
+ rb_ary_push(val, INT2FIX(0));
76
+
77
+ /* catch_table */
78
+ rb_ary_push(val, exception);
79
+
80
+ /* bytecode */
81
+ rb_ary_push(body, putnil);
82
+ rb_ary_push(body, pop);
83
+ rb_ary_push(body, getlocal0);
84
+ rb_ary_push(body, getlocal1);
85
+ rb_ary_push(body, getlocal2);
86
+ rb_ary_push(body, send);
87
+ rb_ary_push(body, leave);
88
+ rb_ary_push(val, body);
89
+
90
+ /* create iseq from ary */
91
+ iseqval = rb_iseq_load(val, Qnil, Qnil);
92
+ if (rb_class_of(iseqval) != rb_cISeq) {
93
+ rb_bug("construct_inline_api_iseq: should not be reached(0)");
94
+ }
95
+ iseq = DATA_PTR(iseqval);
96
+
97
+ rb_define_singleton_method(rb_mCastOff, rb_id2name(mid), fptr, 2);
98
+ return iseq;
99
+ }
100
+ NOINLINE(static rb_iseq_t *construct_iter_api_iseq(VALUE (*fptr)(ANYARGS), ID mid));
101
+
102
+ static rb_iseq_t*
103
+ search_iter_api_iseq(VALUE (*fptr)(ANYARGS), ID mid)
104
+ {
105
+ VALUE deoptimization_iseq_table, val;
106
+ rb_iseq_t *iseq;
107
+
108
+ deoptimization_iseq_table = rb_const_get(rb_mCastOffCompiler, rb_intern("DEOPTIMIZATION_ISEQ_TABLE"));
109
+ val = rb_hash_aref(deoptimization_iseq_table, ID2SYM(mid));
110
+ if (rb_class_of(val) == rb_cISeq) {
111
+ iseq = DATA_PTR(val);
112
+ } else {
113
+ iseq = construct_iter_api_iseq(fptr, mid);
114
+ if (rb_class_of(iseq->self) != rb_cISeq) {
115
+ rb_bug("search_iter_api_iseq: should not be reached(0), mid = %s", rb_id2name(mid));
116
+ }
117
+ rb_hash_aset(deoptimization_iseq_table, ID2SYM(mid), iseq->self);
118
+ }
119
+
120
+ return iseq;
121
+ }
122
+ NOINLINE(static rb_iseq_t* search_iter_api_iseq(VALUE (*fptr)(ANYARGS), ID mid));
123
+
124
+ #define iter_namegen(klass, mid, suffix) cast_off_ ## klass ## _ ## mid ## _ ## suffix
125
+ #define _iter_strgen(str) #str
126
+ #define iter_strgen(str) _iter_strgen(str)
127
+
128
+ #define define_deoptimization_iseq_fetch_function(klass, mid) \
129
+ static rb_iseq_t* \
130
+ iter_namegen(klass, mid, deoptimization_iseq)(void) \
131
+ { \
132
+ ID mid = rb_intern(iter_strgen(iter_namegen(klass, mid, deoptimize))); \
133
+ return search_iter_api_iseq(iter_namegen(klass, mid, deoptimize), mid); \
134
+ } \
135
+ NOINLINE(static rb_iseq_t* iter_namegen(klass, mid, deoptimization_iseq)(void));
136
+
137
+ #define define_frame_construction_function(klass, mid) \
138
+ static void \
139
+ iter_namegen(klass, mid, construct_frame)(void *key, VALUE blockptr) \
140
+ { \
141
+ VALUE thval = rb_thread_current(); \
142
+ rb_thread_t *th = DATA_PTR(thval); \
143
+ rb_control_frame_t *cfp = th->cfp; \
144
+ rb_iseq_t *iseq = iter_namegen(klass, mid, deoptimization_iseq)(); \
145
+ VALUE *sp = cfp->sp; \
146
+ \
147
+ CHECK_STACK_OVERFLOW(cfp, 1); \
148
+ *sp++ = rb_mCastOff; \
149
+ *sp++ = GC_GUARDED_PTR(key); \
150
+ *sp++ = GC_GUARDED_PTR(blockptr); \
151
+ vm_push_frame(th, iseq, VM_FRAME_MAGIC_METHOD, rb_mCastOff, 0, iseq->iseq_encoded + 1, sp, 0, 1); \
152
+ } \
153
+ NOINLINE(static void iter_namegen(klass, mid, construct_frame)(void *key, VALUE blockptr));
154
+
155
+ #define deoptimization_function_begin(klass, mid) \
156
+ static VALUE \
157
+ iter_namegen(klass, mid, deoptimize)(VALUE recv, VALUE k, VALUE b) \
158
+ { \
159
+ VALUE thval = rb_thread_current(); \
160
+ rb_thread_t *th = DATA_PTR(thval); \
161
+ rb_control_frame_t *cfp = th->cfp; \
162
+ iter_namegen(klass, mid, t) *key = GC_GUARDED_PTR_REF(k); \
163
+ cfp->lfp[0] = b; /* blockptr */ \
164
+ {
165
+
166
+ #define deoptimization_function_end(klass, mid) \
167
+ } \
168
+ } \
169
+ NOINLINE(static VALUE iter_namegen(klass, mid, deoptimize)(VALUE recv, VALUE k, VALUE b));
170
+
171
+ #define ArgError(a, b) rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)", (a), (b))
172
+ static inline int
173
+ cast_off_prepare_iter_api_lambda_args(int use_c, VALUE *use_v, int given_c, VALUE *given_v, int simple, int must, int opt_len, int post_len, int post_start, int rest_index)
174
+ {
175
+ int i, num = -1;
176
+ int rest_c = given_c;
177
+
178
+ if (simple) {
179
+ if (UNLIKELY(use_c != given_c)) {
180
+ ArgError(given_c, use_c);
181
+ }
182
+ for (i = 0; i < use_c; i++) {
183
+ use_v[i] = given_v[i];
184
+ }
185
+ return num;
186
+ }
187
+
188
+ /* mandatory */
189
+ if (given_c < (must + post_len)) { /* check with post arg */
190
+ ArgError(given_c, must + post_len);
191
+ }
192
+
193
+ for (i = 0; i < must; i++) {
194
+ use_v[i] = given_v[i];
195
+ }
196
+ rest_c -= must;
197
+
198
+ /* post arguments */
199
+ if (post_len) {
200
+ for (i = post_start; i < post_start + post_len; i++) {
201
+ use_v[i] = given_v[i];
202
+ }
203
+ rest_c -= post_len;
204
+ }
205
+
206
+ /* opt arguments */
207
+ if (opt_len) {
208
+ if (rest_index == -1 && rest_c > opt_len) {
209
+ ArgError(given_c, must + opt_len + post_len);
210
+ }
211
+
212
+ if (rest_c >= opt_len) {
213
+ for (i = must; i < must + opt_len; i++) {
214
+ use_v[i] = given_v[i];
215
+ }
216
+ num = must + opt_len;
217
+ rest_c -= opt_len;
218
+ } else {
219
+ for (i = must; i< must + rest_c; i++) {
220
+ use_v[i] = given_v[i];
221
+ }
222
+ for (i = must + rest_c; i < must + opt_len; i++) {
223
+ use_v[i] = Qundef;
224
+ }
225
+ num = must + rest_c;
226
+ rest_c = 0;
227
+ }
228
+ }
229
+
230
+ /* rest arguments */
231
+ if (rest_index != -1) {
232
+ if (rest_c) {
233
+ use_v[rest_index] = rb_ary_new4(rest_c, &given_v[must + opt_len]);
234
+ } else {
235
+ use_v[rest_index] = rb_ary_new();
236
+ }
237
+ rest_c = 0;
238
+ }
239
+
240
+ if (rest_c) rb_bug("cast_off_prepare_iter_api_lambda_args: should not be reached(0)");
241
+
242
+ return num;
243
+ }
244
+
245
+ static inline int
246
+ cast_off_prepare_iter_api_block_args(int use_c, VALUE *use_v, int given_c, VALUE *given_v, int splat, int must, int opt_len, int post_len, int post_start, int rest_index)
247
+ {
248
+ int i, cpy;
249
+ volatile VALUE mark;
250
+ int num = -1;
251
+
252
+ if (splat) {
253
+ VALUE ary;
254
+
255
+ if(given_c == 1 && !NIL_P(ary = rb_check_array_type(given_v[0]))) { /* rhs is only an array */
256
+ cpy = given_c = RARRAY_LENINT(ary);
257
+ if (cpy > must) cpy = must;
258
+ MEMCPY(use_v, RARRAY_PTR(ary), VALUE, cpy);
259
+ mark = ary;
260
+ given_v = RARRAY_PTR(ary);
261
+ } else {
262
+ cpy = given_c;
263
+ if (cpy > must) cpy = must;
264
+ for (i = 0; i < cpy; i++) {
265
+ use_v[i] = given_v[i];
266
+ }
267
+ }
268
+ } else {
269
+ cpy = given_c;
270
+ if (cpy > must) cpy = must;
271
+ for (i = 0; i < cpy; i++) {
272
+ use_v[i] = given_v[i];
273
+ }
274
+ }
275
+ for (i = cpy; i < must; i++) {
276
+ use_v[i] = Qnil;
277
+ }
278
+
279
+ if (post_len || opt_len) {
280
+ int rsize = given_c > must ? given_c - must : 0; /* # of arguments which did not consumed yet */
281
+ int psize = rsize > post_len ? post_len : rsize; /* # of post arguments */
282
+ int osize = 0; /* # of opt arguments */
283
+ VALUE ary;
284
+
285
+ /* reserves arguments for post parameters */
286
+ rsize -= psize;
287
+
288
+ if (opt_len) {
289
+ if (rsize >= opt_len) {
290
+ osize = opt_len;
291
+ num = must + opt_len;
292
+ for (i = must; i < num; i++) {
293
+ use_v[i] = given_v[i];
294
+ }
295
+ } else {
296
+ osize = rsize;
297
+ num = must + rsize;
298
+ for (i = must; i < num; i++) {
299
+ use_v[i] = given_v[i];
300
+ }
301
+ for (i = num; i < must + opt_len; i++) {
302
+ use_v[i] = Qundef;
303
+ }
304
+ }
305
+ }
306
+ rsize -= osize;
307
+
308
+ if (rest_index == -1) {
309
+ /* copy post argument */
310
+ MEMMOVE(&use_v[post_start], &given_v[must + osize], VALUE, psize);
311
+ } else {
312
+ ary = rb_ary_new4(rsize, &given_v[rest_index]);
313
+
314
+ /* copy post argument */
315
+ MEMMOVE(&use_v[post_start], &given_v[must + rsize + osize], VALUE, psize);
316
+ use_v[rest_index] = ary;
317
+ }
318
+
319
+ for (i = psize; i < post_len; i++) {
320
+ use_v[post_start + i] = Qnil;
321
+ }
322
+ } else {
323
+ /* not opts and post_index */
324
+ if (rest_index != -1) {
325
+ if (given_c < rest_index) {
326
+ for (i = given_c; i < rest_index; i++) {
327
+ use_v[i] = Qnil;
328
+ }
329
+ use_v[rest_index] = rb_ary_new();
330
+ } else {
331
+ use_v[rest_index] = rb_ary_new4(given_c - rest_index, &given_v[rest_index]);
332
+ }
333
+ }
334
+ }
335
+
336
+ #if 0
337
+ if (block_index != -1) {
338
+ VALUE procval;
339
+
340
+ if (rb_block_given_p()) {
341
+ procval = rb_block_proc();
342
+ } else {
343
+ procval = Qnil;
344
+ }
345
+ use_v[block_index] = procval;
346
+ }
347
+ #endif
348
+
349
+ return num;
350
+ }
351
+
352
+ /* Fixnum#times */
353
+ typedef struct cast_off_Fixnum_times_struct {
354
+ long fin;
355
+ long index;
356
+ } cast_off_Fixnum_times_t;
357
+
358
+ static inline VALUE
359
+ cast_off_Fixnum_times_prep(cast_off_Fixnum_times_t *key, VALUE recv, int prep_argc, ...)
360
+ {
361
+ int i;
362
+ VALUE ret;
363
+
364
+ if (prep_argc != 0) {
365
+ rb_raise(rb_eArgError, "invalid argument");
366
+ }
367
+
368
+ key->fin = FIX2LONG(recv);
369
+ key->index = 0;
370
+
371
+ return recv;
372
+ }
373
+
374
+ static inline VALUE
375
+ cast_off_Fixnum_times_loop(cast_off_Fixnum_times_t *key, VALUE val, int argc, VALUE *argv, int splat, int must, int post_len, int post_start, int rest_index)
376
+ {
377
+ int i;
378
+ long fin = key->fin;
379
+ long index = key->index;
380
+
381
+ if (index < fin) {
382
+ for (i = 0; i < argc; i++) {
383
+ if (i == 0) {
384
+ argv[0] = LONG2FIX(index);
385
+ } else {
386
+ argv[i] = Qnil;
387
+ }
388
+ }
389
+ key->index = index + 1;
390
+ return Qtrue;
391
+ } else {
392
+ return Qfalse;
393
+ }
394
+ }
395
+
396
+ static inline VALUE
397
+ cast_off_Fixnum_times_finl(cast_off_Fixnum_times_t *key)
398
+ {
399
+ return LONG2FIX(key->fin);
400
+ }
401
+
402
+ deoptimization_function_begin(Fixnum, times) {
403
+ while(key->index < key->fin) {
404
+ rb_yield(LONG2FIX(key->index));
405
+ key->index++;
406
+ }
407
+ return LONG2FIX(key->fin);
408
+ };
409
+ deoptimization_function_end(Fixnum, times);
410
+ define_deoptimization_iseq_fetch_function(Fixnum, times);
411
+ define_frame_construction_function(Fixnum, times);
412
+
413
+ /* Array#map */
414
+ typedef struct cast_off_Array_map_struct {
415
+ VALUE recv;
416
+ long index;
417
+ VALUE ret;
418
+ } cast_off_Array_map_t;
419
+
420
+ static inline VALUE
421
+ cast_off_Array_map_prep(cast_off_Array_map_t *key, VALUE recv, int prep_argc, ...)
422
+ {
423
+ VALUE ret;
424
+
425
+ if (prep_argc != 0) {
426
+ rb_raise(rb_eArgError, "invalid argument");
427
+ }
428
+
429
+ ret = rb_ary_new2(RARRAY_LEN(recv));
430
+
431
+ key->recv = recv;
432
+ key->index = 0;
433
+ key->ret = ret;
434
+
435
+ return ret;
436
+ }
437
+
438
+ static inline VALUE
439
+ cast_off_Array_map_loop(cast_off_Array_map_t *key, VALUE val, int argc, VALUE *argv, int splat, int must, int post_len, int post_start, int rest_index)
440
+ {
441
+ int i;
442
+ VALUE recv = key->recv;
443
+ long index = key->index;
444
+
445
+ if (index > 0) {
446
+ rb_ary_push(key->ret, val);
447
+ }
448
+
449
+ if (index < RARRAY_LEN(recv)) {
450
+ VALUE v[1];
451
+
452
+ v[0] = RARRAY_PTR(recv)[index];
453
+ cast_off_prepare_iter_api_block_args(argc, argv, 1, v, splat, must, 0, post_len, post_start, rest_index);
454
+ key->index = index + 1;
455
+ return Qtrue;
456
+ } else {
457
+ return Qfalse;
458
+ }
459
+ }
460
+
461
+ static inline VALUE
462
+ cast_off_Array_map_finl(cast_off_Array_map_t *key)
463
+ {
464
+ return key->ret;
465
+ }
466
+
467
+ deoptimization_function_begin(Array, map) {
468
+ while (key->index < RARRAY_LEN(key->recv)) {
469
+ rb_ary_push(key->ret, rb_yield(RARRAY_PTR(key->recv)[key->index]));
470
+ key->index++;
471
+ }
472
+ return key->ret;
473
+ };
474
+ deoptimization_function_end(Array, map);
475
+ define_deoptimization_iseq_fetch_function(Array, map);
476
+ define_frame_construction_function(Array, map);
477
+
478
+ /* Array#map! */
479
+ typedef struct cast_off_Array_map_bang_struct {
480
+ VALUE recv;
481
+ long index;
482
+ } cast_off_Array_map_bang_t;
483
+
484
+ static inline VALUE
485
+ cast_off_Array_map_bang_prep(cast_off_Array_map_bang_t *key, VALUE recv, int prep_argc, ...)
486
+ {
487
+ if (prep_argc != 0) {
488
+ rb_raise(rb_eArgError, "invalid argument");
489
+ }
490
+
491
+ rb_ary_modify(recv);
492
+
493
+ key->recv = recv;
494
+ key->index = 0;
495
+
496
+ return recv;
497
+ }
498
+
499
+ static inline VALUE
500
+ cast_off_Array_map_bang_loop(cast_off_Array_map_bang_t *key, VALUE val, int argc, VALUE *argv, int splat, int must, int post_len, int post_start, int rest_index)
501
+ {
502
+ int i;
503
+ VALUE recv = key->recv;
504
+ long index = key->index;
505
+
506
+ if (index > 0) {
507
+ rb_ary_store(recv, index - 1, val);
508
+ }
509
+
510
+ if (index < RARRAY_LEN(recv)) {
511
+ VALUE v[1];
512
+
513
+ v[0] = RARRAY_PTR(recv)[index];
514
+ cast_off_prepare_iter_api_block_args(argc, argv, 1, v, splat, must, 0, post_len, post_start, rest_index);
515
+ key->index = index + 1;
516
+ return Qtrue;
517
+ } else {
518
+ return Qfalse;
519
+ }
520
+ }
521
+
522
+ static inline VALUE
523
+ cast_off_Array_map_bang_finl(cast_off_Array_map_bang_t *key)
524
+ {
525
+ return key->recv;
526
+ }
527
+
528
+ deoptimization_function_begin(Array, map_bang) {
529
+ while (key->index < RARRAY_LEN(key->recv)) {
530
+ rb_ary_store(key->recv, key->index, rb_yield(RARRAY_PTR(key->recv)[key->index]));
531
+ key->index++;
532
+ }
533
+ return key->recv;
534
+ };
535
+ deoptimization_function_end(Array, map_bang);
536
+ define_deoptimization_iseq_fetch_function(Array, map_bang);
537
+ define_frame_construction_function(Array, map_bang);
538
+
539
+ /* Array#each */
540
+ typedef struct cast_off_Array_each_struct {
541
+ VALUE recv;
542
+ long index;
543
+ } cast_off_Array_each_t;
544
+
545
+ static inline VALUE
546
+ cast_off_Array_each_prep(cast_off_Array_each_t *key, VALUE recv, int prep_argc, ...)
547
+ {
548
+ int i;
549
+
550
+ if (prep_argc != 0) {
551
+ rb_raise(rb_eArgError, "invalid argument");
552
+ }
553
+
554
+ key->recv = recv;
555
+ key->index = 0;
556
+
557
+ return recv;
558
+ }
559
+
560
+ static inline VALUE
561
+ cast_off_Array_each_loop(cast_off_Array_each_t *key, VALUE val, int argc, VALUE *argv, int splat, int must, int post_len, int post_start, int rest_index)
562
+ {
563
+ int i;
564
+ VALUE recv = key->recv;
565
+ long index = key->index;
566
+
567
+ if (index < RARRAY_LEN(recv)) {
568
+ VALUE v[1];
569
+
570
+ v[0] = RARRAY_PTR(recv)[index];
571
+ cast_off_prepare_iter_api_block_args(argc, argv, 1, v, splat, must, 0, post_len, post_start, rest_index);
572
+ key->index = index + 1;
573
+ return Qtrue;
574
+ } else {
575
+ return Qfalse;
576
+ }
577
+ }
578
+
579
+ static inline VALUE
580
+ cast_off_Array_each_finl(cast_off_Array_each_t *key)
581
+ {
582
+ return key->recv;
583
+ }
584
+
585
+ deoptimization_function_begin(Array, each) {
586
+ while (key->index < RARRAY_LEN(key->recv)) {
587
+ rb_yield(RARRAY_PTR(key->recv)[key->index]);
588
+ key->index++;
589
+ }
590
+ return key->recv;
591
+ };
592
+ deoptimization_function_end(Array, each);
593
+ define_deoptimization_iseq_fetch_function(Array, each);
594
+ define_frame_construction_function(Array, each);
595
+