[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