Feature #6993

Class#allocate の仕様変更(Cレベル)

Added by Koichi Sasada almost 3 years ago. Updated over 2 years ago.

[ruby-dev:46121]
Status:Closed
Priority:Normal
Assignee:Nobuyoshi Nakada

Description

=begin
 ささだです.

 現在,Class#new を呼び出すと,Class#allocate が呼ばれます.Class#allocate は,次のような特徴を持つ,ちょっと特殊なメソッドになっています.

  • 普通に定義しても Class#new からは使われない
  • 実際に動かす処理 func は rb_define_alloc_func(klass, func) として登録する
  • func は ID_ALLOCATOR という特殊なメソッド名で登録される(対応するシンボル名はなし,つまり rb_id2name(ID_ALLOCATOR) は NULL を返す
  • func は rb_funcall(klass, ID_ALLOCATOR, ...) で呼ばれる

これは,変な allocator を定義出来ないようにするための処置だったと思います(多分).

他にも,

  • backtrace には現れない
  • set_trace_func ではスキップする

という特殊な処理をしており,Ruby からは見えないようになっています.ただし,set_trace_func には現れませんが,C で trace_func を登録すると呼べてしまう,という中途半端な感じになっています.

これについて,中田さんと協議したんですが,そもそも allocator function はメソッド呼び出し(rb_funcall)で呼ばないでもいいんでないか,という結論を得ました.具体的には,rb_classext_t に allocator function を登録するようにして,それを呼び出す,ということになります.

あり得る問題点としては,allocator function から super が出来ない,という話がありました.ただし,そんなことやる奴はいないだろう,ということで allocator function の制限とするのがいいのではないか,という議論になりました.

副次的な効果として,allocator function のためにメソッドフレームを積む必要がなくなり,ユーザ定義クラスの生成が若干速くなる,ということがあります.

なお,もう一方の選択肢としては,allocator function を backtrace や set_trace_func などで特別扱いしない,というものがありましたが,今まで見えなかったものが見えると互換性的にまずいかもしれない,という話がありました.

というわけで,こんな感じで(中田さんが)進めようと思うのですが,何かお気づきの点がありましたらご指摘下さい.

=end

Associated revisions

Revision 36925
Added by Nobuyoshi Nakada almost 3 years ago

internal.h: allocator function in rb_classext_t

  • internal.h (struct rb_classext_struct): move allocator function into rb_classext_t from ordinary method table. [Feature #6993]
  • object.c (rb_obj_alloc): call allocator function directly.
  • vm_method.c (rb_define_alloc_func, rb_undef_alloc_func) (rb_get_alloc_func): use allocator function in rb_classext_t.

Revision 36925
Added by Nobuyoshi Nakada almost 3 years ago

internal.h: allocator function in rb_classext_t

  • internal.h (struct rb_classext_struct): move allocator function into rb_classext_t from ordinary method table. [Feature #6993]
  • object.c (rb_obj_alloc): call allocator function directly.
  • vm_method.c (rb_define_alloc_func, rb_undef_alloc_func) (rb_get_alloc_func): use allocator function in rb_classext_t.

History

#1 Updated by Koichi Sasada almost 3 years ago

  • Description updated (diff)

Class#allocate の特徴をちょっと追記.

#2 Updated by Nobuyoshi Nakada almost 3 years ago

  • Tracker changed from Bug to Feature

#3 Updated by Nobuyoshi Nakada almost 3 years ago

  • Status changed from Open to Closed
  • % Done changed from 0 to 100

This issue was solved with changeset r36925.
Koichi, thank you for reporting this issue.
Your contribution to Ruby is greatly appreciated.
May Ruby be with you.


internal.h: allocator function in rb_classext_t

  • internal.h (struct rb_classext_struct): move allocator function into rb_classext_t from ordinary method table. [Feature #6993]
  • object.c (rb_obj_alloc): call allocator function directly.
  • vm_method.c (rb_define_alloc_func, rb_undef_alloc_func) (rb_get_alloc_func): use allocator function in rb_classext_t.

#4 Updated by Yusuke Endoh over 2 years ago

  • Status changed from Closed to Assigned

ささださんなかださん、

で Roger Pack が「ID_ALLOCATOR がなくなったせいで拡張ライブラリ (ruby-prof) がビルドできなくなった」と報告してます。
#define ID_ALLOCATOR 0 を追加するだけで直ります? それとも他に (拡張ライブラリから見える) 挙動に変更があります?
返事してあげてください。

Yusuke Endoh mame@tsg.ne.jp

#5 Updated by Yusuke Endoh over 2 years ago

  • Status changed from Assigned to Closed

Class#allocate は C レベルの set_trace_func でもフックできなくなったという非互換があります、
ということで preview2 を出してみて、文句が来たら reopen して考えましょう。

Yusuke Endoh mame@tsg.ne.jp

#6 Updated by Andrew Grimm over 2 years ago

preview2もはちょっとです:
(Preview 2 is also bad)

$ gem install ruby-prof
Building native extensions.  This could take a while...
ERROR:  Error installing ruby-prof:
    ERROR: Failed to build gem native extension.

        /Users/agrimm/.rvm/rubies/ruby-head/bin/ruby extconf.rb
checking for sys/times.h... yes
checking for rb_os_allocated_objects()... no
checking for rb_gc_allocated_size()... no
checking for rb_gc_collections()... no
checking for rb_gc_time()... no
checking for rb_class_superclass()... yes
checking for rb_heap_total_mem()... no
checking for rb_gc_heap_info()... no
creating Makefile

make
compiling rp_call_info.c
compiling rp_measure.c
compiling rp_measure_allocations.c
compiling rp_measure_cpu_time.c
compiling rp_measure_gc_runs.c
compiling rp_measure_gc_time.c
compiling rp_measure_memory.c
compiling rp_measure_process_time.c
compiling rp_measure_wall_time.c
compiling rp_method.c
rp_method.c: In function ‘method_name’:
rp_method.c:101: error: ‘ID_ALLOCATOR’ undeclared (first use in this function)
rp_method.c:101: error: (Each undeclared identifier is reported only once
rp_method.c:101: error: for each function it appears in.)
make: *** [rp_method.o] Error 1


Gem files will remain installed in /Users/agrimm/.rvm/gems/ruby-head/gems/ruby-prof-0.11.2 for inspection.
Results logged to /Users/agrimm/.rvm/gems/ruby-head/gems/ruby-prof-0.11.2/ext/ruby_prof/gem_make.out
$ ruby --version
ruby 2.0.0dev (2012-12-12) [x86_64-darwin10.8.0]

Mame-san, were you saying "if it doesn't work on preview2, please re-open the issue"? Apologies for re-opening if I misunderstood you.

#7 Updated by Nobuyoshi Nakada over 2 years ago

You can just wrap the lines with #ifdef ID_ALLOCATOR, I guess.

#8 Updated by Yusuke Endoh over 2 years ago

@agrimm: Thank you for the reporting!

My understanding is that this issue will be fixed in the ruby-prof side.
So, currently, we plan to include this incompatibility "as is" in Ruby 2.0.0.
But, if the impact is bigger than we expect (i.e., if this affects other existing code except ruby-prof), we may revert this.

Note that we can NOT fix this incompatibility just by restoring the ID_ALLOCATOR macro definition.
As far as I know, this is a side effect of the improvement of class allocation.
But sorry, I don't understand the improvement itself in depth.

Yusuke Endoh mame@tsg.ne.jp

Also available in: Atom PDF