1414#include "ujit_core.h"
1515#include "ujit_hooks.inc"
1616
17+ VALUE cUjitBlock ;
18+
19+ extern st_table * version_tbl ;
20+ extern codeblock_t * cb ;
21+
22+ static const rb_data_type_t ujit_block_type = {
23+ "UJIT/Block" ,
24+ {0 , 0 , 0 , },
25+ 0 , 0 , RUBY_TYPED_FREE_IMMEDIATELY
26+ };
27+
1728bool rb_ujit_enabled ;
1829
1930// Hash table of encoded instructions
@@ -288,6 +299,87 @@ rb_ujit_compile_iseq(const rb_iseq_t *iseq)
288299#endif
289300}
290301
302+ struct ujit_block_itr {
303+ const rb_iseq_t * iseq ;
304+ VALUE list ;
305+ };
306+
307+ static int
308+ iseqw_ujit_collect_blocks (st_data_t key , st_data_t value , st_data_t argp )
309+ {
310+ block_t * block = (block_t * )value ;
311+ struct ujit_block_itr * itr = (struct ujit_block_itr * )argp ;
312+
313+ if (block -> blockid .iseq == itr -> iseq ) {
314+ VALUE rb_block = TypedData_Wrap_Struct (cUjitBlock , & ujit_block_type , block );
315+ rb_ary_push (itr -> list , rb_block );
316+ }
317+ return ST_CONTINUE ;
318+ }
319+
320+ /* Get a list of the UJIT blocks associated with `rb_iseq` */
321+ static VALUE
322+ ujit_blocks_for (VALUE mod , VALUE rb_iseq )
323+ {
324+ const rb_iseq_t * iseq = rb_iseqw_to_iseq (rb_iseq );
325+ st_table * vt = (st_table * )version_tbl ;
326+ struct ujit_block_itr itr ;
327+ itr .iseq = iseq ;
328+ itr .list = rb_ary_new ();
329+
330+ rb_st_foreach (vt , iseqw_ujit_collect_blocks , (st_data_t )& itr );
331+
332+ return itr .list ;
333+ }
334+
335+ static VALUE
336+ ujit_insert (VALUE mod , VALUE iseq )
337+ {
338+ rb_ujit_compile_iseq (rb_iseqw_to_iseq (iseq ));
339+ return iseq ;
340+ }
341+
342+ /* Get the address of the UJIT::Block */
343+ static VALUE
344+ block_address (VALUE self )
345+ {
346+ block_t * block ;
347+ TypedData_Get_Struct (self , block_t , & ujit_block_type , block );
348+ return LONG2NUM ((intptr_t )block );
349+ }
350+
351+ /* Get the machine code for UJIT::Block as a binary string */
352+ static VALUE
353+ block_code (VALUE self )
354+ {
355+ block_t * block ;
356+ TypedData_Get_Struct (self , block_t , & ujit_block_type , block );
357+
358+ return rb_str_new (cb -> mem_block + block -> start_pos , block -> end_pos - block -> start_pos );
359+ }
360+
361+ /* Get the start index in the Instruction Sequence that corresponds to this
362+ * UJIT::Block */
363+ static VALUE
364+ iseq_start_index (VALUE self )
365+ {
366+ block_t * block ;
367+ TypedData_Get_Struct (self , block_t , & ujit_block_type , block );
368+
369+ return INT2NUM (block -> blockid .idx );
370+ }
371+
372+ /* Get the end index in the Instruction Sequence that corresponds to this
373+ * UJIT::Block */
374+ static VALUE
375+ iseq_end_index (VALUE self )
376+ {
377+ block_t * block ;
378+ TypedData_Get_Struct (self , block_t , & ujit_block_type , block );
379+
380+ return INT2NUM (block -> end_idx );
381+ }
382+
291383void
292384rb_ujit_init (void )
293385{
@@ -301,6 +393,16 @@ rb_ujit_init(void)
301393 ujit_init_core ();
302394 ujit_init_codegen ();
303395
396+ VALUE mUjit = rb_define_module ("UJIT" );
397+ rb_define_module_function (mUjit , "install_entry" , ujit_insert , 1 );
398+ rb_define_module_function (mUjit , "blocks_for" , ujit_blocks_for , 1 );
399+
400+ cUjitBlock = rb_define_class_under (mUjit , "Block" , rb_cObject );
401+ rb_define_method (cUjitBlock , "address" , block_address , 0 );
402+ rb_define_method (cUjitBlock , "code" , block_code , 0 );
403+ rb_define_method (cUjitBlock , "iseq_start_index" , iseq_start_index , 0 );
404+ rb_define_method (cUjitBlock , "iseq_end_index" , iseq_end_index , 0 );
405+
304406 // Initialize the GC hooks
305407 method_lookup_dependency = st_init_numtable ();
306408 struct ujit_root_struct * root ;
0 commit comments