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 CHANGED
@@ -134,7 +134,7 @@ when '2'
134
134
  CastOff.development(false)
135
135
  CastOff.use_base_configuration(true)
136
136
  # step 3
137
- CastOff.load(true)
137
+ CastOff.load()
138
138
  }
139
139
  fin = Object.new
140
140
  ObjectSpace.define_finalizer(fin){
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.6"
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
@@ -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
- VALUE __klass = rb_obj_class(obj);
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("cast_off_get_iseq_signiture: shoult not be reached");
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("cast_off_get_iseq_signiture: shoult not be reached");
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
- VALUE __klass = rb_obj_class(obj);
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
- VALUE __klass = rb_obj_class(obj);
678
- if (__klass == rb_cClass) {
679
- return rb_class_path(obj);
680
- } else if (__klass == rb_cModule) {
681
- return rb_mod_name(obj);
682
- } else {
683
- rb_raise(rb_eCastOffCompileError, "CastOff can't handle singleton object without Class and Module");
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
- rb_ary_push(ary, wrapper->obj);
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 id_method_added, id_singleton_method_added, id_initialize_copy, id_clone;
1364
- VALUE cast_off_ignore_overridden_p(VALUE dummy, VALUE target, VALUE midsym)
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
- mid = cfp->me->called_id;
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 cast_off_singleton_method_added_p(VALUE dummy)
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); /* method_added or singleton_method_added frame */
1467
+ cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); /* target frame */
1405
1468
  if (!cfp->me) {
1406
- rb_bug("cast_off_singleton_method_added_p: should not be reached(0)");
1469
+ rb_bug("cast_off_current_method_id: should not be reached(0)");
1407
1470
  }
1408
- mid = cfp->me->called_id;
1409
- if (mid == id_method_added) {
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
- if (mid == id_singleton_method_added) {
1413
- return Qtrue;
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
- rb_bug("cast_off_singleton_method_added_p: should not be reached(1)");
1478
+ return ID2SYM(mid);
1416
1479
  }
1417
1480
 
1418
- static ID id_include, id_extend;
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
- ID mid;
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); /* method_added or singleton_method_added frame */
1490
+ cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); /* target frame */
1428
1491
  if (!cfp->me) {
1429
- rb_bug("cast_off_extend_p: should not be reached(0)");
1492
+ rb_bug("cast_off_same_method_p: should not be reached(0)");
1430
1493
  }
1431
- mid = cfp->me->called_id;
1432
- if (mid == id_include) {
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
- if (mid == id_extend) {
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, 2);
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=(dir)
32
- CastOff::Compiler::CodeManager.class_variable_set(:@@program_name, dir)
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}/#{generate_signiture(@@program_name)}"
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 c.is_a?(Class) || (c.is_a?(Module) && singleton_p)
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 k.instance_of?(Class) || (k.instance_of?(Module) && sym == :singleton_methods)
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 c.is_a?(Class) || (c.is_a?(Module) && singleton_p)
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.inspect}"
476
+ ary << "#{k.inspect} => #{inspect_class_wrappers(v)}"
477
477
  end
478
478
  @return_value_configuration.each do |(k, v)|
479
- bug() unless k.instance_of?(ClassWrapper)
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 obj.instance_of?(Class) || obj.instance_of?(Module)
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 obj.instance_of?(Class) || obj.instance_of?(Module)
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
- define_method(:method_added) do |mid|
254
- if self == o && !Dependency.ignore_overridden?(self, mid)
255
- if Dependency.singleton_method_added?
256
- CastOff.dlog("singleton method added #{o}.#{mid}")
257
- CastOff.delete_original_singleton_method_iseq(self, mid)
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
- else
261
- CastOff.dlog("method added #{o}##{mid}")
262
- CastOff.delete_original_instance_method_iseq(self, mid)
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
- elsif o == BasicObject && method_added && !Dependency.singleton_method_added?
267
- method_added.bind(self).call(mid)
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 o.instance_of?(Class) || o.instance_of?(Module)
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 m ? __send__(m, klass, mid, argc, recv, param) : false
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 recursive_call_class?(klass, mid)
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 && mid == @translator.mid
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 recursive_call_var?(recv, mid)
1940
- same_class = false
1941
- if @translator.reciever_class && @translator.reciever_class.size() == 1
1942
- same_class = true if recv.is_just?(@translator.reciever_class[0])
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 funcall_code(nil, @translator.allocate_id(@method_id), recv, param, @argc) if !@translator.inline_block?
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 funcall_code(nil, @translator.allocate_id(@method_id), recv, param, @argc)
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 recursive_call_class?(klass, mid) ? recursive_call_code(recv, param, argc) : nil
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
- % kids, mid, singleton, convention, argc = k
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
- % kids, mid, singleton, convention, argc = k
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
- % kids.each do |kid|
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
- ids = klass.to_s.split("::")
902
- ids.each{|k| bug() if k == ''}
903
- key = [ids, mid, klass.singleton?, convention, argc]
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,
@@ -48,8 +48,7 @@ module CastOff
48
48
  true
49
49
  end
50
50
 
51
- def load(force = false)
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
- __send__("register_method_#{manager.signiture}", t)
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
- __send__("register_singleton_method_#{manager.signiture}", obj)
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 klass.is_a?(Class) || (klass.is_a?(Module) && sym == :singleton_methods)
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
- case klass # 変数名が klass だとわかりにくいので、変更すること
711
- when Class
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 key0.is_a?(Class) || (key0.is_a?(Module) && sym == :singleton_methods)
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
- case klass # 変数名が klass だとわかりにくいので、変更すること
738
- when Class
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.6
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-11-30 00:00:00.000000000 Z
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
- - bin/cast_off
101
+ - README
103
102
  homepage: http://github.com/soba1104/CastOff
104
103
  licenses: []
105
104
  post_install_message: