ar = new IntList ar = 1000000 hyper ar = 10
or hyper ar += 10
The 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.