[svn:parrot] r41081 - in trunk: . compilers/imcc config/gen config/gen/makefiles config/gen/platform config/gen/platform/generic config/gen/platform/win32 config/init config/init/hints include/parrot src src/call src/gc src/interp src/ops src/pmc src/runcore t/op t/run tools/dev

bacek at svn.parrot.org bacek at svn.parrot.org
Sun Sep 6 20:40:18 UTC 2009


Author: bacek
Date: Sun Sep  6 20:40:14 2009
New Revision: 41081
URL: https://trac.parrot.org/parrot/changeset/41081

Log:
Merge pluggable_runcore branch into trunk.

Added:
   trunk/config/gen/platform/generic/hires_timer.c
   trunk/config/gen/platform/win32/hires_timer.c
   trunk/tools/dev/pprof2cg.pl
Modified:
   trunk/MANIFEST
   trunk/compilers/imcc/main.c
   trunk/config/gen/makefiles/root.in
   trunk/config/gen/platform.pm
   trunk/config/gen/platform/platform_interface.h
   trunk/config/init/defaults.pm
   trunk/config/init/hints/linux.pm
   trunk/config/init/hints/mswin32.pm
   trunk/config/init/hints/openbsd.pm
   trunk/config/init/hints/solaris.pm
   trunk/include/parrot/interpreter.h
   trunk/include/parrot/pic.h
   trunk/include/parrot/runcore_api.h
   trunk/src/call/pcc.c
   trunk/src/debug.c
   trunk/src/embed.c
   trunk/src/exceptions.c
   trunk/src/exec_start.c
   trunk/src/gc/alloc_resources.c
   trunk/src/gc/gc_malloc.c
   trunk/src/gc/gc_ms.c
   trunk/src/gc/gc_private.h
   trunk/src/gc/incremental_ms.c
   trunk/src/gc/mark_sweep.c
   trunk/src/interp/inter_create.c
   trunk/src/interp/inter_misc.c
   trunk/src/ops/core.ops
   trunk/src/packfile.c
   trunk/src/parrot_debugger.c
   trunk/src/pic.c
   trunk/src/pic_jit.c
   trunk/src/pmc/parrotinterpreter.pmc
   trunk/src/runcore/cores.c
   trunk/src/runcore/main.c
   trunk/src/sub.c
   trunk/t/op/gc.t
   trunk/t/run/options.t

Modified: trunk/MANIFEST
==============================================================================
--- trunk/MANIFEST	Sun Sep  6 20:31:13 2009	(r41080)
+++ trunk/MANIFEST	Sun Sep  6 20:40:14 2009	(r41081)
@@ -1,7 +1,7 @@
 # ex: set ro:
 # $Id$
 #
-# generated by tools/dev/mk_manifest_and_skip.pl Sun Aug 30 20:35:30 2009 UT
+# generated by tools/dev/mk_manifest_and_skip.pl Sun Sep  6 08:59:05 2009 UT
 #
 # See below for documentation on the format of this file.
 #
@@ -341,6 +341,7 @@
 config/gen/platform/generic/dl.h                            []
 config/gen/platform/generic/env.c                           []
 config/gen/platform/generic/exec.c                          []
+config/gen/platform/generic/hires_timer.c                   []
 config/gen/platform/generic/io.h                            []
 config/gen/platform/generic/itimer.c                        []
 config/gen/platform/generic/math.c                          []
@@ -368,6 +369,7 @@
 config/gen/platform/win32/dl.c                              []
 config/gen/platform/win32/env.c                             []
 config/gen/platform/win32/exec.c                            []
+config/gen/platform/win32/hires_timer.c                     []
 config/gen/platform/win32/io.h                              []
 config/gen/platform/win32/misc.c                            []
 config/gen/platform/win32/misc.h                            []
@@ -1885,6 +1887,7 @@
 t/pmc/managedstruct.t                                       [test]
 t/pmc/multidispatch.t                                       [test]
 t/pmc/multisub.t                                            [test]
+t/pmc/namespace-old.t                                       [test]
 t/pmc/namespace.t                                           [test]
 t/pmc/namespace-old.t                                       [test]
 t/pmc/nci.t                                                 [test]
@@ -2161,6 +2164,7 @@
 tools/dev/pbc_to_exe.pir                                    [devel]
 tools/dev/pmcrenumber.pl                                    []
 tools/dev/pmctree.pl                                        []
+tools/dev/pprof2cg.pl                                       []
 tools/dev/reconfigure.pl                                    [devel]
 tools/dev/search-ops.pl                                     []
 tools/dev/svnclobber.pl                                     []

Modified: trunk/compilers/imcc/main.c
==============================================================================
--- trunk/compilers/imcc/main.c	Sun Sep  6 20:31:13 2009	(r41080)
+++ trunk/compilers/imcc/main.c	Sun Sep  6 20:40:14 2009	(r41081)
@@ -33,6 +33,7 @@
 #include "parrot/embed.h"
 #include "parrot/longopt.h"
 #include "parrot/imcc.h"
+#include "parrot/runcore_api.h"
 #include "pbc.h"
 #include "parser.h"
 
@@ -279,7 +280,6 @@
 #define SET_FLAG(flag)   Parrot_set_flag(interp, (flag))
 #define SET_DEBUG(flag)  Parrot_set_debug(interp, (flag))
 #define SET_TRACE(flag)  Parrot_set_trace(interp, (flag))
-#define SET_CORE(core)   interp->run_core |= (core)
 
 #define OPT_GC_DEBUG       128
 #define OPT_DESTROY_FLAG   129
@@ -356,8 +356,10 @@
 const char *
 parseflags(PARROT_INTERP, int *argc, char **argv[])
 {
-    struct longopt_opt_info opt = LONGOPT_OPT_INFO_INIT;
-    int   status;
+    struct longopt_opt_info opt  = LONGOPT_OPT_INFO_INIT;
+    INTVAL                  core = 0;
+    int                     status;
+
     if (*argc == 1) {
         usage(stderr);
         exit(EXIT_SUCCESS);
@@ -370,34 +372,29 @@
         switch (opt.opt_id) {
             case 'R':
                 if (STREQ(opt.opt_arg, "slow") || STREQ(opt.opt_arg, "bounds"))
-                    SET_CORE(PARROT_SLOW_CORE);
+                    core |= PARROT_SLOW_CORE;
                 else if (STREQ(opt.opt_arg, "fast") || STREQ(opt.opt_arg, "function"))
-                    SET_CORE(PARROT_FAST_CORE);
+                    core |= PARROT_FAST_CORE;
                 else if (STREQ(opt.opt_arg, "switch"))
-                    SET_CORE(PARROT_SWITCH_CORE);
+                    core |= PARROT_SWITCH_CORE;
                 else if (STREQ(opt.opt_arg, "cgp"))
-                    SET_CORE(PARROT_CGP_CORE);
+                    core |= PARROT_CGP_CORE;
                 else if (STREQ(opt.opt_arg, "cgoto"))
-                    SET_CORE(PARROT_CGOTO_CORE);
+                    core |= PARROT_CGOTO_CORE;
                 else if (STREQ(opt.opt_arg, "jit"))
-                    SET_CORE(PARROT_JIT_CORE);
+                    core |= PARROT_JIT_CORE;
                 else if (STREQ(opt.opt_arg, "cgp-jit"))
-                    SET_CORE(PARROT_CGP_JIT_CORE);
+                    core |= PARROT_CGP_JIT_CORE;
                 else if (STREQ(opt.opt_arg, "switch-jit"))
-                    SET_CORE(PARROT_SWITCH_JIT_CORE);
+                    core |= PARROT_SWITCH_JIT_CORE;
                 else if (STREQ(opt.opt_arg, "exec"))
-                    SET_CORE(PARROT_EXEC_CORE);
-                else if (STREQ(opt.opt_arg, "trace")) {
-                    SET_CORE(PARROT_SLOW_CORE);
-#ifdef HAVE_COMPUTED_GOTO
-                    SET_CORE(PARROT_CGP_CORE);
-#endif
-#if JIT_CAPABLE
-                    SET_CORE(PARROT_JIT_CORE);
-#endif
-                }
+                    core |= PARROT_EXEC_CORE;
+                else if (STREQ(opt.opt_arg, "trace"))
+                    core |= PARROT_SLOW_CORE;
+                else if (STREQ(opt.opt_arg, "profiling"))
+                    core  = PARROT_PROFILING_CORE;
                 else if (STREQ(opt.opt_arg, "gcdebug"))
-                    SET_CORE(PARROT_GC_DEBUG_CORE);
+                    core |= PARROT_GC_DEBUG_CORE;
                 else
                     Parrot_ex_throw_from_c_args(interp, NULL, 1,
                         "main: Unrecognized runcore '%s' specified."
@@ -498,7 +495,7 @@
                 IMCC_INFO(interp)->allocator = IMCC_GRAPH_ALLOCATOR;
                 /* currently not ok due to different register allocation */
                 if (strchr(opt.opt_arg, 'j')) {
-                    SET_CORE(PARROT_JIT_CORE);
+                    core |= PARROT_JIT_CORE;
                 }
                 if (strchr(opt.opt_arg, '1')) {
                     IMCC_INFO(interp)->optimizer_level |= OPT_PRE;
@@ -507,12 +504,12 @@
                     IMCC_INFO(interp)->optimizer_level |= (OPT_PRE | OPT_CFG);
                 }
                 if (strchr(opt.opt_arg, 't')) {
-                    SET_CORE(PARROT_SWITCH_CORE);
+                    core |= PARROT_SWITCH_CORE;
 #ifdef HAVE_COMPUTED_GOTO
-                    SET_CORE(PARROT_CGP_CORE);
+                    core |= PARROT_CGP_CORE;
 #endif
 #if JIT_CAPABLE
-                    SET_CORE(PARROT_JIT_CORE);
+                    core |= PARROT_JIT_CORE;
 #endif
                 }
                 break;
@@ -546,11 +543,13 @@
                     (*argv)[0]);
         }
     }
+
     if (status == -1) {
         fprintf(stderr, "%s\n", opt.opt_error);
         usage(stderr);
         exit(EX_USAGE);
     }
+
     /* reached the end of the option list and consumed all of argv */
     if (*argc == opt.opt_index) {
         if (interp->output_file) {
@@ -563,9 +562,11 @@
         usage(stderr);
         exit(EX_USAGE);
     }
+
     *argc -= opt.opt_index;
     *argv += opt.opt_index;
 
+    Parrot_set_run_core(interp, (Parrot_Run_core_t) core);
     return (*argv)[0];
 }
 
@@ -719,10 +720,10 @@
     if (opt_level & OPT_SUB)
         opt_desc[i++] = 'c';
 
-    if (interp->run_core & PARROT_JIT_CORE)
+    if (PARROT_RUNCORE_JIT_OPS_TEST(interp->run_core))
         opt_desc[i++] = 'j';
 
-    if (interp->run_core & PARROT_SWITCH_CORE)
+    if (PARROT_RUNCORE_PREDEREF_OPS_TEST(interp->run_core))
         opt_desc[i++] = 't';
 
     opt_desc[i] = '\0';

Modified: trunk/config/gen/makefiles/root.in
==============================================================================
--- trunk/config/gen/makefiles/root.in	Sun Sep  6 20:31:13 2009	(r41080)
+++ trunk/config/gen/makefiles/root.in	Sun Sep  6 20:40:14 2009	(r41081)
@@ -103,7 +103,7 @@
 CC_INC           := @cc_inc@
 C_LIBS           := @libs@
 CC_SHARED        := @cc_shared@
-CFLAGS           := $(CC_INC) @ccflags@ @cc_debug@ @ccwarn@ @cc_hasjit@ @cg_flag@ @gc_flag@ $(CC_SHARED)
+CFLAGS           := $(CC_INC) @ccflags@ @cc_debug@ @ccwarn@ @cc_hasjit@ @cg_flag@ @gc_flag@ @clock_best@ $(CC_SHARED)
 LINK_DYNAMIC     := @link_dynamic@
 LINK             := @link@
 LINKFLAGS        := @linkflags@ @link_debug@ @ld_debug@
@@ -635,6 +635,7 @@
     $(SRC_DIR)/pmc.str \
     $(SRC_DIR)/pmc_freeze.str \
     $(SRC_DIR)/oo.str \
+    $(SRC_DIR)/runcore/cores.str \
     $(SRC_DIR)/scheduler.str \
     $(SRC_DIR)/spf_render.str \
     $(SRC_DIR)/spf_vtable.str \
@@ -1197,7 +1198,8 @@
 
 $(SRC_DIR)/gc/alloc_register$(O) : $(GENERAL_H_FILES) $(SRC_DIR)/pmc/pmc_sub.h
 
-$(SRC_DIR)/runcore/cores$(O) : $(GENERAL_H_FILES)
+$(SRC_DIR)/runcore/cores$(O) : $(GENERAL_H_FILES) $(SRC_DIR)/runcore/cores.str \
+	$(SRC_DIR)/pmc/pmc_sub.h
 
 $(SRC_DIR)/tsq$(O) : $(GENERAL_H_FILES)
 

Modified: trunk/config/gen/platform.pm
==============================================================================
--- trunk/config/gen/platform.pm	Sun Sep  6 20:31:13 2009	(r41080)
+++ trunk/config/gen/platform.pm	Sun Sep  6 20:40:14 2009	(r41081)
@@ -223,6 +223,7 @@
         memexec.c
         exec.c
         misc.c
+        hires_timer.c
         /;
 
     my $plat_c = q{src/platform.c};

Added: trunk/config/gen/platform/generic/hires_timer.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ trunk/config/gen/platform/generic/hires_timer.c	Sun Sep  6 20:40:14 2009	(r41081)
@@ -0,0 +1,76 @@
+/*
+ * $Id$
+ * Copyright (C) 2009, Parrot Foundation.
+ */
+
+/*
+
+=head1 NAME
+
+config/gen/platform/generic/hires_timer.c
+
+=head1 DESCRIPTION
+
+High-resolution timer support
+
+=head2 Functions
+
+=over 4
+
+=cut
+
+*/
+
+#include <time.h>
+
+#define TIME_IN_NS(n) ((n).tv_sec * 1000*1000*1000 + (n).tv_nsec)
+
+/*
+
+=item C<UHUGEINTVAL Parrot_hires_get_time()>
+
+Return a high-resolution number representing how long Parrot has been running.
+
+=cut
+
+*/
+
+UHUGEINTVAL Parrot_hires_get_time()
+{
+    struct timespec ts;
+    clock_gettime(CLOCK_BEST, &ts);
+    return TIME_IN_NS(ts);
+}
+
+/*
+
+=item C<UINTVAL Parrot_hires_get_tick_duration()>
+
+Return the number of ns that each time unit from Parrot_hires_get_time represents.
+
+=cut
+
+*/
+
+UINTVAL Parrot_hires_get_tick_duration()
+{
+    return (UINTVAL) 1;
+}
+
+
+
+
+/*
+
+=back
+
+=cut
+
+*/
+
+/*
+ * Local variables:
+ *   c-file-style: "parrot"
+ * End:
+ * vim: expandtab shiftwidth=4:
+ */

Modified: trunk/config/gen/platform/platform_interface.h
==============================================================================
--- trunk/config/gen/platform/platform_interface.h	Sun Sep  6 20:31:13 2009	(r41080)
+++ trunk/config/gen/platform/platform_interface.h	Sun Sep  6 20:40:14 2009	(r41081)
@@ -126,6 +126,13 @@
 
 #endif
 
+/*
+ * high-resolution timer support
+ */
+
+UHUGEINTVAL Parrot_hires_get_time(void);
+UINTVAL     Parrot_hires_get_tick_duration(void);
+
 
 struct parrot_string_t;
 INTVAL Parrot_Run_OS_Command(Interp*, struct parrot_string_t *);

Added: trunk/config/gen/platform/win32/hires_timer.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ trunk/config/gen/platform/win32/hires_timer.c	Sun Sep  6 20:40:14 2009	(r41081)
@@ -0,0 +1,70 @@
+/*
+ * $Id$
+ * Copyright (C) 2009, Parrot Foundation.
+ */
+
+/*
+
+=head1 NAME
+
+config/gen/platform/win32/hires_timer.c
+
+=head1 DESCRIPTION
+
+High-resolution timer support for win32
+
+=head2 Functions
+
+=over 4
+
+=item C<UHUGEINTVAL Parrot_hires_get_time()>
+
+Return a high-resolution number representing how long Parrot has been running.
+
+=cut
+
+*/
+
+UHUGEINTVAL Parrot_hires_get_time()
+{
+    LARGE_INTEGER ticks;
+    QueryPerformanceCounter(&ticks);
+    return (UHUGEINTVAL) ticks.QuadPart;
+}
+
+/*
+
+=item C<UINTVAL Parrot_hires_get_tick_duration()>
+
+Return the number of nanoseconds that each time unit from Parrot_hires_get_time represents.
+
+=cut
+
+*/
+
+UINTVAL Parrot_hires_get_tick_duration()
+{
+    LARGE_INTEGER ticks;
+    /* QueryPerformanceCounter returns ticks per second, so divide 1 billion by
+     * that to find the length of each tick */
+    QueryPerformanceFrequency(&ticks);
+    return (UINTVAL) (1000*1000*1000 / ticks.QuadPart);
+}
+
+
+
+
+/*
+
+=back
+
+=cut
+
+*/
+
+/*
+ * Local variables:
+ *   c-file-style: "parrot"
+ * End:
+ * vim: expandtab shiftwidth=4:
+ */

Modified: trunk/config/init/defaults.pm
==============================================================================
--- trunk/config/init/defaults.pm	Sun Sep  6 20:31:13 2009	(r41080)
+++ trunk/config/init/defaults.pm	Sun Sep  6 20:40:14 2009	(r41081)
@@ -256,6 +256,9 @@
         );
     }
 
+    #clock_id used to call the clock_gettime() in the profiling runcore.
+    $conf->data->set( clock_best => '-DCLOCK_BEST=CLOCK_PROF' );
+
     $conf->data->set( 'archname', $Config{archname});
     # adjust archname, cc and libs for e.g. --m=32
     # RT#41499 this is maybe gcc only

Modified: trunk/config/init/hints/linux.pm
==============================================================================
--- trunk/config/init/hints/linux.pm	Sun Sep  6 20:31:13 2009	(r41080)
+++ trunk/config/init/hints/linux.pm	Sun Sep  6 20:40:14 2009	(r41081)
@@ -23,9 +23,12 @@
     # should find g++ in most cases
     my $link = $conf->data->get('link') || 'c++';
 
-    if ( $libs !~ /-lpthread/ ) {
+    if ( $libs !~ /-lpthread\b/ ) {
         $libs .= ' -lpthread';
     }
+    if ( $libs !~ /-lrt\b/ ) {
+        $libs .= ' -lrt';
+    }
     my $ld_share_flags = $conf->data->get('ld_share_flags');
     my $cc_shared      = $conf->data->get('cc_shared');
 
@@ -149,6 +152,8 @@
         libparrot_soname       => "-Wl,-soname=libparrot$share_ext.$version",
     );
 
+    $conf->data->set( clock_best => '-DCLOCK_BEST=CLOCK_PROCESS_CPUTIME_ID' );
+
      if ( ( split( m/-/, $conf->data->get_p5('archname'), 2 ) )[0] eq 'ia64' ) {
 
         $conf->data->set( platform_asm => 1 );

Modified: trunk/config/init/hints/mswin32.pm
==============================================================================
--- trunk/config/init/hints/mswin32.pm	Sun Sep  6 20:31:13 2009	(r41080)
+++ trunk/config/init/hints/mswin32.pm	Sun Sep  6 20:40:14 2009	(r41081)
@@ -45,6 +45,8 @@
         $conf->data->set( bindir => Win32::GetShortPathName($bindir) );
     }
 
+    $conf->data->set( clock_best => ' ' );
+
     if ($is_msvc) {
         my $msvcversion = $conf->data->get('msvcversion');
 

Modified: trunk/config/init/hints/openbsd.pm
==============================================================================
--- trunk/config/init/hints/openbsd.pm	Sun Sep  6 20:31:13 2009	(r41080)
+++ trunk/config/init/hints/openbsd.pm	Sun Sep  6 20:40:14 2009	(r41081)
@@ -37,6 +37,7 @@
         $conf->data->set( as => 'as -mregnames' );
     }
 
+    $conf->data->set( clock_best => '-DCLOCK_BEST=CLOCK_MONOTONIC' );
 }
 
 1;

Modified: trunk/config/init/hints/solaris.pm
==============================================================================
--- trunk/config/init/hints/solaris.pm	Sun Sep  6 20:31:13 2009	(r41080)
+++ trunk/config/init/hints/solaris.pm	Sun Sep  6 20:40:14 2009	(r41081)
@@ -17,6 +17,7 @@
         $libs .= ' -lrt';    # Needed for sched_yield.
     }
     $conf->data->set( libs => $libs );
+    $conf->data->set( clock_best => '-DCLOCK_BEST=CLOCK_PROCESS_CPUTIME_ID' );
 
     ################################################################
     # If we're going to be using ICU (or any other C++-compiled library) we

Modified: trunk/include/parrot/interpreter.h
==============================================================================
--- trunk/include/parrot/interpreter.h	Sun Sep  6 20:31:13 2009	(r41080)
+++ trunk/include/parrot/interpreter.h	Sun Sep  6 20:40:14 2009	(r41081)
@@ -72,7 +72,8 @@
     PARROT_SWITCH_JIT_CORE  = 0x12,         /* J P                */
     PARROT_EXEC_CORE        = 0x20,         /* TODO Parrot_exec_run variants */
     PARROT_GC_DEBUG_CORE    = 0x40,         /* run GC before each op */
-    PARROT_DEBUGGER_CORE    = 0x80          /* used by parrot debugger */
+    PARROT_DEBUGGER_CORE    = 0x80,         /* used by parrot debugger */
+    PARROT_PROFILING_CORE   = 0x160         /* used by parrot debugger */
 } Parrot_Run_core_t;
 /* &end_gen */
 
@@ -146,33 +147,6 @@
     Warnings_classes classes;
 } *Warnings;
 
-/* ProfData have these extra items in front followed by
- * one entry per op at (op + extra) */
-
-typedef enum {
-     PARROT_PROF_GC_p1,        /* pass 1 mark root set */
-     PARROT_PROF_GC_p2,        /* pass 2 mark next_for_GC */
-     PARROT_PROF_GC_cp,        /* collect PMCs */
-     PARROT_PROF_GC_cb,        /* collect buffers */
-     PARROT_PROF_GC,
-     PARROT_PROF_EXCEPTION,
-     PARROT_PROF_EXTRA
-} profile_extra_enum;
-
-/* data[op_count] is time spent for exception handling */
-typedef struct ProfData {
-    int op;
-    UINTVAL numcalls;
-    FLOATVAL time;
-} ProfData;
-
-typedef struct _RunProfile {
-    FLOATVAL starttime;
-    FLOATVAL gc_time;
-    opcode_t cur_op;
-    ProfData *data;
-} RunProfile;
-
 /* Forward declaration for imc_info_t -- the actual struct is
  * defined in imcc/imc.h */
 struct _imc_info_t;
@@ -252,10 +226,9 @@
 
     UINTVAL debug_flags;                      /* debug settings */
 
-    INTVAL run_core;                          /* type of core to run the ops */
-
-    /* TODO profile per code segment or global */
-    RunProfile *profile;                      /* profile counters */
+    struct runcore_t  *run_core;              /* type of core to run the ops */
+    struct runcore_t **cores;                 /* array of known runcores */
+    UINTVAL            num_cores;             /* number of known runcores */
 
     INTVAL resume_flag;
     size_t resume_offset;
@@ -609,8 +582,7 @@
     void *prederef_arena);
 void prepare_for_run(PARROT_INTERP);
 void *init_jit(PARROT_INTERP, opcode_t *pc);
-PARROT_EXPORT void dynop_register(PARROT_INTERP, PMC* op_lib);
-void do_prederef(void **pc_prederef, PARROT_INTERP, int type);
+PARROT_EXPORT void dynop_register(PARROT_INTERP, PMC *op_lib);
 
 /* interpreter.pmc */
 void clone_interpreter(Parrot_Interp dest, Parrot_Interp self, INTVAL flags);

Modified: trunk/include/parrot/pic.h
==============================================================================
--- trunk/include/parrot/pic.h	Sun Sep  6 20:31:13 2009	(r41080)
+++ trunk/include/parrot/pic.h	Sun Sep  6 20:40:14 2009	(r41081)
@@ -13,6 +13,8 @@
 #ifndef PARROT_PIC_H_GUARD
 #define PARROT_PIC_H_GUARD
 
+#include "parrot/runcore_api.h"
+
 /*
  * one cache slot
  *
@@ -125,9 +127,10 @@
 void parrot_PIC_prederef(PARROT_INTERP,
     opcode_t op,
     ARGOUT(void **pc_pred),
-    int core)
+    ARGIN(Parrot_runcore_t *core))
         __attribute__nonnull__(1)
         __attribute__nonnull__(3)
+        __attribute__nonnull__(4)
         FUNC_MODIFIES(*pc_pred);
 
 #define ASSERT_ARGS_parrot_PIC_alloc_mic __attribute__unused__ int _ASSERT_ARGS_CHECK = 0
@@ -153,7 +156,8 @@
        PARROT_ASSERT_ARG(interp)
 #define ASSERT_ARGS_parrot_PIC_prederef __attribute__unused__ int _ASSERT_ARGS_CHECK = \
        PARROT_ASSERT_ARG(interp) \
-    || PARROT_ASSERT_ARG(pc_pred)
+    || PARROT_ASSERT_ARG(pc_pred) \
+    || PARROT_ASSERT_ARG(core)
 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
 /* HEADERIZER END: src/pic.c */
 

Modified: trunk/include/parrot/runcore_api.h
==============================================================================
--- trunk/include/parrot/runcore_api.h	Sun Sep  6 20:31:13 2009	(r41080)
+++ trunk/include/parrot/runcore_api.h	Sun Sep  6 20:40:14 2009	(r41081)
@@ -9,11 +9,136 @@
 #ifndef PARROT_RUNCORE_API_H_GUARD
 #define PARROT_RUNCORE_API_H_GUARD
 
+struct runcore_t;
+typedef struct runcore_t Parrot_runcore_t;
+
+struct profiling_runcore_t;
+typedef struct profiling_runcore_t Parrot_profiling_runcore_t;
+
 #include "parrot/parrot.h"
 #include "parrot/op.h"
 
 #  define DO_OP(PC, INTERP) ((PC) = (((INTERP)->op_func_table)[*(PC)])((PC), (INTERP)))
 
+typedef opcode_t * (*runcore_runops_fn_type) (PARROT_INTERP, ARGIN(Parrot_runcore_t *), ARGIN(opcode_t *pc));
+typedef       void (*runcore_destroy_fn_type)(PARROT_INTERP, ARGIN(Parrot_runcore_t *));
+typedef     void * (*runcore_prepare_fn_type)(PARROT_INTERP, ARGIN(Parrot_runcore_t *));
+
+typedef runcore_runops_fn_type  Parrot_runcore_runops_fn_t;
+typedef runcore_destroy_fn_type Parrot_runcore_destroy_fn_t;
+typedef runcore_prepare_fn_type Parrot_runcore_prepare_fn_t;
+
+struct 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;
+};
+
+
+typedef enum Parrot_profiling_flags {
+    PROFILING_EXIT_CHECK_FLAG       = 1 << 0,
+    PROFILING_FIRST_LOOP_FLAG       = 1 << 1,
+    PROFILING_HAVE_PRINTED_CLI_FLAG = 1 << 2
+} Parrot_profiling_flags;
+
+struct profiling_runcore_t {
+    STRING                      *name;
+    int                          id;
+    oplib_init_f                 opinit;
+    Parrot_runcore_runops_fn_t   runops;
+    Parrot_runcore_destroy_fn_t  destroy;
+    Parrot_runcore_prepare_fn_t  prepare_run;
+    INTVAL                       flags;
+
+    /* end of common members */
+    UHUGEINTVAL     runcore_start;
+    UHUGEINTVAL     op_start;
+    UHUGEINTVAL     op_finish;
+    UHUGEINTVAL     runcore_finish;
+    INTVAL          profiling_flags;
+    INTVAL          runloop_count;
+    FILE           *profile_fd;
+    STRING         *profile_filename;
+    PMC            *prev_sub;
+    Parrot_Context *prev_ctx;
+    UINTVAL         level;      /* how many nested runloops */
+    UINTVAL         time_size;  /* how big is the following array */
+    UHUGEINTVAL    *time;       /* time spent between DO_OP and start/end of a runcore */
+};
+
+
+typedef enum Parrot_runcore_flags {
+    RUNCORE_REENTRANT_FLAG    = 1 << 0,
+    RUNCORE_FUNC_TABLE_FLAG   = 1 << 1,
+    RUNCORE_EVENT_CHECK_FLAG  = 1 << 2,
+    RUNCORE_PREDEREF_OPS_FLAG = 1 << 3,
+    RUNCORE_CGOTO_OPS_FLAG    = 1 << 4,
+    RUNCORE_JIT_OPS_FLAG      = 1 << 5
+} Parrot_runcore_flags;
+
+
+#define Profiling_flag_SET(runcore, flag) \
+    ((runcore)->profiling_flags |= flag)
+#define Profiling_flag_TEST(runcore, flag) \
+    ((runcore)->profiling_flags & flag)
+#define Profiling_flag_CLEAR(runcore, flag) \
+    ((runcore)->profiling_flags &= ~(flag))
+
+#define Profiling_exit_check_TEST(o) \
+    Profiling_flag_TEST(o, PROFILING_EXIT_CHECK_FLAG)
+#define Profiling_exit_check_SET(o) \
+    Profiling_flag_SET(o, PROFILING_EXIT_CHECK_FLAG)
+#define Profiling_exit_check_CLEAR(o) \
+    Profiling_flag_CLEAR(o, PROFILING_EXIT_CHECK_FLAG)
+
+#define Profiling_first_loop_TEST(o) \
+    Profiling_flag_TEST(o, PROFILING_FIRST_LOOP_FLAG)
+#define Profiling_first_loop_SET(o) \
+    Profiling_flag_SET(o, PROFILING_FIRST_LOOP_FLAG)
+#define Profiling_first_loop_CLEAR(o) \
+    Profiling_flag_CLEAR(o, PROFILING_FIRST_LOOP_FLAG)
+
+#define Profiling_have_printed_cli_TEST(o) \
+    Profiling_flag_TEST(o, PROFILING_HAVE_PRINTED_CLI_FLAG)
+#define Profiling_have_printed_cli_SET(o) \
+    Profiling_flag_SET(o, PROFILING_HAVE_PRINTED_CLI_FLAG)
+#define Profiling_have_printed_cli_CLEAR(o) \
+    Profiling_flag_CLEAR(o, PROFILING_HAVE_PRINTED_CLI_FLAG)
+
+#define Runcore_flag_SET(runcore, flag) \
+    ((runcore)->flags |= flag)
+#define Runcore_flag_TEST(runcore, flag) \
+    ((runcore)->flags & flag)
+
+#define PARROT_RUNCORE_FUNC_TABLE_TEST(runcore) \
+    Runcore_flag_TEST(runcore, RUNCORE_FUNC_TABLE_FLAG)
+#define PARROT_RUNCORE_FUNC_TABLE_SET(runcore) \
+    Runcore_flag_SET(runcore, RUNCORE_FUNC_TABLE_FLAG)
+
+#define PARROT_RUNCORE_EVENT_CHECK_TEST(runcore) \
+    Runcore_flag_TEST(runcore, RUNCORE_EVENT_CHECK_FLAG)
+#define PARROT_RUNCORE_EVENT_CHECK_SET(runcore) \
+    Runcore_flag_SET(runcore, RUNCORE_EVENT_CHECK_FLAG)
+
+#define PARROT_RUNCORE_PREDEREF_OPS_TEST(runcore) \
+    Runcore_flag_TEST(runcore, RUNCORE_PREDEREF_OPS_FLAG)
+#define PARROT_RUNCORE_PREDEREF_OPS_SET(runcore) \
+    Runcore_flag_SET(runcore, RUNCORE_PREDEREF_OPS_FLAG)
+
+#define PARROT_RUNCORE_CGOTO_OPS_TEST(runcore) \
+    Runcore_flag_TEST(runcore, RUNCORE_CGOTO_OPS_FLAG)
+#define PARROT_RUNCORE_CGOTO_OPS_SET(runcore) \
+    Runcore_flag_SET(runcore, RUNCORE_CGOTO_OPS_FLAG)
+
+#define PARROT_RUNCORE_JIT_OPS_TEST(runcore) \
+    Runcore_flag_TEST(runcore, RUNCORE_JIT_OPS_FLAG)
+#define PARROT_RUNCORE_JIT_OPS_SET(runcore) \
+    Runcore_flag_SET(runcore, RUNCORE_JIT_OPS_FLAG)
+
 /* HEADERIZER BEGIN: src/runcore/main.c */
 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
 
@@ -25,10 +150,25 @@
 void enable_event_checking(PARROT_INTERP)
         __attribute__nonnull__(1);
 
-void do_prederef(ARGIN(void **pc_prederef), PARROT_INTERP, int type)
+PARROT_EXPORT
+INTVAL Parrot_runcore_register(PARROT_INTERP,
+    ARGIN(Parrot_runcore_t *coredata))
         __attribute__nonnull__(1)
         __attribute__nonnull__(2);
 
+PARROT_EXPORT
+void Parrot_runcore_switch(PARROT_INTERP, ARGIN(STRING *name))
+        __attribute__nonnull__(1)
+        __attribute__nonnull__(2);
+
+void do_prederef(
+    ARGIN(void **pc_prederef),
+    PARROT_INTERP,
+    ARGIN(Parrot_runcore_t *runcore))
+        __attribute__nonnull__(1)
+        __attribute__nonnull__(2)
+        __attribute__nonnull__(3);
+
 void dynop_register(PARROT_INTERP, ARGIN(PMC *lib_pmc))
         __attribute__nonnull__(1)
         __attribute__nonnull__(2);
@@ -45,6 +185,9 @@
 void Parrot_runcore_destroy(PARROT_INTERP)
         __attribute__nonnull__(1);
 
+void Parrot_runcore_init(PARROT_INTERP)
+        __attribute__nonnull__(1);
+
 void Parrot_setup_event_func_ptrs(PARROT_INTERP)
         __attribute__nonnull__(1);
 
@@ -58,9 +201,16 @@
        PARROT_ASSERT_ARG(interp)
 #define ASSERT_ARGS_enable_event_checking __attribute__unused__ int _ASSERT_ARGS_CHECK = \
        PARROT_ASSERT_ARG(interp)
+#define ASSERT_ARGS_Parrot_runcore_register __attribute__unused__ int _ASSERT_ARGS_CHECK = \
+       PARROT_ASSERT_ARG(interp) \
+    || PARROT_ASSERT_ARG(coredata)
+#define ASSERT_ARGS_Parrot_runcore_switch __attribute__unused__ int _ASSERT_ARGS_CHECK = \
+       PARROT_ASSERT_ARG(interp) \
+    || PARROT_ASSERT_ARG(name)
 #define ASSERT_ARGS_do_prederef __attribute__unused__ int _ASSERT_ARGS_CHECK = \
        PARROT_ASSERT_ARG(pc_prederef) \
-    || PARROT_ASSERT_ARG(interp)
+    || PARROT_ASSERT_ARG(interp) \
+    || PARROT_ASSERT_ARG(runcore)
 #define ASSERT_ARGS_dynop_register __attribute__unused__ int _ASSERT_ARGS_CHECK = \
        PARROT_ASSERT_ARG(interp) \
     || PARROT_ASSERT_ARG(lib_pmc)
@@ -71,6 +221,8 @@
        PARROT_ASSERT_ARG(interp)
 #define ASSERT_ARGS_Parrot_runcore_destroy __attribute__unused__ int _ASSERT_ARGS_CHECK = \
        PARROT_ASSERT_ARG(interp)
+#define ASSERT_ARGS_Parrot_runcore_init __attribute__unused__ int _ASSERT_ARGS_CHECK = \
+       PARROT_ASSERT_ARG(interp)
 #define ASSERT_ARGS_Parrot_setup_event_func_ptrs __attribute__unused__ int _ASSERT_ARGS_CHECK = \
        PARROT_ASSERT_ARG(interp)
 #define ASSERT_ARGS_prepare_for_run __attribute__unused__ int _ASSERT_ARGS_CHECK = \
@@ -83,71 +235,113 @@
 /* HEADERIZER BEGIN: src/runcore/cores.c */
 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
 
-PARROT_WARN_UNUSED_RESULT
 PARROT_CAN_RETURN_NULL
-opcode_t * runops_cgoto_core(PARROT_INTERP, ARGIN(opcode_t *pc))
+void * destroy_profiling_core(PARROT_INTERP,
+    ARGIN(Parrot_profiling_runcore_t *runcore))
         __attribute__nonnull__(1)
         __attribute__nonnull__(2);
 
 PARROT_WARN_UNUSED_RESULT
-PARROT_CAN_RETURN_NULL
-opcode_t * runops_debugger_core(PARROT_INTERP, ARGIN(opcode_t *pc))
+PARROT_CANNOT_RETURN_NULL
+oplib_init_f get_core_op_lib_init(PARROT_INTERP,
+    ARGIN(Parrot_runcore_t *runcore))
         __attribute__nonnull__(1)
         __attribute__nonnull__(2);
 
 PARROT_WARN_UNUSED_RESULT
-PARROT_CAN_RETURN_NULL
-opcode_t * runops_fast_core(PARROT_INTERP, ARGIN(opcode_t *pc))
+PARROT_CANNOT_RETURN_NULL
+void * init_jit_run(PARROT_INTERP, ARGIN(Parrot_runcore_t *runcore))
         __attribute__nonnull__(1)
         __attribute__nonnull__(2);
 
-PARROT_WARN_UNUSED_RESULT
 PARROT_CAN_RETURN_NULL
-opcode_t * runops_gc_debug_core(PARROT_INTERP, ARGIN(opcode_t *pc))
+void * init_prederef(PARROT_INTERP, ARGIN(Parrot_runcore_t *runcore))
         __attribute__nonnull__(1)
         __attribute__nonnull__(2);
 
-PARROT_WARN_UNUSED_RESULT
-PARROT_CAN_RETURN_NULL
-opcode_t * runops_profile_core(PARROT_INTERP, ARGIN(opcode_t *pc))
+void load_prederef(PARROT_INTERP, ARGIN(Parrot_runcore_t *runcore))
         __attribute__nonnull__(1)
         __attribute__nonnull__(2);
 
-PARROT_WARN_UNUSED_RESULT
-PARROT_CAN_RETURN_NULL
-opcode_t * runops_slow_core(PARROT_INTERP, ARGIN(opcode_t *pc))
-        __attribute__nonnull__(1)
-        __attribute__nonnull__(2);
+void Parrot_runcore_cgoto_init(PARROT_INTERP)
+        __attribute__nonnull__(1);
 
-#define ASSERT_ARGS_runops_cgoto_core __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp) \
-    || PARROT_ASSERT_ARG(pc)
-#define ASSERT_ARGS_runops_debugger_core __attribute__unused__ int _ASSERT_ARGS_CHECK = \
+void Parrot_runcore_cgp_init(PARROT_INTERP)
+        __attribute__nonnull__(1);
+
+void Parrot_runcore_cgp_jit_init(PARROT_INTERP)
+        __attribute__nonnull__(1);
+
+void Parrot_runcore_debugger_init(PARROT_INTERP)
+        __attribute__nonnull__(1);
+
+void Parrot_runcore_exec_init(PARROT_INTERP)
+        __attribute__nonnull__(1);
+
+void Parrot_runcore_fast_init(PARROT_INTERP)
+        __attribute__nonnull__(1);
+
+void Parrot_runcore_gc_debug_init(PARROT_INTERP)
+        __attribute__nonnull__(1);
+
+void Parrot_runcore_jit_init(PARROT_INTERP)
+        __attribute__nonnull__(1);
+
+void Parrot_runcore_profiling_init(PARROT_INTERP)
+        __attribute__nonnull__(1);
+
+void Parrot_runcore_slow_init(PARROT_INTERP)
+        __attribute__nonnull__(1);
+
+void Parrot_runcore_switch_init(PARROT_INTERP)
+        __attribute__nonnull__(1);
+
+void Parrot_runcore_switch_jit_init(PARROT_INTERP)
+        __attribute__nonnull__(1);
+
+#define ASSERT_ARGS_destroy_profiling_core __attribute__unused__ int _ASSERT_ARGS_CHECK = \
        PARROT_ASSERT_ARG(interp) \
-    || PARROT_ASSERT_ARG(pc)
-#define ASSERT_ARGS_runops_fast_core __attribute__unused__ int _ASSERT_ARGS_CHECK = \
+    || PARROT_ASSERT_ARG(runcore)
+#define ASSERT_ARGS_get_core_op_lib_init __attribute__unused__ int _ASSERT_ARGS_CHECK = \
        PARROT_ASSERT_ARG(interp) \
-    || PARROT_ASSERT_ARG(pc)
-#define ASSERT_ARGS_runops_gc_debug_core __attribute__unused__ int _ASSERT_ARGS_CHECK = \
+    || PARROT_ASSERT_ARG(runcore)
+#define ASSERT_ARGS_init_jit_run __attribute__unused__ int _ASSERT_ARGS_CHECK = \
        PARROT_ASSERT_ARG(interp) \
-    || PARROT_ASSERT_ARG(pc)
-#define ASSERT_ARGS_runops_profile_core __attribute__unused__ int _ASSERT_ARGS_CHECK = \
+    || PARROT_ASSERT_ARG(runcore)
+#define ASSERT_ARGS_init_prederef __attribute__unused__ int _ASSERT_ARGS_CHECK = \
        PARROT_ASSERT_ARG(interp) \
-    || PARROT_ASSERT_ARG(pc)
-#define ASSERT_ARGS_runops_slow_core __attribute__unused__ int _ASSERT_ARGS_CHECK = \
+    || PARROT_ASSERT_ARG(runcore)
+#define ASSERT_ARGS_load_prederef __attribute__unused__ int _ASSERT_ARGS_CHECK = \
        PARROT_ASSERT_ARG(interp) \
-    || PARROT_ASSERT_ARG(pc)
+    || PARROT_ASSERT_ARG(runcore)
+#define ASSERT_ARGS_Parrot_runcore_cgoto_init __attribute__unused__ int _ASSERT_ARGS_CHECK = \
+       PARROT_ASSERT_ARG(interp)
+#define ASSERT_ARGS_Parrot_runcore_cgp_init __attribute__unused__ int _ASSERT_ARGS_CHECK = \
+       PARROT_ASSERT_ARG(interp)
+#define ASSERT_ARGS_Parrot_runcore_cgp_jit_init __attribute__unused__ int _ASSERT_ARGS_CHECK = \
+       PARROT_ASSERT_ARG(interp)
+#define ASSERT_ARGS_Parrot_runcore_debugger_init __attribute__unused__ int _ASSERT_ARGS_CHECK = \
+       PARROT_ASSERT_ARG(interp)
+#define ASSERT_ARGS_Parrot_runcore_exec_init __attribute__unused__ int _ASSERT_ARGS_CHECK = \
+       PARROT_ASSERT_ARG(interp)
+#define ASSERT_ARGS_Parrot_runcore_fast_init __attribute__unused__ int _ASSERT_ARGS_CHECK = \
+       PARROT_ASSERT_ARG(interp)
+#define ASSERT_ARGS_Parrot_runcore_gc_debug_init __attribute__unused__ int _ASSERT_ARGS_CHECK = \
+       PARROT_ASSERT_ARG(interp)
+#define ASSERT_ARGS_Parrot_runcore_jit_init __attribute__unused__ int _ASSERT_ARGS_CHECK = \
+       PARROT_ASSERT_ARG(interp)
+#define ASSERT_ARGS_Parrot_runcore_profiling_init __attribute__unused__ int _ASSERT_ARGS_CHECK = \
+       PARROT_ASSERT_ARG(interp)
+#define ASSERT_ARGS_Parrot_runcore_slow_init __attribute__unused__ int _ASSERT_ARGS_CHECK = \
+       PARROT_ASSERT_ARG(interp)
+#define ASSERT_ARGS_Parrot_runcore_switch_init __attribute__unused__ int _ASSERT_ARGS_CHECK = \
+       PARROT_ASSERT_ARG(interp)
+#define ASSERT_ARGS_Parrot_runcore_switch_jit_init \
+     __attribute__unused__ int _ASSERT_ARGS_CHECK = \
+       PARROT_ASSERT_ARG(interp)
 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
 /* HEADERIZER END: src/runcore/cores.c */
 
-opcode_t *runops_fast_core(PARROT_INTERP, opcode_t *);
-
-opcode_t *runops_cgoto_core(PARROT_INTERP, opcode_t *);
-
-opcode_t *runops_slow_core(PARROT_INTERP, opcode_t *);
-
-opcode_t *runops_profile_core(PARROT_INTERP, opcode_t *);
-
 #endif /* PARROT_RUNCORE_API_H_GUARD */
 
 

Modified: trunk/src/call/pcc.c
==============================================================================
--- trunk/src/call/pcc.c	Sun Sep  6 20:31:13 2009	(r41080)
+++ trunk/src/call/pcc.c	Sun Sep  6 20:40:14 2009	(r41081)
@@ -19,6 +19,7 @@
 
 #include "parrot/parrot.h"
 #include "parrot/oplib/ops.h"
+#include "parrot/runcore_api.h"
 #include "pcc.str"
 #include "../pmc/pmc_key.h"
 #include "../pmc/pmc_continuation.h"
@@ -3023,17 +3024,15 @@
     /* Invoke the function */
     dest = VTABLE_invoke(interp, sub_obj, NULL);
 
-    /* PIR Subs need runops to run their opcodes. Methods and NCI subs
-     * don't. */
+    /* PIR Subs need runops to run their opcodes. Methods and NCI subs don't. */
     if (sub_obj->vtable->base_type == enum_class_Sub
-            && PMC_IS_NULL(interp->current_object)) {
-        const INTVAL old_core = interp->run_core;
-        const opcode_t offset = dest - interp->code->base.data;
+    &&  PMC_IS_NULL(interp->current_object)) {
+        Parrot_runcore_t *old_core = interp->run_core;
+        const opcode_t    offset   = dest - interp->code->base.data;
 
         /* can't re-enter the runloop from here with PIC cores: RT #60048 */
-        if (interp->run_core == PARROT_CGP_CORE
-        ||  interp->run_core == PARROT_SWITCH_CORE)
-            interp->run_core = PARROT_SLOW_CORE;
+        if (PARROT_RUNCORE_PREDEREF_OPS_TEST(interp->run_core))
+            Parrot_runcore_switch(interp, CONST_STRING(interp, "slow"));
 
         runops(interp, offset);
         interp->run_core = old_core;

Modified: trunk/src/debug.c
==============================================================================
--- trunk/src/debug.c	Sun Sep  6 20:31:13 2009	(r41080)
+++ trunk/src/debug.c	Sun Sep  6 20:40:14 2009	(r41081)
@@ -1447,8 +1447,9 @@
         pdb->state |= PDB_STOPPED;
         return;
     }
+
     pdb->tracing = n;
-    pdb->debugee->run_core = PARROT_DEBUGGER_CORE;
+    Parrot_runcore_switch(pdb->debugee, CONST_STRING(interp, "debugger"));
 
     TRACEDEB_MSG("PDB_next finished");
 }
@@ -1494,8 +1495,8 @@
         return;
     }
     pdb->tracing = n;
-    pdb->debugee->run_core = PARROT_DEBUGGER_CORE;
-    pdb->state |= PDB_TRACING;
+    pdb->state  |= PDB_TRACING;
+    Parrot_runcore_switch(pdb->debugee, CONST_STRING(interp, "debugger"));
 
     /* Clear the following when done some testing */
 
@@ -1963,8 +1964,9 @@
     */
 
     #if 0
-    pdb->tracing = 0;
-    pdb->debugee->run_core = PARROT_DEBUGGER_CORE;
+    pdb->tracing           = 0;
+    Parrot_runcore_switch(pdb->debugee, CONST_STRING(interp, "debugger"));
+
     new_internal_exception(pdb->debugee);
     if (setjmp(pdb->debugee->exceptions->destination)) {
         Parrot_io_eprintf(pdb->debugee, "Unhandled exception while debugging: %Ss\n",

Modified: trunk/src/embed.c
==============================================================================
--- trunk/src/embed.c	Sun Sep  6 20:31:13 2009	(r41080)
+++ trunk/src/embed.c	Sun Sep  6 20:40:14 2009	(r41081)
@@ -22,6 +22,7 @@
 #include "parrot/embed.h"
 #include "parrot/oplib/ops.h"
 #include "pmc/pmc_sub.h"
+#include "parrot/runcore_api.h"
 
 #include "../compilers/imcc/imc.h"
 
@@ -30,9 +31,6 @@
 /* HEADERIZER BEGIN: static */
 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
 
-static FLOATVAL calibrate(PARROT_INTERP)
-        __attribute__nonnull__(1);
-
 PARROT_CANNOT_RETURN_NULL
 PARROT_OBSERVER
 static const char * op_name(PARROT_INTERP, int k)
@@ -44,16 +42,6 @@
 static void print_debug(PARROT_INTERP, SHIM(int status), SHIM(void *p))
         __attribute__nonnull__(1);
 
-static void print_profile(PARROT_INTERP, SHIM(int status), SHIM(void *p))
-        __attribute__nonnull__(1);
-
-static int prof_sort_f(ARGIN(const void *a), ARGIN(const void *b))
-        __attribute__nonnull__(1)
-        __attribute__nonnull__(2);
-
-static void runcode_print_start_info(PARROT_INTERP)
-        __attribute__nonnull__(1);
-
 PARROT_CANNOT_RETURN_NULL
 static PMC* set_current_sub(PARROT_INTERP)
         __attribute__nonnull__(1);
@@ -63,21 +51,12 @@
         __attribute__nonnull__(1)
         __attribute__nonnull__(3);
 
-#define ASSERT_ARGS_calibrate __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp)
 #define ASSERT_ARGS_op_name __attribute__unused__ int _ASSERT_ARGS_CHECK = \
        PARROT_ASSERT_ARG(interp)
 #define ASSERT_ARGS_print_constant_table __attribute__unused__ int _ASSERT_ARGS_CHECK = \
        PARROT_ASSERT_ARG(interp)
 #define ASSERT_ARGS_print_debug __attribute__unused__ int _ASSERT_ARGS_CHECK = \
        PARROT_ASSERT_ARG(interp)
-#define ASSERT_ARGS_print_profile __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp)
-#define ASSERT_ARGS_prof_sort_f __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(a) \
-    || PARROT_ASSERT_ARG(b)
-#define ASSERT_ARGS_runcode_print_start_info __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp)
 #define ASSERT_ARGS_set_current_sub __attribute__unused__ int _ASSERT_ARGS_CHECK = \
        PARROT_ASSERT_ARG(interp)
 #define ASSERT_ARGS_setup_argv __attribute__unused__ int _ASSERT_ARGS_CHECK = \
@@ -172,7 +151,7 @@
     switch (flag) {
         case PARROT_BOUNDS_FLAG:
         case PARROT_PROFILE_FLAG:
-            Interp_core_SET(interp, PARROT_SLOW_CORE);
+            Parrot_runcore_switch(interp, Parrot_str_new_constant(interp, "slow"));
             break;
         default:
             break;
@@ -235,7 +214,7 @@
 Parrot_set_trace(PARROT_INTERP, UINTVAL flag)
 {
     Parrot_pcc_trace_flags_on(interp, interp->ctx, flag);
-    Interp_core_SET(interp, PARROT_SLOW_CORE);
+    Parrot_runcore_switch(interp, Parrot_str_new_constant(interp, "slow"));
 }
 
 
@@ -361,7 +340,47 @@
 void
 Parrot_set_run_core(PARROT_INTERP, Parrot_Run_core_t core)
 {
-    Interp_core_SET(interp, core);
+    switch (core) {
+        case PARROT_SLOW_CORE:
+            Parrot_runcore_switch(interp, Parrot_str_new_constant(interp, "slow"));
+            break;
+        case PARROT_FAST_CORE:
+            Parrot_runcore_switch(interp, Parrot_str_new_constant(interp, "fast"));
+            break;
+        case PARROT_SWITCH_CORE:
+            Parrot_runcore_switch(interp, Parrot_str_new_constant(interp, "switch"));
+            break;
+        case PARROT_CGP_CORE:
+            Parrot_runcore_switch(interp, Parrot_str_new_constant(interp, "cgp"));
+            break;
+        case PARROT_CGOTO_CORE:
+            Parrot_runcore_switch(interp, Parrot_str_new_constant(interp, "cgoto"));
+            break;
+        case PARROT_JIT_CORE:
+            Parrot_runcore_switch(interp, Parrot_str_new_constant(interp, "jit"));
+            break;
+        case PARROT_CGP_JIT_CORE:
+            Parrot_runcore_switch(interp, Parrot_str_new_constant(interp, "cgp_jit"));
+            break;
+        case PARROT_SWITCH_JIT_CORE:
+            Parrot_runcore_switch(interp, Parrot_str_new_constant(interp, "switch_jit"));
+            break;
+        case PARROT_EXEC_CORE:
+            Parrot_runcore_switch(interp, Parrot_str_new_constant(interp, "exec"));
+            break;
+        case PARROT_GC_DEBUG_CORE:
+            Parrot_runcore_switch(interp, Parrot_str_new_constant(interp, "gc_debug"));
+            break;
+        case PARROT_DEBUGGER_CORE:
+            Parrot_runcore_switch(interp, Parrot_str_new_constant(interp, "debugger"));
+            break;
+        case PARROT_PROFILING_CORE:
+            Parrot_runcore_switch(interp, Parrot_str_new_constant(interp, "profiling"));
+            break;
+        default:
+            Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_UNIMPLEMENTED,
+                "Invalid runcore requested\n");
+    }
 }
 
 
@@ -665,33 +684,6 @@
 
 /*
 
-=item C<static int prof_sort_f(const void *a, const void *b)>
-
-Sort function for profile data, by time.
-
-=cut
-
-*/
-
-static int
-prof_sort_f(ARGIN(const void *a), ARGIN(const void *b))
-{
-    ASSERT_ARGS(prof_sort_f)
-    const FLOATVAL timea = ((const ProfData *)a)->time;
-    const FLOATVAL timeb = ((const ProfData *)b)->time;
-
-    if (timea < timeb)
-        return 1;
-
-    if (timea > timeb)
-        return -1;
-
-    return 0;
-}
-
-
-/*
-
 =item C<static const char * op_name(PARROT_INTERP, int k)>
 
 Returns the name of the opcode.
@@ -706,140 +698,7 @@
 op_name(PARROT_INTERP, int k)
 {
     ASSERT_ARGS(op_name)
-    switch (k) {
-        case PARROT_PROF_GC_p1:
-            return "GC_mark_root";
-        case PARROT_PROF_GC_p2:
-            return "GC_mark_next";
-        case PARROT_PROF_GC_cp:
-            return "GC_collect_PMC";
-        case PARROT_PROF_GC_cb:
-            return "GC_collect_buffers";
-        case PARROT_PROF_GC:
-            return "GC";
-        case PARROT_PROF_EXCEPTION:
-            return "EXCEPTION";
-        default:
-            break;
-    }
-
-    return interp->op_info_table[k - PARROT_PROF_EXTRA].full_name;
-}
-
-
-/*
-
-=item C<static FLOATVAL calibrate(PARROT_INTERP)>
-
-With this calibration, reported times of C<parrot -p> almost match those
-measured with time C<parrot -R bounds>.
-
-=cut
-
-*/
-
-static FLOATVAL
-calibrate(PARROT_INTERP)
-{
-    ASSERT_ARGS(calibrate)
-    opcode_t code[] = { 1 };      /* noop */
-    opcode_t *pc    = code;
-    const size_t   count  = 1000000;
-    size_t   n      = count;
-    const FLOATVAL start  = Parrot_floatval_time();
-    FLOATVAL now    = start;
-
-    /* op timing isn't free; it requires at least one time fetch per op */
-    for (; n; --n) {
-        pc = (interp->op_func_table[*code])(pc, interp);
-        now = Parrot_floatval_time();
-    }
-
-    return (now - start) / (FLOATVAL) count;
-}
-
-
-/*
-
-=item C<static void print_profile(PARROT_INTERP, int status, void *p)>
-
-Prints out a profile listing.
-
-=cut
-
-*/
-
-static void
-print_profile(PARROT_INTERP, SHIM(int status), SHIM(void *p))
-{
-    ASSERT_ARGS(print_profile)
-    RunProfile * const profile = interp->profile;
-
-    if (profile) {
-        UINTVAL        j;
-        int            k, jit;
-        UINTVAL        op_count   = 0;
-        UINTVAL        call_count = 0;
-        FLOATVAL       sum_time   = 0.0;
-        const FLOATVAL empty      = calibrate(interp);
-
-        Parrot_io_printf(interp,
-                   "Calibration: overhead = %.6f ms/op\n", 1000.0 * empty);
-
-        Parrot_io_printf(interp,
-                   " Code J Name                         "
-                   "Calls  Total/s       Avg/ms\n");
-
-        for (j = 0; j < interp->op_count + PARROT_PROF_EXTRA; j++) {
-            const UINTVAL n     = profile->data[j].numcalls;
-            profile->data[j].op = j;
-
-            if (j >= PARROT_PROF_EXTRA) {
-                profile->data[j].time -= empty * n;
-
-                /* faster than noop */
-                if (profile->data[j].time < 0.0)
-                    profile->data[j].time = 0.0;
-            }
-        }
-
-        qsort(profile->data, interp->op_count + PARROT_PROF_EXTRA,
-                sizeof (ProfData), prof_sort_f);
-
-        for (j = 0; j < interp->op_count + PARROT_PROF_EXTRA; j++) {
-            const UINTVAL n = profile->data[j].numcalls;
-
-            if (n > 0) {
-                const FLOATVAL t = profile->data[j].time;
-
-                op_count++;
-                call_count += n;
-                sum_time   += t;
-
-                k   = profile->data[j].op;
-                jit = '-';
-#if JIT_CAPABLE
-                if (k >= PARROT_PROF_EXTRA &&
-                    op_jit[k - PARROT_PROF_EXTRA].extcall != 1)
-                    jit = 'j';
-#endif
-                Parrot_io_printf(interp, " %4d %c %-25s %8vu  %10vf  %10.6vf\n",
-                        k - PARROT_PROF_EXTRA,
-                        jit,
-                        op_name(interp, k),
-                        n,
-                        t,
-                        (FLOATVAL)(t * 1000.0 / (FLOATVAL)n));
-            }
-        }
-
-        Parrot_io_printf(interp, " %4vu - %-25s %8vu  %10vf  %10.6vf\n",
-                op_count,
-                "-",
-                call_count,
-                sum_time,
-                (FLOATVAL)(sum_time * 1000.0 / (FLOATVAL)call_count));
-    }
+    return interp->op_info_table[k].full_name;
 }
 
 
@@ -948,8 +807,18 @@
     PMC *userargv, *main_sub;
 
     /* Debugging mode nonsense. */
-    if (Interp_debug_TEST(interp, PARROT_START_DEBUG_FLAG))
-        runcode_print_start_info(interp);
+    if (Interp_debug_TEST(interp, PARROT_START_DEBUG_FLAG)) {
+        if (Interp_flags_TEST(interp, PARROT_BOUNDS_FLAG)) {
+            Parrot_io_eprintf(interp,
+                    "*** Parrot VM: Bounds checking enabled. ***\n");
+        }
+
+        if (Interp_trace_TEST(interp, PARROT_TRACE_OPS_FLAG))
+            Parrot_io_eprintf(interp, "*** Parrot VM: Tracing enabled. ***\n");
+
+        Parrot_io_eprintf(interp, "*** Parrot VM: %Ss core ***\n",
+                interp->run_core->name);
+    }
 
     /* Set up @ARGS (or whatever this language calls it) in userargv. */
     userargv = setup_argv(interp, argc, argv);
@@ -957,7 +826,8 @@
 #if EXEC_CAPABLE
 
     /* s. runops_exec interpreter.c */
-    if (Interp_core_TEST(interp, PARROT_EXEC_CORE))
+    if (Parrot_str_equal(interp, interp->run_core->name,
+        Parrot_str_new_constant(interp, "exec")))
         Parrot_exec_run = 1;
 
 #endif
@@ -967,7 +837,6 @@
      * before exiting, then print debug infos if turned on.
      */
     Parrot_on_exit(interp, print_debug,   NULL);
-    Parrot_on_exit(interp, print_profile, NULL);
 
     /* Let's kick the tires and light the fires--call interpreter.c:runops. */
     main_sub = Parrot_pcc_get_sub(interp, CURRENT_CONTEXT(interp));
@@ -1290,60 +1159,6 @@
     return NULL;
 }
 
-/*
-
-=item C<static void runcode_print_start_info(PARROT_INTERP)>
-
-Show runcore info at stat,
-
-=cut
-
-*/
-
-static void
-runcode_print_start_info(PARROT_INTERP)
-{
-    ASSERT_ARGS(runcode_print_start_info)
-
-    const char * corename;
-
-    Parrot_io_eprintf(interp,
-            "*** Parrot VM: Setting stack top. ***\n");
-
-    if (Interp_flags_TEST(interp, PARROT_BOUNDS_FLAG)) {
-        Parrot_io_eprintf(interp,
-                "*** Parrot VM: Bounds checking enabled. ***\n");
-    }
-
-    if (Interp_trace_TEST(interp, PARROT_TRACE_OPS_FLAG)) {
-        Parrot_io_eprintf(interp,
-                "*** Parrot VM: Tracing enabled. ***\n");
-    }
-
-    switch (interp->run_core) {
-        case PARROT_SLOW_CORE:
-            corename = "Slow";   break;
-        case PARROT_FAST_CORE:
-            corename = "Fast";   break;
-        case PARROT_SWITCH_CORE:
-        case PARROT_SWITCH_JIT_CORE:
-            corename = "Switch"; break;
-        case PARROT_CGP_CORE:
-        case PARROT_CGP_JIT_CORE:
-            corename = "CGP";    break;
-        case PARROT_CGOTO_CORE:
-            corename = "CGoto";  break;
-        case PARROT_JIT_CORE:
-            corename = "JIT";    break;
-        case PARROT_EXEC_CORE:
-            corename = "EXEC";   break;
-        default:
-            Parrot_ex_throw_from_c_args(interp, NULL, 1,
-                 "Unknown run core");
-    }
-
-    Parrot_io_eprintf(interp, "*** Parrot VM: %s core ***\n", corename);
-}
 
 /*
 

Modified: trunk/src/exceptions.c
==============================================================================
--- trunk/src/exceptions.c	Sun Sep  6 20:31:13 2009	(r41080)
+++ trunk/src/exceptions.c	Sun Sep  6 20:40:14 2009	(r41081)
@@ -356,7 +356,6 @@
     ASSERT_ARGS(Parrot_ex_throw_from_c)
 
     Parrot_runloop    *return_point = interp->current_runloop;
-    RunProfile * const profile      = interp->profile;
     opcode_t *address;
     PMC        * const handler      =
                              Parrot_cx_find_handler_local(interp, exception);
@@ -364,17 +363,6 @@
     if (PMC_IS_NULL(handler))
         die_from_exception(interp, exception);
 
-    /* If profiling, remember end time of lastop and generate entry for
-     * exception. */
-    if (profile && Interp_flags_TEST(interp, PARROT_PROFILE_FLAG)) {
-        const FLOATVAL now = Parrot_floatval_time();
-
-        profile->data[profile->cur_op].time += now - profile->starttime;
-        profile->cur_op                      = PARROT_PROF_EXCEPTION;
-        profile->starttime                   = now;
-        profile->data[PARROT_PROF_EXCEPTION].numcalls++;
-    }
-
     if (Interp_debug_TEST(interp, PARROT_BACKTRACE_DEBUG_FLAG)) {
         STRING * const exit_code = CONST_STRING(interp, "exit_code");
         STRING * const msg       = VTABLE_get_string(interp, exception);

Modified: trunk/src/exec_start.c
==============================================================================
--- trunk/src/exec_start.c	Sun Sep  6 20:31:13 2009	(r41080)
+++ trunk/src/exec_start.c	Sun Sep  6 20:40:14 2009	(r41081)
@@ -1,5 +1,5 @@
 /*
-Copyright (C) 2001-2006, Parrot Foundation.
+Copyright (C) 2001-2009, Parrot Foundation.
 $Id$
 
 =head1 NAME
@@ -97,7 +97,7 @@
 #if defined(JIT_CGP)
     exec_init_prederef(interp, &exec_prederef_code);
 #endif
-    /* Parrot_set_run_core(interp, PARROT_EXEC_CORE);
+    /* Parrot_runcore_switch(interp, Parrot_str_new_constant(interp, "exec"));
     interp->code->base.data =
         (opcode_t *)&((&program_code)[bytecode_offset]);
     Parrot_exec_run = 0; */

Modified: trunk/src/gc/alloc_resources.c
==============================================================================
--- trunk/src/gc/alloc_resources.c	Sun Sep  6 20:31:13 2009	(r41080)
+++ trunk/src/gc/alloc_resources.c	Sun Sep  6 20:40:14 2009	(r41081)
@@ -347,9 +347,6 @@
 
     ++arena_base->gc_sweep_block_level;
 
-    if (interp->profile)
-        Parrot_gc_profile_start(interp);
-
     /* We're collecting */
     arena_base->mem_allocs_since_last_collect    = 0;
     arena_base->header_allocs_since_last_collect = 0;
@@ -550,9 +547,6 @@
     pool->guaranteed_reclaimable = 0;
     pool->possibly_reclaimable   = 0;
 
-    if (interp->profile)
-        Parrot_gc_profile_end(interp, PARROT_PROF_GC);
-
     --arena_base->gc_sweep_block_level;
 }
 

Modified: trunk/src/gc/gc_malloc.c
==============================================================================
--- trunk/src/gc/gc_malloc.c	Sun Sep  6 20:31:13 2009	(r41080)
+++ trunk/src/gc/gc_malloc.c	Sun Sep  6 20:40:14 2009	(r41081)
@@ -82,9 +82,6 @@
     if (flag & POOL_BUFFER)
         clear_cow(interp, pool, 0);
 
-    if (interp->profile && (flag & POOL_PMC))
-        Parrot_gc_profile_end(interp, PARROT_PROF_GC_cp);
-
     *total_free += pool->num_free_objects;
 
     return 0;

Modified: trunk/src/gc/gc_ms.c
==============================================================================
--- trunk/src/gc/gc_ms.c	Sun Sep  6 20:31:13 2009	(r41080)
+++ trunk/src/gc/gc_ms.c	Sun Sep  6 20:40:14 2009	(r41081)
@@ -184,15 +184,11 @@
         header_pools_iterate_callback(interp, POOL_BUFFER | POOL_PMC,
             (void*)&total_free, gc_ms_sweep_cb);
 
-        if (interp->profile)
-            Parrot_gc_profile_end(interp, PARROT_PROF_GC_cb);
     }
     else {
         ++arena_base->gc_lazy_mark_runs;
 
         Parrot_gc_clear_live_bits(interp, arena_base->pmc_pool);
-        if (interp->profile)
-            Parrot_gc_profile_end(interp, PARROT_PROF_GC_p2);
     }
 
     pt_gc_stop_mark(interp);
@@ -282,9 +278,6 @@
 
     Parrot_gc_sweep_pool(interp, pool);
 
-    if (interp->profile && (flag & POOL_PMC))
-        Parrot_gc_profile_end(interp, PARROT_PROF_GC_cp);
-
     *total_free += pool->num_free_objects;
 
     return 0;

Modified: trunk/src/gc/gc_private.h
==============================================================================
--- trunk/src/gc/gc_private.h	Sun Sep  6 20:31:13 2009	(r41080)
+++ trunk/src/gc/gc_private.h	Sun Sep  6 20:40:14 2009	(r41081)
@@ -449,12 +449,6 @@
         __attribute__nonnull__(2)
         FUNC_MODIFIES(* pool);
 
-void Parrot_gc_profile_end(PARROT_INTERP, int what)
-        __attribute__nonnull__(1);
-
-void Parrot_gc_profile_start(PARROT_INTERP)
-        __attribute__nonnull__(1);
-
 void Parrot_gc_run_init(PARROT_INTERP)
         __attribute__nonnull__(1);
 
@@ -504,10 +498,6 @@
      __attribute__unused__ int _ASSERT_ARGS_CHECK = \
        PARROT_ASSERT_ARG(interp) \
     || PARROT_ASSERT_ARG(pool)
-#define ASSERT_ARGS_Parrot_gc_profile_end __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp)
-#define ASSERT_ARGS_Parrot_gc_profile_start __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp)
 #define ASSERT_ARGS_Parrot_gc_run_init __attribute__unused__ int _ASSERT_ARGS_CHECK = \
        PARROT_ASSERT_ARG(interp)
 #define ASSERT_ARGS_Parrot_gc_sweep_pool __attribute__unused__ int _ASSERT_ARGS_CHECK = \

Modified: trunk/src/gc/incremental_ms.c
==============================================================================
--- trunk/src/gc/incremental_ms.c	Sun Sep  6 20:31:13 2009	(r41080)
+++ trunk/src/gc/incremental_ms.c	Sun Sep  6 20:40:14 2009	(r41081)
@@ -773,9 +773,6 @@
 
     Parrot_gc_sweep_pool(interp, pool);
 
-    if (interp->profile && (flag & POOL_PMC))
-        Parrot_gc_profile_end(interp, PARROT_PROF_GC_cp);
-
     *n_obj += pool->total_objects - pool->num_free_objects;
 
     return 0;
@@ -824,9 +821,6 @@
             (void*)&n_objects, sweep_cb);
     UNUSED(ignored);
 
-    if (interp->profile)
-        Parrot_gc_profile_end(interp, PARROT_PROF_GC_cb);
-
     g_ims->state           = GC_IMS_COLLECT;
     g_ims->n_objects       = n_objects;
 }
@@ -905,9 +899,6 @@
     Gc_ims_private *g_ims;
     int             ret;
 
-    if (!check_only && interp->profile)
-        Parrot_gc_profile_start(interp);
-
     g_ims = (Gc_ims_private *)arena_base->gc_private;
 
     ret   = header_pools_iterate_callback(interp, POOL_BUFFER,
@@ -919,9 +910,6 @@
     if (check_only)
         return 0;
 
-    if (interp->profile)
-        Parrot_gc_profile_end(interp, PARROT_PROF_GC);
-
     g_ims->state = GC_IMS_FINISHED;
 #endif
     return 0;

Modified: trunk/src/gc/mark_sweep.c
==============================================================================
--- trunk/src/gc/mark_sweep.c	Sun Sep  6 20:31:13 2009	(r41080)
+++ trunk/src/gc/mark_sweep.c	Sun Sep  6 20:40:14 2009	(r41081)
@@ -180,9 +180,6 @@
         return 0;
     }
 
-    if (interp->profile)
-        Parrot_gc_profile_start(interp);
-
     /* We have to start somewhere; the interpreter globals is a good place */
     if (!arena_base->gc_mark_start) {
         arena_base->gc_mark_start
@@ -248,9 +245,6 @@
     &&  arena_base->num_early_PMCs_seen >= arena_base->num_early_gc_PMCs)
         return 0;
 
-    if (interp->profile)
-        Parrot_gc_profile_end(interp, PARROT_PROF_GC_p1);
-
     return 1;
 }
 
@@ -533,9 +527,6 @@
      * If there is a count of shared PMCs and we have already seen
      * all these, we could skip that.
      */
-    if (interp->profile)
-        Parrot_gc_profile_start(interp);
-
     pt_gc_mark_root_finished(interp);
 
     do {
@@ -575,9 +566,6 @@
     arena_base->gc_mark_start = current;
     arena_base->gc_trace_ptr  = NULL;
 
-    if (interp->profile)
-        Parrot_gc_profile_end(interp, PARROT_PROF_GC_p2);
-
     return 1;
 }
 
@@ -668,59 +656,6 @@
 
 /*
 
-=item C<void Parrot_gc_profile_start(PARROT_INTERP)>
-
-Records the start time of a GC mark run when profiling is enabled.
-
-=cut
-
-*/
-
-void
-Parrot_gc_profile_start(PARROT_INTERP)
-{
-    ASSERT_ARGS(Parrot_gc_profile_start)
-    if (Interp_flags_TEST(interp, PARROT_PROFILE_FLAG))
-        interp->profile->gc_time = Parrot_floatval_time();
-}
-
-/*
-
-=item C<void Parrot_gc_profile_end(PARROT_INTERP, int what)>
-
-Records the end time of the GC mark run part C<what> run when profiling is
-enabled. Also record start time of next part.
-
-=cut
-
-*/
-
-void
-Parrot_gc_profile_end(PARROT_INTERP, int what)
-{
-    ASSERT_ARGS(Parrot_gc_profile_end)
-    if (Interp_flags_TEST(interp, PARROT_PROFILE_FLAG)) {
-        RunProfile * const profile = interp->profile;
-        const FLOATVAL     now     = Parrot_floatval_time();
-
-        profile->data[what].numcalls++;
-        profile->data[what].time += now - profile->gc_time;
-
-        /*
-         * we've recorded the time of a GC piece from
-         * gc_time until now, so add this to the start of the
-         * currently executing opcode, which hasn't run this
-         * interval.
-         */
-        profile->starttime += now - profile->gc_time;
-
-        /* prepare start for next step */
-        profile->gc_time    = now;
-    }
-}
-
-/*
-
 =back
 
 =head2 Header Pool Creation Functions

Modified: trunk/src/interp/inter_create.c
==============================================================================
--- trunk/src/interp/inter_create.c	Sun Sep  6 20:31:13 2009	(r41080)
+++ trunk/src/interp/inter_create.c	Sun Sep  6 20:40:14 2009	(r41081)
@@ -216,6 +216,9 @@
     Parrot_pcc_set_continuation(interp, CURRENT_CONTEXT(interp), NULL); /* TODO Use PMCNULL */
     Parrot_pcc_set_object(interp, CURRENT_CONTEXT(interp), NULL);
 
+    /* initialize built-in runcores */
+    Parrot_runcore_init(interp);
+
     /* Load the core op func and info tables */
     interp->op_lib          = PARROT_CORE_OPLIB_INIT(1);
     interp->op_count        = interp->op_lib->op_count;
@@ -225,7 +228,6 @@
     interp->evc_func_table  = NULL;
     interp->save_func_table = NULL;
     interp->code            = NULL;
-    interp->profile         = NULL;
 
     /* create the root set registry */
     interp->gc_registry     = pmc_new(interp, enum_class_AddrRegistry);
@@ -363,6 +365,10 @@
     /* Now the PIOData gets also cleared */
     Parrot_io_finish(interp);
 
+    /* deinit runcores and dynamic op_libs */
+    if (!interp->parent_interpreter)
+        Parrot_runcore_destroy(interp);
+
     /*
      * now all objects that need timely destruction should be finalized
      * so terminate the event loop
@@ -411,13 +417,6 @@
     if (interp->initial_pf)
         PackFile_destroy(interp, interp->initial_pf);
 
-    if (interp->profile) {
-        mem_sys_free(interp->profile->data);
-        interp->profile->data = NULL;
-        mem_sys_free(interp->profile);
-        interp->profile = NULL;
-    }
-
     destroy_runloop_jump_points(interp);
 
     if (interp->evc_func_table) {
@@ -437,15 +436,6 @@
         /* free vtables */
         parrot_free_vtables(interp);
 
-        /* dynop libs */
-        if (interp->n_libs > 0) {
-            mem_sys_free(interp->op_info_table);
-            mem_sys_free(interp->op_func_table);
-
-            /* deinit op_lib */
-            Parrot_runcore_destroy(interp);
-        }
-
         MUTEX_DESTROY(interpreter_array_mutex);
         mem_sys_free(interp);
 

Modified: trunk/src/interp/inter_misc.c
==============================================================================
--- trunk/src/interp/inter_misc.c	Sun Sep  6 20:31:13 2009	(r41080)
+++ trunk/src/interp/inter_misc.c	Sun Sep  6 20:40:14 2009	(r41081)
@@ -253,8 +253,35 @@
             ret = Parrot_gc_impatient_pmcs(interp);
             break;
         case CURRENT_RUNCORE:
-            ret = interp->run_core;
+        {
+            STRING *name = interp->run_core->name;
+
+            if (Parrot_str_equal(interp, name, CONST_STRING(interp, "slow")))
+                ret = PARROT_SLOW_CORE;
+            else if (Parrot_str_equal(interp, name, CONST_STRING(interp, "fast")))
+                ret = PARROT_FAST_CORE;
+            else if (Parrot_str_equal(interp, name, CONST_STRING(interp, "switch")))
+                ret = PARROT_SWITCH_CORE;
+            else if (Parrot_str_equal(interp, name, CONST_STRING(interp, "cgp")))
+                ret = PARROT_CGP_CORE;
+            else if (Parrot_str_equal(interp, name, CONST_STRING(interp, "cgoto")))
+                ret = PARROT_CGOTO_CORE;
+            else if (Parrot_str_equal(interp, name, CONST_STRING(interp, "jit")))
+                ret = PARROT_JIT_CORE;
+            else if (Parrot_str_equal(interp, name, CONST_STRING(interp, "cgp_jit")))
+                ret = PARROT_CGP_JIT_CORE;
+            else if (Parrot_str_equal(interp, name, CONST_STRING(interp, "switch_jit")))
+                ret = PARROT_SWITCH_JIT_CORE;
+            else if (Parrot_str_equal(interp, name, CONST_STRING(interp, "exec")))
+                ret = PARROT_EXEC_CORE;
+            else if (Parrot_str_equal(interp, name, CONST_STRING(interp, "gc_debug")))
+                ret = PARROT_GC_DEBUG_CORE;
+            else if (Parrot_str_equal(interp, name, CONST_STRING(interp, "debugger")))
+                ret = PARROT_DEBUGGER_CORE;
+            else if (Parrot_str_equal(interp, name, CONST_STRING(interp, "profiling")))
+                ret = PARROT_PROFILING_CORE;
             break;
+        }
         default:        /* or a warning only? */
             Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_UNIMPLEMENTED,
                 "illegal argument in interpinfo");

Modified: trunk/src/ops/core.ops
==============================================================================
--- trunk/src/ops/core.ops	Sun Sep  6 20:31:13 2009	(r41080)
+++ trunk/src/ops/core.ops	Sun Sep  6 20:40:14 2009	(r41081)
@@ -113,7 +113,7 @@
        we want to throw an error. Seriously people: Do not use this opcode
        directly in PIR. Ever. It absolutely makes no sense and it doesn't do
        anything productive. You've been warned. */
-    if (interp->run_core & PARROT_JIT_CORE) {
+   if (PARROT_RUNCORE_JIT_OPS_TEST(interp->run_core)) {
 #ifdef __GNUC__
 #  ifdef I386
         __asm__("ret");
@@ -150,12 +150,12 @@
 
 inline op prederef__() :internal :flow {
     opcode_t * const _this = CUR_OPCODE;
-    if (interp->run_core & PARROT_CGOTO_CORE) {
+    if (PARROT_RUNCORE_CGOTO_OPS_TEST(interp->run_core)) {
         /* must be CGP then - check for events in not yet prederefed code */
         Parrot_cx_runloop_wake(interp, interp->scheduler);
     /*    _this = CHECK_EVENTS(interp, _this); */
     }
-    do_prederef((void**)cur_opcode, interp, op_lib.core_type);
+    do_prederef((void**)cur_opcode, interp, interp->run_core);
     goto ADDRESS(_this); /* force this being a branch op */
 }
 

Modified: trunk/src/packfile.c
==============================================================================
--- trunk/src/packfile.c	Sun Sep  6 20:31:13 2009	(r41080)
+++ trunk/src/packfile.c	Sun Sep  6 20:40:14 2009	(r41081)
@@ -28,6 +28,7 @@
 #include "parrot/embed.h"
 #include "parrot/extend.h"
 #include "parrot/packfile.h"
+#include "parrot/runcore_api.h"
 #include "jit.h"
 #include "../compilers/imcc/imc.h"
 #include "packfile.str"
@@ -672,21 +673,20 @@
 run_sub(PARROT_INTERP, ARGIN(PMC *sub_pmc))
 {
     ASSERT_ARGS(run_sub)
-    const INTVAL old = interp->run_core;
-    PMC *retval;
+    Parrot_runcore_t *old_core = interp->run_core;
+    PMC              *retval;
 
     /* turn off JIT and prederef - both would act on the whole
      * PackFile which probably isn't worth the effort */
-    if (interp->run_core != PARROT_CGOTO_CORE
-    &&  interp->run_core != PARROT_SLOW_CORE
-    &&  interp->run_core != PARROT_FAST_CORE)
-            interp->run_core = PARROT_FAST_CORE;
+    if (PARROT_RUNCORE_JIT_OPS_TEST(interp->run_core)
+    ||  PARROT_RUNCORE_PREDEREF_OPS_TEST(interp->run_core))
+        Parrot_runcore_switch(interp, CONST_STRING(interp, "fast"));
 
     Parrot_pcc_set_constants(interp, CURRENT_CONTEXT(interp),
             interp->code->const_table->constants);
 
     retval           = (PMC *)Parrot_runops_fromc_args(interp, sub_pmc, "P");
-    interp->run_core = old;
+    interp->run_core = old_core;
 
     return retval;
 }

Modified: trunk/src/parrot_debugger.c
==============================================================================
--- trunk/src/parrot_debugger.c	Sun Sep  6 20:31:13 2009	(r41080)
+++ trunk/src/parrot_debugger.c	Sun Sep  6 20:40:14 2009	(r41081)
@@ -263,10 +263,9 @@
     else
         PDB_printwelcome();
 
-    interp->run_core = PARROT_DEBUGGER_CORE;
+    Parrot_runcore_switch(interp, Parrot_str_new_constant(interp, "debugger"));
     PDB_run_code(interp, argc - nextarg, argv + nextarg);
 
-
     Parrot_exit(interp, 0);
 }
 

Modified: trunk/src/pic.c
==============================================================================
--- trunk/src/pic.c	Sun Sep  6 20:31:13 2009	(r41080)
+++ trunk/src/pic.c	Sun Sep  6 20:40:14 2009	(r41081)
@@ -78,6 +78,7 @@
 
 #include "parrot/parrot.h"
 #include "parrot/oplib/ops.h"
+#include "parrot/runcore_api.h"
 #include "pmc/pmc_fixedintegerarray.h"
 #include "pmc/pmc_continuation.h"
 #ifdef HAVE_COMPUTED_GOTO
@@ -109,10 +110,11 @@
 static int is_pic_func(PARROT_INTERP,
     ARGIN(void **pc),
     ARGOUT(Parrot_MIC *mic),
-    int core_type)
+    ARGIN(Parrot_runcore_t *runcore))
         __attribute__nonnull__(1)
         __attribute__nonnull__(2)
         __attribute__nonnull__(3)
+        __attribute__nonnull__(4)
         FUNC_MODIFIES(*mic);
 
 static int is_pic_param(PARROT_INTERP,
@@ -197,7 +199,8 @@
 #define ASSERT_ARGS_is_pic_func __attribute__unused__ int _ASSERT_ARGS_CHECK = \
        PARROT_ASSERT_ARG(interp) \
     || PARROT_ASSERT_ARG(pc) \
-    || PARROT_ASSERT_ARG(mic)
+    || PARROT_ASSERT_ARG(mic) \
+    || PARROT_ASSERT_ARG(runcore)
 #define ASSERT_ARGS_is_pic_param __attribute__unused__ int _ASSERT_ARGS_CHECK = \
        PARROT_ASSERT_ARG(interp) \
     || PARROT_ASSERT_ARG(pc) \
@@ -417,9 +420,10 @@
 #ifdef HAVE_COMPUTED_GOTO
     op_lib_t *cg_lib;
 #endif
-    const int core = interp->run_core;
+    const Parrot_runcore_t *core = interp->run_core;
 
-    if (core == PARROT_SWITCH_CORE || core == PARROT_SWITCH_JIT_CORE)
+    if (PARROT_RUNCORE_PREDEREF_OPS_TEST(core)
+    && !PARROT_RUNCORE_CGOTO_OPS_TEST(core))
         return (void *)op;
 #ifdef HAVE_COMPUTED_GOTO
     cg_lib = PARROT_CORE_CGP_OPLIB_INIT(1);
@@ -427,6 +431,7 @@
 #else
     return NULL;
 #endif
+
 }
 
 /*
@@ -766,15 +771,16 @@
 
 /*
 
-=item C<static int is_pic_func(PARROT_INTERP, void **pc, Parrot_MIC *mic, int
-core_type)>
+=item C<static int is_pic_func(PARROT_INTERP, void **pc, Parrot_MIC *mic,
+Parrot_runcore_t *runcore)>
 
 =cut
 
 */
 
 static int
-is_pic_func(PARROT_INTERP, ARGIN(void **pc), ARGOUT(Parrot_MIC *mic), int core_type)
+is_pic_func(PARROT_INTERP, ARGIN(void **pc), ARGOUT(Parrot_MIC *mic),
+            ARGIN(Parrot_runcore_t *runcore))
 {
     ASSERT_ARGS(is_pic_func)
     /*
@@ -811,7 +817,7 @@
     if (*op != PARROT_OP_set_p_pc)
         return 0;
 
-    do_prederef(pc, interp, core_type);
+    do_prederef(pc, interp, runcore);
     sub = (PMC *)(pc[2]);
 
     PARROT_ASSERT(PObj_is_PMC_TEST(sub));
@@ -825,7 +831,7 @@
     if (*op != PARROT_OP_get_results_pc)
         return 0;
 
-    do_prederef(pc, interp, core_type);
+    do_prederef(pc, interp, runcore);
     sig_results = (PMC *)(pc[1]);
     ASSERT_SIG_PMC(sig_results);
 
@@ -841,8 +847,8 @@
 
 /*
 
-=item C<void parrot_PIC_prederef(PARROT_INTERP, opcode_t op, void **pc_pred, int
-core)>
+=item C<void parrot_PIC_prederef(PARROT_INTERP, opcode_t op, void **pc_pred,
+Parrot_runcore_t *core)>
 
 Define either the normal prederef function or the PIC stub, if PIC for
 this opcode function is available. Called from C<do_prederef>.
@@ -852,7 +858,8 @@
 */
 
 void
-parrot_PIC_prederef(PARROT_INTERP, opcode_t op, ARGOUT(void **pc_pred), int core)
+parrot_PIC_prederef(PARROT_INTERP, opcode_t op, ARGOUT(void **pc_pred),
+    ARGIN(Parrot_runcore_t *core))
 {
     ASSERT_ARGS(parrot_PIC_prederef)
     op_func_t * const prederef_op_func = interp->op_lib->op_func_table;
@@ -897,7 +904,8 @@
     }
 
     /* rewrite opcode */
-    if (core == PARROT_SWITCH_CORE || core == PARROT_SWITCH_JIT_CORE)
+    if (PARROT_RUNCORE_PREDEREF_OPS_TEST(core)
+    && !PARROT_RUNCORE_CGOTO_OPS_TEST(core))
         *pc_pred = (void **)op;
     else
         *pc_pred = ((void **)prederef_op_func)[op];

Modified: trunk/src/pic_jit.c
==============================================================================
--- trunk/src/pic_jit.c	Sun Sep  6 20:31:13 2009	(r41080)
+++ trunk/src/pic_jit.c	Sun Sep  6 20:40:14 2009	(r41081)
@@ -34,6 +34,7 @@
 #include "parrot/parrot.h"
 #include "parrot/oplib/ops.h"
 #include "pmc/pmc_sub.h"
+#include "parrot/runcore_api.h"
 
 /* HEADERIZER HFILE: include/parrot/pic.h */
 
@@ -488,7 +489,7 @@
      * 0) if runcore setting doesn't contain JIT
      *    forget it
      */
-    if (!(interp->run_core & PARROT_JIT_CORE))
+    if (!(PARROT_RUNCORE_JIT_OPS_TEST(interp->run_core)))
         return 0;
 
     /* 1) if the JIT system can't JIT_CODE_SUB_REGS_ONLY

Modified: trunk/src/pmc/parrotinterpreter.pmc
==============================================================================
--- trunk/src/pmc/parrotinterpreter.pmc	Sun Sep  6 20:31:13 2009	(r41080)
+++ trunk/src/pmc/parrotinterpreter.pmc	Sun Sep  6 20:40:14 2009	(r41081)
@@ -28,6 +28,7 @@
 #include "parrot/embed.h"
 #include "parrot/dynext.h"
 #include "parrot/io.h"
+#include "parrot/runcore_api.h"
 #include "pmc_class.h"
 #include "pmc_sub.h"
 
@@ -55,8 +56,9 @@
     d->scheduler = pmc_new(d, enum_class_Scheduler);
     d->scheduler = VTABLE_share_ro(d, d->scheduler);
 
+    /* can't copy directly, unless you want double-frees */
     if (flags & PARROT_CLONE_RUNOPS)
-        d->run_core = s->run_core;
+        Parrot_runcore_switch(d, s->run_core->name);
 
     if (flags & PARROT_CLONE_INTERP_FLAGS) {
         /* XXX setting of IS_THREAD? */

Modified: trunk/src/runcore/cores.c
==============================================================================
--- trunk/src/runcore/cores.c	Sun Sep  6 20:31:13 2009	(r41080)
+++ trunk/src/runcore/cores.c	Sun Sep  6 20:40:14 2009	(r41081)
@@ -241,9 +241,27 @@
 #include "parrot/runcore_api.h"
 #include "parrot/embed.h"
 #include "parrot/runcore_trace.h"
+#include "cores.str"
+
+#include "parrot/oplib/ops.h"
+#include "parrot/oplib/core_ops.h"
+#include "parrot/oplib/core_ops_switch.h"
+#include "parrot/dynext.h"
+
+#include "../pmc/pmc_sub.h"
 
 #ifdef HAVE_COMPUTED_GOTO
 #  include "parrot/oplib/core_ops_cg.h"
+#  include "parrot/oplib/core_ops_cgp.h"
+#endif
+
+#if JIT_CAPABLE
+#  include "parrot/exec.h"
+#  include "../jit.h"
+#endif
+
+#ifdef WIN32
+#  define getpid _getpid
 #endif
 
 /* HEADERIZER HFILE: include/parrot/runcore_api.h */
@@ -251,31 +269,531 @@
 /* HEADERIZER BEGIN: static */
 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
 
+PARROT_CAN_RETURN_NULL
+static void * init_profiling_core(PARROT_INTERP,
+    ARGIN(Parrot_profiling_runcore_t *runcore),
+    ARGIN(opcode_t *pc))
+        __attribute__nonnull__(1)
+        __attribute__nonnull__(2)
+        __attribute__nonnull__(3);
+
+PARROT_WARN_UNUSED_RESULT
+PARROT_CAN_RETURN_NULL
+static opcode_t * runops_cgoto_core(PARROT_INTERP,
+    ARGIN(Parrot_runcore_t *runcore),
+    ARGIN(opcode_t *pc))
+        __attribute__nonnull__(1)
+        __attribute__nonnull__(2)
+        __attribute__nonnull__(3);
+
+PARROT_WARN_UNUSED_RESULT
+PARROT_CANNOT_RETURN_NULL
+static opcode_t * runops_cgp_core(PARROT_INTERP,
+    ARGIN(Parrot_runcore_t *runcore),
+    ARGIN(opcode_t *pc))
+        __attribute__nonnull__(1)
+        __attribute__nonnull__(2)
+        __attribute__nonnull__(3);
+
+PARROT_WARN_UNUSED_RESULT
+PARROT_CAN_RETURN_NULL
+static opcode_t * runops_debugger_core(PARROT_INTERP,
+    ARGIN(Parrot_runcore_t *runcore),
+    ARGIN(opcode_t *pc))
+        __attribute__nonnull__(1)
+        __attribute__nonnull__(2)
+        __attribute__nonnull__(3);
+
+PARROT_WARN_UNUSED_RESULT
+PARROT_CAN_RETURN_NULL
+static opcode_t * runops_exec_core(PARROT_INTERP,
+    ARGIN(Parrot_runcore_t *runcore),
+    ARGIN(opcode_t *pc))
+        __attribute__nonnull__(1)
+        __attribute__nonnull__(2)
+        __attribute__nonnull__(3);
+
+PARROT_WARN_UNUSED_RESULT
+PARROT_CAN_RETURN_NULL
+static opcode_t * runops_fast_core(PARROT_INTERP,
+    ARGIN(Parrot_runcore_t *runcore),
+    ARGIN(opcode_t *pc))
+        __attribute__nonnull__(1)
+        __attribute__nonnull__(2)
+        __attribute__nonnull__(3);
+
+PARROT_WARN_UNUSED_RESULT
+PARROT_CAN_RETURN_NULL
+static opcode_t * runops_gc_debug_core(PARROT_INTERP,
+    ARGIN(Parrot_runcore_t *runcore),
+    ARGIN(opcode_t *pc))
+        __attribute__nonnull__(1)
+        __attribute__nonnull__(2)
+        __attribute__nonnull__(3);
+
+PARROT_WARN_UNUSED_RESULT
+PARROT_CAN_RETURN_NULL
+static opcode_t * runops_jit_core(PARROT_INTERP,
+    ARGIN(Parrot_runcore_t *runcore),
+    ARGIN(opcode_t *pc))
+        __attribute__nonnull__(1)
+        __attribute__nonnull__(2)
+        __attribute__nonnull__(3);
+
 PARROT_WARN_UNUSED_RESULT
 PARROT_CAN_RETURN_NULL
-static opcode_t * runops_trace_core(PARROT_INTERP, ARGIN(opcode_t *pc))
+static opcode_t * runops_profiling_core(PARROT_INTERP,
+    ARGIN(Parrot_profiling_runcore_t *runcore),
+    ARGIN(opcode_t *pc))
+        __attribute__nonnull__(1)
+        __attribute__nonnull__(2)
+        __attribute__nonnull__(3);
+
+PARROT_WARN_UNUSED_RESULT
+PARROT_CAN_RETURN_NULL
+static opcode_t * runops_slow_core(PARROT_INTERP,
+    ARGIN(Parrot_runcore_t *runcore),
+    ARGIN(opcode_t *pc))
+        __attribute__nonnull__(1)
+        __attribute__nonnull__(2)
+        __attribute__nonnull__(3);
+
+PARROT_WARN_UNUSED_RESULT
+PARROT_CANNOT_RETURN_NULL
+static opcode_t * runops_switch_core(PARROT_INTERP,
+    ARGIN(Parrot_runcore_t *runcore),
+    ARGIN(opcode_t *pc))
         __attribute__nonnull__(1)
-        __attribute__nonnull__(2);
+        __attribute__nonnull__(2)
+        __attribute__nonnull__(3);
 
+PARROT_WARN_UNUSED_RESULT
+PARROT_CAN_RETURN_NULL
+static opcode_t * runops_trace_core(PARROT_INTERP,
+    ARGIN(Parrot_runcore_t *runcore),
+    ARGIN(opcode_t *pc))
+        __attribute__nonnull__(1)
+        __attribute__nonnull__(2)
+        __attribute__nonnull__(3);
+
+#define ASSERT_ARGS_init_profiling_core __attribute__unused__ int _ASSERT_ARGS_CHECK = \
+       PARROT_ASSERT_ARG(interp) \
+    || PARROT_ASSERT_ARG(runcore) \
+    || PARROT_ASSERT_ARG(pc)
+#define ASSERT_ARGS_runops_cgoto_core __attribute__unused__ int _ASSERT_ARGS_CHECK = \
+       PARROT_ASSERT_ARG(interp) \
+    || PARROT_ASSERT_ARG(runcore) \
+    || PARROT_ASSERT_ARG(pc)
+#define ASSERT_ARGS_runops_cgp_core __attribute__unused__ int _ASSERT_ARGS_CHECK = \
+       PARROT_ASSERT_ARG(interp) \
+    || PARROT_ASSERT_ARG(runcore) \
+    || PARROT_ASSERT_ARG(pc)
+#define ASSERT_ARGS_runops_debugger_core __attribute__unused__ int _ASSERT_ARGS_CHECK = \
+       PARROT_ASSERT_ARG(interp) \
+    || PARROT_ASSERT_ARG(runcore) \
+    || PARROT_ASSERT_ARG(pc)
+#define ASSERT_ARGS_runops_exec_core __attribute__unused__ int _ASSERT_ARGS_CHECK = \
+       PARROT_ASSERT_ARG(interp) \
+    || PARROT_ASSERT_ARG(runcore) \
+    || PARROT_ASSERT_ARG(pc)
+#define ASSERT_ARGS_runops_fast_core __attribute__unused__ int _ASSERT_ARGS_CHECK = \
+       PARROT_ASSERT_ARG(interp) \
+    || PARROT_ASSERT_ARG(runcore) \
+    || PARROT_ASSERT_ARG(pc)
+#define ASSERT_ARGS_runops_gc_debug_core __attribute__unused__ int _ASSERT_ARGS_CHECK = \
+       PARROT_ASSERT_ARG(interp) \
+    || PARROT_ASSERT_ARG(runcore) \
+    || PARROT_ASSERT_ARG(pc)
+#define ASSERT_ARGS_runops_jit_core __attribute__unused__ int _ASSERT_ARGS_CHECK = \
+       PARROT_ASSERT_ARG(interp) \
+    || PARROT_ASSERT_ARG(runcore) \
+    || PARROT_ASSERT_ARG(pc)
+#define ASSERT_ARGS_runops_profiling_core __attribute__unused__ int _ASSERT_ARGS_CHECK = \
+       PARROT_ASSERT_ARG(interp) \
+    || PARROT_ASSERT_ARG(runcore) \
+    || PARROT_ASSERT_ARG(pc)
+#define ASSERT_ARGS_runops_slow_core __attribute__unused__ int _ASSERT_ARGS_CHECK = \
+       PARROT_ASSERT_ARG(interp) \
+    || PARROT_ASSERT_ARG(runcore) \
+    || PARROT_ASSERT_ARG(pc)
+#define ASSERT_ARGS_runops_switch_core __attribute__unused__ int _ASSERT_ARGS_CHECK = \
+       PARROT_ASSERT_ARG(interp) \
+    || PARROT_ASSERT_ARG(runcore) \
+    || PARROT_ASSERT_ARG(pc)
 #define ASSERT_ARGS_runops_trace_core __attribute__unused__ int _ASSERT_ARGS_CHECK = \
        PARROT_ASSERT_ARG(interp) \
+    || PARROT_ASSERT_ARG(runcore) \
     || PARROT_ASSERT_ARG(pc)
 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
 /* HEADERIZER END: static */
 
-#ifdef code_start
-#  undef code_start
-#endif
-#ifdef code_end
-#  undef code_end
-#endif
 
-#define  code_start interp->code->base.data
-#define  code_end (interp->code->base.data + interp->code->base.size)
+/*
+
+=item C<void Parrot_runcore_slow_init(PARROT_INTERP)>
+
+Registers the slow runcore with Parrot.
+
+=cut
+
+*/
+
+void
+Parrot_runcore_slow_init(PARROT_INTERP)
+{
+    ASSERT_ARGS(Parrot_runcore_slow_init)
+
+    Parrot_runcore_t *coredata = mem_allocate_typed(Parrot_runcore_t);
+    coredata->name             = CONST_STRING(interp, "slow");
+    coredata->id               = PARROT_SLOW_CORE;
+    coredata->opinit           = PARROT_CORE_OPLIB_INIT;
+    coredata->runops           = runops_slow_core;
+    coredata->prepare_run      = NULL;
+    coredata->destroy          = NULL;
+
+    PARROT_RUNCORE_FUNC_TABLE_SET(coredata);
+
+    Parrot_runcore_register(interp, coredata);
+
+    /* it's the first runcore and the default runcore */
+    Parrot_runcore_switch(interp, coredata->name);
+}
+
 
 /*
 
-=item C<opcode_t * runops_fast_core(PARROT_INTERP, opcode_t *pc)>
+=item C<void Parrot_runcore_fast_init(PARROT_INTERP)>
+
+Registers the fast runcore with Parrot.
+
+=cut
+
+*/
+
+void
+Parrot_runcore_fast_init(PARROT_INTERP)
+{
+    ASSERT_ARGS(Parrot_runcore_fast_init)
+
+    Parrot_runcore_t *coredata = mem_allocate_typed(Parrot_runcore_t);
+    coredata->name             = CONST_STRING(interp, "fast");
+    coredata->id               = PARROT_FAST_CORE;
+    coredata->opinit           = PARROT_CORE_OPLIB_INIT;
+    coredata->runops           = runops_fast_core;
+    coredata->destroy          = NULL;
+    coredata->prepare_run      = NULL;
+
+    PARROT_RUNCORE_FUNC_TABLE_SET(coredata);
+
+    Parrot_runcore_register(interp, coredata);
+}
+
+
+/*
+
+=item C<void Parrot_runcore_switch_init(PARROT_INTERP)>
+
+Registers the switch runcore with Parrot.
+
+=cut
+
+*/
+
+void
+Parrot_runcore_switch_init(PARROT_INTERP)
+{
+    ASSERT_ARGS(Parrot_runcore_switch_init)
+
+    Parrot_runcore_t *coredata = mem_allocate_typed(Parrot_runcore_t);
+    coredata->name             = CONST_STRING(interp, "switch");
+    coredata->id               = PARROT_SWITCH_CORE;
+    coredata->opinit           = PARROT_CORE_SWITCH_OPLIB_INIT;
+    coredata->runops           = runops_switch_core;
+    coredata->prepare_run      = init_prederef;
+    coredata->destroy          = NULL;
+
+    PARROT_RUNCORE_PREDEREF_OPS_SET(coredata);
+
+    Parrot_runcore_register(interp, coredata);
+}
+
+
+/*
+
+=item C<void Parrot_runcore_jit_init(PARROT_INTERP)>
+
+Registers the jit runcore with Parrot.
+
+=cut
+
+*/
+
+void
+Parrot_runcore_jit_init(PARROT_INTERP)
+{
+    ASSERT_ARGS(Parrot_runcore_jit_init)
+
+    Parrot_runcore_t *coredata = mem_allocate_typed(Parrot_runcore_t);
+    coredata->name             = CONST_STRING(interp, "jit");
+    coredata->id               = PARROT_JIT_CORE;
+    coredata->opinit           = PARROT_CORE_OPLIB_INIT;
+    coredata->prepare_run      = init_jit_run;
+    coredata->runops           = runops_jit_core;
+    coredata->destroy          = NULL;
+
+    PARROT_RUNCORE_JIT_OPS_SET(coredata);
+
+    Parrot_runcore_register(interp, coredata);
+}
+
+
+/*
+
+=item C<void Parrot_runcore_switch_jit_init(PARROT_INTERP)>
+
+Registers the switch_jit runcore with Parrot.
+
+=cut
+
+*/
+
+void
+Parrot_runcore_switch_jit_init(PARROT_INTERP)
+{
+    ASSERT_ARGS(Parrot_runcore_switch_jit_init)
+
+    Parrot_runcore_t *coredata = mem_allocate_typed(Parrot_runcore_t);
+    coredata->name             = CONST_STRING(interp, "switch_jit");
+    coredata->id               = PARROT_SWITCH_JIT_CORE;
+    coredata->opinit           = PARROT_CORE_SWITCH_OPLIB_INIT;
+    coredata->destroy          = NULL;
+    coredata->prepare_run      = init_prederef;
+    coredata->runops           = runops_switch_core;
+
+    PARROT_RUNCORE_PREDEREF_OPS_SET(coredata);
+    PARROT_RUNCORE_JIT_OPS_SET(coredata);
+
+    Parrot_runcore_register(interp, coredata);
+}
+
+
+/*
+
+=item C<void Parrot_runcore_exec_init(PARROT_INTERP)>
+
+Registers the exec runcore with Parrot.
+
+=cut
+
+*/
+
+void
+Parrot_runcore_exec_init(PARROT_INTERP)
+{
+    ASSERT_ARGS(Parrot_runcore_exec_init)
+
+    Parrot_runcore_t *coredata = mem_allocate_typed(Parrot_runcore_t);
+    coredata->name             = CONST_STRING(interp, "exec");
+    coredata->id               = PARROT_EXEC_CORE;
+    coredata->opinit           = PARROT_CORE_OPLIB_INIT;
+    coredata->runops           = runops_exec_core;
+    coredata->destroy          = NULL;
+    coredata->prepare_run      = NULL;
+
+    Parrot_runcore_register(interp, coredata);
+}
+
+
+/*
+
+=item C<void Parrot_runcore_gc_debug_init(PARROT_INTERP)>
+
+Registers the gc_debug runcore with Parrot.
+
+=cut
+
+*/
+
+void
+Parrot_runcore_gc_debug_init(PARROT_INTERP)
+{
+    ASSERT_ARGS(Parrot_runcore_gc_debug_init)
+
+    Parrot_runcore_t *coredata = mem_allocate_typed(Parrot_runcore_t);
+    coredata->name             = CONST_STRING(interp, "gc_debug");
+    coredata->id               = PARROT_GC_DEBUG_CORE;
+    coredata->opinit           = PARROT_CORE_OPLIB_INIT;
+    coredata->runops           = runops_gc_debug_core;
+    coredata->destroy          = NULL;
+    coredata->prepare_run      = NULL;
+
+    PARROT_RUNCORE_FUNC_TABLE_SET(coredata);
+
+    Parrot_runcore_register(interp, coredata);
+}
+
+
+/*
+
+=item C<void Parrot_runcore_debugger_init(PARROT_INTERP)>
+
+Registers the debugger runcore with Parrot.
+
+=cut
+
+*/
+
+void
+Parrot_runcore_debugger_init(PARROT_INTERP)
+{
+    ASSERT_ARGS(Parrot_runcore_debugger_init)
+
+    Parrot_runcore_t *coredata = mem_allocate_typed(Parrot_runcore_t);
+    coredata->name             = CONST_STRING(interp, "debugger");
+    coredata->id               = PARROT_DEBUGGER_CORE;
+    coredata->opinit           = PARROT_CORE_OPLIB_INIT;
+    coredata->prepare_run      = init_prederef;
+    coredata->runops           = runops_debugger_core;
+    coredata->destroy          = NULL;
+
+    PARROT_RUNCORE_FUNC_TABLE_SET(coredata);
+
+    Parrot_runcore_register(interp, coredata);
+}
+
+
+/*
+
+=item C<void Parrot_runcore_cgp_init(PARROT_INTERP)>
+
+Registers the CGP runcore with Parrot.
+
+=cut
+
+*/
+
+#ifdef HAVE_COMPUTED_GOTO
+
+void
+Parrot_runcore_cgp_init(PARROT_INTERP)
+{
+    ASSERT_ARGS(Parrot_runcore_cgp_init)
+
+    Parrot_runcore_t *coredata = mem_allocate_typed(Parrot_runcore_t);
+    coredata->name             = CONST_STRING(interp, "cgp");
+    coredata->id               = PARROT_CGP_CORE;
+    coredata->opinit           = PARROT_CORE_CGP_OPLIB_INIT;
+    coredata->prepare_run      = init_prederef;
+    coredata->runops           = runops_cgp_core;
+
+    coredata->destroy          = NULL;
+
+    PARROT_RUNCORE_CGOTO_OPS_SET(coredata);
+    PARROT_RUNCORE_EVENT_CHECK_SET(coredata);
+    PARROT_RUNCORE_PREDEREF_OPS_SET(coredata);
+
+    Parrot_runcore_register(interp, coredata);
+}
+
+
+/*
+
+=item C<void Parrot_runcore_cgoto_init(PARROT_INTERP)>
+
+Registers the cgoto runcore with Parrot.
+
+=cut
+
+*/
+
+void
+Parrot_runcore_cgoto_init(PARROT_INTERP)
+{
+    ASSERT_ARGS(Parrot_runcore_cgoto_init)
+
+    Parrot_runcore_t *coredata = mem_allocate_typed(Parrot_runcore_t);
+    coredata->name             = CONST_STRING(interp, "cgoto");
+    coredata->id               = PARROT_CGOTO_CORE;
+    coredata->opinit           = PARROT_CORE_CG_OPLIB_INIT;
+    coredata->runops           = runops_cgoto_core;
+    coredata->destroy          = NULL;
+    coredata->prepare_run      = NULL;
+
+    PARROT_RUNCORE_FUNC_TABLE_SET(coredata);
+    PARROT_RUNCORE_CGOTO_OPS_SET(coredata);
+
+    Parrot_runcore_register(interp, coredata);
+}
+
+
+/*
+
+=item C<void Parrot_runcore_cgp_jit_init(PARROT_INTERP)>
+
+Registers the CGP/JIT runcore with Parrot.
+
+=cut
+
+*/
+
+
+void
+Parrot_runcore_cgp_jit_init(PARROT_INTERP)
+{
+    ASSERT_ARGS(Parrot_runcore_cgp_jit_init)
+
+    Parrot_runcore_t *coredata = mem_allocate_typed(Parrot_runcore_t);
+    coredata->name             = CONST_STRING(interp, "cgp_jit");
+    coredata->id               = PARROT_CGP_JIT_CORE;
+    coredata->opinit           = PARROT_CORE_CGP_OPLIB_INIT;
+    coredata->prepare_run      = init_prederef;
+    coredata->runops           = runops_cgp_core;
+    coredata->destroy          = NULL;
+
+    PARROT_RUNCORE_JIT_OPS_SET(coredata);
+    PARROT_RUNCORE_CGOTO_OPS_SET(coredata);
+    PARROT_RUNCORE_EVENT_CHECK_SET(coredata);
+    PARROT_RUNCORE_PREDEREF_OPS_SET(coredata);
+
+    Parrot_runcore_register(interp, coredata);
+}
+
+#endif /* #ifdef HAVE_COMPUTED_GOTO */
+
+/*
+
+=item C<void Parrot_runcore_profiling_init(PARROT_INTERP)>
+
+Registers the profiling runcore with Parrot.
+
+=cut
+
+*/
+
+void
+Parrot_runcore_profiling_init(PARROT_INTERP)
+{
+    ASSERT_ARGS(Parrot_runcore_profiling_init)
+
+    Parrot_profiling_runcore_t *coredata =
+                                 mem_allocate_typed(Parrot_profiling_runcore_t);
+    coredata->name             = CONST_STRING(interp, "profiling");
+    coredata->id               = PARROT_PROFILING_CORE;
+    coredata->opinit           = PARROT_CORE_OPLIB_INIT;
+    coredata->runops           = (Parrot_runcore_runops_fn_t) init_profiling_core;
+    coredata->destroy          = NULL;
+    coredata->prepare_run      = NULL;
+
+    PARROT_RUNCORE_FUNC_TABLE_SET(coredata);
+
+    Parrot_runcore_register(interp, (Parrot_runcore_t *) coredata);
+}
+
+
+/*
+
+=item C<static opcode_t * runops_fast_core(PARROT_INTERP, Parrot_runcore_t
+*runcore, opcode_t *pc)>
 
 Runs the Parrot operations starting at C<pc> until there are no more
 operations.  This performs no bounds checking, profiling, or tracing.
@@ -286,8 +804,8 @@
 
 PARROT_WARN_UNUSED_RESULT
 PARROT_CAN_RETURN_NULL
-opcode_t *
-runops_fast_core(PARROT_INTERP, ARGIN(opcode_t *pc))
+static opcode_t *
+runops_fast_core(PARROT_INTERP, ARGIN(Parrot_runcore_t *runcore), ARGIN(opcode_t *pc))
 {
     ASSERT_ARGS(runops_fast_core)
 
@@ -311,7 +829,8 @@
 
 /*
 
-=item C<opcode_t * runops_cgoto_core(PARROT_INTERP, opcode_t *pc)>
+=item C<static opcode_t * runops_cgoto_core(PARROT_INTERP, Parrot_runcore_t
+*runcore, opcode_t *pc)>
 
 Runs the Parrot operations starting at C<pc> until there are no more
 operations, using the computed C<goto> core, performing no bounds checking,
@@ -325,8 +844,8 @@
 
 PARROT_WARN_UNUSED_RESULT
 PARROT_CAN_RETURN_NULL
-opcode_t *
-runops_cgoto_core(PARROT_INTERP, ARGIN(opcode_t *pc))
+static opcode_t *
+runops_cgoto_core(PARROT_INTERP, ARGIN(Parrot_runcore_t *runcore), ARGIN(opcode_t *pc))
 {
     ASSERT_ARGS(runops_cgoto_core)
 
@@ -344,10 +863,22 @@
 #endif
 }
 
+#ifdef code_start
+#  undef code_start
+#endif
+#ifdef code_end
+#  undef code_end
+#endif
+
+#define  code_start interp->code->base.data
+#define  code_end (interp->code->base.data + interp->code->base.size)
+
+
 
 /*
 
-=item C<static opcode_t * runops_trace_core(PARROT_INTERP, opcode_t *pc)>
+=item C<static opcode_t * runops_trace_core(PARROT_INTERP, Parrot_runcore_t
+*runcore, opcode_t *pc)>
 
 Runs the Parrot operations starting at C<pc> until there are no more
 operations, using the tracing interpreter.
@@ -359,7 +890,7 @@
 PARROT_WARN_UNUSED_RESULT
 PARROT_CAN_RETURN_NULL
 static opcode_t *
-runops_trace_core(PARROT_INTERP, ARGIN(opcode_t *pc))
+runops_trace_core(PARROT_INTERP, ARGIN(Parrot_runcore_t *runcore), ARGIN(opcode_t *pc))
 {
     ASSERT_ARGS(runops_trace_core)
 
@@ -436,7 +967,8 @@
 
 /*
 
-=item C<opcode_t * runops_slow_core(PARROT_INTERP, opcode_t *pc)>
+=item C<static opcode_t * runops_slow_core(PARROT_INTERP, Parrot_runcore_t
+*runcore, opcode_t *pc)>
 
 Runs the Parrot operations starting at C<pc> until there are no more
 operations, with tracing and bounds checking enabled.
@@ -447,13 +979,13 @@
 
 PARROT_WARN_UNUSED_RESULT
 PARROT_CAN_RETURN_NULL
-opcode_t *
-runops_slow_core(PARROT_INTERP, ARGIN(opcode_t *pc))
+static opcode_t *
+runops_slow_core(PARROT_INTERP, ARGIN(Parrot_runcore_t *runcore), ARGIN(opcode_t *pc))
 {
     ASSERT_ARGS(runops_slow_core)
 
     if (Interp_trace_TEST(interp, PARROT_TRACE_OPS_FLAG))
-        return runops_trace_core(interp, pc);
+        return runops_trace_core(interp, runcore, pc);
 #if 0
     if (interp->debugger && interp->debugger->pdb)
         return Parrot_debug(interp, interp->debugger, pc);
@@ -475,7 +1007,8 @@
 
 /*
 
-=item C<opcode_t * runops_gc_debug_core(PARROT_INTERP, opcode_t *pc)>
+=item C<static opcode_t * runops_gc_debug_core(PARROT_INTERP, Parrot_runcore_t
+*runcore, opcode_t *pc)>
 
 Runs the Parrot operations starting at C<pc> until there are no more
 operations, performing a full GC run before each op.  This is very slow, but
@@ -487,8 +1020,8 @@
 
 PARROT_WARN_UNUSED_RESULT
 PARROT_CAN_RETURN_NULL
-opcode_t *
-runops_gc_debug_core(PARROT_INTERP, ARGIN(opcode_t *pc))
+static opcode_t *
+runops_gc_debug_core(PARROT_INTERP, ARGIN(Parrot_runcore_t *runcore), ARGIN(opcode_t *pc))
 {
     ASSERT_ARGS(runops_gc_debug_core)
     while (pc) {
@@ -505,13 +1038,86 @@
     return pc;
 }
 
-#undef code_start
-#undef code_end
 
+/*
+
+=item C<static void * init_profiling_core(PARROT_INTERP,
+Parrot_profiling_runcore_t *runcore, opcode_t *pc)>
+
+Perform initialization for the profiling runcore.
+
+=cut
+
+*/
+
+PARROT_CAN_RETURN_NULL
+static void *
+init_profiling_core(PARROT_INTERP, ARGIN(Parrot_profiling_runcore_t *runcore), ARGIN(opcode_t *pc))
+{
+    ASSERT_ARGS(init_profiling_core)
+
+    char *profile_filename, *profile_output_var;
+    int free_env_var;
+
+    profile_output_var = Parrot_getenv("PARROT_PROFILING_OUTPUT", &free_env_var);
+
+    if (profile_output_var) {
+
+        STRING  *lc_filename;
+        runcore->profile_filename = Parrot_str_new(interp, profile_output_var, 0);
+        profile_filename          = Parrot_str_to_cstring(interp, runcore->profile_filename);
+        lc_filename               = Parrot_str_downcase(interp, runcore->profile_filename);
+
+        if (Parrot_str_equal(interp, lc_filename, CONST_STRING(interp, "stderr"))) {
+            runcore->profile_fd       = stderr;
+            runcore->profile_filename = lc_filename;
+        }
+        else if (Parrot_str_equal(interp, lc_filename, CONST_STRING(interp, "stdout"))) {
+            runcore->profile_fd       = stdout;
+            runcore->profile_filename = lc_filename;
+        }
+        else {
+            runcore->profile_fd = fopen(profile_filename, "w");
+        }
+
+        if (free_env_var)
+            mem_sys_free(profile_output_var);
+    }
+    else {
+        runcore->profile_filename = Parrot_sprintf_c(interp, "parrot.pprof.%d", getpid());
+        profile_filename          = Parrot_str_to_cstring(interp, runcore->profile_filename);
+        runcore->profile_fd       = fopen(profile_filename, "w");
+    }
+
+    /* profile_filename gets collected if it's not marked or in the root set. */
+    gc_register_pmc(interp, (PMC *) runcore->profile_filename);
+
+    runcore->runops  = (Parrot_runcore_runops_fn_t)  runops_profiling_core;
+    runcore->destroy = (Parrot_runcore_destroy_fn_t) destroy_profiling_core;
+
+    runcore->prev_ctx        = 0;
+    runcore->profiling_flags = 0;
+    runcore->runloop_count   = 0;
+    runcore->level           = 0;
+    runcore->time_size       = 32;
+    runcore->time            = mem_allocate_n_typed(runcore->time_size, UHUGEINTVAL);
+    Profiling_first_loop_SET(runcore);
+
+    if (!runcore->profile_fd) {
+        fprintf(stderr, "unable to open %s for writing", profile_filename);
+        mem_sys_free(profile_filename);
+        exit(1);
+    }
+
+    mem_sys_free(profile_filename);
+
+    return runops_profiling_core(interp, runcore, pc);
+}
 
 /*
 
-=item C<opcode_t * runops_profile_core(PARROT_INTERP, opcode_t *pc)>
+=item C<static opcode_t * runops_profiling_core(PARROT_INTERP,
+Parrot_profiling_runcore_t *runcore, opcode_t *pc)>
 
 Runs the Parrot operations starting at C<pc> until there are no more
 operations, with tracing, bounds checking, and profiling enabled.
@@ -522,45 +1128,207 @@
 
 PARROT_WARN_UNUSED_RESULT
 PARROT_CAN_RETURN_NULL
-opcode_t *
-runops_profile_core(PARROT_INTERP, ARGIN(opcode_t *pc))
+static opcode_t *
+runops_profiling_core(PARROT_INTERP, ARGIN(Parrot_profiling_runcore_t *runcore),
+ARGIN(opcode_t *pc))
 {
-    ASSERT_ARGS(runops_profile_core)
-    RunProfile * const profile = interp->profile;
-    const opcode_t     old_op  = profile->cur_op;
-
-    /* if reentering the runloop, remember old op and calc time 'til now */
-    if (old_op)
-        profile->data[old_op].time +=
-            Parrot_floatval_time() - profile->starttime;
+    ASSERT_ARGS(runops_profiling_core)
 
-    while (pc) {/* && pc >= code_start && pc < code_end) */
-        opcode_t cur_op;
+    Parrot_Context_info preop_info, postop_info;
+    PMC                *preop_sub, *argv;
+    opcode_t           *preop_pc;
+    UHUGEINTVAL         op_time;
+    STRING             *unknown_file = CONST_STRING(interp, "<unknown file>");
+
+    runcore->runcore_start = Parrot_hires_get_time();
+
+    /* if we're in a nested runloop, */
+    if (runcore->level != 0) {
+
+        if (runcore->level > runcore->time_size) {
+            runcore->time_size *= 2;
+            runcore->time =
+                mem_realloc_n_typed(runcore->time, runcore->time_size+1, UHUGEINTVAL);
+        }
 
-        Parrot_pcc_set_pc(interp, CURRENT_CONTEXT(interp), pc);
-        profile->cur_op                   = cur_op = *pc + PARROT_PROF_EXTRA;
-        profile->starttime                = Parrot_floatval_time();
-        profile->data[cur_op].numcalls++;
+        /* store the time between DO_OP and the start of this runcore in this
+         * op's running total */
+        runcore->time[runcore->level] = runcore->runcore_start - runcore->op_start;
+    }
+
+    Parrot_Context_get_info(interp, CURRENT_CONTEXT(interp), &postop_info);
+
+    argv = VTABLE_get_pmc_keyed_int(interp, interp->iglobals, IGLOBALS_ARGV_LIST);
+
+    if (argv && !Profiling_have_printed_cli_TEST(runcore)) {
+
+        /* silly way to avoid line length codingstds nit */
+        PMC    *iglobals     = interp->iglobals;
+        PMC    *executable   = VTABLE_get_pmc_keyed_int(interp, iglobals, IGLOBALS_EXECUTABLE);
+        STRING *command_line = Parrot_str_join(interp, CONST_STRING(interp, " "), argv);
+
+        char   *exec_cstr, *command_line_cstr;
+
+        exec_cstr         = Parrot_str_to_cstring(interp, VTABLE_get_string(interp, executable));
+        command_line_cstr = Parrot_str_to_cstring(interp, command_line);
+
+        /* The CLI line won't reflect any options passed to the parrot binary. */
+        fprintf(runcore->profile_fd, "CLI:%s %s\n", exec_cstr, command_line_cstr);
+
+        mem_sys_free(exec_cstr);
+        mem_sys_free(command_line_cstr);
+
+        Profiling_have_printed_cli_SET(runcore);
+    }
 
-        DO_OP(pc, interp);
 
-        /* profile->cur_op may be different, if exception was thrown */
-        profile->data[profile->cur_op].time +=
-            Parrot_floatval_time() - profile->starttime;
+    if (Profiling_first_loop_TEST(runcore)) {
+
+        fprintf(runcore->profile_fd, "VERSION:1\n");
+        /* silly hack to make all separate runloops appear to come from a single source */
+        /* NOTE: yes, {x{ foo:bar }x} is ugly an inefficient.  Escaping would
+         * be more effort but the priority right now is to get the runcore
+         * working correctly.  Once all the bugs are ironed out we'll switch to
+         * a nice efficient compressed binary format. */
+        fprintf(runcore->profile_fd,
+                "CS:{x{ns:main}x}{x{file:no_file}x}{x{sub:0x1}x}{x{ctx:0x1}x}\n");
+        fprintf(runcore->profile_fd,
+                "OP:{x{line:%d}x}{x{time:0}x}{x{op:noop}x}\n", (int) runcore->runloop_count);
+        runcore->runloop_count++;
+        Profiling_first_loop_CLEAR(runcore);
     }
 
-    if (old_op) {
-        /* old opcode continues */
-        profile->starttime = Parrot_floatval_time();
-        profile->cur_op    = old_op;
+    while (pc) {
+
+        STRING         *postop_file_name;
+        Parrot_Context *preop_ctx;
+
+        if (pc < code_start || pc >= code_end) {
+            Parrot_ex_throw_from_c_args(interp, NULL, 1,
+                    "attempt to access code outside of current code segment");
+        }
+
+        /* avoid an extra call to Parrot_Context_get_info */
+        mem_sys_memcopy(&preop_info, &postop_info, sizeof (Parrot_Context_info));
+
+        Parrot_Context_get_info(interp, CURRENT_CONTEXT(interp), &postop_info);
+
+        CONTEXT(interp)->current_pc = pc;
+        preop_sub = CONTEXT(interp)->current_sub;
+        preop_pc = pc;
+        preop_ctx = CONTEXT(interp);
+
+        runcore->level++;
+        Profiling_exit_check_CLEAR(runcore);
+        runcore->op_start = Parrot_hires_get_time();
+        DO_OP(pc, interp);
+        runcore->op_finish = Parrot_hires_get_time();
+
+        if (Profiling_exit_check_TEST(runcore)) {
+            op_time  = runcore->op_finish - runcore->runcore_finish;
+            op_time += runcore->time[runcore->level];
+            runcore->time[runcore->level] = 0;
+        }
+        else {
+            op_time = runcore->op_finish - runcore->op_start;
+        }
+
+        runcore->level--;
+        postop_file_name = postop_info.file;
+
+        if (!postop_file_name) postop_file_name = unknown_file;
+
+        /* if current context changed since the last time a CS line was printed... */
+        /* Occasionally the ctx stays the same while the sub changes, possible
+         * with a call to a subclass' method. */
+        if ((runcore->prev_ctx != preop_ctx) || runcore->prev_sub != preop_ctx->current_sub) {
+
+            if (preop_ctx->current_sub) {
+                STRING *sub_name;
+                char *sub_cstr, *filename_cstr, *ns_cstr;
+
+                GETATTR_Sub_name(interp, preop_ctx->current_sub, sub_name);
+                sub_cstr      = Parrot_str_to_cstring(interp, sub_name);
+                filename_cstr = Parrot_str_to_cstring(interp, postop_file_name);
+                ns_cstr       = Parrot_str_to_cstring(interp,
+                                  VTABLE_get_string(interp, preop_ctx->current_namespace));
+
+                fprintf(runcore->profile_fd,
+                        "CS:{x{ns:%s;%s}x}{x{file:%s}x}{x{sub:0x%X}x}{x{ctx:0x%X}x}\n",
+                        ns_cstr, sub_cstr, filename_cstr,
+                        (unsigned int) preop_ctx->current_sub,
+                        (unsigned int) preop_ctx);
+
+                mem_sys_free(sub_cstr);
+                mem_sys_free(filename_cstr);
+                mem_sys_free(ns_cstr);
+            }
+
+            runcore->prev_ctx = preop_ctx;
+            runcore->prev_sub = preop_ctx->current_sub;
+        }
+
+        /* I'd expect that preop_info.line would be the right thing to use here
+         * but it gives me obviously incorrect results while postop_info.line
+         * works.  It might be an imcc bug or it might just be me
+         * misunderstanding something. */
+        fprintf(runcore->profile_fd, "OP:{x{line:%d}x}{x{time:%lli}x}{x{op:%s}x}\n",
+                postop_info.line, op_time,
+                (interp->op_info_table)[*preop_pc].name);
+
+    } /* while (pc) */
+
+    /* make it easy to tell separate runloops apart */
+    if (runcore->level == 0) {
+        fprintf(runcore->profile_fd, "END_OF_RUNLOOP\n");
+        /* silly hack to make all separate runloops appear to come from a single source */
+        fprintf(runcore->profile_fd,
+                "CS:{x{ns:main}x}{x{file:no_file}x}{x{sub:0x1}x}{x{ctx:0x1}x}\n");
+        fprintf(runcore->profile_fd,
+                "OP:{x{line:%d}x}{x{time:0}x}{x{op:noop}x}\n", (int) runcore->runloop_count);
+        runcore->runloop_count++;
     }
 
+    Profiling_exit_check_SET(runcore);
+    runcore->runcore_finish = Parrot_hires_get_time();;
     return pc;
 }
 
+
+/*
+
+=item C<void * destroy_profiling_core(PARROT_INTERP, Parrot_profiling_runcore_t
+*runcore)>
+
+Perform any finalization needed by the profiling runcore.
+
+=cut
+
+*/
+
+PARROT_CAN_RETURN_NULL
+void *
+destroy_profiling_core(PARROT_INTERP, ARGIN(Parrot_profiling_runcore_t *runcore))
+{
+    ASSERT_ARGS(destroy_profiling_core)
+
+    char *filename_cstr = Parrot_str_to_cstring(interp, runcore->profile_filename);
+    fprintf(stderr, "\nPROFILING RUNCORE: Wrote profile to %s .\n", filename_cstr);
+    mem_sys_free(filename_cstr);
+
+    fclose(runcore->profile_fd);
+    mem_sys_free(runcore->time);
+
+    return NULL;
+}
+
+#undef code_start
+#undef code_end
+
 /*
 
-=item C<opcode_t * runops_debugger_core(PARROT_INTERP, opcode_t *pc)>
+=item C<static opcode_t * runops_debugger_core(PARROT_INTERP, Parrot_runcore_t
+*runcore, opcode_t *pc)>
 
 Used by the debugger, under construction
 
@@ -570,17 +1338,15 @@
 
 PARROT_WARN_UNUSED_RESULT
 PARROT_CAN_RETURN_NULL
-opcode_t *
-runops_debugger_core(PARROT_INTERP, ARGIN(opcode_t *pc))
+static opcode_t *
+runops_debugger_core(PARROT_INTERP, ARGIN(Parrot_runcore_t *runcore), ARGIN(opcode_t *pc))
 {
     ASSERT_ARGS(runops_debugger_core)
-    /*fprintf(stderr, "Enter runops_debugger_core\n");*/
 
     PARROT_ASSERT(interp->pdb);
 
-    if (interp->pdb->state & PDB_ENTER) {
+    if (interp->pdb->state & PDB_ENTER)
         Parrot_debugger_start(interp, pc);
-    }
 
     while (pc) {
         if (pc < interp->code->base.data || pc >= interp->code->base.data + interp->code->base.size)
@@ -604,24 +1370,335 @@
         if (interp->pdb->state & PDB_STOPPED) {
             Parrot_debugger_start(interp, pc);
         }
-        else
-        {
+        else {
             if (PDB_break(interp)) {
                 Parrot_debugger_start(interp, pc);
                 continue;
             }
 
-            if (interp->pdb->tracing) {
-                if (--interp->pdb->tracing == 0) {
-                    Parrot_debugger_start(interp, pc);
-                }
-            }
+            if (interp->pdb->tracing && --interp->pdb->tracing == 0)
+                Parrot_debugger_start(interp, pc);
         }
     }
 
     return pc;
 }
 
+
+/*
+
+=item C<static opcode_t * runops_switch_core(PARROT_INTERP, Parrot_runcore_t
+*runcore, opcode_t *pc)>
+
+Runs the C<switch> core.
+
+=cut
+
+*/
+
+PARROT_WARN_UNUSED_RESULT
+PARROT_CANNOT_RETURN_NULL
+static opcode_t *
+runops_switch_core(PARROT_INTERP, ARGIN(Parrot_runcore_t *runcore), ARGIN(opcode_t *pc))
+{
+    ASSERT_ARGS(runops_switch_core)
+    opcode_t * const code_start = (opcode_t *)interp->code->base.data;
+    opcode_t        *pc_prederef;
+
+    init_prederef(interp, runcore);
+    pc_prederef = (opcode_t*)interp->code->prederef.code + (pc - code_start);
+
+    return switch_core(pc_prederef, interp);
+}
+
+
+/*
+
+=item C<void * init_prederef(PARROT_INTERP, Parrot_runcore_t *runcore)>
+
+Initialize: load prederef C<func_table>, file prederef.code.
+
+=cut
+
+*/
+
+PARROT_CAN_RETURN_NULL
+void *
+init_prederef(PARROT_INTERP, ARGIN(Parrot_runcore_t *runcore))
+{
+    ASSERT_ARGS(init_prederef)
+    load_prederef(interp, runcore);
+
+    if (!interp->code->prederef.code) {
+        void        *pred_func;
+        opcode_t    *pc = interp->code->base.data;
+        const size_t N  = interp->code->base.size;
+        size_t       i, n_pics;
+
+/* Parrot_memalign_if_possible in OpenBSD allocates 256 if you ask for 312
+   -- Need to verify this, it may have been a bug elsewhere. If it works now,
+   we can remove the mem_sys_allocate_zeroed line below. */
+
+#if 0
+        void **temp = (void **)mem_sys_allocate_zeroed(N * sizeof (void *));
+#else
+        void **temp = (void **)Parrot_memalign_if_possible(256,
+                N * sizeof (void *));
+#endif
+        /* calc and remember pred_offset */
+        CONTEXT(interp)->pred_offset = pc - (opcode_t *)temp;
+
+        /* fill with the prederef__ opcode function */
+        if (PARROT_RUNCORE_PREDEREF_OPS_TEST(runcore)
+        && !PARROT_RUNCORE_CGOTO_OPS_TEST(runcore))
+            pred_func = (void *)CORE_OPS_prederef__;
+        else {
+            PARROT_ASSERT(interp->op_lib->op_func_table);
+            pred_func = ((void **)
+                    interp->op_lib->op_func_table)[CORE_OPS_prederef__];
+        }
+
+        for (i = n_pics = 0; i < N;) {
+            op_info_t * const opinfo = &interp->op_info_table[*pc];
+            size_t            n      = opinfo->op_count;
+
+            temp[i] = pred_func;
+
+            ADD_OP_VAR_PART(interp, interp->code, pc, n);
+
+            /* count ops that need a PIC */
+            if (parrot_PIC_op_is_cached(*pc))
+                n_pics++;
+
+            pc += n;
+            i  += n;
+        }
+
+        interp->code->prederef.code = temp;
+
+        /* allocate pic store, which starts from 1 */
+        if (n_pics)
+            parrot_PIC_alloc_store(interp->code, n_pics + 1);
+    }
+
+    return NULL;
+}
+
+
+/*
+
+=item C<void load_prederef(PARROT_INTERP, Parrot_runcore_t *runcore)>
+
+C<< interp->op_lib >> = prederefed oplib.
+
+=cut
+
+*/
+
+void
+load_prederef(PARROT_INTERP, ARGIN(Parrot_runcore_t *runcore))
+{
+    ASSERT_ARGS(load_prederef)
+    const oplib_init_f init_func = get_core_op_lib_init(interp, runcore);
+
+    int (*get_op)(const char * name, int full);
+
+    get_op          = interp->op_lib->op_code;
+    interp->op_lib  = init_func(1);
+
+    /* preserve the get_op function */
+    interp->op_lib->op_code = get_op;
+
+    if (interp->op_lib->op_count != interp->op_count)
+        Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_PREDEREF_LOAD_ERROR,
+            "Illegal op count (%d) in prederef oplib\n",
+            (int)interp->op_lib->op_count);
+}
+
+
+/*
+
+=item C<oplib_init_f get_core_op_lib_init(PARROT_INTERP, Parrot_runcore_t
+*runcore)>
+
+Returns an opcode's library C<op_lib> init function.
+
+=cut
+
+*/
+
+PARROT_WARN_UNUSED_RESULT
+PARROT_CANNOT_RETURN_NULL
+oplib_init_f
+get_core_op_lib_init(PARROT_INTERP, ARGIN(Parrot_runcore_t *runcore))
+{
+    ASSERT_ARGS(get_core_op_lib_init)
+    return runcore->opinit;
+}
+
+
+/*
+
+=item C<void * init_jit_run(PARROT_INTERP, Parrot_runcore_t *runcore)>
+
+Initializes JIT function for the specified opcode and runs it.
+
+=cut
+
+*/
+
+PARROT_WARN_UNUSED_RESULT
+PARROT_CANNOT_RETURN_NULL
+void *
+init_jit_run(PARROT_INTERP, ARGIN(Parrot_runcore_t *runcore))
+{
+    ASSERT_ARGS(init_jit_run)
+    return init_jit(interp, interp->code->base.data);
+}
+
+
+#ifdef PARROT_EXEC_OS_AIX
+extern void* aix_get_toc();
+#endif
+
+/*
+
+=item C<static opcode_t * runops_jit_core(PARROT_INTERP, Parrot_runcore_t
+*runcore, opcode_t *pc)>
+
+Runs the JIT code for the specified opcode.
+
+=cut
+
+*/
+
+PARROT_WARN_UNUSED_RESULT
+PARROT_CAN_RETURN_NULL
+static opcode_t *
+runops_jit_core(PARROT_INTERP, ARGIN(Parrot_runcore_t *runcore), ARGIN(opcode_t *pc))
+{
+    ASSERT_ARGS(runops_jit_core)
+#if JIT_CAPABLE
+#  ifdef PARROT_EXEC_OS_AIX
+    /* AIX calling convention requires that function-call-by-ptr be made
+       through the following struct: */
+    struct ptrgl_t { jit_f functPtr; void *toc; void *env; } ptrgl_t;
+
+    ptrgl_t.functPtr = (jit_f) D2FPTR(init_jit(interp, pc));
+    ptrgl_t.env      = NULL;
+
+    /* r2 (TOC) needs to point back here so we can return from non-JIT
+       functions */
+    ptrgl_t.toc = aix_get_toc();
+
+    ((jit_f) D2FPTR(&ptrgl_t)) (interp, pc);
+#  else
+    jit_f jit_code = (jit_f)(init_jit(interp, pc));
+    (jit_code) (interp, pc);
+#  endif
+#else
+    UNUSED(interp);
+    UNUSED(pc);
+#endif
+    return NULL;
+}
+
+
+/*
+
+=item C<static opcode_t * runops_exec_core(PARROT_INTERP, Parrot_runcore_t
+*runcore, opcode_t *pc)>
+
+Runs the native executable version of the specified opcode.
+
+=cut
+
+*/
+
+#if EXEC_CAPABLE
+    extern int Parrot_exec_run;
+#endif
+
+PARROT_WARN_UNUSED_RESULT
+PARROT_CAN_RETURN_NULL
+static opcode_t *
+runops_exec_core(PARROT_INTERP, ARGIN(Parrot_runcore_t *runcore), ARGIN(opcode_t *pc))
+{
+    ASSERT_ARGS(runops_exec_core)
+#if EXEC_CAPABLE
+    opcode_t *code_start = interp->code->base.data;
+
+    /* size in opcodes */
+    UINTVAL   code_size  = interp->code->base.size;
+    opcode_t *code_end   = code_start + code_size;
+
+#  if defined HAVE_COMPUTED_GOTO && defined USE_CGP
+#    ifdef __GNUC__
+#      ifdef PARROT_I386
+    init_prederef(interp, PARROT_CGP_CORE);
+#      endif
+#    endif
+#  endif
+    if (Parrot_exec_run == 2) {
+        void *ignored;
+        Parrot_exec_run = 0;
+
+        Parrot_runcore_switch(interp, CONST_STRING(interp, "jit"));
+
+        ignored         = runops_jit_core(interp, runcore, pc);
+        UNUSED(ignored);
+
+        Parrot_runcore_switch(interp, CONST_STRING(interp, "exec"));
+    }
+    else if (Parrot_exec_run == 1)
+        Parrot_exec(interp, pc, code_start, code_end);
+    else
+        run_native(interp, pc, code_start);
+
+#else
+    UNUSED(interp);
+    UNUSED(pc);
+#endif
+
+    return NULL;
+}
+
+
+/*
+
+=item C<static opcode_t * runops_cgp_core(PARROT_INTERP, Parrot_runcore_t
+*runcore, opcode_t *pc)>
+
+Runs the computed goto and predereferenced core.
+
+=cut
+
+*/
+
+PARROT_WARN_UNUSED_RESULT
+PARROT_CANNOT_RETURN_NULL
+static opcode_t *
+runops_cgp_core(PARROT_INTERP, ARGIN(Parrot_runcore_t *runcore), ARGIN(opcode_t *pc))
+{
+    ASSERT_ARGS(runops_cgp_core)
+#ifdef HAVE_COMPUTED_GOTO
+    opcode_t * const code_start = (opcode_t *)interp->code->base.data;
+    opcode_t        *pc_prederef;
+
+    init_prederef(interp, runcore);
+
+    pc_prederef = (opcode_t *)interp->code->prederef.code + (pc - code_start);
+    return cgp_core(pc_prederef, interp);
+
+#else
+    UNUSED(pc);
+    Parrot_io_eprintf(interp,
+            "Computed goto unavailable in this configuration.\n");
+    Parrot_exit(interp, 1);
+#endif
+
+}
+
 /*
 
 =back

Modified: trunk/src/runcore/main.c
==============================================================================
--- trunk/src/runcore/main.c	Sun Sep  6 20:31:13 2009	(r41080)
+++ trunk/src/runcore/main.c	Sun Sep  6 20:40:14 2009	(r41081)
@@ -64,23 +64,12 @@
 
 PARROT_WARN_UNUSED_RESULT
 PARROT_CANNOT_RETURN_NULL
-static oplib_init_f get_core_op_lib_init(PARROT_INTERP, int which)
-        __attribute__nonnull__(1);
-
-PARROT_WARN_UNUSED_RESULT
-PARROT_CANNOT_RETURN_NULL
 static oplib_init_f get_dynamic_op_lib_init(SHIM_INTERP,
     ARGIN(const PMC *lib))
         __attribute__nonnull__(2);
 
-static void init_prederef(PARROT_INTERP, int which)
-        __attribute__nonnull__(1);
-
-static void load_prederef(PARROT_INTERP, int which)
-        __attribute__nonnull__(1);
-
 static void notify_func_table(PARROT_INTERP,
-    ARGIN(op_func_t* table),
+    ARGIN(op_func_t *table),
     int on)
         __attribute__nonnull__(1)
         __attribute__nonnull__(2);
@@ -96,30 +85,6 @@
         __attribute__nonnull__(4)
         FUNC_MODIFIES(*pc_prederef);
 
-PARROT_WARN_UNUSED_RESULT
-PARROT_CANNOT_RETURN_NULL
-static opcode_t * runops_cgp(PARROT_INTERP, ARGIN(opcode_t *pc))
-        __attribute__nonnull__(1)
-        __attribute__nonnull__(2);
-
-PARROT_WARN_UNUSED_RESULT
-PARROT_CAN_RETURN_NULL
-static opcode_t * runops_exec(PARROT_INTERP, ARGIN(opcode_t *pc))
-        __attribute__nonnull__(1)
-        __attribute__nonnull__(2);
-
-PARROT_WARN_UNUSED_RESULT
-PARROT_CAN_RETURN_NULL
-static opcode_t * runops_jit(PARROT_INTERP, ARGIN(opcode_t *pc))
-        __attribute__nonnull__(1)
-        __attribute__nonnull__(2);
-
-PARROT_WARN_UNUSED_RESULT
-PARROT_CANNOT_RETURN_NULL
-static opcode_t * runops_switch(PARROT_INTERP, ARGIN(opcode_t *pc))
-        __attribute__nonnull__(1)
-        __attribute__nonnull__(2);
-
 static void stop_prederef(PARROT_INTERP)
         __attribute__nonnull__(1);
 
@@ -129,14 +94,8 @@
 #define ASSERT_ARGS_dynop_register_switch __attribute__unused__ int _ASSERT_ARGS_CHECK = 0
 #define ASSERT_ARGS_dynop_register_xx __attribute__unused__ int _ASSERT_ARGS_CHECK = \
        PARROT_ASSERT_ARG(interp)
-#define ASSERT_ARGS_get_core_op_lib_init __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp)
 #define ASSERT_ARGS_get_dynamic_op_lib_init __attribute__unused__ int _ASSERT_ARGS_CHECK = \
        PARROT_ASSERT_ARG(lib)
-#define ASSERT_ARGS_init_prederef __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp)
-#define ASSERT_ARGS_load_prederef __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp)
 #define ASSERT_ARGS_notify_func_table __attribute__unused__ int _ASSERT_ARGS_CHECK = \
        PARROT_ASSERT_ARG(interp) \
     || PARROT_ASSERT_ARG(table)
@@ -145,18 +104,6 @@
     || PARROT_ASSERT_ARG(interp) \
     || PARROT_ASSERT_ARG(pc) \
     || PARROT_ASSERT_ARG(opinfo)
-#define ASSERT_ARGS_runops_cgp __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp) \
-    || PARROT_ASSERT_ARG(pc)
-#define ASSERT_ARGS_runops_exec __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp) \
-    || PARROT_ASSERT_ARG(pc)
-#define ASSERT_ARGS_runops_jit __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp) \
-    || PARROT_ASSERT_ARG(pc)
-#define ASSERT_ARGS_runops_switch __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp) \
-    || PARROT_ASSERT_ARG(pc)
 #define ASSERT_ARGS_stop_prederef __attribute__unused__ int _ASSERT_ARGS_CHECK = \
        PARROT_ASSERT_ARG(interp)
 #define ASSERT_ARGS_turn_ev_check __attribute__unused__ int _ASSERT_ARGS_CHECK = \
@@ -164,9 +111,104 @@
 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
 /* HEADERIZER END: static */
 
-#if EXEC_CAPABLE
-    extern int Parrot_exec_run;
+/*
+
+=item C<void Parrot_runcore_init(PARROT_INTERP)>
+
+Initializes the runcores.
+
+=cut
+
+*/
+
+void
+Parrot_runcore_init(PARROT_INTERP)
+{
+    ASSERT_ARGS(Parrot_runcore_init)
+
+    interp->cores     = NULL;
+    interp->num_cores = 0;
+
+    Parrot_runcore_slow_init(interp);
+    Parrot_runcore_fast_init(interp);
+    Parrot_runcore_switch_init(interp);
+
+    Parrot_runcore_jit_init(interp);
+    Parrot_runcore_switch_jit_init(interp);
+    Parrot_runcore_exec_init(interp);
+    Parrot_runcore_gc_debug_init(interp);
+    Parrot_runcore_debugger_init(interp);
+
+    Parrot_runcore_profiling_init(interp);
+
+#ifdef HAVE_COMPUTED_GOTO
+    Parrot_runcore_cgp_init(interp);
+    Parrot_runcore_cgoto_init(interp);
+    Parrot_runcore_cgp_jit_init(interp);
 #endif
+}
+
+
+/*
+
+=item C<INTVAL Parrot_runcore_register(PARROT_INTERP, Parrot_runcore_t
+*coredata)>
+
+Registers a new runcore with Parrot.  Returns 1 on success, 0 on failure.
+
+=cut
+
+*/
+
+PARROT_EXPORT
+INTVAL
+Parrot_runcore_register(PARROT_INTERP, ARGIN(Parrot_runcore_t *coredata))
+{
+    ASSERT_ARGS(Parrot_runcore_register)
+    size_t num_cores = ++interp->num_cores;
+
+    mem_realloc_n_typed(interp->cores, num_cores, Parrot_runcore_t *);
+
+    interp->cores[num_cores - 1] = coredata;
+
+    return 1;
+}
+
+
+/*
+
+=item C<void Parrot_runcore_switch(PARROT_INTERP, STRING *name)>
+
+Switches to a named runcore.  Throws an exception on an unknown runcore.
+
+=cut
+
+*/
+
+PARROT_EXPORT
+void
+Parrot_runcore_switch(PARROT_INTERP, ARGIN(STRING *name))
+{
+    ASSERT_ARGS(Parrot_runcore_switch)
+
+    size_t num_cores = interp->num_cores;
+    size_t i;
+
+    if (interp->run_core
+    &&  Parrot_str_equal(interp, name, interp->run_core->name))
+        return;
+
+    for (i = 0; i < num_cores; ++i) {
+        if (Parrot_str_equal(interp, name, interp->cores[i]->name)) {
+            interp->run_core = interp->cores[i];
+            return;
+        }
+    }
+
+    Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_UNIMPLEMENTED,
+        "Invalid runcore %Ss requested\n", name);
+}
+
 
 /*
 
@@ -286,7 +328,8 @@
 
 /*
 
-=item C<void do_prederef(void **pc_prederef, PARROT_INTERP, int type)>
+=item C<void do_prederef(void **pc_prederef, PARROT_INTERP, Parrot_runcore_t
+*runcore)>
 
 This is called from within the run cores to predereference the current
 opcode.
@@ -298,7 +341,7 @@
 */
 
 void
-do_prederef(ARGIN(void **pc_prederef), PARROT_INTERP, int type)
+do_prederef(ARGIN(void **pc_prederef), PARROT_INTERP, ARGIN(Parrot_runcore_t *runcore))
 {
     ASSERT_ARGS(do_prederef)
     const size_t     offset = pc_prederef - interp->code->prederef.code;
@@ -314,18 +357,11 @@
 
     prederef_args(pc_prederef, interp, pc, opinfo);
 
-    switch (type) {
-        case PARROT_SWITCH_CORE:
-        case PARROT_SWITCH_JIT_CORE:
-        case PARROT_CGP_CORE:
-        case PARROT_CGP_JIT_CORE:
-            parrot_PIC_prederef(interp, *pc, pc_prederef, type);
-            break;
-        default:
-            Parrot_ex_throw_from_c_args(interp, NULL, 1,
-                "Tried to prederef wrong core");
-            break;
-    }
+    if (PARROT_RUNCORE_PREDEREF_OPS_TEST(runcore))
+        parrot_PIC_prederef(interp, *pc, pc_prederef, interp->run_core);
+    else
+        Parrot_ex_throw_from_c_args(interp, NULL, 1,
+            "Tried to prederef wrong core");
 
     /* now remember backward branches, invoke and similar opcodes */
     n = opinfo->op_count;
@@ -400,57 +436,6 @@
 
 /*
 
-=item C<static oplib_init_f get_core_op_lib_init(PARROT_INTERP, int which)>
-
-Returns an opcode's library C<op_lib> init function.
-
-C<which> is the run core type.
-
-=cut
-
-*/
-
-PARROT_WARN_UNUSED_RESULT
-PARROT_CANNOT_RETURN_NULL
-static oplib_init_f
-get_core_op_lib_init(PARROT_INTERP, int which)
-{
-    ASSERT_ARGS(get_core_op_lib_init)
-    oplib_init_f init_func;
-    switch (which) {
-        case PARROT_SWITCH_CORE:
-        case PARROT_SWITCH_JIT_CORE:
-            init_func = PARROT_CORE_SWITCH_OPLIB_INIT;
-            break;
-#ifdef HAVE_COMPUTED_GOTO
-        case PARROT_CGP_CORE:
-        case PARROT_CGP_JIT_CORE:
-            init_func = PARROT_CORE_CGP_OPLIB_INIT;
-            break;
-        case PARROT_CGOTO_CORE:
-            init_func = PARROT_CORE_CG_OPLIB_INIT;
-            break;
-#endif
-        /* normal func core */
-        case PARROT_EXEC_CORE:
-        case PARROT_JIT_CORE:
-        case PARROT_SLOW_CORE:
-        case PARROT_FAST_CORE:
-        case PARROT_GC_DEBUG_CORE:
-        case PARROT_DEBUGGER_CORE:
-            init_func = PARROT_CORE_OPLIB_INIT;
-            break;
-        default:
-            Parrot_ex_throw_from_c_args(interp, NULL, 1,
-                "Couldn't find init_func for core %d", which);
-    }
-
-    return init_func;
-}
-
-
-/*
-
 =item C<static oplib_init_f get_dynamic_op_lib_init(PARROT_INTERP, const PMC
 *lib)>
 
@@ -475,103 +460,6 @@
 
 /*
 
-=item C<static void load_prederef(PARROT_INTERP, int which)>
-
-C<< interp->op_lib >> = prederefed oplib.
-
-=cut
-
-*/
-
-static void
-load_prederef(PARROT_INTERP, int which)
-{
-    ASSERT_ARGS(load_prederef)
-    const oplib_init_f init_func = get_core_op_lib_init(interp, which);
-
-    int (*get_op)(const char * name, int full);
-
-    get_op          = interp->op_lib->op_code;
-    interp->op_lib  = init_func(1);
-
-    /* preserve the get_op function */
-    interp->op_lib->op_code = get_op;
-
-    if (interp->op_lib->op_count != interp->op_count)
-        Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_PREDEREF_LOAD_ERROR,
-            "Illegal op count (%d) in prederef oplib\n",
-            (int)interp->op_lib->op_count);
-}
-
-
-/*
-
-=item C<static void init_prederef(PARROT_INTERP, int which)>
-
-Initialize: load prederef C<func_table>, file prederef.code.
-
-=cut
-
-*/
-
-static void
-init_prederef(PARROT_INTERP, int which)
-{
-    ASSERT_ARGS(init_prederef)
-    load_prederef(interp, which);
-    if (!interp->code->prederef.code) {
-        void        *pred_func;
-        opcode_t    *pc = interp->code->base.data;
-        const size_t N  = interp->code->base.size;
-        size_t       i, n_pics;
-
-/* Parrot_memalign_if_possible in OpenBSD allocates 256 if you ask for 312
-   -- Need to verify this, it may have been a bug elsewhere. If it works now,
-   we can remove the mem_sys_allocate_zeroed line below. */
-
-#if 0
-        void **temp = (void **)mem_sys_allocate_zeroed(N * sizeof (void *));
-#else
-        void **temp = (void **)Parrot_memalign_if_possible(256,
-                N * sizeof (void *));
-#endif
-        /* calc and remember pred_offset */
-        Parrot_pcc_set_pred_offset(interp, CURRENT_CONTEXT(interp), pc - (opcode_t *)temp);
-
-        /* fill with the prederef__ opcode function */
-        if (which == PARROT_SWITCH_CORE || which == PARROT_SWITCH_JIT_CORE)
-            pred_func = (void *)CORE_OPS_prederef__;
-        else
-            pred_func = ((void **)
-                    interp->op_lib->op_func_table)[CORE_OPS_prederef__];
-
-        for (i = n_pics = 0; i < N;) {
-            op_info_t * const opinfo = &interp->op_info_table[*pc];
-            size_t            n      = opinfo->op_count;
-
-            temp[i] = pred_func;
-
-            ADD_OP_VAR_PART(interp, interp->code, pc, n);
-
-            /* count ops that need a PIC */
-            if (parrot_PIC_op_is_cached(*pc))
-                n_pics++;
-
-            pc += n;
-            i  += n;
-        }
-
-        interp->code->prederef.code = temp;
-
-        /* allocate pic store, which starts from 1 */
-        if (n_pics)
-            parrot_PIC_alloc_store(interp->code, n_pics + 1);
-    }
-}
-
-
-/*
-
 =item C<static void stop_prederef(PARROT_INTERP)>
 
 Restore the interpreter's op function tables to their initial state.
@@ -617,7 +505,11 @@
 exec_init_prederef(PARROT_INTERP, ARGIN(void *prederef_arena))
 {
     ASSERT_ARGS(exec_init_prederef)
-    load_prederef(interp, PARROT_CGP_CORE);
+    Parrot_runcore_t *old_runcore = interp->run_core;
+    Parrot_runcore_switch(interp, Parrot_str_new_constant(interp, "cgp"));
+
+    load_prederef(interp, interp->run_core);
+    interp->run_core = old_runcore;
 
     if (!interp->code->prederef.code) {
         void ** const temp = (void **)prederef_arena;
@@ -694,185 +586,10 @@
 prepare_for_run(PARROT_INTERP)
 {
     ASSERT_ARGS(prepare_for_run)
-    void *ignored;
+    const runcore_prepare_fn_type prepare_run = interp->run_core->prepare_run;
 
-    switch (interp->run_core) {
-        case PARROT_JIT_CORE:
-            ignored = init_jit(interp, interp->code->base.data);
-            UNUSED(ignored);
-            break;
-        case PARROT_SWITCH_CORE:
-        case PARROT_SWITCH_JIT_CORE:
-        case PARROT_CGP_CORE:
-        case PARROT_CGP_JIT_CORE:
-        case PARROT_DEBUGGER_CORE:
-            init_prederef(interp, interp->run_core);
-            break;
-        default:
-            break;
-    }
-}
-
-
-#ifdef PARROT_EXEC_OS_AIX
-extern void* aix_get_toc();
-#endif
-
-/*
-
-=item C<static opcode_t * runops_jit(PARROT_INTERP, opcode_t *pc)>
-
-Runs the JIT code for the specified opcode.
-
-=cut
-
-*/
-
-PARROT_WARN_UNUSED_RESULT
-PARROT_CAN_RETURN_NULL
-static opcode_t *
-runops_jit(PARROT_INTERP, ARGIN(opcode_t *pc))
-{
-    ASSERT_ARGS(runops_jit)
-#if JIT_CAPABLE
-#  ifdef PARROT_EXEC_OS_AIX
-    /* AIX calling convention requires that function-call-by-ptr be made
-       through the following struct: */
-    struct ptrgl_t { jit_f functPtr; void *toc; void *env; } ptrgl_t;
-
-    ptrgl_t.functPtr = (jit_f) D2FPTR(init_jit(interp, pc));
-    ptrgl_t.env      = NULL;
-
-    /* r2 (TOC) needs to point back here so we can return from non-JIT
-       functions */
-    ptrgl_t.toc = aix_get_toc();
-
-    ((jit_f) D2FPTR(&ptrgl_t)) (interp, pc);
-#  else
-    jit_f jit_code = (jit_f)(init_jit(interp, pc));
-    (jit_code) (interp, pc);
-#  endif
-#else
-    UNUSED(interp);
-    UNUSED(pc);
-#endif
-    return NULL;
-}
-
-
-/*
-
-=item C<static opcode_t * runops_exec(PARROT_INTERP, opcode_t *pc)>
-
-Runs the native executable version of the specified opcode.
-
-=cut
-
-*/
-
-PARROT_WARN_UNUSED_RESULT
-PARROT_CAN_RETURN_NULL
-static opcode_t *
-runops_exec(PARROT_INTERP, ARGIN(opcode_t *pc))
-{
-    ASSERT_ARGS(runops_exec)
-#if EXEC_CAPABLE
-    opcode_t *code_start;
-    UINTVAL   code_size;          /* in opcodes */
-    opcode_t *code_end;
-
-    code_start = interp->code->base.data;
-    code_size = interp->code->base.size;
-    code_end = code_start + code_size;
-#  if defined HAVE_COMPUTED_GOTO && defined USE_CGP
-#    ifdef __GNUC__
-#      ifdef PARROT_I386
-    init_prederef(interp, PARROT_CGP_CORE);
-#      endif
-#    endif
-#  endif
-    if (Parrot_exec_run == 2) {
-        void *ignored;
-        Parrot_exec_run = 0;
-
-        Interp_core_SET(interp, PARROT_JIT_CORE);
-        ignored         = runops_jit(interp, pc);
-        UNUSED(ignored);
-
-        Interp_core_SET(interp, PARROT_EXEC_CORE);
-    }
-    else if (Parrot_exec_run == 1)
-        Parrot_exec(interp, pc, code_start, code_end);
-    else
-        run_native(interp, pc, code_start);
-
-#else
-    UNUSED(interp);
-    UNUSED(pc);
-#endif
-
-    return NULL;
-}
-
-
-/*
-
-=item C<static opcode_t * runops_cgp(PARROT_INTERP, opcode_t *pc)>
-
-Runs the C C<goto>, predereferenced core.
-
-=cut
-
-*/
-
-PARROT_WARN_UNUSED_RESULT
-PARROT_CANNOT_RETURN_NULL
-static opcode_t *
-runops_cgp(PARROT_INTERP, ARGIN(opcode_t *pc))
-{
-    ASSERT_ARGS(runops_cgp)
-#ifdef HAVE_COMPUTED_GOTO
-    opcode_t * const code_start = (opcode_t *)interp->code->base.data;
-    opcode_t        *pc_prederef;
-
-    init_prederef(interp, PARROT_CGP_CORE);
-
-    pc_prederef = (opcode_t*)interp->code->prederef.code + (pc - code_start);
-    return cgp_core(pc_prederef, interp);
-
-#else
-    UNUSED(pc);
-    Parrot_io_eprintf(interp,
-            "Computed goto unavailable in this configuration.\n");
-    Parrot_exit(interp, 1);
-#endif
-
-}
-
-
-/*
-
-=item C<static opcode_t * runops_switch(PARROT_INTERP, opcode_t *pc)>
-
-Runs the C<switch> core.
-
-=cut
-
-*/
-
-PARROT_WARN_UNUSED_RESULT
-PARROT_CANNOT_RETURN_NULL
-static opcode_t *
-runops_switch(PARROT_INTERP, ARGIN(opcode_t *pc))
-{
-    ASSERT_ARGS(runops_switch)
-    opcode_t * const code_start = (opcode_t *)interp->code->base.data;
-    opcode_t        *pc_prederef;
-
-    init_prederef(interp, PARROT_SWITCH_CORE);
-    pc_prederef = (opcode_t*)interp->code->prederef.code + (pc - code_start);
-
-    return switch_core(pc_prederef, interp);
+    if (prepare_run)
+        (*prepare_run)(interp, interp->run_core);
 }
 
 
@@ -893,7 +610,6 @@
 runops_int(PARROT_INTERP, size_t offset)
 {
     ASSERT_ARGS(runops_int)
-    opcode_t *(*core) (PARROT_INTERP, opcode_t *) = NULL;
 
     /* setup event function ptrs */
     if (!interp->save_func_table)
@@ -905,81 +621,12 @@
     while (interp->resume_flag & RESUME_RESTART) {
         opcode_t * const pc = (opcode_t *)
             interp->code->base.data + interp->resume_offset;
+        const runcore_runops_fn_type core = interp->run_core->runops;
 
         interp->resume_offset = 0;
         interp->resume_flag  &= ~(RESUME_RESTART | RESUME_INITIAL);
 
-        switch (interp->run_core) {
-            case PARROT_SLOW_CORE:
-                core = runops_slow_core;
-
-                if (Interp_flags_TEST(interp, PARROT_PROFILE_FLAG)) {
-                    core = runops_profile_core;
-                    if (interp->profile == NULL) {
-                        interp->profile = mem_allocate_zeroed_typed(RunProfile);
-                        interp->profile->data =
-                            mem_allocate_n_typed((interp->op_count +
-                                        PARROT_PROF_EXTRA), ProfData);
-                    }
-                }
-                break;
-            case PARROT_FAST_CORE:
-                core = runops_fast_core;
-                break;
-            case PARROT_CGOTO_CORE:
-#ifdef HAVE_COMPUTED_GOTO
-                core = runops_cgoto_core;
-#else
-                Parrot_ex_throw_from_c_args(interp, NULL, 1,
-                    "Error: PARROT_CGOTO_CORE not available");
-#endif
-                break;
-            case PARROT_CGP_CORE:
-            case PARROT_CGP_JIT_CORE:
-#ifdef HAVE_COMPUTED_GOTO
-                core = runops_cgp;
-#else
-                Parrot_ex_throw_from_c_args(interp, NULL, 1,
-                    "Error: PARROT_CGP_CORE not available");
-#endif
-                break;
-            case PARROT_SWITCH_CORE:
-            case PARROT_SWITCH_JIT_CORE:
-                core = runops_switch;
-                break;
-            case PARROT_JIT_CORE:
-#if !JIT_CAPABLE
-                Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_UNAVAILABLE,
-                    "Error: PARROT_JIT_FLAG is set, "
-                    "but interpreter is not JIT_CAPABLE!\n");
-#else
-                core = runops_jit;
-#endif
-                break;
-            case PARROT_EXEC_CORE:
-#if !EXEC_CAPABLE
-                Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_EXEC_UNAVAILABLE,
-                    "Error: PARROT_EXEC_FLAG is set, "
-                    "but interpreter is not EXEC_CAPABLE!\n");
-#else
-                core = runops_exec;
-#endif
-                break;
-            case PARROT_GC_DEBUG_CORE:
-                core = runops_gc_debug_core;
-                break;
-            case PARROT_DEBUGGER_CORE:
-                core = runops_debugger_core;
-                break;
-            default:
-                Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_UNIMPLEMENTED,
-                    "ambigious runcore switch used");
-                break;
-        }
-
-
-        /* run it finally */
-        core(interp, pc);
+        (*core)(interp, interp->run_core, pc);
 
         /* if we have fallen out with resume and we were running CGOTO, set
          * the stacktop again to a sane value, so that restarting the runloop
@@ -1048,10 +695,33 @@
 Parrot_runcore_destroy(PARROT_INTERP)
 {
     ASSERT_ARGS(Parrot_runcore_destroy)
-    op_lib_t    *cg_lib;
+    op_lib_t         *cg_lib;
+    size_t            num_cores = interp->num_cores;
+    size_t            i;
+
+    for (i = 0; i < num_cores; ++i) {
+        Parrot_runcore_t        *core    = interp->cores[i];
+        runcore_destroy_fn_type  destroy = core->destroy;
+
+        if (destroy)
+            (*destroy)(interp, core);
+
+        mem_sys_free(core);
+    }
+
+    if (interp->cores)
+        mem_sys_free(interp->cores);
+
+    interp->cores    = NULL;
+    interp->run_core = NULL;
+
+    /* dynop libs */
+    if (interp->n_libs <= 0)
+        return;
 
 #ifdef HAVE_COMPUTED_GOTO
     cg_lib = PARROT_CORE_CGP_OPLIB_INIT(1);
+
     if (cg_lib->op_func_table)
         mem_sys_free(cg_lib->op_func_table);
     cg_lib->op_func_table = NULL;
@@ -1061,6 +731,11 @@
         mem_sys_free(cg_lib->op_func_table);
     cg_lib->op_func_table = NULL;
 #endif
+
+    mem_sys_free(interp->op_info_table);
+    mem_sys_free(interp->op_func_table);
+    interp->op_info_table = NULL;
+    interp->op_func_table = NULL;
 }
 
 
@@ -1286,7 +961,7 @@
     }
 
     /* if we are running this core, update event check ops */
-    if ((int)interp->run_core == cg_lib->core_type) {
+    if (interp->run_core->id == cg_lib->core_type) {
         size_t i;
 
         for (i = n_old; i < n_tot; ++i)
@@ -1325,7 +1000,7 @@
 
 /*
 
-=item C<static void notify_func_table(PARROT_INTERP, op_func_t* table, int on)>
+=item C<static void notify_func_table(PARROT_INTERP, op_func_t *table, int on)>
 
 Tell the interpreter's running core about the new function table.
 
@@ -1334,27 +1009,20 @@
 */
 
 static void
-notify_func_table(PARROT_INTERP, ARGIN(op_func_t* table), int on)
+notify_func_table(PARROT_INTERP, ARGIN(op_func_t *table), int on)
 {
     ASSERT_ARGS(notify_func_table)
     const oplib_init_f init_func = get_core_op_lib_init(interp, interp->run_core);
 
     init_func((long) table);
-    switch (interp->run_core) {
-        case PARROT_SLOW_CORE:      /* normal func core */
-        case PARROT_FAST_CORE:      /* normal func core */
-        case PARROT_CGOTO_CORE:     /* cgoto address list  */
-        case PARROT_DEBUGGER_CORE:
-            PARROT_ASSERT(table);
-            interp->op_func_table = table;
-            break;
-        case PARROT_CGP_CORE:
-        case PARROT_CGP_JIT_CORE:
-            turn_ev_check(interp, on);
-            break;
-        default:
-            break;
+
+    if (PARROT_RUNCORE_FUNC_TABLE_TEST(interp->run_core)) {
+        PARROT_ASSERT(table);
+        interp->op_func_table = table;
     }
+
+    if (PARROT_RUNCORE_EVENT_CHECK_TEST(interp->run_core))
+        turn_ev_check(interp, on);
 }
 
 

Modified: trunk/src/sub.c
==============================================================================
--- trunk/src/sub.c	Sun Sep  6 20:31:13 2009	(r41080)
+++ trunk/src/sub.c	Sun Sep  6 20:40:14 2009	(r41081)
@@ -188,6 +188,7 @@
     ARGOUT(Parrot_Context_info *info))
 {
     ASSERT_ARGS(Parrot_Context_get_info)
+    PMC                   *subpmc;
     Parrot_Sub_attributes *sub;
 
     /* set file/line/pc defaults */
@@ -198,8 +199,10 @@
     info->subname  = NULL;
     info->fullname = NULL;
 
+    subpmc = Parrot_pcc_get_sub(interp, ctx);
+
     /* is the current sub of the specified context valid? */
-    if (PMC_IS_NULL(Parrot_pcc_get_sub(interp, ctx))) {
+    if (PMC_IS_NULL(subpmc)) {
         info->subname  = Parrot_str_new(interp, "???", 3);
         info->nsname   = info->subname;
         info->fullname = Parrot_str_new(interp, "??? :: ???", 10);
@@ -208,10 +211,10 @@
     }
 
     /* fetch Parrot_sub of the current sub in the given context */
-    if (!VTABLE_isa(interp, Parrot_pcc_get_sub(interp, ctx), CONST_STRING(interp, "Sub")))
+    if (!VTABLE_isa(interp, subpmc, CONST_STRING(interp, "Sub")))
         return 1;
 
-    PMC_get_sub(interp, Parrot_pcc_get_sub(interp, ctx), sub);
+    PMC_get_sub(interp, subpmc, sub);
     /* set the sub name */
     info->subname = sub->name;
 
@@ -222,7 +225,7 @@
     }
     else {
         info->nsname   = VTABLE_get_string(interp, sub->namespace_name);
-        info->fullname = Parrot_full_sub_name(interp, Parrot_pcc_get_sub(interp, ctx));
+        info->fullname = Parrot_full_sub_name(interp, subpmc);
     }
 
     /* return here if there is no current pc */

Modified: trunk/t/op/gc.t
==============================================================================
--- trunk/t/op/gc.t	Sun Sep  6 20:31:13 2009	(r41080)
+++ trunk/t/op/gc.t	Sun Sep  6 20:40:14 2009	(r41081)
@@ -1,6 +1,6 @@
 #! parrot
 # Copyright (C) 2001-2009, Parrot Foundation.
-# $Id: string.t 40481 2009-08-11 06:09:35Z dukeleto $
+# $Id$
 
 =head1 NAME
 

Modified: trunk/t/run/options.t
==============================================================================
--- trunk/t/run/options.t	Sun Sep  6 20:31:13 2009	(r41080)
+++ trunk/t/run/options.t	Sun Sep  6 20:40:14 2009	(r41081)
@@ -88,7 +88,7 @@
     is( qx{$cmd}, "second\n", "-r option <$cmd>" );
 
     $cmd = qq{"$PARROT" -D 8 -R slow "$second_pir_file" 2>&1};
-    like( qx{$cmd}, qr/Parrot VM: Slow core/, "-r option <$cmd>" );
+    like( qx{$cmd}, qr/Parrot VM: slow core/, "-r option <$cmd>" );
 }
 
 ## RT#46815 test remaining options

Added: trunk/tools/dev/pprof2cg.pl
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ trunk/tools/dev/pprof2cg.pl	Sun Sep  6 20:40:14 2009	(r41081)
@@ -0,0 +1,289 @@
+#! perl
+
+# Copyright (C) 2009, Parrot Foundation.
+# $Id$
+
+use strict;
+use warnings;
+
+use Data::Dumper;
+
+=head1 NAME
+
+tools/dev/pprof2cg.pl
+
+=head1 DESCRIPTION
+
+Convert the output of Parrot's profiling runcore to a Callgrind-compatible
+format.
+
+=head1 USAGE
+
+Generate a profile by passing C<-Rprofiling> to parrot, for example C<./parrot
+-Rprofiling perl6.pbc hello.p6>.  Once execution completes, parrot will print a
+message specifying the location of profile.  The profile will usually be named
+parrot.pprof.XXXX, where XXXX is the PID of the parrot process.
+
+To generate a Callgrind-compatible profile, run this script with the pprof
+filename as the first argument.  The output file will be in parrot.out.XXXX,
+where XXXX again is the PID of the original parrot process.
+
+XXX: document $stats format
+
+=cut
+
+
+
+main(\@ARGV);
+
+sub main {
+    my $argv      = shift;
+    my $stats     = {};
+    my $ctx_stack = [];
+    my $filename  = $argv->[0];
+
+    open(my $in_fh, '<', $filename) or die "couldn't open $filename for reading: $!";
+
+    while (my $line = <$in_fh>) {
+        process_line($line, $stats, $ctx_stack);
+    }
+    close($in_fh) or die "couldn't close $filename: $!";
+
+    #print_stats($stats);
+
+    unless ($filename =~ s/\.pprof\./.out./) {
+        $filename = "$filename.out";
+    }
+
+    open(my $out_fh, '>', $filename) or die "couldn't open $filename for writing: $!";
+    my $cg_profile = get_cg_profile($stats);
+    print $out_fh $cg_profile;
+    close($out_fh) or die "couldn't close $filename: $!";
+}
+
+
+sub process_line {
+
+    my $line      = shift;
+    my $stats     = shift;
+    my $ctx_stack = shift;
+
+    for ($line) {
+        if (/^#/) {
+            #comments are always ignored
+        }
+        elsif (/^VERSION:(\d+)$/) {
+            my $version = $1;
+            if ($version != 1) {
+                die "profile was generated by an incompatible version of the profiling runcore.";
+            }
+        }
+        elsif (/^CLI:(.*)$/) {
+            $stats->{'global_stats'}{'cli'} = $1;
+        }
+        #context switch
+        elsif (/^CS:(.*)$/) {
+
+            my $cs_hash      = split_vars($1);
+            my $is_first     = scalar(@$ctx_stack) == 0;
+            my $is_redundant = !$is_first && ($ctx_stack->[0]{'ctx'} eq $cs_hash->{'ctx'});
+            my $reused_ctx   = $is_redundant && ($ctx_stack->[0]{'sub'} ne $cs_hash->{'sub'});
+            my $is_call      = scalar(grep {$_->{'ctx'} eq $cs_hash->{'ctx'}} @$ctx_stack) == 0;
+
+            if ($is_first) {
+                $ctx_stack->[0] = $cs_hash;
+            }
+            elsif ($reused_ctx) {
+                $ctx_stack->[0]{'sub'} = $cs_hash->{'sub'};
+                $ctx_stack->[0]{'ns'}  = $cs_hash->{'ns'};
+            }
+            elsif ($is_redundant) {
+                #don't do anything
+            }
+            elsif ($is_call) {
+                $ctx_stack->[0]{'op_num'}++;
+                my $extra = {
+                    op_name => "CALL",
+                    target  => $cs_hash->{'ns'}
+                };
+                store_stats($stats, $ctx_stack->[0], 0, $extra );
+                unshift @$ctx_stack, $cs_hash;
+            }
+            else {
+                #shift contexts off the stack until one matches the current ctx
+                while ($ctx_stack->[0]->{'ctx'} ne $cs_hash->{'ctx'}) {
+                    my $ctx = shift @$ctx_stack;
+                }
+            }
+            #print Dumper($ctx_stack);
+        }
+        elsif (/^END_OF_RUNLOOP$/) {
+            #end of loop
+            @$ctx_stack = ();
+        }
+        elsif (/^OP:(.*)$/) {
+            my $op_hash = split_vars($1);
+
+            die "input file did not specify an initial context" if (@$ctx_stack == 0);
+
+            if (exists $ctx_stack->[0]{'line'} && $op_hash->{'line'} == $ctx_stack->[0]{'line'}) {
+                $ctx_stack->[0]{'op_num'}++;
+            }
+            else {
+                $ctx_stack->[0]{'op_num'} = 0;
+            }
+
+            $ctx_stack->[0]{'line'} = $op_hash->{'line'};
+            my $extra = { op_name => $op_hash->{'op'} };
+            store_stats($stats, $ctx_stack->[0], $op_hash->{'time'}, $extra);
+
+            $extra->{'no_hits'} = 1;
+            for my $frame (@$ctx_stack[1 .. scalar(@$ctx_stack)-1 ]) {
+                store_stats($stats, $frame, $op_hash->{'time'}, $extra);
+            }
+        }
+        else {
+            die "Unrecognized line format: \"$line\"";
+        }
+    }
+}
+
+sub print_stats {
+    my $stats = shift;
+
+    for my $file (grep {$_ ne 'global_stats'} sort keys %$stats) {
+        for my $ns (sort keys %{ $stats->{$file} }) {
+            for my $line_num (sort {$a<=>$b} keys %{ $stats->{$file}{$ns} }) {
+                for my $op_num (0 .. $#{$stats->{$file}{$ns}{$line_num}}) {
+
+                    print "$file  $ns  line/op:$line_num/$op_num ";
+
+                    for my $attr (sort keys %{ $stats->{$file}{$ns}{$line_num}[$op_num] }) {
+                        print "{ $attr => $stats->{$file}{$ns}{$line_num}[$op_num]{$attr} } ";
+                    }
+                    print "\n";
+                }
+            }
+            print "\n";
+        }
+    }
+}
+
+sub split_vars {
+    my $href;
+    my $str = shift;
+    die "invalidly formed line '$str'"
+        unless $str =~ /({x{  [^:]+  : (.*?) }x})+/x;
+    while ($str =~ /\G   {x{ ([^:]+) : (.*?) }x} /cxg) {
+        $href->{$1} = $2;
+    }
+    return $href;
+}
+
+sub store_stats {
+    my $stats   = shift;
+    my $locator = shift;
+    my $time    = shift;
+    my $extra   = shift;
+
+    my $file   = $locator->{'file'};
+    my $ns     = $locator->{'ns'};
+    my $line   = $locator->{'line'};
+    my $op_num = $locator->{'op_num'};
+
+    if (exists $stats->{'global_stats'}{'total_time'}) {
+        $stats->{'global_stats'}{'total_time'} += $time;
+    }
+    else {
+        $stats->{'global_stats'}{'total_time'} = $time;
+    }
+
+    if (exists $stats->{$file}{$ns}{$line}[$op_num]) {
+        $stats->{$file}{$ns}{$line}[$op_num]{'hits'}++
+            unless exists $extra->{no_hits};
+        $stats->{$file}{$ns}{$line}[$op_num]{'time'} += $time;
+    }
+    else {
+        $stats->{$file}{$ns}{$line}[$op_num]{'hits'} = 1;
+        $stats->{$file}{$ns}{$line}[$op_num]{'time'} = $time;
+        for my $key (keys %{$extra}) {
+            $stats->{$file}{$ns}{$line}[$op_num]{$key} = $extra->{$key};
+        }
+    }
+}
+
+
+sub get_cg_profile {
+
+    my $stats = shift;
+    my @output = ();
+
+    push @output, <<"HEADER";
+version: 1
+creator: 3.4.1-Debian
+pid: 5751
+cmd: $stats->{'global_stats'}{'cli'}
+
+part: 1
+desc: I1 cache:
+desc: D1 cache:
+desc: L2 cache:
+desc: Timerange: Basic block 0 - $stats->{'global_stats'}{'total_time'}
+desc: Trigger: Program termination
+positions: line
+events: Ir
+summary: $stats->{'global_stats'}{'total_time'}
+
+HEADER
+
+    for my $file (grep {$_ ne 'global_stats'} keys %$stats) {
+
+        push @output, "fl=$file";
+
+        for my $ns (keys %{ $stats->{$file} }) {
+            push @output, "\nfn=$ns";
+
+            for my $line (sort keys %{ $stats->{$file}{$ns} }) {
+
+                my $curr_op    = 0;
+                my $line_stats = $stats->{$file}{$ns}{$line};
+                my $op_count   = scalar(@$line_stats);
+                my $op_time    = 0;
+
+                while ($curr_op < $op_count && $line_stats->[$curr_op]{'op_name'} ne 'CALL') {
+                    $op_time += $line_stats->[$curr_op]{'time'};
+                    $curr_op++;
+                }
+                push @output, "$line $op_time";
+
+                if ($curr_op < $op_count && $line_stats->[$curr_op]{'op_name'} eq 'CALL') {
+                    my $call_target = $line_stats->[$curr_op]{'target'};
+                    my $call_count  = $line_stats->[$curr_op]{'hits'};
+                    my $call_cost   = $line_stats->[$curr_op]{'time'};
+
+                    push @output, "cfn=$call_target";
+                    push @output, "calls=$call_count $call_cost";
+                }
+
+                if ($curr_op < $op_count) {
+                    $op_time = 0;
+                    while ($curr_op < $op_count) {
+                        $op_time += $line_stats->[$curr_op]{'time'};
+                        $curr_op++;
+                    }
+                    push @output, "$line $op_time";
+                }
+            }
+        }
+    }
+
+    push @output, "totals: $stats->{'global_stats'}{'total_time'}";
+    return join("\n", @output);
+}
+
+# Local Variables:
+#   mode: cperl
+#   cperl-indent-level: 4
+#   fill-column: 100
+# End:
+# vim: expandtab shiftwidth=4:


More information about the parrot-commits mailing list