Nanoparrot
From perl6.cz
Ukázka jedné z možností (CGOTO core) jak virtuální stroj Parrot interpretuje bytekód.
Source for nanoparrot.c: examples/c/nanoparrot.c
gcc -E nanoparrot.c > nanoparrot-prep.c vim nanoparrot-prep.c cat nanoparrot-prep.c
/*
* Copyright (C) 2001-2006, The Perl Foundation.
* $Id: mj%20and%20Parrot%3A%20nanoparrot,v 1.1 2006/06/17 11:17:46 nobody Exp nobody $
*
* - demonstrates how the interpreter interprets bytecode
* its vastly simplified but the very basics are the same
*
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
// 26 "nanoparrot.c" 2
typedef int INTVAL;
typedef int opcode_t;
typedef double FLOATVAL;
typedef void PMC;
typedef void STRING;
struct Reg {
INTVAL int_reg;
FLOATVAL num_reg;
STRING *string_reg;
PMC *pmc_reg;
};
// 54 "nanoparrot.c"
struct pf {
opcode_t *byte_code;
char **const_table;
};
typedef struct Interp {
struct Reg *bp;
struct pf *code;
opcode_t *(**op_func)(opcode_t *, struct Interp*);
const char **op_info;
int flags;
} Interp;
// 84 "nanoparrot.c"
typedef enum {
OP_end,
OP_print_sc,
OP_print_i,
OP_set_i_ic,
OP_if_i_ic,
OP_sub_i_i_i,
OP_MAX
} opcodes;
// 155 "nanoparrot.c"
static void run(Interp *interpreter, opcode_t *pc) {
static void *labels[] = {
&&lOP_end,
&&lOP_print_sc,
&&lOP_print_i,
&&lOP_set_i_ic,
&&lOP_if_i_ic,
&&lOP_sub_i_i_i,
&&lOP_MAX
};
// 174 "nanoparrot.c"
goto *labels[*pc];
lOP_end:
return;
lOP_print_sc:
printf("%s", interpreter->code->const_table[pc[1]]);
pc += 2;
goto *labels[*pc];
lOP_print_i:
printf("%d", interpreter->bp[pc[1]].int_reg);
pc += 2;
goto *labels[*pc];
lOP_set_i_ic:
interpreter->bp[pc[1]].int_reg = pc[2];
pc += 3;
goto *labels[*pc];
lOP_if_i_ic:
if (interpreter->bp[pc[1]].int_reg)
pc += pc[2];
else
pc += 3;
goto *labels[*pc];
lOP_sub_i_i_i:
interpreter->bp[pc[1]].int_reg =
interpreter->bp[pc[2]].int_reg - interpreter->bp[pc[3]].int_reg;
pc += 4;
goto *labels[*pc];
lOP_MAX:
printf("illegal opcode\n");
exit(1);
goto *labels[*pc];
}
// 215 "nanoparrot.c"
static void
init(Interp *interpreter, opcode_t *prog) {
interpreter->bp = calloc(32, sizeof(struct Reg));
interpreter->op_func = malloc(OP_MAX * sizeof(void*));
interpreter->op_info = malloc(OP_MAX * sizeof(char*));
interpreter->op_info[OP_end] = "end";
interpreter->op_info[OP_print_sc] = "print_sc";
interpreter->op_info[OP_print_i] = "print_i";
interpreter->op_info[OP_set_i_ic] = "set_i_ic";
interpreter->op_info[OP_if_i_ic] = "if_i_ic";
interpreter->op_info[OP_sub_i_i_i] = "sub_i_i_i";
interpreter->code = malloc(sizeof(struct pf));
interpreter->code->byte_code = prog;
interpreter->code->const_table = malloc(4 * sizeof(char*));
interpreter->code->const_table[0] = "\n";
interpreter->code->const_table[1] = "done\n";
interpreter->code->const_table[2] = "error\n";
interpreter->code->const_table[3] = "usage: ./nanoparrot mops\n";
}
int main(int argc, char *argv[]) {
opcode_t *prog;
opcode_t mops[] = {
OP_set_i_ic, 4, 1000000000,
OP_print_i, 4,
OP_print_sc, 0,
OP_set_i_ic, 5, 1,
OP_sub_i_i_i, 4, 4, 5,
OP_if_i_ic, 4, -4,
OP_print_sc, 1,
OP_end
};
opcode_t usage[] = {
OP_set_i_ic, 0, 2,
OP_if_i_ic, 0, 6,
OP_print_sc, 2,
OP_end,
OP_print_sc, 3,
OP_end
};
Interp *interpreter = malloc(sizeof(Interp));
prog = usage;
if (argc > 1) {
if (!strcmp(argv[1], "mops"))
prog = mops;
}
init(interpreter, prog);
run(interpreter, prog);
return 0;
}
real PASM - Parrot assembler
cat nanoparrot.pasm
set I4, 1000000000
print I4
print "\n"
set I5, 1
LABEL_MINUS4:
sub I4, I4, I5
ne I4, 0, LABEL_MINUS4
print "\n"
end
nanoparrot mops for perl users:
cat nanoparrot.pl
$I4 = 1_000_000_000;
print $I4;
print "\n";
$I5 = 1;
LABEL_MINUS4:
$I4 = $I4 - $I5;
goto LABEL_MINUS4 if $I4;
print "\n";
exit(0);
and "benchmarks":
cat /proc/cpuinfo | grep -P "bogomips|cpu MHz|processor" processor : 0 cpu MHz : 3000.267 bogomips : 5914.62 processor : 1 cpu MHz : 3000.267 bogomips : 5980.16
gcc -o nanoparrot-prep -Wall nanoparrot-prep.c -O3 && time ./nanoparrot-prep mops
real 0m7.155s user 0m7.105s sys 0m0.007s
./parrot --version && time ./parrot ./nanoparrot.pasm && time ./parrot -j ./nanoparrot.pasm
Parrot 0.4.4-devel (r12885) real 0m38.742s user 0m38.718s sys 0m0.020s real 0m0.519s user 0m0.511s sys 0m0.008s
time perl ./nanoparrot.pl
real 5m22.974s user 5m22.942s sys 0m0.051s
Externí odkazy
- Threaded code (anglická Wikipedie)
- Python Issue 4753 Faster opcode dispatch on gcc