cast_off 0.3.6 → 0.3.7
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.
- data/bin/cast_off +1 -1
- data/cast_off.gemspec +5 -3
- data/doc/about.pdf +0 -0
- data/ext/cast_off/cast_off.c.rb +124 -52
- data/lib/cast_off/compile/code_manager.rb +18 -3
- data/lib/cast_off/compile/configuration.rb +23 -15
- data/lib/cast_off/compile/dependency.rb +60 -46
- data/lib/cast_off/compile/ir/call_ir.rb +20 -23
- data/lib/cast_off/compile/translator.rb +25 -8
- data/lib/cast_off/compile.rb +34 -27
- metadata +6 -7
data/bin/cast_off
CHANGED
data/cast_off.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |spec|
|
2
2
|
spec.name = "cast_off"
|
3
|
-
spec.version = "0.3.
|
3
|
+
spec.version = "0.3.7"
|
4
4
|
spec.platform = Gem::Platform::RUBY
|
5
5
|
spec.summary = "Compiler for Ruby1.9.3"
|
6
6
|
spec.description = <<-EOS
|
@@ -8,15 +8,17 @@ CastOff is a compiler for Ruby1.9.3.
|
|
8
8
|
Command line tool cast_off is available after installation.
|
9
9
|
See 'cast_off --help' for more information.
|
10
10
|
EOS
|
11
|
-
spec.files = Dir['{lib/**/*,ext/**/*}'] + %w[
|
11
|
+
spec.files = Dir['{lib/**/*,ext/**/*,bin/**/*,doc/**/*}'] + %w[
|
12
12
|
cast_off.gemspec
|
13
|
+
README.en
|
14
|
+
README
|
13
15
|
]
|
14
16
|
spec.bindir = 'bin'
|
15
17
|
spec.executables << 'cast_off'
|
16
18
|
spec.require_path = 'lib'
|
17
19
|
spec.extensions = 'ext/cast_off/extconf.rb'
|
18
20
|
spec.has_rdoc = false
|
19
|
-
spec.extra_rdoc_files = ['README', 'README.en']
|
21
|
+
#spec.extra_rdoc_files = ['README', 'README.en']
|
20
22
|
#spec.test_files = Dir['test/*']
|
21
23
|
spec.author = 'Satoshi Shiba'
|
22
24
|
spec.email = 'shiba@rvm.jp'
|
data/doc/about.pdf
ADDED
Binary file
|
data/ext/cast_off/cast_off.c.rb
CHANGED
@@ -61,6 +61,7 @@ VALUE rb_cCastOffSingletonClass;
|
|
61
61
|
VALUE rb_cCastOffClassWrapper;
|
62
62
|
VALUE rb_cCastOffMethodWrapper;
|
63
63
|
VALUE rb_cCastOffModuleWrapper;
|
64
|
+
VALUE oMain, cDumpMain;
|
64
65
|
|
65
66
|
static VALUE
|
66
67
|
gen_headers(void)
|
@@ -238,6 +239,8 @@ cast_off_instruction_stack_usage(VALUE self, VALUE insns)
|
|
238
239
|
return INT2FIX(insn_stack_increase(0, insn, opes));
|
239
240
|
}
|
240
241
|
|
242
|
+
|
243
|
+
static int class_wrapper_support(VALUE obj, VALUE is_wrap);
|
241
244
|
static VALUE
|
242
245
|
cast_off_instruction_class_information_in_ic(VALUE self, VALUE iseqval)
|
243
246
|
{
|
@@ -301,8 +304,7 @@ cast_off_instruction_class_information_in_ic(VALUE self, VALUE iseqval)
|
|
301
304
|
|
302
305
|
if (FL_TEST(klass, FL_SINGLETON)) {
|
303
306
|
VALUE obj = rb_iv_get(klass, "__attached__");
|
304
|
-
|
305
|
-
if (__klass != rb_cClass && __klass != rb_cModule) {
|
307
|
+
if (rb_class_of(obj) != klass || !class_wrapper_support(obj, Qfalse)) {
|
306
308
|
return Qnil;
|
307
309
|
}
|
308
310
|
return rb_funcall(rb_cCastOffClassWrapper, rb_intern("new"), 2, obj, Qfalse);
|
@@ -447,6 +449,23 @@ static VALUE cast_off_get_iseq(VALUE self, VALUE obj, VALUE mid, VALUE singleton
|
|
447
449
|
rb_raise(rb_eCastOffUnsupportedError, "%s (%s#%s)", msg, RSTRING_PTR(name), rb_id2name(SYM2ID(mid)));
|
448
450
|
}
|
449
451
|
|
452
|
+
static VALUE cast_off_get_compilable_iseq(VALUE self, VALUE obj, VALUE mid, VALUE singleton_p)
|
453
|
+
{
|
454
|
+
rb_method_entry_t *me;
|
455
|
+
VALUE km = (RTEST(singleton_p)) ? rb_class_of(obj) : obj;
|
456
|
+
|
457
|
+
me = search_method(km, SYM2ID(mid));
|
458
|
+
if (!me) {
|
459
|
+
return Qnil;
|
460
|
+
}
|
461
|
+
|
462
|
+
if (me->def->type == VM_METHOD_TYPE_ISEQ) {
|
463
|
+
return me->def->body.iseq->self;
|
464
|
+
} else {
|
465
|
+
return Qnil;
|
466
|
+
}
|
467
|
+
}
|
468
|
+
|
450
469
|
static VALUE cast_off_get_iseq_from_block(VALUE self, VALUE block)
|
451
470
|
{
|
452
471
|
rb_iseq_t *iseq;
|
@@ -471,7 +490,7 @@ static VALUE cast_off_get_iseq_line(VALUE self, VALUE iseqval)
|
|
471
490
|
rb_iseq_t *iseq;
|
472
491
|
|
473
492
|
if (rb_class_of(iseqval) != rb_cISeq) {
|
474
|
-
rb_bug("
|
493
|
+
rb_bug("cast_off_get_iseq_line: shoult not be reached");
|
475
494
|
}
|
476
495
|
|
477
496
|
iseq = DATA_PTR(iseqval);
|
@@ -484,7 +503,7 @@ static VALUE cast_off_get_iseq_filepath(VALUE self, VALUE iseqval)
|
|
484
503
|
rb_iseq_t *iseq;
|
485
504
|
|
486
505
|
if (rb_class_of(iseqval) != rb_cISeq) {
|
487
|
-
rb_bug("
|
506
|
+
rb_bug("cast_off_get_iseq_filepath: shoult not be reached");
|
488
507
|
}
|
489
508
|
|
490
509
|
iseq = DATA_PTR(iseqval);
|
@@ -567,13 +586,16 @@ static VALUE cast_off_initialize_class_wrapper(VALUE self, VALUE obj, VALUE is_w
|
|
567
586
|
|
568
587
|
switch(is_wrap) {
|
569
588
|
case Qtrue:
|
589
|
+
if (rb_obj_class(obj) != rb_cClass) {
|
590
|
+
rb_bug("ClassWrapper#initialize: should not be reached(0)");
|
591
|
+
}
|
570
592
|
wrap = 1;
|
571
593
|
break;
|
572
594
|
case Qfalse:
|
573
595
|
wrap = 0;
|
574
596
|
break;
|
575
597
|
default:
|
576
|
-
rb_bug("ClassWrapper#initialize: should not be reached");
|
598
|
+
rb_bug("ClassWrapper#initialize: should not be reached(1)");
|
577
599
|
}
|
578
600
|
|
579
601
|
if (wrap) {
|
@@ -654,14 +676,10 @@ static VALUE cast_off_class_wrapper_singleton_p(VALUE self)
|
|
654
676
|
VALUE obj = wrapper->obj;
|
655
677
|
|
656
678
|
if (FL_TEST(klass, FL_SINGLETON)) {
|
657
|
-
|
658
|
-
if (__klass == rb_cClass) {
|
679
|
+
if (class_wrapper_support(obj, Qfalse)) {
|
659
680
|
return Qtrue;
|
660
|
-
} else if (__klass == rb_cModule) {
|
661
|
-
return Qtrue;
|
662
|
-
} else {
|
663
|
-
rb_raise(rb_eCastOffCompileError, "CastOff can't handle singleton object without Class and Module");
|
664
681
|
}
|
682
|
+
rb_raise(rb_eCastOffCompileError, "CastOff can't handle un-marshalable object");
|
665
683
|
} else {
|
666
684
|
return Qfalse;
|
667
685
|
}
|
@@ -674,14 +692,17 @@ static VALUE cast_off_class_wrapper_to_s(VALUE self)
|
|
674
692
|
VALUE obj = wrapper->obj;
|
675
693
|
|
676
694
|
if (FL_TEST(klass, FL_SINGLETON)) {
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
695
|
+
if (class_wrapper_support(obj, Qfalse)) {
|
696
|
+
VALUE __klass = rb_obj_class(obj);
|
697
|
+
if (__klass == rb_cClass) {
|
698
|
+
return rb_class_path(obj);
|
699
|
+
} else if (__klass == rb_cModule) {
|
700
|
+
return rb_mod_name(obj);
|
701
|
+
} else {
|
702
|
+
return rb_funcall(obj, rb_intern("to_s"), 0);
|
703
|
+
}
|
684
704
|
}
|
705
|
+
rb_raise(rb_eCastOffCompileError, "CastOff can't handle un-marshalable object");
|
685
706
|
} else {
|
686
707
|
return rb_class_path(klass);
|
687
708
|
}
|
@@ -696,7 +717,17 @@ static VALUE cast_off_class_wrapper_marshal_dump(VALUE self)
|
|
696
717
|
rb_ary_push(ary, rb_class_path(wrapper->klass));
|
697
718
|
rb_ary_push(ary, Qtrue);
|
698
719
|
} else {
|
699
|
-
|
720
|
+
VALUE obj = wrapper->obj;
|
721
|
+
|
722
|
+
if (!class_wrapper_support(obj, Qfalse)) {
|
723
|
+
rb_bug("cast_off_class_wrapper_marshal_dump: should not be reached");
|
724
|
+
}
|
725
|
+
|
726
|
+
if (obj == oMain) {
|
727
|
+
rb_ary_push(ary, cDumpMain);
|
728
|
+
} else {
|
729
|
+
rb_ary_push(ary, obj);
|
730
|
+
}
|
700
731
|
rb_ary_push(ary, Qfalse);
|
701
732
|
}
|
702
733
|
|
@@ -710,6 +741,10 @@ static VALUE cast_off_class_wrapper_marshal_load(VALUE self, VALUE ary)
|
|
710
741
|
|
711
742
|
if (is_wrap == Qtrue) {
|
712
743
|
obj = rb_path_to_class(obj);
|
744
|
+
} else {
|
745
|
+
if (obj == cDumpMain) {
|
746
|
+
obj = oMain;
|
747
|
+
}
|
713
748
|
}
|
714
749
|
|
715
750
|
return cast_off_initialize_class_wrapper(self, obj, is_wrap);
|
@@ -863,6 +898,35 @@ static VALUE cast_off_class_wrapper_each_method_search_target(VALUE self, VALUE
|
|
863
898
|
return Qtrue;
|
864
899
|
}
|
865
900
|
|
901
|
+
static int class_wrapper_support(VALUE obj, VALUE is_wrap)
|
902
|
+
{
|
903
|
+
VALUE klass = rb_obj_class(obj);
|
904
|
+
|
905
|
+
if (RTEST(is_wrap)) {
|
906
|
+
return klass == rb_cClass;
|
907
|
+
}
|
908
|
+
|
909
|
+
if (klass == rb_cClass || klass == rb_cModule) {
|
910
|
+
return 1;
|
911
|
+
}
|
912
|
+
|
913
|
+
klass == rb_class_of(obj);
|
914
|
+
if (!FL_TEST(klass, FL_SINGLETON)) {
|
915
|
+
return 1;
|
916
|
+
}
|
917
|
+
|
918
|
+
if (obj == oMain) {
|
919
|
+
return 1;
|
920
|
+
}
|
921
|
+
|
922
|
+
return 0;
|
923
|
+
}
|
924
|
+
|
925
|
+
static VALUE cast_off_class_wrapper_s_support_p(VALUE self, VALUE obj, VALUE is_wrap)
|
926
|
+
{
|
927
|
+
return class_wrapper_support(obj, is_wrap) ? Qtrue : Qfalse;
|
928
|
+
}
|
929
|
+
|
866
930
|
#define define_type_checker(klass) \
|
867
931
|
static VALUE cast_off_class_wrapper_##klass##_p(VALUE self) \
|
868
932
|
{ \
|
@@ -1360,8 +1424,8 @@ static VALUE cast_off_hook_method_invocation(VALUE self, VALUE proc)
|
|
1360
1424
|
return Qtrue;
|
1361
1425
|
}
|
1362
1426
|
|
1363
|
-
static ID
|
1364
|
-
VALUE cast_off_ignore_overridden_p(VALUE dummy
|
1427
|
+
static ID id_initialize_copy, id_clone;
|
1428
|
+
VALUE cast_off_ignore_overridden_p(VALUE dummy)
|
1365
1429
|
{
|
1366
1430
|
VALUE thval = rb_thread_current();
|
1367
1431
|
rb_thread_t *th = DATA_PTR(thval);
|
@@ -1369,12 +1433,11 @@ VALUE cast_off_ignore_overridden_p(VALUE dummy, VALUE target, VALUE midsym)
|
|
1369
1433
|
ID mid;
|
1370
1434
|
|
1371
1435
|
cfp = th->cfp; /* this method frame */
|
1372
|
-
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); /* method_added or singleton_method_added frame */
|
1436
|
+
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); /* method_added or singleton_method_added or include or extend frame */
|
1373
1437
|
if (!cfp->me) {
|
1374
1438
|
rb_bug("cast_off_ignore_overridden_p: should not be reached(0)");
|
1375
1439
|
}
|
1376
|
-
|
1377
|
-
if (mid != id_method_added && mid != id_singleton_method_added) {
|
1440
|
+
if (cfp->me->def->type != VM_METHOD_TYPE_BMETHOD) {
|
1378
1441
|
rb_bug("cast_off_ignore_overridden_p: should not be reached(1)");
|
1379
1442
|
}
|
1380
1443
|
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
|
@@ -1393,7 +1456,7 @@ VALUE cast_off_ignore_overridden_p(VALUE dummy, VALUE target, VALUE midsym)
|
|
1393
1456
|
return Qtrue;
|
1394
1457
|
}
|
1395
1458
|
|
1396
|
-
VALUE
|
1459
|
+
VALUE cast_off_current_method_id(VALUE dummy)
|
1397
1460
|
{
|
1398
1461
|
VALUE thval = rb_thread_current();
|
1399
1462
|
rb_thread_t *th = DATA_PTR(thval);
|
@@ -1401,42 +1464,49 @@ VALUE cast_off_singleton_method_added_p(VALUE dummy)
|
|
1401
1464
|
ID mid;
|
1402
1465
|
|
1403
1466
|
cfp = th->cfp; /* this method frame */
|
1404
|
-
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); /*
|
1467
|
+
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); /* target frame */
|
1405
1468
|
if (!cfp->me) {
|
1406
|
-
rb_bug("
|
1469
|
+
rb_bug("cast_off_current_method_id: should not be reached(0)");
|
1407
1470
|
}
|
1408
|
-
|
1409
|
-
|
1410
|
-
return Qfalse;
|
1471
|
+
if (cfp->me->def->type != VM_METHOD_TYPE_BMETHOD) {
|
1472
|
+
rb_bug("cast_off_current_method_id: should not be reached(1)");
|
1411
1473
|
}
|
1412
|
-
|
1413
|
-
|
1474
|
+
mid = cfp->me->called_id;
|
1475
|
+
if (!mid) {
|
1476
|
+
rb_bug("cast_off_current_method_id: should not be reached(2)");
|
1414
1477
|
}
|
1415
|
-
|
1478
|
+
return ID2SYM(mid);
|
1416
1479
|
}
|
1417
1480
|
|
1418
|
-
|
1419
|
-
VALUE cast_off_extend_p(VALUE dummy)
|
1481
|
+
VALUE cast_off_same_method_p(VALUE dummy, VALUE obj, VALUE mid)
|
1420
1482
|
{
|
1483
|
+
VALUE klass = rb_class_of(obj);
|
1421
1484
|
VALUE thval = rb_thread_current();
|
1422
1485
|
rb_thread_t *th = DATA_PTR(thval);
|
1423
1486
|
rb_control_frame_t *cfp;
|
1424
|
-
|
1487
|
+
rb_method_entry_t *me0, *me1;
|
1425
1488
|
|
1426
1489
|
cfp = th->cfp; /* this method frame */
|
1427
|
-
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); /*
|
1490
|
+
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); /* target frame */
|
1428
1491
|
if (!cfp->me) {
|
1429
|
-
rb_bug("
|
1492
|
+
rb_bug("cast_off_same_method_p: should not be reached(0)");
|
1430
1493
|
}
|
1431
|
-
|
1432
|
-
|
1433
|
-
return Qfalse;
|
1494
|
+
if (cfp->me->def->type != VM_METHOD_TYPE_BMETHOD) {
|
1495
|
+
rb_bug("cast_off_same_method_p: should not be reached(1)");
|
1434
1496
|
}
|
1435
|
-
|
1497
|
+
|
1498
|
+
me0 = cfp->me;
|
1499
|
+
me1 = search_method(klass, SYM2ID(mid));
|
1500
|
+
|
1501
|
+
if (!me1) {
|
1502
|
+
rb_bug("cast_off_same_method_p: should not be reached(2)");
|
1503
|
+
}
|
1504
|
+
|
1505
|
+
if (rb_method_definition_eq(me0->def, me1->def)) {
|
1436
1506
|
return Qtrue;
|
1507
|
+
} else {
|
1508
|
+
return Qfalse;
|
1437
1509
|
}
|
1438
|
-
/* TODO 別名に対応 */
|
1439
|
-
rb_bug("cast_off_extend_p: should not be reached(1)");
|
1440
1510
|
}
|
1441
1511
|
|
1442
1512
|
/* for deoptimization */
|
@@ -1463,7 +1533,8 @@ void Init_cast_off(void)
|
|
1463
1533
|
rb_eCastOffLoadError = rb_define_class_under(rb_mCastOff, "LoadError", rb_eStandardError);
|
1464
1534
|
rb_eCastOffUnsupportedError = rb_define_class_under(rb_mCastOff, "UnsupportedError", rb_eStandardError);
|
1465
1535
|
rb_define_method(rb_mCastOffCompiler, "override_target", cast_off_override_target, 2);
|
1466
|
-
rb_define_method(rb_mCastOffCompiler, "get_iseq", cast_off_get_iseq, 3);
|
1536
|
+
rb_define_method(rb_mCastOffCompiler, "get_iseq", cast_off_get_iseq, 3); /* TODO rename => get_compilable_iseq! */
|
1537
|
+
rb_define_method(rb_mCastOffCompiler, "get_compilable_iseq", cast_off_get_compilable_iseq, 3);
|
1467
1538
|
rb_define_method(rb_mCastOffCompiler, "get_iseq_from_block", cast_off_get_iseq_from_block, 1);
|
1468
1539
|
rb_define_method(rb_mCastOffCompiler, "get_iseq_filepath", cast_off_get_iseq_filepath, 1);
|
1469
1540
|
rb_define_method(rb_mCastOffCompiler, "get_iseq_line", cast_off_get_iseq_line, 1);
|
@@ -1471,6 +1542,8 @@ void Init_cast_off(void)
|
|
1471
1542
|
rb_define_method(rb_mCastOffCompiler, "get_caller", cast_off_get_caller, 0);
|
1472
1543
|
rb_define_method(rb_mCastOffCompiler, "hook_method_invocation", cast_off_hook_method_invocation, 1);
|
1473
1544
|
rb_define_method(rb_mCastOffCompiler, "hook_class_definition_end", cast_off_hook_class_definition_end, 1);
|
1545
|
+
rb_define_method(rb_mCastOffCompiler, "current_method_id", cast_off_current_method_id, 0);
|
1546
|
+
rb_define_method(rb_mCastOffCompiler, "same_method?", cast_off_same_method_p, 2);
|
1474
1547
|
rb_define_method(rb_mCastOffCompilerInstruction, "get_child_iseq", cast_off_get_child_iseq, 2);
|
1475
1548
|
rb_define_const(rb_mCastOffCompilerInstruction, "ROBJECT_EMBED_LEN_MAX", LONG2FIX(ROBJECT_EMBED_LEN_MAX));
|
1476
1549
|
rb_define_const(rb_mCastOffCompilerInstruction, "THROW_TAG_RETURN", LONG2FIX(TAG_RETURN));
|
@@ -1523,6 +1596,7 @@ void Init_cast_off(void)
|
|
1523
1596
|
rb_define_method(rb_cCastOffClassWrapper, "Array?", cast_off_class_wrapper_Array_p, 0);
|
1524
1597
|
rb_define_method(rb_cCastOffClassWrapper, "Fixnum?", cast_off_class_wrapper_Fixnum_p, 0);
|
1525
1598
|
rb_define_method(rb_cCastOffClassWrapper, "Float?", cast_off_class_wrapper_Float_p, 0);
|
1599
|
+
rb_define_singleton_method(rb_cCastOffClassWrapper, "support?", cast_off_class_wrapper_s_support_p, 2);
|
1526
1600
|
|
1527
1601
|
rb_define_alloc_func(rb_cCastOffModuleWrapper, cast_off_allocate_module_wrapper);
|
1528
1602
|
rb_define_method(rb_cCastOffModuleWrapper, "initialize", cast_off_initialize_module_wrapper, 1);
|
@@ -1547,19 +1621,17 @@ void Init_cast_off(void)
|
|
1547
1621
|
rb_define_const(rb_mCastOffCompiler, "Headers", gen_headers());
|
1548
1622
|
rb_define_const(rb_mCastOffCompiler, "DEOPTIMIZATION_ISEQ_TABLE", rb_hash_new());
|
1549
1623
|
|
1550
|
-
id_method_added = rb_intern("method_added");
|
1551
|
-
id_singleton_method_added = rb_intern("singleton_method_added");
|
1552
|
-
id_include = rb_intern("include");
|
1553
|
-
id_extend = rb_intern("extend");
|
1554
1624
|
id_initialize_copy = rb_intern("initialize_copy");
|
1555
1625
|
id_clone = rb_intern("clone");
|
1556
|
-
rb_define_singleton_method(rb_cCastOffDependency, "ignore_overridden?", cast_off_ignore_overridden_p,
|
1557
|
-
rb_define_singleton_method(rb_cCastOffDependency, "singleton_method_added?", cast_off_singleton_method_added_p, 0);
|
1558
|
-
rb_define_singleton_method(rb_cCastOffDependency, "extend?", cast_off_extend_p, 0);
|
1626
|
+
rb_define_singleton_method(rb_cCastOffDependency, "ignore_overridden?", cast_off_ignore_overridden_p, 0);
|
1559
1627
|
|
1560
1628
|
rb_define_singleton_method(rb_mCastOffCompiler, "destroy_last_finish", cast_off_destroy_last_finish, 0);
|
1561
1629
|
rb_funcall(rb_mCastOffCompiler, rb_intern("module_eval"), 1, rb_str_new2("def self.vm_exec(); destroy_last_finish() end"));
|
1562
1630
|
|
1631
|
+
oMain = rb_funcall(rb_mKernel, rb_intern("eval"), 2, rb_str_new2("self"), rb_const_get(rb_cObject, rb_intern("TOPLEVEL_BINDING")));
|
1632
|
+
rb_define_const(rb_mCastOffCompiler, "MAIN", oMain);
|
1633
|
+
cDumpMain = rb_define_class_under(rb_cCastOffClassWrapper, "DumpMain", rb_cObject);
|
1634
|
+
|
1563
1635
|
init_insn_table();
|
1564
1636
|
}
|
1565
1637
|
|
@@ -27,14 +27,18 @@ module CastOff
|
|
27
27
|
FileUtils.mkdir(BaseDir) unless File.exist?(BaseDir)
|
28
28
|
|
29
29
|
@@program_name = File.basename($PROGRAM_NAME)
|
30
|
+
@@program_sign = generate_signiture(@@program_name)
|
30
31
|
CastOff::Compiler.class_eval do
|
31
|
-
def program_name=(
|
32
|
-
CastOff::Compiler::CodeManager.
|
32
|
+
def program_name=(name)
|
33
|
+
sign = CastOff::Compiler::CodeManager.generate_signiture(name)
|
34
|
+
CastOff::Compiler::CodeManager.class_variable_set(:@@program_sign, sign)
|
35
|
+
CastOff::Compiler::CodeManager.class_variable_set(:@@program_name, name)
|
36
|
+
name
|
33
37
|
end
|
34
38
|
end
|
35
39
|
|
36
40
|
def self.program_dir()
|
37
|
-
dir = "#{BaseDir}/#{
|
41
|
+
dir = "#{BaseDir}/#{@@program_sign}"
|
38
42
|
FileUtils.mkdir(dir) unless File.exist?(dir)
|
39
43
|
dir
|
40
44
|
end
|
@@ -54,6 +58,12 @@ module CastOff
|
|
54
58
|
return true
|
55
59
|
end
|
56
60
|
|
61
|
+
def self.compiled_method_exist?(filepath, line_no)
|
62
|
+
return false unless filepath && line_no >= 0
|
63
|
+
base_sign = generate_signiture("#{filepath}_#{line_no}")
|
64
|
+
File.exist?("#{BaseDir}/#{@@program_sign}/#{base_sign}/loadable")
|
65
|
+
end
|
66
|
+
|
57
67
|
@@compiled_methods_fetch_str = nil
|
58
68
|
@@compiled_methods_load_str = nil
|
59
69
|
def self.load_autocompiled()
|
@@ -156,6 +166,7 @@ Max length of signiture is #{FILEPATH_LIMIT} in this environment.
|
|
156
166
|
@annotation_path = "#{@dstdir}/#{@signiture}.ann"
|
157
167
|
@development_mark_file = "development"
|
158
168
|
@development_mark_path = "#{@dstdir}/#{@development_mark_file}"
|
169
|
+
@loadable_mark_path = "#{@dstdir}/loadable"
|
159
170
|
@dstbin = "#{@dstdir}/#{@signiture}.#{CONFIG['DLEXT']}"
|
160
171
|
@longpath = @base_configuration_path # FIXME
|
161
172
|
check_length()
|
@@ -264,6 +275,10 @@ Failed to compile c source: status = (#{$?})
|
|
264
275
|
FileUtils.touch(@development_mark_path) if conf.development?
|
265
276
|
end
|
266
277
|
|
278
|
+
def loadable()
|
279
|
+
FileUtils.touch(@loadable_mark_path)
|
280
|
+
end
|
281
|
+
|
267
282
|
def save_base_configuration(conf)
|
268
283
|
begin
|
269
284
|
File.open(@base_configuration_path, 'wb:us-ascii') do |f|
|
@@ -304,7 +304,7 @@ o = Object
|
|
304
304
|
# annotation of variables
|
305
305
|
a0 = v
|
306
306
|
a0 = a0.map{|(c, singleton_p)|
|
307
|
-
bug(c) unless
|
307
|
+
bug(c) unless ClassWrapper.support?(c, !singleton_p)
|
308
308
|
bug() unless c != SingletonClass
|
309
309
|
if singleton_p
|
310
310
|
wrapper = ClassWrapper.new(c, false)
|
@@ -342,7 +342,7 @@ o = Object
|
|
342
342
|
bug() unless sym == :singleton_methods || sym == :instance_methods
|
343
343
|
bug() unless mtbl.is_a?(Hash)
|
344
344
|
mtbl.each do |(k, v)|
|
345
|
-
bug() unless
|
345
|
+
bug() unless ClassWrapper.support?(k, sym == :instance_methods)
|
346
346
|
bug() unless v.instance_of?(Hash)
|
347
347
|
if k == SingletonClass
|
348
348
|
bug() if sym == :singleton_methods
|
@@ -378,7 +378,7 @@ o = Object
|
|
378
378
|
end
|
379
379
|
next if @ignore_configuration_of_return_values[k] && @ignore_configuration_of_return_values[k].include?(mid)
|
380
380
|
klasses0 = klasses0.map{|(c, singleton_p)|
|
381
|
-
bug(c) unless
|
381
|
+
bug(c) unless ClassWrapper.support?(c, !singleton_p)
|
382
382
|
bug() unless c != SingletonClass
|
383
383
|
if singleton_p
|
384
384
|
wrapper = ClassWrapper.new(c, false)
|
@@ -473,24 +473,14 @@ Currently, CastOff doesn't support object, which cannot marshal dump (e.g. STDIN
|
|
473
473
|
ary = []
|
474
474
|
@variable_configuration.each do |(k, v)|
|
475
475
|
bug() unless k.instance_of?(Symbol)
|
476
|
-
ary << "#{k.inspect} => #{v
|
476
|
+
ary << "#{k.inspect} => #{inspect_class_wrappers(v)}"
|
477
477
|
end
|
478
478
|
@return_value_configuration.each do |(k, v)|
|
479
|
-
|
480
|
-
ary << "#{k.inspect} => #{inspect_method_return_value(v)}"
|
479
|
+
ary << "#{inspect_class_wrapper(k)} => #{inspect_method_return_value(v)}"
|
481
480
|
end
|
482
481
|
"{#{ary.join(",\n ")}}"
|
483
482
|
end
|
484
483
|
|
485
|
-
def inspect_method_return_value(h)
|
486
|
-
bug() unless h.instance_of?(Hash)
|
487
|
-
'{' + h.map{|(mid, classes)|
|
488
|
-
bug() unless mid.instance_of?(Symbol)
|
489
|
-
bug() unless classes.instance_of?(Array)
|
490
|
-
"#{mid.inspect} => #{classes.inspect}"
|
491
|
-
}.join(', ') + '}'
|
492
|
-
end
|
493
|
-
|
494
484
|
DIRECT_CALL_TARGETS = [
|
495
485
|
[BasicObject, :initialize, :class],
|
496
486
|
[BasicObject, :==, :class],
|
@@ -2452,6 +2442,24 @@ Currently, CastOff doesn't support object, which cannot marshal dump (e.g. STDIN
|
|
2452
2442
|
|
2453
2443
|
private
|
2454
2444
|
|
2445
|
+
def inspect_class_wrapper(k)
|
2446
|
+
bug() unless k.instance_of?(ClassWrapper)
|
2447
|
+
k.singleton? ? "SingletonClassOf<#{k.to_s}>" : k.to_s
|
2448
|
+
end
|
2449
|
+
|
2450
|
+
def inspect_class_wrappers(a)
|
2451
|
+
bug() unless a.instance_of?(Array)
|
2452
|
+
a.map{|k| inspect_class_wrapper(k)}.inspect
|
2453
|
+
end
|
2454
|
+
|
2455
|
+
def inspect_method_return_value(h)
|
2456
|
+
bug() unless h.instance_of?(Hash)
|
2457
|
+
'{' + h.map{|(mid, classes)|
|
2458
|
+
bug() unless mid.instance_of?(Symbol)
|
2459
|
+
"#{mid.inspect} => #{inspect_class_wrappers(classes)}"
|
2460
|
+
}.join(', ') + '}'
|
2461
|
+
end
|
2462
|
+
|
2455
2463
|
def __ignore_configuration_of_variables(sign)
|
2456
2464
|
deletes = []
|
2457
2465
|
@ignore_configuration_of_variables.each do |(k, v)|
|
@@ -77,7 +77,7 @@ module CastOff
|
|
77
77
|
end
|
78
78
|
|
79
79
|
def self.singleton_method_depend?(obj, mid)
|
80
|
-
bug() unless
|
80
|
+
bug() unless ClassWrapper.support?(obj, false)
|
81
81
|
dep = @@singleton_method_dependency[obj]
|
82
82
|
return false unless dep
|
83
83
|
return false unless dep.include?(mid)
|
@@ -92,7 +92,7 @@ module CastOff
|
|
92
92
|
end
|
93
93
|
|
94
94
|
def self.singleton_method_strongly_depend?(obj, mid)
|
95
|
-
bug() unless
|
95
|
+
bug() unless ClassWrapper.support?(obj, false)
|
96
96
|
dep = @@singleton_method_strong_dependency[obj]
|
97
97
|
dep.instance_of?(Array) ? dep.include?(mid) : false
|
98
98
|
end
|
@@ -189,8 +189,10 @@ Currently, CastOff doesn't support object, which cannot marshal dump (e.g. STDIN
|
|
189
189
|
end
|
190
190
|
s.class_eval do
|
191
191
|
def override_singleton_method(obj, mid, flag)
|
192
|
+
CastOff.dlog("singleton method added #{obj}.#{mid}")
|
193
|
+
CastOff.delete_original_singleton_method_iseq(self, mid)
|
192
194
|
if initializers = Dependency.singleton_method_depend?(obj, mid)
|
193
|
-
if Dependency.singleton_method_strongly_depend?(obj, mid)
|
195
|
+
if Dependency.singleton_method_strongly_depend?(obj, mid) && !CastOff.method_replacing?
|
194
196
|
raise(ExecutionError.new("Should not be override #{obj}.#{mid}"))
|
195
197
|
end
|
196
198
|
# TODO Array.each の上書きチェック
|
@@ -202,8 +204,10 @@ Currently, CastOff doesn't support object, which cannot marshal dump (e.g. STDIN
|
|
202
204
|
end
|
203
205
|
|
204
206
|
def override_method(obj, mid, flag)
|
207
|
+
CastOff.dlog("method added #{obj}##{mid}")
|
208
|
+
CastOff.delete_original_instance_method_iseq(self, mid)
|
205
209
|
if initializers = Dependency.instance_method_depend?(obj, mid)
|
206
|
-
if Dependency.instance_method_strongly_depend?(obj, mid)
|
210
|
+
if Dependency.instance_method_strongly_depend?(obj, mid) && !CastOff.method_replacing?
|
207
211
|
raise(ExecutionError.new("Should not be override #{obj}##{mid}"))
|
208
212
|
end
|
209
213
|
# TODO Array.each の上書きチェック
|
@@ -214,69 +218,79 @@ Currently, CastOff doesn't support object, which cannot marshal dump (e.g. STDIN
|
|
214
218
|
end
|
215
219
|
end
|
216
220
|
|
217
|
-
# include のフックまで入れると読み込み時間が結構遅くなるので注意
|
218
|
-
begin
|
219
|
-
m_include = o.method(:include).unbind
|
220
|
-
m_extend = o.method(:extend).unbind
|
221
|
-
rescue NameError
|
222
|
-
raise(ExecutionError.new("#{o}: include or extend not defined"))
|
223
|
-
end
|
224
|
-
define_method(:include) do |*mods|
|
225
|
-
extend_p = Dependency.extend?
|
226
|
-
CastOff.dlog("#{self} #{extend_p ? 'extends' : 'includes'} #{mods}")
|
227
|
-
bug() unless m_include && m_extend
|
228
|
-
m = extend_p ? m_extend : m_include
|
229
|
-
# include, extend の対象は self なので、self 以外が include, extend することはない。
|
230
|
-
m.bind(self).call(*mods)
|
231
|
-
return unless o == self
|
232
|
-
mods.each do |mod|
|
233
|
-
next unless mod.is_a?(Module)
|
234
|
-
Dependency.copy(mod, self, extend_p)
|
235
|
-
Dependency.hook(mod) unless mod.singleton_methods(false).include?(:override_singleton_method)
|
236
|
-
methods = mod.instance_methods(false) + mod.private_instance_methods(false)
|
237
|
-
override_callback = extend_p ? :override_singleton_method : :override_method
|
238
|
-
methods.each{|mid| o.__send__(override_callback, o, mid, extend_p ? :extend : :include)}
|
239
|
-
end
|
240
|
-
end
|
241
|
-
alias extend include
|
242
|
-
|
243
221
|
begin
|
244
222
|
singleton_method_added = o.method(:singleton_method_added).unbind
|
245
223
|
rescue NameError
|
246
224
|
singleton_method_added = nil
|
247
225
|
end
|
226
|
+
|
248
227
|
begin
|
249
228
|
method_added = o.method(:method_added).unbind
|
250
229
|
rescue NameError
|
251
230
|
method_added = nil
|
252
231
|
end
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
232
|
+
|
233
|
+
begin
|
234
|
+
m_include = o.method(:include).unbind
|
235
|
+
m_extend = o.method(:extend).unbind
|
236
|
+
rescue NameError
|
237
|
+
raise(ExecutionError.new("#{o}: include or extend not defined"))
|
238
|
+
end
|
239
|
+
|
240
|
+
define_method(:method_added) do |*args|
|
241
|
+
ignore_overridden_p = Dependency.ignore_overridden?
|
242
|
+
current_mid = CastOff.current_method_id
|
243
|
+
case current_mid
|
244
|
+
when :extend, :include
|
245
|
+
mods = args
|
246
|
+
extend_p = current_mid == :extend
|
247
|
+
CastOff.dlog("#{self} #{extend_p ? 'extends' : 'includes'} #{mods}")
|
248
|
+
bug() unless m_include && m_extend
|
249
|
+
m = extend_p ? m_extend : m_include
|
250
|
+
# include, extend の対象は self なので、self 以外が include, extend することはない。
|
251
|
+
m.bind(self).call(*mods)
|
252
|
+
return unless o == self
|
253
|
+
mods.each do |mod|
|
254
|
+
next unless mod.is_a?(Module)
|
255
|
+
Dependency.copy(mod, self, extend_p)
|
256
|
+
Dependency.hook(mod) unless mod.singleton_methods(false).include?(:override_singleton_method)
|
257
|
+
methods = mod.instance_methods(false) + mod.private_instance_methods(false)
|
258
|
+
override_callback = extend_p ? :override_singleton_method : :override_method
|
259
|
+
methods.each{|mid| o.__send__(override_callback, o, mid, extend_p ? :extend : :include)}
|
260
|
+
end
|
261
|
+
when :singleton_method_added
|
262
|
+
mid = args.first
|
263
|
+
CastOff.bug() unless mid.instance_of?(Symbol)
|
264
|
+
if self == o && !ignore_overridden_p
|
258
265
|
override_singleton_method(o, mid, :added)
|
259
266
|
singleton_method_added.bind(self).call(mid) if singleton_method_added
|
260
|
-
|
261
|
-
|
262
|
-
|
267
|
+
elsif o == Module && singleton_method_added
|
268
|
+
singleton_method_added.bind(self).call(mid)
|
269
|
+
end
|
270
|
+
super(mid) rescue NoMethodError
|
271
|
+
when :method_added
|
272
|
+
mid = args.first
|
273
|
+
CastOff.bug() unless mid.instance_of?(Symbol)
|
274
|
+
if self == o && !ignore_overridden_p
|
263
275
|
override_method(o, mid, :added)
|
264
276
|
method_added.bind(self).call(mid) if method_added
|
277
|
+
elsif o == Module && method_added
|
278
|
+
method_added.bind(self).call(mid)
|
265
279
|
end
|
266
|
-
|
267
|
-
|
280
|
+
super(mid) rescue NoMethodError
|
281
|
+
else
|
282
|
+
raise(ExecutionError.new("CastOff expected include, extend, method_added or singleton_method_added but #{current_mid} was called"))
|
268
283
|
end
|
269
|
-
super(mid) rescue NoMethodError
|
270
284
|
end
|
285
|
+
alias extend method_added
|
286
|
+
alias include method_added
|
271
287
|
alias singleton_method_added method_added
|
272
288
|
CastOff.dlog("hook #{o}")
|
273
289
|
end
|
274
290
|
@@singleton_method_dependency[o] ||= []
|
275
|
-
@@singleton_method_dependency[o] |= [:method_added, :singleton_method_added, :include]
|
291
|
+
@@singleton_method_dependency[o] |= [:method_added, :singleton_method_added, :include, :extend]
|
276
292
|
@@singleton_method_strong_dependency[o] ||= []
|
277
|
-
@@singleton_method_strong_dependency[o] |= [:method_added]
|
278
|
-
@@singleton_method_strong_dependency[o] |= [:singleton_method_added]
|
279
|
-
@@singleton_method_strong_dependency[o] |= [:include]
|
293
|
+
@@singleton_method_strong_dependency[o] |= [:method_added, :singleton_method_added, :include, :extend]
|
280
294
|
end
|
281
295
|
|
282
296
|
def hook(function_pointer_initializer)
|
@@ -286,7 +300,7 @@ Currently, CastOff doesn't support object, which cannot marshal dump (e.g. STDIN
|
|
286
300
|
m.each{|mid| self.class.singleton_method_depend(klass, mid, function_pointer_initializer)}
|
287
301
|
m.each{|mid| self.class.singleton_method_strongly_depend(klass, mid) if @strong_dependency.include?([klass, mid])}
|
288
302
|
o = klass.contain_object
|
289
|
-
bug() unless
|
303
|
+
bug() unless ClassWrapper.support?(o, false)
|
290
304
|
else
|
291
305
|
m.each{|mid| self.class.instance_method_depend(klass, mid, function_pointer_initializer)}
|
292
306
|
m.each{|mid| self.class.instance_method_strongly_depend(klass, mid) if @strong_dependency.include?([klass, mid])}
|
@@ -1854,13 +1854,17 @@ You should not use #{@method_id} method in compilation target of CastOff.
|
|
1854
1854
|
bug() if !can_unbox_result && @return_value.unboxed?
|
1855
1855
|
suffix << (@return_value.unboxed? ? unboxed_decl(@return_value) : 'VALUE')
|
1856
1856
|
suffix = suffix.join('_')
|
1857
|
+
@dependency.add(klass, @method_id, true)
|
1857
1858
|
return " #{@return_value} = cast_off_inline_#{klass.to_s.downcase}_#{name}_#{suffix}(#{recv}#{s_param});"
|
1858
1859
|
else
|
1860
|
+
@dependency.add(klass, @method_id, true)
|
1859
1861
|
return " #{@return_value} = cast_off_inline_#{klass.to_s.downcase}_#{name}(#{recv}#{s_param});"
|
1860
1862
|
end
|
1861
1863
|
else
|
1862
1864
|
m = SpecializeTable1[[mid, argc, MethodWrapper.new(klass, mid)]]
|
1863
|
-
return
|
1865
|
+
return false unless m
|
1866
|
+
@dependency.add(klass, @method_id, true)
|
1867
|
+
return __send__(m, klass, mid, argc, recv, param)
|
1864
1868
|
end
|
1865
1869
|
bug()
|
1866
1870
|
end
|
@@ -1923,42 +1927,32 @@ You should not use #{@method_id} method in compilation target of CastOff.
|
|
1923
1927
|
bug()
|
1924
1928
|
end
|
1925
1929
|
|
1926
|
-
def
|
1930
|
+
def recursive_call?(klass)
|
1927
1931
|
same_class = false
|
1928
1932
|
bug() unless klass.is_a?(ClassWrapper)
|
1929
1933
|
if @translator.reciever_class && @translator.reciever_class.include?(klass)
|
1930
1934
|
same_class = true
|
1931
1935
|
end
|
1932
|
-
if same_class &&
|
1936
|
+
if same_class && @method_id == @translator.mid
|
1933
1937
|
true
|
1934
1938
|
else
|
1935
1939
|
false
|
1936
1940
|
end
|
1937
1941
|
end
|
1938
1942
|
|
1939
|
-
def
|
1940
|
-
|
1941
|
-
|
1942
|
-
|
1943
|
-
end
|
1944
|
-
recv_defn = param_irs.first.get_definition(recv)
|
1945
|
-
if recv_defn.size == 1 && (@translator.inline_block? || @insn.iseq.root?)
|
1946
|
-
recv_defn = recv_defn.first
|
1947
|
-
same_class |= recv_defn.is_a?(SubIR) && recv_defn.src.is_a?(Self)
|
1948
|
-
end
|
1949
|
-
if same_class && mid == @translator.mid
|
1950
|
-
true
|
1951
|
-
else
|
1952
|
-
false
|
1953
|
-
end
|
1943
|
+
def recursive_call_depend(recv)
|
1944
|
+
bug() if recv.dynamic?
|
1945
|
+
classes = recv.types
|
1946
|
+
classes.each{|klass| @dependency.add(klass, @method_id, true)}
|
1954
1947
|
end
|
1955
1948
|
|
1956
1949
|
def recursive_call_code(recv, param, argc)
|
1957
|
-
return
|
1950
|
+
return nil if !@translator.inline_block?
|
1958
1951
|
fname = @translator.this_function_name()
|
1959
1952
|
if @translator.complex_call?
|
1960
1953
|
if splatcall?
|
1961
1954
|
call_code = "#{@return_value} = #{fname}(argc, argv, #{recv});"
|
1955
|
+
recursive_call_depend(recv)
|
1962
1956
|
return SPLATCALL_TEMPLATE_ARGV.trigger(binding)
|
1963
1957
|
else
|
1964
1958
|
ret = ""
|
@@ -1966,18 +1960,21 @@ You should not use #{@method_id} method in compilation target of CastOff.
|
|
1966
1960
|
param.each_with_index do |arg, i|
|
1967
1961
|
ret += " #{c_ary}[#{i}] = #{arg};\n"
|
1968
1962
|
end
|
1963
|
+
recursive_call_depend(recv)
|
1969
1964
|
return ret + " #{@return_value} = #{fname}(#{argc - 1}, #{c_ary}, #{recv});"
|
1970
1965
|
end
|
1971
1966
|
else
|
1972
1967
|
if splatcall?
|
1973
1968
|
splat_call_argc = @translator.root_iseq.args.arg_size
|
1974
1969
|
fnam_code = fname
|
1970
|
+
recursive_call_depend(recv)
|
1975
1971
|
return SPLATCALL_TEMPLATE_CFUNC.trigger(binding)
|
1976
1972
|
else
|
1977
1973
|
if param.size == @translator.root_iseq.args.arg_size
|
1974
|
+
recursive_call_depend(recv)
|
1978
1975
|
return " #{@return_value} = #{fname}(#{recv}#{param.empty? ? nil : ", #{param.join(", ")}"});"
|
1979
1976
|
else
|
1980
|
-
return
|
1977
|
+
return nil
|
1981
1978
|
end
|
1982
1979
|
end
|
1983
1980
|
end
|
@@ -2043,6 +2040,8 @@ You should not use #{@method_id} method in compilation target of CastOff.
|
|
2043
2040
|
|
2044
2041
|
def not_funcall_code(klass, mid, recv, param, argc)
|
2045
2042
|
bug() unless klass.is_a?(ClassWrapper)
|
2043
|
+
code = recursive_call_code(recv, param, argc) if recursive_call?(klass)
|
2044
|
+
return code if code
|
2046
2045
|
case klass.get_method_type(mid)
|
2047
2046
|
when :cfunc
|
2048
2047
|
cfunc_argc = klass.get_cfunc_argc(mid)
|
@@ -2062,7 +2061,7 @@ You should not use #{@method_id} method in compilation target of CastOff.
|
|
2062
2061
|
@dependency.add(klass, mid, false)
|
2063
2062
|
return " #{@return_value} = rb_attr_get(#{recv}, #{@translator.allocate_id(klass.get_attr_id(mid))});"
|
2064
2063
|
when false
|
2065
|
-
return
|
2064
|
+
return nil
|
2066
2065
|
end
|
2067
2066
|
bug()
|
2068
2067
|
end
|
@@ -2083,8 +2082,6 @@ You should not use #{@method_id} method in compilation target of CastOff.
|
|
2083
2082
|
if @configuration.force_dispatch_method?
|
2084
2083
|
# ユーザからの指定に基づいているので、Suggestion は吐かない
|
2085
2084
|
ret << funcall_code(nil, id, recv, param, @argc)
|
2086
|
-
elsif recursive_call_var?(recv, @method_id)
|
2087
|
-
ret << recursive_call_code(recv, param, @argc)
|
2088
2085
|
else
|
2089
2086
|
if @configuration.development? && @source
|
2090
2087
|
@translator.add_type_suggestion([get_definition_str(recv), @method_id.to_s, @source_line, @source])
|
@@ -46,6 +46,7 @@ static VALUE rb_cCastOffSingletonClass;
|
|
46
46
|
static VALUE rb_cCastOffConfiguration;
|
47
47
|
static VALUE rb_cCastOffClassWrapper;
|
48
48
|
static VALUE rb_cCastOffMethodWrapper;
|
49
|
+
static VALUE oMain, cMain;
|
49
50
|
|
50
51
|
#include "vm_api.h"
|
51
52
|
#include "iter_api.h"
|
@@ -97,7 +98,7 @@ static void sampling_variable(VALUE val, VALUE sym)
|
|
97
98
|
hash = RHASH_TBL(hashval);
|
98
99
|
|
99
100
|
if (FL_TEST(klass, FL_SINGLETON)) {
|
100
|
-
if (rb_obj_class(val) == rb_cClass || rb_obj_class(val) == rb_cModule) {
|
101
|
+
if (rb_obj_class(val) == rb_cClass || rb_obj_class(val) == rb_cModule || val == oMain) {
|
101
102
|
klass = val;
|
102
103
|
singleton_class_or_module_obj_p = Qtrue;
|
103
104
|
} else {
|
@@ -127,7 +128,7 @@ static void __sampling_poscall(VALUE val, VALUE method_klass, VALUE method_id)
|
|
127
128
|
if (FL_TEST(method_klass, FL_SINGLETON)) {
|
128
129
|
VALUE recv = rb_ivar_get(method_klass, rb_intern("__attached__"));
|
129
130
|
if (rb_class_of(recv) == method_klass) {
|
130
|
-
if ((rb_obj_class(recv) == rb_cClass || rb_obj_class(recv) == rb_cModule)) {
|
131
|
+
if ((rb_obj_class(recv) == rb_cClass || rb_obj_class(recv) == rb_cModule) || recv == oMain) {
|
131
132
|
method_klass = recv;
|
132
133
|
class_method_or_module_function_p = Qtrue;
|
133
134
|
} else {
|
@@ -190,7 +191,7 @@ static void sampling_poscall(VALUE val, VALUE recv, VALUE method_id)
|
|
190
191
|
%end
|
191
192
|
|
192
193
|
%@fptr.each do |(k, fps)|
|
193
|
-
%
|
194
|
+
% name, mid, singleton, convention, argc = k
|
194
195
|
% mid = allocate_id(mid)
|
195
196
|
% fps.each do |fp|
|
196
197
|
|
@@ -324,12 +325,19 @@ static VALUE cast_off_initialize_fptr_<%= signiture() %>(VALUE dummy)
|
|
324
325
|
feval = me->def->body.cfunc.func;
|
325
326
|
|
326
327
|
%@fptr.each do |(k, v)|
|
327
|
-
%
|
328
|
+
% name, mid, singleton, convention, argc = k
|
328
329
|
% mid = allocate_id(mid)
|
329
330
|
% fps = v
|
331
|
+
% case name
|
332
|
+
% when Symbol
|
333
|
+
klass = <%= name %>;
|
334
|
+
% when Array
|
330
335
|
klass = rb_cObject;
|
331
|
-
%
|
336
|
+
% name.each do |kid|
|
332
337
|
klass = rb_const_get(klass, rb_intern("<%= kid %>"));
|
338
|
+
% end
|
339
|
+
% else
|
340
|
+
% bug()
|
333
341
|
% end
|
334
342
|
% if singleton
|
335
343
|
should_be_singleton(klass);
|
@@ -734,6 +742,8 @@ void Init_<%= signiture() %>(void)
|
|
734
742
|
rb_cCastOffConfiguration = rb_const_get(rb_mCastOffCompiler, rb_intern("Configuration"));
|
735
743
|
rb_cCastOffClassWrapper = rb_const_get(rb_mCastOffCompiler, rb_intern("ClassWrapper"));
|
736
744
|
rb_cCastOffMethodWrapper = rb_const_get(rb_mCastOffCompiler, rb_intern("MethodWrapper"));
|
745
|
+
oMain = rb_const_get(rb_mCastOffCompiler, rb_intern("MAIN"));
|
746
|
+
cMain = rb_class_of(oMain);
|
737
747
|
|
738
748
|
%if !@mid
|
739
749
|
rb_define_method(rb_mCastOffCompiler, "<%= signiture() %>", <%= this_function_name() %>, 1);
|
@@ -898,9 +908,14 @@ Source line is #{@root_iseq.source_line}.
|
|
898
908
|
suffix = klass.singleton? ? 'singleton' : 'instance'
|
899
909
|
fptr = "fptr_#{klass}_#{@namespace.new(mid).name}_#{suffix}"
|
900
910
|
fptr.gsub!(/:/, '_')
|
901
|
-
|
902
|
-
|
903
|
-
|
911
|
+
name = C_CLASS_MAP[klass]
|
912
|
+
unless name
|
913
|
+
path = klass.to_s
|
914
|
+
bug() if path == "::main"
|
915
|
+
name = path.split("::")
|
916
|
+
name.each{|k| bug() if k == ''}
|
917
|
+
end
|
918
|
+
key = [name, mid, klass.singleton?, convention, argc]
|
904
919
|
entry = @fptr[key] || []
|
905
920
|
fptr.concat("_#{argc}_#{entry.size}")
|
906
921
|
entry << fptr
|
@@ -961,6 +976,7 @@ Source line is #{@root_iseq.source_line}.
|
|
961
976
|
end
|
962
977
|
|
963
978
|
def prefetch_constant(var, path, singleton_p)
|
979
|
+
bug() if path == "::main"
|
964
980
|
if @prefetch_constants[var]
|
965
981
|
bug() unless @prefetch_constants[var] == [path, singleton_p]
|
966
982
|
else
|
@@ -1008,6 +1024,7 @@ Source line is #{@root_iseq.source_line}.
|
|
1008
1024
|
ClassWrapper.new(Enumerator, true) => :rb_cEnumerator,
|
1009
1025
|
ClassWrapper.new(Fiber, true) => :rb_cFiber,
|
1010
1026
|
ClassWrapper.new(Data, true) => :rb_cData,
|
1027
|
+
ClassWrapper.new(MAIN, false) => :cMain,
|
1011
1028
|
#ClassWrapper.new(Generator, true) => :rb_cGenerator,
|
1012
1029
|
#ClassWrapper.new(Continuation, true) => :rb_cContinuation,
|
1013
1030
|
#ClassWrapper.new(ISeq, true) => :rb_cISeq,
|
data/lib/cast_off/compile.rb
CHANGED
@@ -48,8 +48,7 @@ module CastOff
|
|
48
48
|
true
|
49
49
|
end
|
50
50
|
|
51
|
-
def load(
|
52
|
-
return @@autoload_proc.call() if autoload_running? && !force
|
51
|
+
def load()
|
53
52
|
compiled = CodeManager.load_autocompiled()
|
54
53
|
return false unless compiled
|
55
54
|
__load(compiled)
|
@@ -174,7 +173,7 @@ module CastOff
|
|
174
173
|
load_binary(manager, configuration, suggestion, iseq)
|
175
174
|
t = override_target(target, mid)
|
176
175
|
dlog("override target of #{target}##{mid} is #{t}")
|
177
|
-
|
176
|
+
replace_method(t, manager, false)
|
178
177
|
@@original_instance_method_iseq[[t, mid]] = iseq
|
179
178
|
@@manager_table[manager.signiture] = manager
|
180
179
|
end
|
@@ -194,7 +193,7 @@ module CastOff
|
|
194
193
|
manager.compilation_target_is_a(obj, mid, true)
|
195
194
|
set_direct_call(obj, mid, :singleton, manager, configuration)
|
196
195
|
load_binary(manager, configuration, suggestion, iseq)
|
197
|
-
|
196
|
+
replace_method(obj, manager, true)
|
198
197
|
@@original_singleton_method_iseq[[obj, mid]] = iseq
|
199
198
|
@@manager_table[manager.signiture] = manager
|
200
199
|
end
|
@@ -231,6 +230,10 @@ module CastOff
|
|
231
230
|
!!Thread.current[COMPILER_RUNNING_KEY]
|
232
231
|
end
|
233
232
|
|
233
|
+
def method_replacing?
|
234
|
+
!!Thread.current[METHOD_REPLACING_KEY]
|
235
|
+
end
|
236
|
+
|
234
237
|
private
|
235
238
|
|
236
239
|
COMPILER_RUNNING_KEY = :CastOffCompilerRunning
|
@@ -238,6 +241,11 @@ module CastOff
|
|
238
241
|
Thread.current[COMPILER_RUNNING_KEY] = bool
|
239
242
|
end
|
240
243
|
|
244
|
+
METHOD_REPLACING_KEY = :CastOffMethodReplacing
|
245
|
+
def method_replacing(bool)
|
246
|
+
Thread.current[METHOD_REPLACING_KEY] = bool
|
247
|
+
end
|
248
|
+
|
241
249
|
Lock = Mutex.new()
|
242
250
|
def execute_no_hook()
|
243
251
|
bug() unless block_given?
|
@@ -409,6 +417,7 @@ Currently, CastOff cannot compile method which source file is not exist.
|
|
409
417
|
manager.compile_c_source(c_source, conf, dep)
|
410
418
|
manager.save_annotation(annotation)
|
411
419
|
manager.dump_development_mark(conf)
|
420
|
+
manager.loadable()
|
412
421
|
conf
|
413
422
|
end
|
414
423
|
|
@@ -483,11 +492,11 @@ Currently, CastOff cannot compile method which source file is not exist.
|
|
483
492
|
end
|
484
493
|
end
|
485
494
|
end
|
486
|
-
Module.class_eval do
|
487
|
-
define_method(:autoload) do |*args|
|
488
|
-
raise(ExecutionError.new("Currently, CastOff doesn't support Module#autoload"))
|
489
|
-
end
|
490
|
-
end
|
495
|
+
#Module.class_eval do
|
496
|
+
#define_method(:autoload) do |*args|
|
497
|
+
#raise(ExecutionError.new("Currently, CastOff doesn't support Module#autoload"))
|
498
|
+
#end
|
499
|
+
#end
|
491
500
|
Kernel.module_eval do
|
492
501
|
def set_trace_func(*args, &p)
|
493
502
|
raise(ExecutionError.new("Currently, CastOff doesn't support set_trace_func"))
|
@@ -648,7 +657,7 @@ Currently, CastOff cannot compile method which source file is not exist.
|
|
648
657
|
bug() unless mtbl.is_a?(Hash)
|
649
658
|
bug() unless val0.is_a?(Hash)
|
650
659
|
val0.each do |(klass, midtbl)|
|
651
|
-
bug() unless
|
660
|
+
bug() unless ClassWrapper.support?(klass, sym == :instance_methods)
|
652
661
|
bug() unless midtbl.is_a?(Hash)
|
653
662
|
newval = {}
|
654
663
|
midtbl.each do |(key1, val1)|
|
@@ -707,14 +716,8 @@ Currently, CastOff cannot compile method which source file is not exist.
|
|
707
716
|
val0.each do |(klass, singleton_p)|
|
708
717
|
kstr = klass.to_s
|
709
718
|
if singleton_p
|
710
|
-
|
711
|
-
|
712
|
-
kstr = "Class<#{kstr}>"
|
713
|
-
when Module
|
714
|
-
kstr = "Module<#{kstr}>"
|
715
|
-
else
|
716
|
-
bug()
|
717
|
-
end
|
719
|
+
bug() unless ClassWrapper.support?(klass, false)
|
720
|
+
kstr = "SingletonClassOf<#{kstr}>"
|
718
721
|
end
|
719
722
|
ary << [key0.to_s, kstr]
|
720
723
|
end
|
@@ -728,20 +731,14 @@ Currently, CastOff cannot compile method which source file is not exist.
|
|
728
731
|
bug() unless sym == :singleton_methods || sym == :instance_methods
|
729
732
|
bug() unless mtbl.is_a?(Hash)
|
730
733
|
mtbl.each do |key0, val0|
|
731
|
-
bug() unless
|
734
|
+
bug() unless ClassWrapper.support?(key0, sym == :instance_methods)
|
732
735
|
bug() unless val0.is_a?(Hash)
|
733
736
|
val0.each do |(mid, classes)|
|
734
737
|
classes.each do |(klass, singleton_p)|
|
735
738
|
kstr = klass.to_s
|
736
739
|
if singleton_p
|
737
|
-
|
738
|
-
|
739
|
-
kstr = "Class<#{kstr}>"
|
740
|
-
when Module
|
741
|
-
kstr = "Module<#{kstr}>"
|
742
|
-
else
|
743
|
-
bug()
|
744
|
-
end
|
740
|
+
bug() unless ClassWrapper.support?(klass, false)
|
741
|
+
kstr = "SingletonClassOf<#{kstr}>"
|
745
742
|
end
|
746
743
|
ary << ["#{key0}#{sym == :singleton_methods ? '.' : '#'}#{mid}", kstr]
|
747
744
|
end
|
@@ -771,6 +768,16 @@ Currently, CastOff cannot compile method which source file is not exist.
|
|
771
768
|
end
|
772
769
|
end
|
773
770
|
|
771
|
+
def replace_method(target, manager, singleton_p)
|
772
|
+
begin
|
773
|
+
method_replacing(true)
|
774
|
+
mid = "register#{singleton_p ? '_singleton_' : '_'}method_#{manager.signiture}"
|
775
|
+
__send__(mid, target)
|
776
|
+
ensure
|
777
|
+
method_replacing(false)
|
778
|
+
end
|
779
|
+
end
|
780
|
+
|
774
781
|
def set_direct_call(obj, mid, type, manager, configuration)
|
775
782
|
bug() unless configuration
|
776
783
|
return if configuration.use_method_frame?
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cast_off
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.7
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-
|
12
|
+
date: 2011-12-04 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: ! 'CastOff is a compiler for Ruby1.9.3.
|
15
15
|
|
@@ -23,9 +23,7 @@ executables:
|
|
23
23
|
- cast_off
|
24
24
|
extensions:
|
25
25
|
- ext/cast_off/extconf.rb
|
26
|
-
extra_rdoc_files:
|
27
|
-
- README
|
28
|
-
- README.en
|
26
|
+
extra_rdoc_files: []
|
29
27
|
files:
|
30
28
|
- lib/cast_off.rb
|
31
29
|
- lib/cast_off/compile.rb
|
@@ -96,10 +94,11 @@ files:
|
|
96
94
|
- ext/cast_off/ruby_source/1.9.2/vm_insnhelper.c
|
97
95
|
- ext/cast_off/ruby_source/1.9.2/vm_core.h
|
98
96
|
- ext/cast_off/ruby_source/1.9.2/eval_intern.h
|
97
|
+
- bin/cast_off
|
98
|
+
- doc/about.pdf
|
99
99
|
- cast_off.gemspec
|
100
|
-
- README
|
101
100
|
- README.en
|
102
|
-
-
|
101
|
+
- README
|
103
102
|
homepage: http://github.com/soba1104/CastOff
|
104
103
|
licenses: []
|
105
104
|
post_install_message:
|