Week 6: Vtable madness

Posted by khairul – July 6, 2010

Done the past week:

  1. Finished up instrumenting GC.
    GC events are now fully instrumented, with the exception of the following 3 functions (is_blocked_mark, is_blocked_sweep, get_gc_info). An example of how to use this is shown below:

    gc_do_gc_mark.pir:

    .sub '' :anon :init :load
        load_bytecode 'Instrument/InstrumentLib.pbc'
    .end
    
    .sub 'main' :main
        .param pmc args
        $S0 = shift args
    
        # Create an Instrument::Event::GC object.
        $P0 = get_hll_global ['Instrument';'Event'], 'GC'
        $P1 = $P0.'new'()
        $P1.'callback'('do_gc_mark_callback')
        $P1.'inspect'('do_gc_mark')
    
        $P2 = new ['Instrument']
        $P2.'attach'($P1)
    
        $S0 = args[0]
        $P2.'run'($S0, args)
    .end
    
    .sub 'do_gc_mark_callback'
        .param pmc data
    
        $I0 = data['line']
        $S0 = data['file']
        $S1 = data['type']
    
        print '('
        print $S1
        print ') at line '
        print $I0
        print ' in file '
        say $S0
    .end
    

    gc_sample.pir:

    .sub main :main
        meh()
    
        sweep 1
        collect
    
        say "End main"
    .end
    
    .sub meh
        $P0 = new ['Hash']
    
        $I0 = 0
        LOOP:
          $P0 = new ['String']
          inc $I0
        unless $I0 > 1 goto LOOP
    
        sweep 1
        collect
    
        say "End"
    .end
    

    Running the command: “./parrot gc_do_mark_sweep.pir gc_sample.pir” will yield the following output:

    (do_gc_mark) at line 19 in file gc_sample.pir
    End
    (do_gc_mark) at line 4 in file gc_sample.pir
    End main
    
  2. Refactored EventDispatcher.
    Previously, my implementation of EventDispatcher only allows registered handlers for specific events, such as ‘Instrument::Event::GC::administration::do_gc_mark’. With the implementation of InstrumentGC, this design was rather inadequate, as I found out when I wanted to register a handler for all GC events, or a certain subset of GC events.

    So refactoring and changing the internals of EventDispatcher came as a natural consequence of that. For what I wanted to do, I found that splitting the event type into 3 parts, namely Category, Group and Specific would do nicely for all cases that I could think of. To give an example, ‘GC::allocate::allocate_pmc_header’. If I’m only interested in the specific event, I can just register a handler for ‘GC::allocate::allocate_pmc_header’. If I’m only interested in events in the ‘allocate’ group, I can register a handler for ‘GC::allocate’. Similarly, for all GC events, I can register a handler for ‘GC’.

    Thinking ahead for what I want to do in week 7, this dovetails nicely with Classes. As an example, ‘Class::ResizablePMCArray::push’, ‘Vtable::ResizablePMCArray::push_pmc’. On hindsight, maybe refactoring it again to handle more levels would be better, as looking above for the Vtable example, adding 1 more level would allow catching of push_* vtable entries as a group, ie. ‘Vtable::ResizablePMCArray::push::push_pmc’.

  3. Added tests for EventDispatcher.
    Rather self-explanatory.
  4. Added tests for InstrumentGC.
    Rather self-explanatory too.
  5. Initial cut of InstrumentVtable.
    As of now, all vtable entries have a working stub that can be attached and removed at will. What is missing is getting the information about the arguments to the vtable entry. As an example, VTABLE_push_pmc(INTERP, obj, pmc), currently, only the information ‘push_pmc’ can be obtained, with obj and pmc on the way. As an example:

    vtable_push_pmc.pir

    .sub '' :anon :load :init
        load_bytecode 'Instrument/InstrumentLib.pbc'
    .end
    
    .sub main :main
        .param pmc args
        $S0 = shift args
    
        $P0 = new ['Instrument']
        $P1 = new ['InstrumentVtable'], $P0
        $P2 = $P0['eventdispatcher']
    
        # Register a handler
        $P3 = get_global 'class_handler'
        $P2.'register'('Class', $P3)
    
        # Instrument push_pmc of class ResizablePMCArray
        $P1.'attach_to_class'('ResizablePMCArray')
        $P1.'insert_vtable_hook'('push_pmc')
    
        $S0 = args[0]
        $P0.'run'($S0, args)
    .end
    
    .sub class_handler
        .param pmc data
    
        $I0 = data['line']
    
        print 'Line: '
        say $I0
    .end
    

    vtable_test.pir

    .sub main :main
    
        $I0 = 0
    
        LOOP:
          if $I0 > 5 goto DONE
    
          $P0 = new ['ResizablePMCArray']
          $P1 = box $I0
          push $P0, $P1
          inc $I0
    
          goto LOOP
        DONE:
    
        say 'Done'
    .end
    

    Running the command: “./parrot vtable_push_pmc.pir vtable_test.pir” yields the following output:

    Line: -1
    Line: 8
    Line: 8
    Line: 8
    Line: 8
    Line: 10
    Line: 10
    Line: 10
    Line: 10
    Line: 10
    Line: 10
    Done
    

    Since I have not implemented the appropriate Instrument::Event class for Vtable events, the code in ‘vtable_push_pmc.pir’ is rather lower-level than I would have preferred. But it will do for now.

With that, this week I would like to:

  1. Finish up InstrumentVtable
    • Implement the Instrument::Event class
    • Add a way to get at the vtable arguments
    • Documentation + Tests
  2. Do InstrumentClass, InstrumentObject
    • Build on InstrumentVtable to add support for methods.
    • Add ability to instrument a single object.
  3. Start on user documentation.
    There is currently no tutorial or anything on how to use the framework. Write something to show the simple stuff, instrumenting the ops.
  • 0 Comments – Feed
0 Comments on Week 6: Vtable madness

Respond | Trackback

Respond

Click here to cancel reply.
Comments

Comments

« Week 5: Unforseen troubles.
Week 7: Refactor refactor »

gipoco.com is neither affiliated with the authors of this page nor responsible for its contents. This is a safe-cache copy of the original web site.