ar = new IntList
ar = 1000000
hyper
ar = 10or
hyper
ar += 10The atached tests fill an integer array with one Meg int constants and then increment each value 5 times.
Here are the timing results (unoptimized parrot) $ time parrot -j i.imc 6060
real 0m1.927s
$ time parrot ih.imc 6060
real 0m0.328s
Plain run core or JIT doesn't matter for the hyper version.
Only the set and add opcodes with constants are done. But it's not hard to extend the scheme and generalize it.
Comments welcome, leo
$ cat ih.imc
.sub _main @MAIN
loadlib P11, "myops_ops"
.local pmc ar
ar = new IntList
ar = 1000000
hyper
ar = 10
.local int j
j = 0
lp1:
hyper
ar += 10
inc j
if j < 5 goto lp1
set $I0, ar[0]
print $I0
set $I0, ar[999999]
print $I0
print "\n"
.end$ cat i.imc
.sub _main @MAIN
.local pmc ar
ar = new IntList
ar = 1000000
.local int i
i = 0
lp:
ar[i] = 10
inc i
if i < 1000000 goto lp
.local int j
j = 0
lp1:
i = 0
lp2:
$I0 = ar[i]
$I0 += 10
ar[i] = $I0
inc i
if i < 1000000 goto lp2
inc j
if j < 5 goto lp1
set $I0, ar[0]
print $I0
set $I0, ar[999999]
print $I0
print "\n"
.end# from dynops/myops.ops
op hyper() {
opcode_t *pc = expr NEXT();
INTVAL i,l;
UINTVAL c;
op_info_t *opinfo = &interpreter->op_info_table[*pc];
PMC *ar = REG_PMC(pc[1]); /* TODO inspect opcode */
List *list = PMC_data(ar);
List_chunk *chunk;
INTVAL v = pc[2], *p;
int op = *pc;
l = list_length(interpreter, list);
i = 0;
for (chunk = list->first; chunk; chunk = chunk->next) {
if (chunk->flags & sparse)
goto slow;
p = PObj_bufstart(&chunk->data);
for (c = 0; c < chunk->items; ++c, ++p) {
switch (op) {
case 906: /* set_p_ic */
*(INTVAL*) p = v;
break;
case 460: /* add_p_ic */
*(INTVAL*) p += v;
break;
}
}
i += c;
}
goto done;
slow:
for (i; i < l; ++i)
list_assign(interpreter, list, i, INTVAL2PTR(void*, v),
enum_type_INTVAL);
done:
pc += opinfo->arg_count;
goto ADDRESS(pc);
}PS needs latest CVS for a missing intlist vtable.
