@@ -50,6 +50,22 @@ struct Recorder {
5050 inst_meth_id : ID ,
5151 parameters_id : ID ,
5252 class_id : ID ,
53+ to_a_id : ID ,
54+ begin_id : ID ,
55+ end_id : ID ,
56+ to_i_id : ID ,
57+ nsec_id : ID ,
58+ source_id : ID ,
59+ options_id : ID ,
60+ members_id : ID ,
61+ values_id : ID ,
62+ to_h_id : ID ,
63+ instance_variables_id : ID ,
64+ instance_variable_get_id : ID ,
65+ set_const_id : ID ,
66+ open_struct_const_id : ID ,
67+ set_class : VALUE ,
68+ open_struct_class : VALUE ,
5369 struct_type_versions : HashMap < String , usize > ,
5470}
5571
@@ -167,6 +183,20 @@ unsafe extern "C" fn ruby_recorder_alloc(klass: VALUE) -> VALUE {
167183 let inst_meth_id = rb_intern ( b"instance_method\0 " . as_ptr ( ) as * const c_char ) ;
168184 let parameters_id = rb_intern ( b"parameters\0 " . as_ptr ( ) as * const c_char ) ;
169185 let class_id = rb_intern ( b"class\0 " . as_ptr ( ) as * const c_char ) ;
186+ let to_a_id = rb_intern ( b"to_a\0 " . as_ptr ( ) as * const c_char ) ;
187+ let begin_id = rb_intern ( b"begin\0 " . as_ptr ( ) as * const c_char ) ;
188+ let end_id = rb_intern ( b"end\0 " . as_ptr ( ) as * const c_char ) ;
189+ let to_i_id = rb_intern ( b"to_i\0 " . as_ptr ( ) as * const c_char ) ;
190+ let nsec_id = rb_intern ( b"nsec\0 " . as_ptr ( ) as * const c_char ) ;
191+ let source_id = rb_intern ( b"source\0 " . as_ptr ( ) as * const c_char ) ;
192+ let options_id = rb_intern ( b"options\0 " . as_ptr ( ) as * const c_char ) ;
193+ let members_id = rb_intern ( b"members\0 " . as_ptr ( ) as * const c_char ) ;
194+ let values_id = rb_intern ( b"values\0 " . as_ptr ( ) as * const c_char ) ;
195+ let to_h_id = rb_intern ( b"to_h\0 " . as_ptr ( ) as * const c_char ) ;
196+ let instance_variables_id = rb_intern ( b"instance_variables\0 " . as_ptr ( ) as * const c_char ) ;
197+ let instance_variable_get_id = rb_intern ( b"instance_variable_get\0 " . as_ptr ( ) as * const c_char ) ;
198+ let set_const_id = rb_intern ( b"Set\0 " . as_ptr ( ) as * const c_char ) ;
199+ let open_struct_const_id = rb_intern ( b"OpenStruct\0 " . as_ptr ( ) as * const c_char ) ;
170200 let recorder = Box :: new ( Recorder {
171201 tracer,
172202 active : false ,
@@ -176,6 +206,22 @@ unsafe extern "C" fn ruby_recorder_alloc(klass: VALUE) -> VALUE {
176206 inst_meth_id,
177207 parameters_id,
178208 class_id,
209+ to_a_id,
210+ begin_id,
211+ end_id,
212+ to_i_id,
213+ nsec_id,
214+ source_id,
215+ options_id,
216+ members_id,
217+ values_id,
218+ to_h_id,
219+ instance_variables_id,
220+ instance_variable_get_id,
221+ set_const_id,
222+ open_struct_const_id,
223+ set_class : Qnil . into ( ) ,
224+ open_struct_class : Qnil . into ( ) ,
179225 struct_type_versions : HashMap :: new ( ) ,
180226 } ) ;
181227 let ty = std:: ptr:: addr_of!( RECORDER_TYPE ) as * const rb_data_type_t ;
@@ -333,7 +379,7 @@ unsafe fn to_value(recorder: &mut Recorder, val: VALUE, depth: usize, to_s_id: I
333379 } ;
334380 }
335381 if RB_TYPE_P ( val, rb_sys:: ruby_value_type:: RUBY_T_HASH ) {
336- let pairs = rb_funcall ( val, rb_intern ( b"to_a \0 " . as_ptr ( ) as * const c_char ) , 0 ) ;
382+ let pairs = rb_funcall ( val, recorder . to_a_id , 0 ) ;
337383 let len = RARRAY_LEN ( pairs) as usize ;
338384 let ptr = RARRAY_CONST_PTR ( pairs) ;
339385 let mut elements = Vec :: new ( ) ;
@@ -362,8 +408,8 @@ unsafe fn to_value(recorder: &mut Recorder, val: VALUE, depth: usize, to_s_id: I
362408 } ;
363409 }
364410 if rb_obj_is_kind_of ( val, rb_cRange) != 0 {
365- let begin_val = rb_funcall ( val, rb_intern ( b"begin \0 " . as_ptr ( ) as * const c_char ) , 0 ) ;
366- let end_val = rb_funcall ( val, rb_intern ( b"end \0 " . as_ptr ( ) as * const c_char ) , 0 ) ;
411+ let begin_val = rb_funcall ( val, recorder . begin_id , 0 ) ;
412+ let end_val = rb_funcall ( val, recorder . end_id , 0 ) ;
367413 return struct_value (
368414 recorder,
369415 "Range" ,
@@ -373,31 +419,32 @@ unsafe fn to_value(recorder: &mut Recorder, val: VALUE, depth: usize, to_s_id: I
373419 to_s_id,
374420 ) ;
375421 }
376- let set_id = rb_intern ( b"Set\0 " . as_ptr ( ) as * const c_char ) ;
377- if rb_const_defined ( rb_cObject, set_id) != 0 {
378- let set_cls = rb_const_get ( rb_cObject, set_id) ;
379- if rb_obj_is_kind_of ( val, set_cls) != 0 {
380- let arr = rb_funcall ( val, rb_intern ( b"to_a\0 " . as_ptr ( ) as * const c_char ) , 0 ) ;
381- if RB_TYPE_P ( arr, rb_sys:: ruby_value_type:: RUBY_T_ARRAY ) {
382- let len = RARRAY_LEN ( arr) as usize ;
383- let ptr = RARRAY_CONST_PTR ( arr) ;
384- let mut elements = Vec :: new ( ) ;
385- for i in 0 ..len {
386- let elem = * ptr. add ( i) ;
387- elements. push ( to_value ( recorder, elem, depth - 1 , to_s_id) ) ;
388- }
389- let type_id = recorder. tracer . ensure_type_id ( TypeKind :: Seq , "Set" ) ;
390- return ValueRecord :: Sequence {
391- elements,
392- is_slice : false ,
393- type_id,
394- } ;
422+ if NIL_P ( recorder. set_class ) {
423+ if rb_const_defined ( rb_cObject, recorder. set_const_id ) != 0 {
424+ recorder. set_class = rb_const_get ( rb_cObject, recorder. set_const_id ) ;
425+ }
426+ }
427+ if !NIL_P ( recorder. set_class ) && rb_obj_is_kind_of ( val, recorder. set_class ) != 0 {
428+ let arr = rb_funcall ( val, recorder. to_a_id , 0 ) ;
429+ if RB_TYPE_P ( arr, rb_sys:: ruby_value_type:: RUBY_T_ARRAY ) {
430+ let len = RARRAY_LEN ( arr) as usize ;
431+ let ptr = RARRAY_CONST_PTR ( arr) ;
432+ let mut elements = Vec :: new ( ) ;
433+ for i in 0 ..len {
434+ let elem = * ptr. add ( i) ;
435+ elements. push ( to_value ( recorder, elem, depth - 1 , to_s_id) ) ;
395436 }
437+ let type_id = recorder. tracer . ensure_type_id ( TypeKind :: Seq , "Set" ) ;
438+ return ValueRecord :: Sequence {
439+ elements,
440+ is_slice : false ,
441+ type_id,
442+ } ;
396443 }
397444 }
398445 if rb_obj_is_kind_of ( val, rb_cTime) != 0 {
399- let sec = rb_funcall ( val, rb_intern ( b"to_i \0 " . as_ptr ( ) as * const c_char ) , 0 ) ;
400- let nsec = rb_funcall ( val, rb_intern ( b"nsec \0 " . as_ptr ( ) as * const c_char ) , 0 ) ;
446+ let sec = rb_funcall ( val, recorder . to_i_id , 0 ) ;
447+ let nsec = rb_funcall ( val, recorder . nsec_id , 0 ) ;
401448 return struct_value (
402449 recorder,
403450 "Time" ,
@@ -408,8 +455,8 @@ unsafe fn to_value(recorder: &mut Recorder, val: VALUE, depth: usize, to_s_id: I
408455 ) ;
409456 }
410457 if rb_obj_is_kind_of ( val, rb_cRegexp) != 0 {
411- let src = rb_funcall ( val, rb_intern ( b"source \0 " . as_ptr ( ) as * const c_char ) , 0 ) ;
412- let opts = rb_funcall ( val, rb_intern ( b"options \0 " . as_ptr ( ) as * const c_char ) , 0 ) ;
458+ let src = rb_funcall ( val, recorder . source_id , 0 ) ;
459+ let opts = rb_funcall ( val, recorder . options_id , 0 ) ;
413460 return struct_value (
414461 recorder,
415462 "Regexp" ,
@@ -422,8 +469,8 @@ unsafe fn to_value(recorder: &mut Recorder, val: VALUE, depth: usize, to_s_id: I
422469 if rb_obj_is_kind_of ( val, rb_cStruct) != 0 {
423470 let class_name =
424471 cstr_to_string ( rb_obj_classname ( val) ) . unwrap_or_else ( || "Struct" . to_string ( ) ) ;
425- let members = rb_funcall ( val, rb_intern ( b"members \0 " . as_ptr ( ) as * const c_char ) , 0 ) ;
426- let values = rb_funcall ( val, rb_intern ( b"values \0 " . as_ptr ( ) as * const c_char ) , 0 ) ;
472+ let members = rb_funcall ( val, recorder . members_id , 0 ) ;
473+ let values = rb_funcall ( val, recorder . values_id , 0 ) ;
427474 if !RB_TYPE_P ( members, rb_sys:: ruby_value_type:: RUBY_T_ARRAY )
428475 || !RB_TYPE_P ( values, rb_sys:: ruby_value_type:: RUBY_T_ARRAY )
429476 {
@@ -446,21 +493,18 @@ unsafe fn to_value(recorder: &mut Recorder, val: VALUE, depth: usize, to_s_id: I
446493 }
447494 return struct_value ( recorder, & class_name, & names, & vals, depth, to_s_id) ;
448495 }
449- let open_struct_id = rb_intern ( b"OpenStruct\0 " . as_ptr ( ) as * const c_char ) ;
450- if rb_const_defined ( rb_cObject, open_struct_id) != 0 {
451- let open_struct = rb_const_get ( rb_cObject, open_struct_id) ;
452- if rb_obj_is_kind_of ( val, open_struct) != 0 {
453- let h = rb_funcall ( val, rb_intern ( b"to_h\0 " . as_ptr ( ) as * const c_char ) , 0 ) ;
454- return to_value ( recorder, h, depth - 1 , to_s_id) ;
496+ if NIL_P ( recorder. open_struct_class ) {
497+ if rb_const_defined ( rb_cObject, recorder. open_struct_const_id ) != 0 {
498+ recorder. open_struct_class = rb_const_get ( rb_cObject, recorder. open_struct_const_id ) ;
455499 }
456500 }
501+ if !NIL_P ( recorder. open_struct_class ) && rb_obj_is_kind_of ( val, recorder. open_struct_class ) != 0 {
502+ let h = rb_funcall ( val, recorder. to_h_id , 0 ) ;
503+ return to_value ( recorder, h, depth - 1 , to_s_id) ;
504+ }
457505 let class_name = cstr_to_string ( rb_obj_classname ( val) ) . unwrap_or_else ( || "Object" . to_string ( ) ) ;
458506 // generic object
459- let ivars = rb_funcall (
460- val,
461- rb_intern ( b"instance_variables\0 " . as_ptr ( ) as * const c_char ) ,
462- 0 ,
463- ) ;
507+ let ivars = rb_funcall ( val, recorder. instance_variables_id , 0 ) ;
464508 if !RB_TYPE_P ( ivars, rb_sys:: ruby_value_type:: RUBY_T_ARRAY ) {
465509 let text = value_to_string ( val, to_s_id) . unwrap_or_default ( ) ;
466510 let type_id = recorder. tracer . ensure_type_id ( TypeKind :: Raw , & class_name) ;
@@ -476,12 +520,7 @@ unsafe fn to_value(recorder: &mut Recorder, val: VALUE, depth: usize, to_s_id: I
476520 let cstr = rb_id2name ( id) ;
477521 let name = CStr :: from_ptr ( cstr) . to_str ( ) . unwrap_or ( "?" ) ;
478522 names. push ( name) ;
479- let value = rb_funcall (
480- val,
481- rb_intern ( b"instance_variable_get\0 " . as_ptr ( ) as * const c_char ) ,
482- 1 ,
483- sym,
484- ) ;
523+ let value = rb_funcall ( val, recorder. instance_variable_get_id , 1 , sym) ;
485524 vals. push ( value) ;
486525 }
487526 if !names. is_empty ( ) {
0 commit comments