[svn:parrot] r46967 - in branches/gsoc_instrument: . config/gen/makefiles examples/library runtime/parrot/library/Instrument src/dynpmc

khairul at svn.parrot.org khairul at svn.parrot.org
Mon May 24 16:08:05 UTC 2010


Author: khairul
Date: Mon May 24 16:08:04 2010
New Revision: 46967
URL: https://trac.parrot.org/parrot/changeset/46967

Log:
added instrument dynpmc, probe library and simple example.

Added:
   branches/gsoc_instrument/examples/library/tracer.pir
   branches/gsoc_instrument/runtime/parrot/library/Instrument/
   branches/gsoc_instrument/runtime/parrot/library/Instrument/Instrument.pir
   branches/gsoc_instrument/runtime/parrot/library/Instrument/Probe.pir
   branches/gsoc_instrument/src/dynpmc/instrument.pmc
Modified:
   branches/gsoc_instrument/MANIFEST
   branches/gsoc_instrument/config/gen/makefiles/root.in
   branches/gsoc_instrument/src/dynpmc/Defines.in
   branches/gsoc_instrument/src/dynpmc/Rules.in

Modified: branches/gsoc_instrument/MANIFEST
==============================================================================
--- branches/gsoc_instrument/MANIFEST	Mon May 24 15:31:33 2010	(r46966)
+++ branches/gsoc_instrument/MANIFEST	Mon May 24 16:08:04 2010	(r46967)
@@ -1,12 +1,12 @@
 # ex: set ro:
 # $Id$
 #
-# generated by tools/dev/mk_manifest_and_skip.pl Mon May 24 08:07:25 2010 UT
+# generated by ./tools/dev/mk_manifest_and_skip.pl Mon May 24 15:54:07 2010 UT
 #
 # See below for documentation on the format of this file.
 #
 # See docs/submissions.pod and the documentation in
-# tools/dev/mk_manifest_and_skip.pl on how to recreate this file after SVN
+# ./tools/dev/mk_manifest_and_skip.pl on how to recreate this file after SVN
 # has been told about new or deleted files.
 .gitignore                                                  []
 CREDITS                                                     [main]doc
@@ -646,6 +646,7 @@
 examples/library/md5sum.pir                                 [examples]
 examples/library/ncurses_life.pir                           [examples]
 examples/library/pcre.pir                                   [examples]
+examples/library/tracer.pir                                 [examples]
 examples/mops/README                                        [examples]
 examples/mops/mops.c                                        [examples]
 examples/mops/mops.cs                                       [examples]
@@ -1155,6 +1156,8 @@
 runtime/parrot/library/Getopt/Obj.pir                       [library]
 runtime/parrot/library/HTTP/Daemon.pir                      [library]
 runtime/parrot/library/HTTP/Message.pir                     [library]
+runtime/parrot/library/Instrument/Instrument.pir            [library]
+runtime/parrot/library/Instrument/Probe.pir                 [library]
 runtime/parrot/library/Iter.pir                             [library]
 runtime/parrot/library/JSON.pir                             [library]
 runtime/parrot/library/LWP/Protocol.pir                     [library]
@@ -1265,6 +1268,7 @@
 src/dynpmc/foo.pmc                                          []
 src/dynpmc/foo2.pmc                                         []
 src/dynpmc/gziphandle.pmc                                   []
+src/dynpmc/instrument.pmc                                   []
 src/dynpmc/main.pasm                                        []
 src/dynpmc/os.pmc                                           []
 src/dynpmc/pccmethod_test.pmc                               []

Modified: branches/gsoc_instrument/config/gen/makefiles/root.in
==============================================================================
--- branches/gsoc_instrument/config/gen/makefiles/root.in	Mon May 24 15:31:33 2010	(r46966)
+++ branches/gsoc_instrument/config/gen/makefiles/root.in	Mon May 24 16:08:04 2010	(r46967)
@@ -326,7 +326,9 @@
     $(LIBRARY_DIR)/YAML/Dumper.pbc \
     $(LIBRARY_DIR)/STM.pbc \
     $(LIBRARY_DIR)/libpcre.pbc \
-    $(LIBRARY_DIR)/postgres.pbc
+    $(LIBRARY_DIR)/postgres.pbc \
+    $(LIBRARY_DIR)/Instrument/Instrument.pbc \
+    $(LIBRARY_DIR)/Instrument/Probe.pbc 
 
 FLUID_FILES_1 = \
     $(GEN_HEADERS) \

Added: branches/gsoc_instrument/examples/library/tracer.pir
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ branches/gsoc_instrument/examples/library/tracer.pir	Mon May 24 16:08:04 2010	(r46967)
@@ -0,0 +1,142 @@
+# Copyright (C) 2010, Parrot Foundation.
+# $Id$
+
+=head1 NAME
+
+examples/library/tracer.pir - A simple op tracing example for the Instrument dynpmc
+
+=head1 SYNOPSIS
+
+    % ./parrot examples/library/tracer.pir <file>
+
+=head1 DESCRIPTION
+
+A simple example of how to use the Instrument dynpmc
+and associated libraries.
+
+=cut
+
+.sub '_init' :anon :load :init
+    # Load the Instrument libraries.
+    load_bytecode 'Instrument/Instrument.pbc'
+    load_bytecode 'Instrument/Probe.pbc'
+.end
+
+.sub 'main' :main
+    .param pmc args
+	.local pmc instr, probe, probe2
+	.local string me, file
+    
+    # Create a catchall probe which will be called for
+    #  each op.
+    probe = new ['Instrument';'Probe';'Catchall']
+    probe.'set_callback'('catchall_callback')
+    #probe.'set_finalize'('catchall_finalize')
+    
+    # Create a probe that will be called whenever the
+    #  specified ops are encountered.
+    probe2 = new ['Instrument';'Probe']
+    probe2.'inspect'('lt')
+    probe2.'inspect'('gt')
+    probe2.'set_callback'('specific_callback')
+    probe2.'set_finalize'('specific_finalize')
+
+    # Create an instance of Instrument and
+    #  attach the probes to it.
+	instr = new ['Instrument']
+	instr.'attach'(probe)
+	instr.'attach'(probe2)
+	
+	# Shift this file out of the command line argument list.
+	me = shift args
+	file = args[0]
+	
+	# Create globals for the counters.
+	$P0 = new ['Integer']
+	$P0 = 0
+	set_global '$INSTR_CNT', $P0
+	
+	$P0 = new ['Integer']
+	$P0 = 0
+	set_global '$GT_CNT', $P0
+	
+	$P0 = new ['Integer']
+	$P0 = 0
+	set_global '$LT_CNT', $P0
+	
+	# Execute the file.
+	instr.'run'(file, args)
+
+	.return()
+.end
+
+.sub 'catchall_callback'
+    .param string op_name
+    
+    # Update instruction counter.
+    .local pmc counter
+    counter = get_global '$INSTR_CNT'
+    counter += 1
+    set_global '$INSTR_CNT', counter
+    
+    .return()
+.end
+
+.sub 'catchall_finalize'
+    # Print the total instructions executed.
+    print 'Total Instruction count: '
+    $P0 = get_global '$INSTR_CNT'
+    say $P0
+
+    .return()
+.end
+
+.sub 'specific_callback'
+    .param string op_name
+    .local int ind
+    .local pmc counter
+    
+    # Check if it is lt or gt
+    #  and update accordingly.
+    ind = index op_name, 'gt'
+    if ind == 0 goto GT_OP
+
+LT_OP:
+    counter = get_global '$LT_CNT'
+    counter += 1
+    set_global '$LT_CNT', counter
+    goto DONE
+
+GT_OP:
+    counter = get_global '$GT_CNT'
+    counter += 1
+    set_global '$GT_CNT', counter
+
+DONE:
+    .return()
+.end
+
+
+.sub 'specific_finalize'
+    .local pmc gt_cnt, lt_cnt
+    
+    gt_cnt = get_global '$GT_CNT'
+    lt_cnt = get_global '$LT_CNT'
+    
+    print 'gt encountered '
+    print gt_cnt
+    say ' times'
+    
+    print 'lt encountered '
+    print lt_cnt
+    say ' times'
+
+    .return()
+.end
+
+
+# Local Variables:
+#   mode: pir
+#   fill-column: 100
+# End:
+# vim: expandtab shiftwidth=4 ft=pir:

Added: branches/gsoc_instrument/runtime/parrot/library/Instrument/Instrument.pir
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ branches/gsoc_instrument/runtime/parrot/library/Instrument/Instrument.pir	Mon May 24 16:08:04 2010	(r46967)
@@ -0,0 +1,32 @@
+# Copyright (C) 2010, Parrot Foundation.
+# $Id$
+
+=head1 NAME
+
+runtime/parrot/library/Instrument/Instrument.pir - Loads all libraries required by Instrument.
+
+=head1 SYNOPSIS
+
+   # Load the instrument dynpmc and required libraries.
+   load_bytecode 'Instrument/Instrument.pbc'
+   
+=cut
+
+.sub '__instrument_lib_init' :init :load :anon
+    .local pmc lib
+
+    lib = loadlib 'instrument'
+    $I0 = defined lib
+    if $I0 goto END
+    
+    die 'Could not load the instrument dynpmc'
+
+END:
+    .return()
+.end
+
+# Local Variables:
+#   mode: pir
+#   fill-column: 100
+# End:
+# vim: expandtab shiftwidth=4 ft=pir:

Added: branches/gsoc_instrument/runtime/parrot/library/Instrument/Probe.pir
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ branches/gsoc_instrument/runtime/parrot/library/Instrument/Probe.pir	Mon May 24 16:08:04 2010	(r46967)
@@ -0,0 +1,614 @@
+# Copyright (C) 2010, Parrot Foundation.
+# $Id$
+
+=head1 NAME
+
+runtime/parrot/library/Instrument/Probe.pir - A class to automate the task of creating probes for instruments.
+
+=head1 SYNOPSIS
+
+    # Create a catchall probe which will be called for
+    #  each op.
+    probe = new ['Instrument';'Probe';'Catchall']
+    probe.'set_callback'('catchall_callback')
+    probe.'set_finalize'('catchall_finalize')
+    
+    # Create a probe that will be called whenever the
+    #  specified ops are encountered.
+    probe2 = new ['Instrument';'Probe']
+    probe2.'inspect'('lt')
+    probe2.'inspect'('gt')
+    probe2.'set_callback'('specific_callback')
+    probe2.'set_finalize'('specific_finalize')
+
+=head2 TODO
+1. Refactor, too much copy and paste for now.
+
+=cut
+
+
+=head2 Class Instrument;Probe
+
+Class Instrument;Probe creates a probe who's callback will be called
+when the specified ops are encountered during execution.
+
+=cut
+.namespace ['Instrument';'Probe']
+
+.sub '' :anon :init :load
+    .local pmc class
+
+    class = newclass ['Instrument';'Probe']
+    addattribute class, 'instr_obj'
+    addattribute class, 'callback'
+    addattribute class, 'ops_unprocessed'
+    addattribute class, 'ops_processed'
+    addattribute class, 'enabled'
+    addattribute class, 'finalize'
+
+    .return()
+.end
+
+=item init
+
+=cut
+
+.sub 'init' :vtable :method
+    .local pmc instr_pmc, callback, ops_u, ops_p, enabled
+
+    # Probe is still unattached to an Instrument object.
+    # This attribute will be set by the Instrument object
+    #  when the probe is attached to it.
+    instr_pmc = new ['Undef']
+    setattribute self, 'instr_obj', instr_pmc
+    
+    # Callback is still undefined.
+    callback = new ['Undef']
+    setattribute self, 'callback', callback
+    
+    # Ops is an empty Hash
+    ops_u = new ['Hash']
+    ops_p = new ['Hash']
+    setattribute self, 'ops_unprocessed', ops_u
+    setattribute self, 'ops_processed', ops_p
+    
+    # Enabled is a Boolean.
+    # Each probe is initially disabled
+    enabled = new ['Boolean']
+    enabled = 0
+    setattribute self, 'enabled', enabled
+
+.end
+
+=item inspect
+
+=cut
+
+.sub 'inspect' :method
+    .param pmc ops
+    .local pmc ops_attr
+    ops_attr = getattribute self, 'ops_unprocessed'
+    
+    # ops can be either:
+    # 1. String : Identify an op through a string.
+    # 2. Integer: Identify an op through the op number.
+    # 3. ResizableIntegerArray: A group of op numbers.
+    # 4. ResizableStringArray: A group of op names.
+    #
+    # Anything other than these types are rejected.
+    .local string type
+    type = typeof ops
+
+    if type == 'String' goto T_STR
+    if type == 'Integer' goto T_INT
+    if type == 'ResizableIntegerArray' goto T_ARR
+    if type == 'ResizableStringArray' goto T_ARR
+    
+    # If we get here, it is an unknown type.
+    # Throw an exception.
+    .local pmc ex
+    .local string msg
+    msg = 'Unknown type: '
+    msg .= type
+    
+    ex = new ['Exception']
+    ex = msg
+    throw ex
+
+T_STR:
+T_INT:
+    # Given either the op name or the op number,
+    #  we do nothing other than stashing it into
+    #  the ops attribute. When the probe is enabled,
+    #  the ops attribute is inspected and hooks are
+    #  inserted based on the contents of that hash.
+    # Each entry into the hash is simply given a boolean
+    #  value.
+    # Validation of the op's name or number is done
+    #  when the probe is enabled.
+    ops_attr[ops] = 1
+    .return()
+
+T_ARR:
+    # Iterate through the array and stash the current
+    #  value into the ops_attr hash.
+    .local pmc it, cur
+    it = iter ops
+    
+T_ARR_BEG:
+
+    unless it goto T_ARR_END
+    
+    cur = shift it
+    ops_attr[cur] = 1
+
+    goto T_ARR_BEG
+    
+T_ARR_END:
+    .return()
+
+.end
+
+=item set_callback
+
+=cut
+
+.sub 'set_callback' :method
+    .param pmc sub
+    .local pmc ex
+    .local string msg
+    # If sub is of type string, we need to lookup
+    #  the symbol in the namespace.
+    .local string type
+
+CHECK:
+    type = typeof sub
+        
+    if type == 'String' goto LOOKUP
+    if type == 'Sub' goto SET
+    
+    # If we reached here, we couldn't find the
+    #  symbol or a bad parameter was passed in.
+    msg = 'Unknown type of callback: '
+    msg .= type
+
+EXC:    
+    ex = new ['Exception']
+    ex = msg
+    throw ex
+
+LOOKUP:
+    # Lookup the symbol in the namespace
+    # (Not sure if this is foolproof)
+    .local string name
+    name = sub
+    
+    # Try relative namespace
+    sub = get_global name
+    $I0 = defined sub
+    if $I0 goto CHECK
+    
+    # Try HLL namespace
+    sub = get_hll_global name
+    $I0 = defined sub
+    if $I0 goto CHECK
+    
+    # Try root namespace
+    sub = get_root_global name
+    $I0 = defined sub
+    if $I0 goto CHECK
+
+    # Cannot find the symbol!
+    msg = 'Could not find symbol '
+    msg .= name
+    msg .= '.'
+    
+    goto EXC
+
+SET:
+    # Set the attribute callback and return.
+    setattribute self, 'callback', sub
+    .return()
+.end
+
+=item set_finalize
+
+=cut
+
+.sub 'set_finalize' :method
+    .param pmc sub
+    .local pmc ex
+    .local string msg
+    # If sub is of type string, we need to lookup
+    #  the symbol in the namespace.
+    .local string type
+
+CHECK:
+    type = typeof sub
+        
+    if type == 'String' goto LOOKUP
+    if type == 'Sub' goto SET
+    
+    # If we reached here, we couldn't find the
+    #  symbol or a bad parameter was passed in.
+    msg = 'Unknown type of callback: '
+    msg .= type
+
+EXC:    
+    ex = new ['Exception']
+    ex = msg
+    throw ex
+
+LOOKUP:
+    # Lookup the symbol in the namespace
+    # (Not sure if this is foolproof)
+    .local string name
+    name = sub
+    
+    # Try relative namespace
+    sub = get_global name
+    $I0 = defined sub
+    if $I0 goto CHECK
+    
+    # Try HLL namespace
+    sub = get_hll_global name
+    $I0 = defined sub
+    if $I0 goto CHECK
+    
+    # Try root namespace
+    sub = get_root_global name
+    $I0 = defined sub
+    if $I0 goto CHECK
+
+    # Cannot find the symbol!
+    msg = 'Could not find symbol '
+    msg .= name
+    msg .= '.'
+    
+    goto EXC
+
+SET:
+    # Set the attribute callback and return.
+    setattribute self, 'finalize', sub
+    .return()
+.end
+
+=item enable
+
+=cut
+
+.sub 'enable' :method
+    .local pmc instr_attr, ops_u_attr, ops_p_attr, en_attr, cb_attr
+    .local pmc it, key
+    .local string msg, type, op_name
+    .local int op_num
+
+    instr_attr = getattribute self, 'instr_obj'
+    ops_u_attr = getattribute self, 'ops_unprocessed'
+    ops_p_attr = getattribute self, 'ops_processed'
+    en_attr    = getattribute self, 'enabled'
+    cb_attr    = getattribute self, 'callback'
+    
+    # Check to see if we are already enabled.
+    if en_attr == 1 goto ENABLE_DONE
+    
+    # Check to see if the instr_pmc attribute
+    #  has been set. if not we cannot do anything.
+    msg  = 'Probe is not attached to an Instrument. Could not enable'
+    type = typeof instr_attr
+    
+    if type != 'Instrument' goto EXCEP
+    
+    # Process the unprocessed ops in ops_u_attr.
+    
+    # Because we simply dump in both integers
+    #  and string into the hash, first we get
+    #  the key from the iterator, then we force
+    #  it to be a string, then we try to convert it
+    #  to an integer.
+    # If it fails to get converted into an integer,
+    #  op_num will be 0. Check if op_num == 0, then we
+    #  need to lookup the name by querying instr_attr.
+
+    it = iter ops_u_attr
+
+UNPROC_BEG:
+    unless it goto UNPROC_DONE
+    
+    key = shift it
+    op_name = key
+    op_num  = op_name
+    
+UNPROC_CHECK:
+    # Check if the op is really 0
+    if op_num == 0 goto OPS_LOOKUP
+
+    # If we can convert op_name to op_num, that means that
+    #  the op passed was by number. So we do not need to care
+    #  about variants.
+    # Put this op into the processed hash, with the value
+    #  being a reference to the callback pmc.
+    # TODO: Ensure that the value is not duplicated. Check how Hash works.
+    ops_p_attr[op_num] = cb_attr
+  
+UNPROC_LOOKUPED:
+
+    goto UNPROC_BEG
+
+UNPROC_DONE:
+ENABLE_DONE:
+
+    # All unprocessed ops are done at this point.
+    # Pass ops_p_attr to the instrument pmc for hooking.
+    instr_attr.'insert_op_hooks'(ops_p_attr)
+
+    # We are done with enabling.
+    # Set the enabled attribute and return.
+    en_attr = 1
+    setattribute self, 'enabled', en_attr
+    
+    .return()
+    
+
+EXCEP:
+    # Throw an exception with the message
+    #  in msg.
+    .local pmc ex
+    ex = new ['Exception']
+    ex = msg
+    throw ex
+
+OPS_LOOKUP:
+    # Lookup the op number from op_name
+    # This will return an array, so for each element
+    #  in the array, insert it into ops_p_attr.
+    .local pmc query_ret, op_lu_it, op_lu_cur
+
+    query_ret = instr_attr.'op_query'(0, op_name)
+    op_lu_it = iter query_ret
+
+OPS_LOOKUP_BEG:
+    unless op_lu_it goto OPS_LOOKUP_END
+
+    op_lu_cur = shift op_lu_it
+    op_num = op_lu_cur
+    
+    ops_p_attr[op_num] = cb_attr
+    
+    goto OPS_LOOKUP_BEG
+
+OPS_LOOKUP_END:
+
+    goto UNPROC_LOOKUPED
+    
+.end
+
+=item disable
+
+=cut
+
+.sub 'disable' :method
+.end
+
+
+=head2 Class Instrument;Probe;Catchall
+
+Class Instrument;Probe;Catchall creates a probe who's callback is called
+for all ops encountered during execution
+
+=cut
+
+.namespace ['Instrument';'Probe';'Catchall']
+
+.sub '' :anon :init :load
+    .local pmc class
+
+    class = newclass ['Instrument';'Probe';'Catchall']
+    addattribute class, 'instr_obj'
+    addattribute class, 'callback'
+    addattribute class, 'enabled'
+    addattribute class, 'finalize'
+
+    .return()
+.end
+
+=item init
+
+=cut
+
+.sub 'init' :vtable :method
+    .local pmc instr_pmc, callback, ops_u, ops_p, enabled
+
+    # Probe is still unattached to an Instrument object.
+    # This attribute will be set by the Instrument object
+    #  when the probe is attached to it.
+    instr_pmc = new ['Undef']
+    setattribute self, 'instr_obj', instr_pmc
+    
+    # Callback is still undefined.
+    callback = new ['Undef']
+    setattribute self, 'callback', callback
+    
+    # Enabled is a Boolean.
+    # Each probe is initially disabled
+    enabled = new ['Boolean']
+    enabled = 0
+    setattribute self, 'enabled', enabled
+
+.end
+
+=item set_callback
+
+=cut
+
+.sub 'set_callback' :method
+    .param pmc sub
+    .local pmc ex
+    .local string msg
+    # If sub is of type string, we need to lookup
+    #  the symbol in the namespace.
+    .local string type
+
+CHECK:
+    type = typeof sub
+        
+    if type == 'String' goto LOOKUP
+    if type == 'Sub' goto SET
+    
+    # If we reached here, we couldn't find the
+    #  symbol or a bad parameter was passed in.
+    msg = 'Unknown type of callback: '
+    msg .= type
+
+EXC:    
+    ex = new ['Exception']
+    ex = msg
+    throw ex
+
+LOOKUP:
+    # Lookup the symbol in the namespace
+    # (Not sure if this is foolproof)
+    .local string name
+    name = sub
+    
+    # Try relative namespace
+    sub = get_global name
+    $I0 = defined sub
+    if $I0 goto CHECK
+    
+    # Try HLL namespace
+    sub = get_hll_global name
+    $I0 = defined sub
+    if $I0 goto CHECK
+    
+    # Try root namespace
+    sub = get_root_global name
+    $I0 = defined sub
+    if $I0 goto CHECK
+
+    # Cannot find the symbol!
+    msg = 'Could not find symbol '
+    msg .= name
+    msg .= '.'
+    
+    goto EXC
+
+SET:
+    # Set the attribute callback and return.
+    setattribute self, 'callback', sub
+    .return()
+.end
+
+=item set_finalize
+
+=cut
+
+.sub 'set_finalize' :method
+    .param pmc sub
+    .local pmc ex
+    .local string msg
+    # If sub is of type string, we need to lookup
+    #  the symbol in the namespace.
+    .local string type
+
+CHECK:
+    type = typeof sub
+        
+    if type == 'String' goto LOOKUP
+    if type == 'Sub' goto SET
+    
+    # If we reached here, we couldn't find the
+    #  symbol or a bad parameter was passed in.
+    msg = 'Unknown type of callback: '
+    msg .= type
+
+EXC:    
+    ex = new ['Exception']
+    ex = msg
+    throw ex
+
+LOOKUP:
+    # Lookup the symbol in the namespace
+    # (Not sure if this is foolproof)
+    .local string name
+    name = sub
+    
+    # Try relative namespace
+    sub = get_global name
+    $I0 = defined sub
+    if $I0 goto CHECK
+    
+    # Try HLL namespace
+    sub = get_hll_global name
+    $I0 = defined sub
+    if $I0 goto CHECK
+    
+    # Try root namespace
+    sub = get_root_global name
+    $I0 = defined sub
+    if $I0 goto CHECK
+
+    # Cannot find the symbol!
+    msg = 'Could not find symbol '
+    msg .= name
+    msg .= '.'
+    
+    goto EXC
+
+SET:
+    # Set the attribute callback and return.
+    setattribute self, 'finalize', sub
+    .return()
+.end
+
+=item enable
+
+=cut
+
+.sub 'enable' :method
+    .local pmc instr_attr, en_attr, cb_attr
+    .local string msg, type
+
+    instr_attr = getattribute self, 'instr_obj'
+    en_attr    = getattribute self, 'enabled'
+    cb_attr    = getattribute self, 'callback'
+    
+    # Check to see if we are already enabled.
+    if en_attr == 1 goto ENABLE_DONE
+    
+    # Check to see if the instr_pmc attribute
+    #  has been set. if not we cannot do anything.
+    msg  = 'Probe is not attached to an Instrument. Could not enable'
+    type = typeof instr_attr
+    
+    if type != 'Instrument' goto EXCEP
+    
+ENABLE_DONE:
+
+    # Catchall hooks are treated separate from specific hooks.
+    # They are called first too.
+    instr_attr.'insert_op_catchall'(cb_attr)
+
+    # We are done with enabling.
+    # Set the enabled attribute and return.
+    en_attr = 1
+    setattribute self, 'enabled', en_attr
+    
+    .return()
+    
+
+EXCEP:
+    # Throw an exception with the message
+    #  in msg.
+    .local pmc ex
+    ex = new ['Exception']
+    ex = msg
+    throw ex
+    
+.end
+
+# Local Variables:
+#   mode: pir
+#   fill-column: 100
+# End:
+# vim: expandtab shiftwidth=4 ft=pir:

Modified: branches/gsoc_instrument/src/dynpmc/Defines.in
==============================================================================
--- branches/gsoc_instrument/src/dynpmc/Defines.in	Mon May 24 15:31:33 2010	(r46966)
+++ branches/gsoc_instrument/src/dynpmc/Defines.in	Mon May 24 16:08:04 2010	(r46967)
@@ -10,7 +10,8 @@
     $(DYNEXT_DIR)/pccmethod_test$(LOAD_EXT) \
     $(DYNEXT_DIR)/rotest$(LOAD_EXT) \
     $(DYNEXT_DIR)/rational$(LOAD_EXT) \
-    $(DYNEXT_DIR)/subproxy$(LOAD_EXT)
+    $(DYNEXT_DIR)/subproxy$(LOAD_EXT) \
+    $(DYNEXT_DIR)/instrument$(LOAD_EXT) 
 
 DYNPMC_FOO = \
     src/dynpmc/foo.pmc \

Modified: branches/gsoc_instrument/src/dynpmc/Rules.in
==============================================================================
--- branches/gsoc_instrument/src/dynpmc/Rules.in	Mon May 24 15:31:33 2010	(r46966)
+++ branches/gsoc_instrument/src/dynpmc/Rules.in	Mon May 24 16:08:04 2010	(r46967)
@@ -176,3 +176,22 @@
 
 src/dynpmc/subproxy.dump: src/dynpmc/subproxy.pmc vtable.dump $(CLASS_O_FILES)
 	$(PMC2CD) src/dynpmc/subproxy.pmc
+	
+
+$(DYNEXT_DIR)/instrument$(LOAD_EXT): src/dynpmc/instrument$(O)
+	$(LD)  @ld_out@$(DYNEXT_DIR)/instrument$(LOAD_EXT) src/dynpmc/instrument$(O) $(LINKARGS)
+#IF(win32):	if exist $@.manifest mt.exe -nologo -manifest $@.manifest -outputresource:$@;2
+#IF(cygwin or hpux):   $(CHMOD) 0775 $@
+
+src/dynpmc/pmc_instrument.h : src/dynpmc/instrument.c
+
+src/dynpmc/instrument$(O): src/dynpmc/instrument.c $(DYNPMC_H_FILES) \
+    src/dynpmc/pmc_instrument.h
+
+src/dynpmc/instrument.c: src/dynpmc/instrument.dump
+	$(PMC2CC) src/dynpmc/instrument.pmc
+
+src/dynpmc/instrument.dump: src/dynpmc/instrument.pmc vtable.dump $(CLASS_O_FILES)
+	$(PMC2CD) src/dynpmc/instrument.pmc
+
+

Added: branches/gsoc_instrument/src/dynpmc/instrument.pmc
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ branches/gsoc_instrument/src/dynpmc/instrument.pmc	Mon May 24 16:08:04 2010	(r46967)
@@ -0,0 +1,699 @@
+/*
+Copyright (C) 2010, Parrot Foundation.
+$Id$
+
+=head1 NAME
+
+src/dynpmc/instrument.pmc - Interface to hook into a child interpreter.
+
+=head1 DESCRIPTION
+
+C<Instrument> is a PMC class that allows dynamic execution introspection
+to be done on a child interpreter.
+
+=head2 Methods
+
+=over 4
+
+=cut
+
+*/
+
+#include "parrot/parrot.h"
+#include "parrot/imcc.h"
+#include "parrot/runcore_api.h"
+#include "parrot/embed.h"
+
+/*
+ * Extend the runcore_t struct to include a reference
+ *  to the supervisor interpreter.
+ */
+typedef struct Instrument_runcore_t {
+    STRING                  *name;
+    int                      id;
+    oplib_init_f             opinit;
+    runcore_runops_fn_type   runops;
+    runcore_destroy_fn_type  destroy;
+    runcore_prepare_fn_type  prepare_run;
+    INTVAL                   flags;
+    
+    /* End of common members */
+    PMC                     *supervisor;
+} Instrument_runcore_t;
+
+/* Define the enumeration for op lookups */
+typedef enum {
+    OP_LOOKUP   = 0,
+    OP_INFO     = 1,
+    OP_FULLNAME = 2,
+    OP_NAME     = 3,
+    OP_ARGS     = 4,
+    OP_COUNT    = 5
+} Instrument_op_query_t;
+
+/* Runcore Function Prototypes */
+static void Instrument_runcore_init (PARROT_INTERP, PMC *supervisor);
+static opcode_t * Instrument_runcore_runops(PARROT_INTERP, Parrot_runcore_t *runcore, opcode_t *pc);
+
+/* Helper Function Prototypes */
+static void gather_params(PARROT_INTERP, opcode_t *pc, PMC *supervisor, PMC *params);
+
+pmclass Instrument auto_attrs dynpmc {
+    ATTR Parrot_Interp  supervisor;  /* The interpreter that created this instance */
+    ATTR Parrot_Interp  supervised;  /* The interpreter running the code */
+    ATTR PMC           *op_hooks;    /* A ResizablePMCArray for holding references to op hooks */
+    ATTR PMC           *op_catchall; /* These callbacks are to be called on each op */
+    ATTR PMC           *probes;      /* A list of probes registered. */
+
+/*
+
+=item C<void init()>
+
+Initializes the pmc and creates a child interpreter.
+
+=cut
+
+*/
+
+    VTABLE void init () {
+        struct parrot_interp_t *in;
+        Parrot_Instrument_attributes * const attr = PARROT_INSTRUMENT(SELF);
+        
+        /* Create the child interpreter PMC */
+        attr->supervisor  = INTERP;
+        attr->supervised  = Parrot_new(attr->supervisor);
+        attr->op_hooks    = Parrot_pmc_new(INTERP, enum_class_ResizablePMCArray);
+        attr->op_catchall = Parrot_pmc_new(INTERP, enum_class_ResizablePMCArray);
+        attr->probes      = Parrot_pmc_new(INTERP, enum_class_ResizablePMCArray);
+        
+        /* Initialize the runcore for the child interpreter */  
+        Instrument_runcore_init(attr->supervised, SELF);
+        
+        /* Set self to destroy manually */
+        PObj_custom_mark_destroy_SETALL(SELF);
+    }
+
+/*
+
+=item C<void destroy()>
+
+Cleans up after the PMC.
+
+=cut
+
+*/
+
+    VTABLE void destroy () {
+        Parrot_Instrument_attributes * const attr = PARROT_INSTRUMENT(SELF);
+        
+        /* Delete the supervised interpreter */
+        Parrot_destroy(attr->supervised);
+        
+        /* Set the references to null */
+        /* TODO: Is there a better way to delete them? */
+        attr->supervisor  = NULL;
+        attr->supervised  = NULL;
+        attr->op_hooks    = NULL;
+        attr->op_catchall = NULL;
+        attr->probes      = NULL;
+    }
+
+/*
+
+=item C<void mark()>
+
+Marks internal data structures as live to the gc.
+
+=cut
+
+*/
+
+    VTABLE void mark () {
+        Parrot_Instrument_attributes * const attr = PARROT_INSTRUMENT(SELF);
+    
+        /* Mark attributes as alive */
+        Parrot_gc_mark_PMC_alive_fun(INTERP, attr->op_hooks);
+        Parrot_gc_mark_PMC_alive_fun(INTERP, attr->op_catchall);
+        Parrot_gc_mark_PMC_alive_fun(INTERP, attr->probes);
+    }
+
+/*
+
+=item C<void * get_pointer()>
+
+Returns a reference to the supervising interpreter,
+meaning the interpreter that runs the instruments.
+
+=cut
+
+*/
+
+    VTABLE void * get_pointer () {
+        Parrot_Instrument_attributes * const attr = PARROT_INSTRUMENT(SELF);
+        return attr->supervisor;
+    }
+
+/*
+
+=item C<void set_pointer(void *pc_pointer)>
+
+With the pc_pointer passed in, execute the current op at
+the given address after firing all hooks that apply.
+
+=cut
+
+*/
+
+    VTABLE void set_pointer (void *pc_pointer) {
+        opcode_t *pc = (opcode_t *) pc_pointer;
+        INTVAL hook_count, cur_hook, catchall_count, cur_catchall;
+        PMC *hooks;
+        Parrot_Instrument_attributes * const attr = PARROT_INSTRUMENT(SELF);
+        STRING *full_name;
+        
+        /* Set the full name of the op. */
+        full_name = CONST_STRING(INTERP, attr->supervised->op_info_table[*pc].full_name);
+        
+        /* Fire the catchall hooks first */
+        catchall_count = VTABLE_get_integer(INTERP, attr->op_catchall);
+        for(cur_catchall = 0; cur_catchall < catchall_count; cur_catchall++) {
+            PMC *cur_catchall_sub;
+            
+            cur_catchall_sub = VTABLE_get_pmc_keyed_int(INTERP, attr->op_catchall,
+                                                    cur_catchall);
+            if(!PMC_IS_NULL(cur_catchall_sub)) 
+                Parrot_ext_call(INTERP, cur_catchall_sub, "S->", full_name);
+        }
+        
+        /* Fire the specific probes */
+        hooks = VTABLE_get_pmc_keyed_int(INTERP, attr->op_hooks, *pc);
+        if(!PMC_IS_NULL(hooks)) {
+        
+            hook_count = VTABLE_get_integer(INTERP, hooks);
+            for(cur_hook = 0; cur_hook < hook_count; cur_hook++) {
+                PMC *cur_hook_sub;
+                
+                cur_hook_sub = VTABLE_get_pmc_keyed_int(INTERP, hooks, cur_hook);
+                if(!PMC_IS_NULL(cur_hook_sub)) 
+                    Parrot_ext_call(INTERP, cur_hook_sub, "S->", full_name);
+            }
+        }
+        
+        /* Done firing hooks */
+        return;
+    }
+
+/*
+
+=item C<void run(STRING file, PMC *args)>
+
+Loads the given file and run it with the args given.
+
+=cut
+
+*/
+
+    METHOD run (STRING file, PMC *args) {
+        PMC *entry_point;
+        int argc = 0, status;
+        char * default_argv[] = {NULL};
+        char ** argv = default_argv;
+        Parrot_Instrument_attributes * const attr = PARROT_INSTRUMENT(SELF);
+        PMC *probe_iter;
+            
+        /* If args is not null, is of type ResizableStringArray and has at
+           least 1 element, process it so we can pass it to the child interpreter.
+         */
+        if(!Parrot_pmc_is_null(INTERP, args)
+           && VTABLE_type(INTERP, args) == enum_class_ResizableStringArray
+           && VTABLE_get_integer(INTERP, args) > 0) {
+            /* There are some arguments to be passed to
+               the child interpreter. We need to convert
+               them from Parrot strings to c-strings so
+               that we can pass it to imcc.
+            */
+            
+            /* Get the number of argument values */
+            int count = VTABLE_get_integer(INTERP, args);
+            
+            /* Allocate enough memory for the argv pointer array */
+            argv = (char **) mem_gc_allocate_n_zeroed_typed(INTERP, count, char *);
+            
+            /* Populate the argv array, updating argc in the process */
+            for(argc = 0; argc < count; argc++) {
+                STRING *cur;
+                
+                cur = VTABLE_get_string_keyed_int(INTERP, args, argc);
+                argv[argc] = Parrot_str_to_cstring(INTERP, cur);
+            }
+        }
+        
+        /* Begin Execution */
+        status = imcc_run(attr->supervised,
+                    Parrot_str_cstring(attr->supervised, file),
+                    argc, (const char **) argv);
+        if (status)
+            imcc_run_pbc(attr->supervised,
+                         attr->supervised->output_file,
+                         argc,(const char **) argv);
+        
+        /* Finalize the instruments */
+        probe_iter = VTABLE_get_iter(INTERP, attr->probes);
+        while(VTABLE_get_bool(INTERP, probe_iter)) {
+            PMC *cur_probe, *finalize_sub;
+            
+            /* For the current probe, get the finalize attribute. */
+            cur_probe = VTABLE_shift_pmc(INTERP, probe_iter);
+            finalize_sub = VTABLE_get_attr_str(INTERP, cur_probe,
+                                               CONST_STRING(INTERP, "finalize"));
+            
+            /* If it is set, call that sub. */
+            if(!PMC_IS_NULL(finalize_sub)) {
+                Parrot_ext_call(INTERP, finalize_sub, "->");
+            }
+        }
+        
+        /* We should free the cstrings allocated above if needed */
+        if(argc > 0) {
+            for(; argc > 0; argc--) {
+                Parrot_str_free_cstring(argv[argc - 1]);
+                argv[argc - 1] = NULL;
+            }
+            
+            /* Free the memory allocated to hold the string pointers */
+            mem_gc_free(INTERP, argv);
+            argv = NULL;
+        }
+    }
+
+/*
+
+=item C<void attach(PMC *obj)>
+
+With the passed in object, assume it is a class with the method 'enable'
+and attribute 'instr_obj'. Set the 'instr_obj' to SELF and call the
+'enable' method of the object for the object to commence attaching the hooks.
+
+=cut
+
+*/
+
+    METHOD attach (PMC *obj) {
+        PMC *enable_method;
+        Parrot_Instrument_attributes * const attr = PARROT_INSTRUMENT(SELF);
+    
+        /* We do not care what type of object it is,
+           as long as the object has the attribute instr_obj and
+           the method enable. */
+        
+        /* Set the instrument reference attribute of the object,
+           and call its enable method. */
+        VTABLE_set_attr_str(
+            INTERP, obj,
+            CONST_STRING(INTERP, "instr_obj"),
+            SELF
+        );
+        
+        /* Find the enable method */
+        enable_method = VTABLE_find_method(INTERP, obj, CONST_STRING(INTERP, "enable"));
+        if(PMC_IS_NULL(enable_method)) {
+            /* Error! Could not find the enable method. */
+            Parrot_ex_throw_from_c_args(
+                INTERP, NULL, 1,
+                "Could not locate the method 'enable'."
+            );
+        }
+        
+        /* Call the method.
+           The first parameter to a method is the object itself.
+           The enable method will be calling insert_hooks(HASH) to register the hooks. */
+        Parrot_ext_call(INTERP, enable_method, "P->", obj);
+        
+        /* Register the probe. */
+        VTABLE_push_pmc(INTERP, attr->probes, obj);
+    }
+
+/*
+
+=item C<void *op_query(INTVAL query_type, PMC *key :optional)>
+
+Performs a op query, based on the query_type.
+0: Lookup the op number given the ops' name. Returns an array of all the indexes with that name.
+1: Returns a hash with the key and data as in the op's op_info_t entry.
+2: Returns the op's full name.
+3: Returns the op's short name.
+4: Returns an array with the type of arguments the op expects.
+5: Returns the total number of ops in the op_lib.
+
+TODO: Create a .pasm file for the constants.
+
+=cut
+
+*/
+
+    METHOD op_query (INTVAL query_type, PMC *key :optional) {
+        PMC *res;
+        Parrot_Instrument_attributes * const attr = PARROT_INSTRUMENT(SELF);
+        
+        /* Perform the required lookup */
+        switch (query_type) {
+          case OP_LOOKUP:
+            {
+                /* Given the name of the op, return its number.
+                   Name given can be either short or long name.
+                   Return value is in the form of a ResizableIntegerArray */
+                int index;
+                op_info_t *head    = attr->supervised->op_info_table;
+                STRING *name       = VTABLE_get_string(INTERP, key);
+                char const *c_name = Parrot_str_cstring(INTERP, name);
+                res                = Parrot_pmc_new(INTERP, enum_class_ResizableIntegerArray);
+
+                
+                
+                /* Find the first index of the op. */
+                index = attr->supervised->op_lib->op_code(attr->supervised, c_name, 0);
+                if(index < 0) {
+                    index = attr->supervised->op_lib->op_code(attr->supervised, c_name, 1);
+                }
+                
+                /* Check if long or short name lookups fail. */
+                if(index < 0) {
+                    break;
+                }
+                
+                /* Iterate onwards until the name does not match. */
+                do {
+                
+                    VTABLE_push_integer(INTERP, res, index);
+                    index++;
+                    
+                } while (STREQ(c_name, head[index].name)
+                         || STREQ(c_name, head[index].full_name));
+            
+                break; 
+            }
+                
+          case OP_INFO:
+            /* Returns a Hash with the op info as shown in
+               the op_info_table */
+            /* TODO */
+            res = Parrot_pmc_new(INTERP, enum_class_Undef);
+            
+            break;
+                
+          case OP_FULLNAME:
+            {
+                /* Given the op number, return the full name of the op */
+                size_t index;
+                STRING *name;
+                char const *c_name;
+                index = VTABLE_get_integer(INTERP, key);
+                
+                if(index > attr->supervised->op_lib->op_count) {
+                    /* Error! Index given is out of range. */
+                    Parrot_ex_throw_from_c_args(
+                        INTERP, NULL, 1,
+                        "Op index out of range."
+                    );
+                }
+                
+                c_name = attr->supervised->op_info_table[index].full_name;
+                name = Parrot_str_new(INTERP, c_name, strlen(c_name));
+                res  = Parrot_pmc_new(INTERP, enum_class_String);
+                
+                VTABLE_set_string_native(INTERP, res, name);
+                
+                break;
+            }
+               
+          case OP_NAME:
+            {
+                /* Given the op number, return the short name of the op */
+                size_t index;
+                STRING *name;
+                char const *c_name;
+                index = VTABLE_get_integer(INTERP, key);
+                
+                if(index > attr->supervised->op_lib->op_count) {
+                    /* Error! Index given is out of range. */
+                    Parrot_ex_throw_from_c_args(
+                        INTERP, NULL, 1,
+                        "Op index out of range."
+                    );
+                }
+                
+                c_name = attr->supervised->op_info_table[index].name;
+                name = Parrot_str_new(INTERP, c_name, strlen(c_name));
+                res  = Parrot_pmc_new(INTERP, enum_class_String);
+                
+                VTABLE_set_string_native(INTERP, res, name);
+                
+                break;
+            }
+            
+          case OP_ARGS:
+            /* Return a ResizablePMCArray with the types of arguments
+               in order of how the op expects it. */
+            /* TODO */
+            res = Parrot_pmc_new(INTERP, enum_class_Undef);
+            
+            break;
+            
+          case OP_COUNT:
+            {
+                /* Return the total number of ops in the supervised
+                   ops table */
+                INTVAL count;
+                res = Parrot_pmc_new(INTERP, enum_class_Integer);
+                count = attr->supervised->op_count;
+                VTABLE_set_integer_native(INTERP, res, count);
+                
+                break;
+            }
+        default:
+            res = Parrot_pmc_new(INTERP, enum_class_Undef);
+        }
+        
+        RETURN(PMC* res);
+    }
+
+/*
+
+=item C<void *insert_op_hooks(PMC *hook_hash)>
+
+Insert hooks based on what is given in hook_hash.
+Keys are op numbers and values are sub pmcs.
+
+=cut
+
+*/
+
+    METHOD insert_op_hooks (PMC *hook_hash) {
+        PMC *iter;
+        Parrot_Instrument_attributes * const attr = PARROT_INSTRUMENT(SELF);
+        
+        /* Iterate through hook_hash. For each
+           key (op_num), push the callback to the
+           appropriate entry in op_hooks. */
+        iter = VTABLE_get_iter(INTERP, hook_hash);
+        while(VTABLE_get_bool(INTERP, iter)) {
+            INTVAL op_num;
+            PMC *iter_key, *cur, *callback, *op_num_hooks;
+            
+            iter_key = VTABLE_shift_pmc(INTERP, iter);
+            cur      = VTABLE_get_pmc(INTERP, iter_key);
+            op_num   = VTABLE_get_integer(INTERP, cur);
+            callback = VTABLE_get_pmc_keyed(INTERP, hook_hash, cur);
+            
+            op_num_hooks = VTABLE_get_pmc_keyed_int(INTERP, attr->op_hooks, op_num);
+            if(PMC_IS_NULL(op_num_hooks)) {
+                op_num_hooks = Parrot_pmc_new(INTERP, enum_class_ResizablePMCArray);
+                VTABLE_set_pmc_keyed_int(INTERP, attr->op_hooks, op_num, op_num_hooks);
+            }
+            
+            VTABLE_push_pmc(INTERP, op_num_hooks, callback);
+        }
+    }
+
+/*
+=item C<void *insert_op_catchall(PMC *callback)>
+
+Register a catchall op callback
+
+=cut
+*/
+
+    METHOD insert_op_catchall (PMC *callback) {
+        Parrot_Instrument_attributes * const attr = PARROT_INSTRUMENT(SELF);
+        
+        VTABLE_push_pmc(INTERP, attr->op_catchall, callback);
+    }
+}
+
+/*
+ * Runcore Function Implementations
+ */
+
+/*
+ * This is the simplified custom runops function.
+ * This is based on the PARROT_FAST_RUNCORE.
+ */
+static
+opcode_t *
+Instrument_runcore_runops(PARROT_INTERP, Parrot_runcore_t *runcore, opcode_t *pc)
+{	
+    Instrument_runcore_t *core = (Instrument_runcore_t *) runcore;
+    
+    PMC *pmc = core->supervisor;
+    Parrot_Interp supervisor = (Parrot_Interp) VTABLE_get_pointer(interp, pmc);
+
+    while (pc) {
+		Parrot_pcc_set_pc(interp, CURRENT_CONTEXT(interp), pc);
+		
+		/* Fire the hooks */
+		VTABLE_set_pointer(supervisor, pmc, pc);
+
+        DO_OP(pc, interp);
+    }
+	
+    return pc;
+	
+}
+
+/*
+ * This is the initializer for the runcore.
+ * Sets up runcore_t.
+ */
+static
+void
+Instrument_runcore_init (PARROT_INTERP, PMC *supervisor) {
+	Instrument_runcore_t * const coredata =
+	    mem_gc_allocate_zeroed_typed(interp, Instrument_runcore_t);
+	
+	/* Ensure the current loaded runcore is the slow core */
+	Parrot_set_run_core(interp, PARROT_SLOW_CORE);
+	
+	/* Copy the runcore entry for the PARROT_SLOW_CORE,
+	   and then make modifications to it.
+	   Copy so that we get the opinit function pointer.
+	*/
+	mem_copy_n_typed(coredata, interp->run_core, 1, Parrot_runcore_t);
+	
+	coredata->name			= string_from_literal(interp, "instrument");
+	coredata->runops		= Instrument_runcore_runops;
+	coredata->prepare_run	= NULL;
+	coredata->destroy		= NULL;
+	coredata->flags			= 0;
+	coredata->supervisor   = supervisor;
+	
+	PARROT_RUNCORE_FUNC_TABLE_SET((Parrot_runcore_t *)coredata);
+	
+	Parrot_runcore_register(interp, (Parrot_runcore_t *) coredata);
+	
+	//Switch to this runcore.
+	Parrot_runcore_switch(interp, coredata->name);
+}
+
+/*
+ * Helper function to gather the parameters of an op
+ * and put it into the passed in ResizablePMCArray.
+ * TODO: This is incomplete and currently unused.
+ */
+static
+void
+gather_params(Parrot_Interp interp, opcode_t *pc, PMC *supervisor, PMC *params) {
+    INTVAL no_params, cur_param;
+    PMC *cc; /* Current context */
+    Parrot_Interp instr_in = (Parrot_Interp) VTABLE_get_pointer(interp, supervisor);
+    
+    /* Retrieve the current context.
+       Current context refers to the registers + some other stuff */
+    cc = CURRENT_CONTEXT(interp); /* defined in parrot/interpreter.h */
+    
+    /* Figure out how many parameters the op takes,
+        referring to op_info_table
+        We want the op_count field of the current op's
+        op_info_t, which also includes the op as a parameter. */
+    no_params = interp->op_info_table[*pc].op_count - 1;
+     
+    /* Begin gathering the parameters.
+       Each parameter is of a certain type, and based on this
+       type, we can access the current_context and get the
+       parameter.
+       
+       The types are listed in parrot/op.h.
+    */
+    for(cur_param = 0; cur_param < no_params; cur_param++) {
+        arg_type_t type; /* parrot/op.h */
+        
+        /* Get the type of the current param */
+        type = interp->op_info_table[*pc].types[cur_param];
+        
+        /* For keyed types, remove the keyed flag,
+           instead treating it as a normal ARG type. */
+        if((type & PARROT_ARG_KEYED) == PARROT_ARG_KEYED) {
+            type &= ~PARROT_ARG_KEYED;
+        }
+        
+        /* Gather the params and put it into the
+           ResizablePMCArray pointed to by params.
+         */
+        switch(type) {
+          case PARROT_ARG_IC:            
+            /* Integer constants are stored as part of the opcode
+               in the packfile */
+            VTABLE_push_integer(instr_in, params, pc[cur_param + 1]);
+            
+            break;
+          case PARROT_ARG_I:
+            VTABLE_push_integer(instr_in, params,
+                                *Parrot_pcc_get_INTVAL_reg(interp, cc, pc[cur_param + 1]));
+            break;
+          case PARROT_ARG_NC:
+            VTABLE_push_float(instr_in, params,
+                              Parrot_pcc_get_num_constant_func(interp, cc, pc[cur_param + 1]));
+            
+            break;
+          case PARROT_ARG_N:
+            VTABLE_push_float(instr_in, params,
+                              *Parrot_pcc_get_FLOATVAL_reg(interp, cc, pc[cur_param + 1]));
+            break;
+          case PARROT_ARG_PC:
+            VTABLE_push_pmc(instr_in, params,
+                              Parrot_pcc_get_pmc_constant_func(interp, cc, pc[cur_param + 1]));
+            
+            break;
+          case PARROT_ARG_P:
+            VTABLE_push_pmc(instr_in, params,
+                              *Parrot_pcc_get_PMC_reg(interp, cc, pc[cur_param + 1]));
+            break;
+          case PARROT_ARG_SC:
+            VTABLE_push_string(instr_in, params,
+                              Parrot_pcc_get_string_constant_func(interp, cc, pc[cur_param + 1]));
+            
+            break;
+          case PARROT_ARG_S:
+            VTABLE_push_string(instr_in, params,
+                              *Parrot_pcc_get_STRING_reg(interp, cc, pc[cur_param + 1]));
+            break;
+          default:
+            /* printf("\tUnhandled arg type: %d\n", type); */
+            break;
+        };
+     }
+}
+
+/*
+=back
+
+=head1 SEE ALS0
+
+=cut
+*/
+
+/*
+ * Local Variables:
+ *   c-file-style: "parrot"
+ * End:
+ * vim: expandtab shiftwidth=4:
+ */


More information about the parrot-commits mailing list