1
0
mirror of https://github.com/janet-lang/janet synced 2024-12-23 23:10:26 +00:00

Fix large function compilation issue.

This commit is contained in:
Calvin Rose 2018-07-01 15:49:33 -04:00
parent f4fc4a0bcc
commit 6822400abe
12 changed files with 120 additions and 161 deletions

View File

@ -266,7 +266,7 @@ value."
subloop subloop
(tuple ':= bindings (tuple + bindings inc))))) (tuple ':= bindings (tuple + bindings inc)))))
:keys (do :keys (do
(def $dict (gensym "dict")) (def $dict (gensym))
(def preds @['and (tuple not= nil bindings)]) (def preds @['and (tuple not= nil bindings)])
(def subloop (doone (+ i 3) preds)) (def subloop (doone (+ i 3) preds))
(tuple 'do (tuple 'do
@ -276,9 +276,9 @@ value."
subloop subloop
(tuple ':= bindings (tuple next $dict bindings))))) (tuple ':= bindings (tuple next $dict bindings)))))
:in (do :in (do
(def $len (gensym "len")) (def $len (gensym))
(def $i (gensym "i")) (def $i (gensym))
(def $indexed (gensym "indexed")) (def $indexed (gensym))
(def preds @['and (tuple < $i $len)]) (def preds @['and (tuple < $i $len)])
(def subloop (doone (+ i 3) preds)) (def subloop (doone (+ i 3) preds))
(tuple 'do (tuple 'do
@ -295,7 +295,7 @@ value."
(defmacro for (defmacro for
"Similar to loop, but accumulates the loop body into an array and returns that." "Similar to loop, but accumulates the loop body into an array and returns that."
[head & body] [head & body]
(def $accum (gensym "accum")) (def $accum (gensym))
(tuple 'do (tuple 'do
(tuple 'def $accum @[]) (tuple 'def $accum @[])
(tuple 'loop head (tuple 'loop head
@ -1062,8 +1062,8 @@ onvalue."
(do (do
(file.write stdout " [" source "]") (file.write stdout " [" source "]")
(if source-line (file.write stdout " on line " (if source-line (file.write stdout " on line "
(string source-line) ", column " (string source-col)))) (string source-line) ", column " (string source-col)))))
(if pc (file.write stdout " at (pc=" (string pc) ")"))) (if pc (file.write stdout " (pc=" (string pc) ")"))
(when tail (file.write stdout " (tailcall)")) (when tail (file.write stdout " (tailcall)"))
(file.write stdout "\n")))) (file.write stdout "\n"))))

View File

@ -101,7 +101,7 @@ DstSlot dstc_cslot(Dst x) {
DstSlot dstc_nearslot(DstCompiler *c, DstcRegisterTemp tag) { DstSlot dstc_nearslot(DstCompiler *c, DstcRegisterTemp tag) {
DstSlot ret; DstSlot ret;
ret.flags = DST_SLOTTYPE_ANY; ret.flags = DST_SLOTTYPE_ANY;
ret.index = dstc_getreg_temp(c, tag); ret.index = dstc_allocnear(c, tag);
ret.constant = dst_wrap_nil(); ret.constant = dst_wrap_nil();
ret.envindex = -1; ret.envindex = -1;
return ret; return ret;
@ -111,7 +111,7 @@ DstSlot dstc_nearslot(DstCompiler *c, DstcRegisterTemp tag) {
DstSlot dstc_farslot(DstCompiler *c) { DstSlot dstc_farslot(DstCompiler *c) {
DstSlot ret; DstSlot ret;
ret.flags = DST_SLOTTYPE_ANY; ret.flags = DST_SLOTTYPE_ANY;
ret.index = dstc_getreg(c); ret.index = dstc_allocfar(c);
ret.constant = dst_wrap_nil(); ret.constant = dst_wrap_nil();
ret.envindex = -1; ret.envindex = -1;
return ret; return ret;
@ -314,7 +314,7 @@ DstSlot dstc_gettarget(DstFopts opts) {
slot.envindex = -1; slot.envindex = -1;
slot.constant = dst_wrap_nil(); slot.constant = dst_wrap_nil();
slot.flags = 0; slot.flags = 0;
slot.index = dstc_getreg_temp(opts.compiler, DSTC_REGTEMP_3); slot.index = dstc_allocnear(opts.compiler, DSTC_REGTEMP_3);
} }
return slot; return slot;
} }
@ -399,13 +399,13 @@ static DstSlot dstc_call(DstFopts opts, DstSlot *slots, DstSlot fun) {
dstc_pushslots(c, slots); dstc_pushslots(c, slots);
int32_t fun_register; int32_t fun_register;
if (opts.flags & DST_FOPTS_TAIL) { if (opts.flags & DST_FOPTS_TAIL) {
fun_register = dstc_to_reg(c, fun); fun_register = dstc_regfar(c, fun, DSTC_REGTEMP_0);
dstc_emit(c, DOP_TAILCALL | (fun_register << 8)); dstc_emit(c, DOP_TAILCALL | (fun_register << 8));
retslot = dstc_cslot(dst_wrap_nil()); retslot = dstc_cslot(dst_wrap_nil());
retslot.flags = DST_SLOT_RETURNED; retslot.flags = DST_SLOT_RETURNED;
} else { } else {
retslot = dstc_gettarget(opts); retslot = dstc_gettarget(opts);
fun_register = dstc_to_tempreg(c, fun, DSTC_REGTEMP_0); fun_register = dstc_regnear(c, fun, DSTC_REGTEMP_0);
dstc_emit(c, DOP_CALL | dstc_emit(c, DOP_CALL |
(retslot.index << 8) | (retslot.index << 8) |
(fun_register << 16)); (fun_register << 16));

View File

@ -25,7 +25,7 @@
#include "emit.h" #include "emit.h"
/* Get a register */ /* Get a register */
int32_t dstc_getreg(DstCompiler *c) { int32_t dstc_allocfar(DstCompiler *c) {
int32_t reg = dstc_regalloc_1(&c->scope->ra); int32_t reg = dstc_regalloc_1(&c->scope->ra);
if (reg > 0xFFFF) { if (reg > 0xFFFF) {
dstc_cerror(c, "ran out of internal registers"); dstc_cerror(c, "ran out of internal registers");
@ -34,7 +34,7 @@ int32_t dstc_getreg(DstCompiler *c) {
} }
/* Get a register less than 256 */ /* Get a register less than 256 */
int32_t dstc_getreg_temp(DstCompiler *c, DstcRegisterTemp tag) { int32_t dstc_allocnear(DstCompiler *c, DstcRegisterTemp tag) {
return dstc_regalloc_temp(&c->scope->ra, tag); return dstc_regalloc_temp(&c->scope->ra, tag);
} }
@ -107,10 +107,10 @@ static void dstc_loadconst(DstCompiler *c, Dst k, int32_t reg) {
} }
/* Convert a slot to a two byte register */ /* Convert a slot to a two byte register */
int32_t dstc_to_reg(DstCompiler *c, DstSlot s) { int32_t dstc_regfar(DstCompiler *c, DstSlot s, DstcRegisterTemp tag) {
int32_t reg; int32_t reg;
if (s.flags & (DST_SLOT_CONSTANT | DST_SLOT_REF)) { if (s.flags & (DST_SLOT_CONSTANT | DST_SLOT_REF)) {
reg = dstc_getreg(c); reg = dstc_allocnear(c, tag);
dstc_loadconst(c, s.constant, reg); dstc_loadconst(c, s.constant, reg);
/* If we also are a reference, deref the one element array */ /* If we also are a reference, deref the one element array */
if (s.flags & DST_SLOT_REF) { if (s.flags & DST_SLOT_REF) {
@ -119,8 +119,8 @@ int32_t dstc_to_reg(DstCompiler *c, DstSlot s) {
(reg << 8) | (reg << 8) |
DOP_GET_INDEX); DOP_GET_INDEX);
} }
} else if (s.envindex >= 0 || s.index > 0xFF) { } else if (s.envindex >= 0) {
reg = dstc_getreg(c); reg = dstc_allocnear(c, tag);
dstc_emit(c, dstc_emit(c,
((uint32_t)(s.index) << 24) | ((uint32_t)(s.index) << 24) |
((uint32_t)(s.envindex) << 16) | ((uint32_t)(s.envindex) << 16) |
@ -134,10 +134,10 @@ int32_t dstc_to_reg(DstCompiler *c, DstSlot s) {
} }
/* Convert a slot to a temporary 1 byte register */ /* Convert a slot to a temporary 1 byte register */
int32_t dstc_to_tempreg(DstCompiler *c, DstSlot s, DstcRegisterTemp tag) { int32_t dstc_regnear(DstCompiler *c, DstSlot s, DstcRegisterTemp tag) {
int32_t reg; int32_t reg;
if (s.flags & (DST_SLOT_CONSTANT | DST_SLOT_REF)) { if (s.flags & (DST_SLOT_CONSTANT | DST_SLOT_REF)) {
reg = dstc_getreg_temp(c, tag); reg = dstc_allocnear(c, tag);
dstc_loadconst(c, s.constant, reg); dstc_loadconst(c, s.constant, reg);
/* If we also are a reference, deref the one element array */ /* If we also are a reference, deref the one element array */
if (s.flags & DST_SLOT_REF) { if (s.flags & DST_SLOT_REF) {
@ -146,15 +146,15 @@ int32_t dstc_to_tempreg(DstCompiler *c, DstSlot s, DstcRegisterTemp tag) {
(reg << 8) | (reg << 8) |
DOP_GET_INDEX); DOP_GET_INDEX);
} }
} else if (s.envindex >= 0 || s.index > 0xFF) { } else if (s.envindex >= 0) {
reg = dstc_getreg_temp(c, tag); reg = dstc_allocnear(c, tag);
dstc_emit(c, dstc_emit(c,
((uint32_t)(s.index) << 24) | ((uint32_t)(s.index) << 24) |
((uint32_t)(s.envindex) << 16) | ((uint32_t)(s.envindex) << 16) |
((uint32_t)(reg) << 8) | ((uint32_t)(reg) << 8) |
DOP_LOAD_UPVALUE); DOP_LOAD_UPVALUE);
} else if (s.index > 0xFF) { } else if (s.index > 0xFF) {
reg = dstc_getreg_temp(c, tag); reg = dstc_allocnear(c, tag);
dstc_emit(c, dstc_emit(c,
((uint32_t)(s.index) << 16) | ((uint32_t)(s.index) << 16) |
((uint32_t)(reg) << 8) | ((uint32_t)(reg) << 8) |
@ -175,7 +175,7 @@ void dstc_free_reg(DstCompiler *c, DstSlot s, int32_t reg) {
} }
/* Check if two slots are equal */ /* Check if two slots are equal */
int dstc_sequal(DstSlot lhs, DstSlot rhs) { static int dstc_sequal(DstSlot lhs, DstSlot rhs) {
if (lhs.flags == rhs.flags && if (lhs.flags == rhs.flags &&
lhs.index == rhs.index && lhs.index == rhs.index &&
lhs.envindex == rhs.envindex) { lhs.envindex == rhs.envindex) {
@ -190,7 +190,7 @@ int dstc_sequal(DstSlot lhs, DstSlot rhs) {
/* Move values from one slot to another. The destination must /* Move values from one slot to another. The destination must
* be writeable (not a literal). */ * be writeable (not a literal). */
int dstc_copy( void dstc_copy(
DstCompiler *c, DstCompiler *c,
DstSlot dest, DstSlot dest,
DstSlot src) { DstSlot src) {
@ -202,11 +202,11 @@ int dstc_copy(
/* Can't write to constants */ /* Can't write to constants */
if (dest.flags & DST_SLOT_CONSTANT) { if (dest.flags & DST_SLOT_CONSTANT) {
dstc_cerror(c, "cannot write to constant"); dstc_cerror(c, "cannot write to constant");
return 0; return;
} }
/* Short circuit if dest and source are equal */ /* Short circuit if dest and source are equal */
if (dstc_sequal(dest, src)) return 0; if (dstc_sequal(dest, src)) return;
/* Types of slots - src */ /* Types of slots - src */
/* constants */ /* constants */
@ -243,19 +243,19 @@ int dstc_copy(
(dest.index << 8) | (dest.index << 8) |
DOP_MOVE_NEAR); DOP_MOVE_NEAR);
} }
return 1; return;
} }
/* Process: src -> srclocal -> destlocal -> dest */ /* Process: src -> srclocal -> destlocal -> dest */
/* src -> srclocal */ /* src -> srclocal */
srclocal = dstc_to_tempreg(c, src, DSTC_REGTEMP_0); srclocal = dstc_regnear(c, src, DSTC_REGTEMP_0);
/* Pull down dest (find destlocal) */ /* Pull down dest (find destlocal) */
if (dest.flags & DST_SLOT_REF) { if (dest.flags & DST_SLOT_REF) {
writeback = 1; writeback = 1;
destlocal = srclocal; destlocal = srclocal;
reflocal = dstc_getreg_temp(c, DSTC_REGTEMP_1); reflocal = dstc_allocnear(c, DSTC_REGTEMP_1);
dstc_emit(c, dstc_emit(c,
(dstc_const(c, dest.constant) << 16) | (dstc_const(c, dest.constant) << 16) |
(reflocal << 8) | (reflocal << 8) |
@ -302,13 +302,12 @@ int dstc_copy(
dstc_regalloc_free(&c->scope->ra, reflocal); dstc_regalloc_free(&c->scope->ra, reflocal);
} }
dstc_free_reg(c, src, srclocal); dstc_free_reg(c, src, srclocal);
return 1;
} }
/* Instruction templated emitters */ /* Instruction templated emitters */
static int32_t emit1s(DstCompiler *c, uint8_t op, DstSlot s, int32_t rest) { static int32_t emit1s(DstCompiler *c, uint8_t op, DstSlot s, int32_t rest) {
int32_t reg = dstc_to_tempreg(c, s, DSTC_REGTEMP_0); int32_t reg = dstc_regnear(c, s, DSTC_REGTEMP_0);
int32_t label = dst_v_count(c->buffer); int32_t label = dst_v_count(c->buffer);
dstc_emit(c, op | (reg << 8) | (rest << 16)); dstc_emit(c, op | (reg << 8) | (rest << 16));
dstc_free_reg(c, s, reg); dstc_free_reg(c, s, reg);
@ -316,7 +315,7 @@ static int32_t emit1s(DstCompiler *c, uint8_t op, DstSlot s, int32_t rest) {
} }
int32_t dstc_emit_s(DstCompiler *c, uint8_t op, DstSlot s) { int32_t dstc_emit_s(DstCompiler *c, uint8_t op, DstSlot s) {
int32_t reg = dstc_to_reg(c, s); int32_t reg = dstc_regfar(c, s, DSTC_REGTEMP_0);
int32_t label = dst_v_count(c->buffer); int32_t label = dst_v_count(c->buffer);
dstc_emit(c, op | (reg << 8)); dstc_emit(c, op | (reg << 8));
dstc_free_reg(c, s, reg); dstc_free_reg(c, s, reg);
@ -345,8 +344,8 @@ int32_t dstc_emit_su(DstCompiler *c, uint8_t op, DstSlot s, uint16_t immediate)
} }
static int32_t emit2s(DstCompiler *c, uint8_t op, DstSlot s1, DstSlot s2, int32_t rest) { static int32_t emit2s(DstCompiler *c, uint8_t op, DstSlot s1, DstSlot s2, int32_t rest) {
int32_t reg1 = dstc_to_tempreg(c, s1, DSTC_REGTEMP_0); int32_t reg1 = dstc_regnear(c, s1, DSTC_REGTEMP_0);
int32_t reg2 = dstc_to_tempreg(c, s2, DSTC_REGTEMP_1); int32_t reg2 = dstc_regnear(c, s2, DSTC_REGTEMP_1);
int32_t label = dst_v_count(c->buffer); int32_t label = dst_v_count(c->buffer);
dstc_emit(c, op | (reg1 << 8) | (reg2 << 16) | (rest << 24)); dstc_emit(c, op | (reg1 << 8) | (reg2 << 16) | (rest << 24));
dstc_free_reg(c, s1, reg1); dstc_free_reg(c, s1, reg1);
@ -355,8 +354,8 @@ static int32_t emit2s(DstCompiler *c, uint8_t op, DstSlot s1, DstSlot s2, int32_
} }
int32_t dstc_emit_ss(DstCompiler *c, uint8_t op, DstSlot s1, DstSlot s2) { int32_t dstc_emit_ss(DstCompiler *c, uint8_t op, DstSlot s1, DstSlot s2) {
int32_t reg1 = dstc_to_tempreg(c, s1, DSTC_REGTEMP_0); int32_t reg1 = dstc_regnear(c, s1, DSTC_REGTEMP_0);
int32_t reg2 = dstc_to_reg(c, s2); int32_t reg2 = dstc_regfar(c, s2, DSTC_REGTEMP_1);
int32_t label = dst_v_count(c->buffer); int32_t label = dst_v_count(c->buffer);
dstc_emit(c, op | (reg1 << 8) | (reg2 << 16)); dstc_emit(c, op | (reg1 << 8) | (reg2 << 16));
dstc_free_reg(c, s1, reg1); dstc_free_reg(c, s1, reg1);
@ -373,9 +372,9 @@ int32_t dstc_emit_ssu(DstCompiler *c, uint8_t op, DstSlot s1, DstSlot s2, uint8_
} }
int32_t dstc_emit_sss(DstCompiler *c, uint8_t op, DstSlot s1, DstSlot s2, DstSlot s3) { int32_t dstc_emit_sss(DstCompiler *c, uint8_t op, DstSlot s1, DstSlot s2, DstSlot s3) {
int32_t reg1 = dstc_to_tempreg(c, s1, DSTC_REGTEMP_0); int32_t reg1 = dstc_regnear(c, s1, DSTC_REGTEMP_0);
int32_t reg2 = dstc_to_tempreg(c, s2, DSTC_REGTEMP_1); int32_t reg2 = dstc_regnear(c, s2, DSTC_REGTEMP_1);
int32_t reg3 = dstc_to_tempreg(c, s3, DSTC_REGTEMP_2); int32_t reg3 = dstc_regnear(c, s3, DSTC_REGTEMP_2);
int32_t label = dst_v_count(c->buffer); int32_t label = dst_v_count(c->buffer);
dstc_emit(c, op | (reg1 << 8) | (reg2 << 16) | (reg3 << 24)); dstc_emit(c, op | (reg1 << 8) | (reg2 << 16) | (reg3 << 24));
dstc_free_reg(c, s1, reg1); dstc_free_reg(c, s1, reg1);

View File

@ -27,11 +27,11 @@
void dstc_emit(DstCompiler *c, uint32_t instr); void dstc_emit(DstCompiler *c, uint32_t instr);
int32_t dstc_getreg(DstCompiler *c); int32_t dstc_allocfar(DstCompiler *c);
int32_t dstc_getreg_temp(DstCompiler *c, DstcRegisterTemp); int32_t dstc_allocnear(DstCompiler *c, DstcRegisterTemp);
int32_t dstc_to_reg(DstCompiler *c, DstSlot s); int32_t dstc_regfar(DstCompiler *c, DstSlot s, DstcRegisterTemp tag);
int32_t dstc_to_tempreg(DstCompiler *c, DstSlot s, DstcRegisterTemp tag); int32_t dstc_regnear(DstCompiler *c, DstSlot s, DstcRegisterTemp tag);
void dstc_free_reg(DstCompiler *c, DstSlot s, int32_t reg); void dstc_free_reg(DstCompiler *c, DstSlot s, int32_t reg);
int32_t dstc_emit_s(DstCompiler *c, uint8_t op, DstSlot s); int32_t dstc_emit_s(DstCompiler *c, uint8_t op, DstSlot s);
@ -45,6 +45,6 @@ int32_t dstc_emit_ssu(DstCompiler *c, uint8_t op, DstSlot s1, DstSlot s2, uint8_
int32_t dstc_emit_sss(DstCompiler *c, uint8_t op, DstSlot s1, DstSlot s2, DstSlot s3); int32_t dstc_emit_sss(DstCompiler *c, uint8_t op, DstSlot s1, DstSlot s2, DstSlot s3);
/* Move value from one slot to another. Cannot copy to constant slots. */ /* Move value from one slot to another. Cannot copy to constant slots. */
int dstc_copy(DstCompiler *c, DstSlot dest, DstSlot src); void dstc_copy(DstCompiler *c, DstSlot dest, DstSlot src);
#endif #endif

View File

@ -29,6 +29,7 @@ void dstc_regalloc_init(DstcRegisterAllocator *ra) {
ra->count = 0; ra->count = 0;
ra->capacity = 0; ra->capacity = 0;
ra->max = 0; ra->max = 0;
ra->regtemps = 0;
} }
void dstc_regalloc_deinit(DstcRegisterAllocator *ra) { void dstc_regalloc_deinit(DstcRegisterAllocator *ra) {
@ -126,9 +127,16 @@ int32_t dstc_regalloc_1(DstcRegisterAllocator *ra) {
* without being freed. */ * without being freed. */
void dstc_regalloc_free(DstcRegisterAllocator *ra, int32_t reg) { void dstc_regalloc_free(DstcRegisterAllocator *ra, int32_t reg) {
/* We cannot free reserved slots */ /* We cannot free reserved slots */
if (reg < 0 || (reg >= 240 && reg <= 255)) if (reg < 0)
return; return;
if (reg >= 0xF0 && reg <= 0xFF) {
ra->regtemps &= ~(1 << (reg - 0xF0));
return;
}
int32_t chunk = reg >> 5; int32_t chunk = reg >> 5;
/* Outside normal chunk range */
if (chunk >= ra->count)
return;
int32_t bit = reg & 0x1F; int32_t bit = reg & 0x1F;
ra->chunks[chunk] &= ~ithbit(bit); ra->chunks[chunk] &= ~ithbit(bit);
} }
@ -139,6 +147,8 @@ void dstc_regalloc_free(DstcRegisterAllocator *ra, int32_t reg) {
int32_t dstc_regalloc_temp(DstcRegisterAllocator *ra, DstcRegisterTemp nth) { int32_t dstc_regalloc_temp(DstcRegisterAllocator *ra, DstcRegisterTemp nth) {
int32_t oldmax = ra->max; int32_t oldmax = ra->max;
int32_t reg = dstc_regalloc_1(ra); int32_t reg = dstc_regalloc_1(ra);
dst_assert(~(ra->regtemps & (1 << nth)), "regtemp already allocated");
ra->regtemps |= 1 << nth;
if (reg > 0xFF) { if (reg > 0xFF) {
reg = 0xF0 + nth; reg = 0xF0 + nth;
ra->max = (reg > oldmax) ? reg : oldmax; ra->max = (reg > oldmax) ? reg : oldmax;
@ -146,8 +156,9 @@ int32_t dstc_regalloc_temp(DstcRegisterAllocator *ra, DstcRegisterTemp nth) {
return reg; return reg;
} }
/* Check if a range is free. Returns the next index to check if not free, /* Disable multi-slot allocation for now. */
* -1 if free. */
/*
static int32_t checkrange(DstcRegisterAllocator *ra, int32_t start, int32_t end) { static int32_t checkrange(DstcRegisterAllocator *ra, int32_t start, int32_t end) {
int32_t startchunk = start / 32; int32_t startchunk = start / 32;
int32_t endchunk = end / 32; int32_t endchunk = end / 32;
@ -161,7 +172,6 @@ static int32_t checkrange(DstcRegisterAllocator *ra, int32_t start, int32_t end)
uint32_t block = ra->chunks[chunk]; uint32_t block = ra->chunks[chunk];
uint32_t masking = mask & block; uint32_t masking = mask & block;
if (masking) { if (masking) {
/* If block is full, skip it completely. */
int32_t nextbit = (block == 0xFFFFFFFF) int32_t nextbit = (block == 0xFFFFFFFF)
? 32 ? 32
: count_trailing_zeros(masking) + 1; : count_trailing_zeros(masking) + 1;
@ -171,7 +181,6 @@ static int32_t checkrange(DstcRegisterAllocator *ra, int32_t start, int32_t end)
return -1; return -1;
} }
/* Mark a range */
static void markrange(DstcRegisterAllocator *ra, int32_t start, int32_t end) { static void markrange(DstcRegisterAllocator *ra, int32_t start, int32_t end) {
int32_t startchunk = start / 32; int32_t startchunk = start / 32;
int32_t endchunk = end / 32; int32_t endchunk = end / 32;
@ -185,7 +194,6 @@ static void markrange(DstcRegisterAllocator *ra, int32_t start, int32_t end) {
} }
} }
/* Free a range of registers. */
void dstc_regalloc_freerange(DstcRegisterAllocator *ra, int32_t start, int32_t n) { void dstc_regalloc_freerange(DstcRegisterAllocator *ra, int32_t start, int32_t n) {
int32_t end = start + n - 1; int32_t end = start + n - 1;
int32_t startchunk = start / 32; int32_t startchunk = start / 32;
@ -200,8 +208,6 @@ void dstc_regalloc_freerange(DstcRegisterAllocator *ra, int32_t start, int32_t n
} }
} }
/* Allocate n contiguous registers. Returns the first register
* in the range allocated. */
int32_t dstc_regalloc_n(DstcRegisterAllocator *ra, int32_t n) { int32_t dstc_regalloc_n(DstcRegisterAllocator *ra, int32_t n) {
int32_t start = 0, end = 0, next = 0; int32_t start = 0, end = 0, next = 0;
while (next >= 0) { while (next >= 0) {
@ -210,15 +216,11 @@ int32_t dstc_regalloc_n(DstcRegisterAllocator *ra, int32_t n) {
next = checkrange(ra, start, end); next = checkrange(ra, start, end);
} }
markrange(ra, start, end); markrange(ra, start, end);
/* Set max */
if (end > ra->max) if (end > ra->max)
ra->max = end; ra->max = end;
return start; return start;
} }
/* Allocates registers for a function call. Tries to not move the callee,
* but will find nargs + 1 other contiguous registers if there is not enough
* space after the callee. */
int32_t dstc_regalloc_call(DstcRegisterAllocator *ra, int32_t callee, int32_t nargs) { int32_t dstc_regalloc_call(DstcRegisterAllocator *ra, int32_t callee, int32_t nargs) {
if (checkrange(ra, callee, callee + nargs) < 0) { if (checkrange(ra, callee, callee + nargs) < 0) {
markrange(ra, callee + 1, callee + nargs); markrange(ra, callee + 1, callee + nargs);
@ -227,3 +229,4 @@ int32_t dstc_regalloc_call(DstcRegisterAllocator *ra, int32_t callee, int32_t na
return dstc_regalloc_n(ra, nargs + 1); return dstc_regalloc_n(ra, nargs + 1);
} }
*/

View File

@ -44,6 +44,7 @@ typedef struct {
int32_t count; /* number of chunks in chunks */ int32_t count; /* number of chunks in chunks */
int32_t capacity; /* amount allocated for chunks */ int32_t capacity; /* amount allocated for chunks */
int32_t max; /* The maximum allocated register so far */ int32_t max; /* The maximum allocated register so far */
int32_t regtemps; /* Hold which tempregistered are alloced. */
} DstcRegisterAllocator; } DstcRegisterAllocator;
void dstc_regalloc_init(DstcRegisterAllocator *ra); void dstc_regalloc_init(DstcRegisterAllocator *ra);
@ -51,56 +52,15 @@ void dstc_regalloc_deinit(DstcRegisterAllocator *ra);
int32_t dstc_regalloc_1(DstcRegisterAllocator *ra); int32_t dstc_regalloc_1(DstcRegisterAllocator *ra);
void dstc_regalloc_free(DstcRegisterAllocator *ra, int32_t reg); void dstc_regalloc_free(DstcRegisterAllocator *ra, int32_t reg);
void dstc_regalloc_freerange(DstcRegisterAllocator *ra, int32_t regstart, int32_t n);
int32_t dstc_regalloc_temp(DstcRegisterAllocator *ra, DstcRegisterTemp nth); int32_t dstc_regalloc_temp(DstcRegisterAllocator *ra, DstcRegisterTemp nth);
int32_t dstc_regalloc_n(DstcRegisterAllocator *ra, int32_t n);
int32_t dstc_regalloc_call(DstcRegisterAllocator *ra, int32_t callee, int32_t nargs);
void dstc_regalloc_clone(DstcRegisterAllocator *dest, DstcRegisterAllocator *src); void dstc_regalloc_clone(DstcRegisterAllocator *dest, DstcRegisterAllocator *src);
void dstc_regalloc_touch(DstcRegisterAllocator *ra, int32_t reg); void dstc_regalloc_touch(DstcRegisterAllocator *ra, int32_t reg);
/* Test code */ /* Mutli-slot allocation disabled */
/* /*
#include <stdio.h> int32_t dstc_regalloc_n(DstcRegisterAllocator *ra, int32_t n);
static void printreg(DstcRegisterAllocator *ra) { int32_t dstc_regalloc_call(DstcRegisterAllocator *ra, int32_t callee, int32_t nargs);
printf("count=%d, cap=%d, max=%d\n", ra->count, ra->capacity, ra->max); void dstc_regalloc_freerange(DstcRegisterAllocator *ra, int32_t regstart, int32_t n);
for (int row = 0; row < ra->count; row++) {
uint32_t chunk = ra->chunks[row];
putc('[', stdout);
for (int i = 0; i < 32; i++) {
putc(
(chunk & (1 << i))
? '*'
: '.', stdout);
}
putc(']', stdout);
putc('\n', stdout);
}
putc('\n', stdout);
}
static void runtest(void) {
DstcRegisterAllocator ra, rb;
dstc_regalloc_init(&ra);
int32_t a = dstc_regalloc_1(&ra);
int32_t b = dstc_regalloc_1(&ra);
int32_t c = dstc_regalloc_1(&ra);
int32_t d = dstc_regalloc_1(&ra);
int32_t e = dstc_regalloc_1(&ra);
printreg(&ra);
dstc_regalloc_free(&ra, b);
dstc_regalloc_free(&ra, d);
printreg(&ra);
int32_t x = dstc_regalloc_n(&ra, 32);
printreg(&ra);
dstc_regalloc_1(&ra);
printreg(&ra);
int32_t y = dstc_regalloc_n(&ra, 101);
printreg(&ra);
dstc_regalloc_clone(&rb, &ra);
printreg(&rb);
dstc_regalloc_deinit(&ra);
dstc_regalloc_deinit(&rb);
}
*/ */
#endif #endif

View File

@ -63,8 +63,8 @@ static void destructure(DstCompiler *c,
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
DstSlot nextright; DstSlot nextright;
Dst subval = values[i]; Dst subval = values[i];
right_register = dstc_to_tempreg(c, right, DSTC_REGTEMP_0); right_register = dstc_regnear(c, right, DSTC_REGTEMP_0);
subval_register = dstc_getreg_temp(c, DSTC_REGTEMP_1); subval_register = dstc_allocnear(c, DSTC_REGTEMP_1);
if (i < 0x100) { if (i < 0x100) {
dstc_emit(c, DOP_GET_INDEX | dstc_emit(c, DOP_GET_INDEX |
(subval_register << 8) | (subval_register << 8) |
@ -72,7 +72,7 @@ static void destructure(DstCompiler *c,
(i << 24)); (i << 24));
} else { } else {
DstSlot islot = dstc_cslot(dst_wrap_integer(i)); DstSlot islot = dstc_cslot(dst_wrap_integer(i));
int32_t i_register = dstc_to_tempreg(c, islot, DSTC_REGTEMP_2); int32_t i_register = dstc_regnear(c, islot, DSTC_REGTEMP_2);
dstc_emit(c, DOP_GET_INDEX | dstc_emit(c, DOP_GET_INDEX |
(subval_register << 8) | (subval_register << 8) |
(right_register << 16) | (right_register << 16) |
@ -88,8 +88,6 @@ static void destructure(DstCompiler *c,
dstc_free_reg(c, right, right_register); dstc_free_reg(c, right, right_register);
} }
} }
/* Free right */
dstc_freeslot(c, right);
break; break;
case DST_TABLE: case DST_TABLE:
case DST_STRUCT: case DST_STRUCT:
@ -100,9 +98,9 @@ static void destructure(DstCompiler *c,
DstSlot nextright; DstSlot nextright;
DstSlot kslot = dstc_value(dstc_fopts_default(c), kv->key); DstSlot kslot = dstc_value(dstc_fopts_default(c), kv->key);
right_register = dstc_to_tempreg(c, right, DSTC_REGTEMP_0); right_register = dstc_regnear(c, right, DSTC_REGTEMP_0);
subval_register = dstc_getreg_temp(c, DSTC_REGTEMP_1); subval_register = dstc_allocnear(c, DSTC_REGTEMP_1);
k_register = dstc_to_tempreg(c, kslot, DSTC_REGTEMP_2); k_register = dstc_regnear(c, kslot, DSTC_REGTEMP_2);
dstc_emit(c, DOP_GET | dstc_emit(c, DOP_GET |
(subval_register << 8) | (subval_register << 8) |
(right_register << 16) | (right_register << 16) |
@ -117,11 +115,8 @@ static void destructure(DstCompiler *c,
dstc_free_reg(c, right, right_register); dstc_free_reg(c, right, right_register);
} }
} }
/* Free right */
dstc_freeslot(c, right);
break; break;
} }
} }
DstSlot dstc_varset(DstFopts opts, int32_t argn, const Dst *argv) { DstSlot dstc_varset(DstFopts opts, int32_t argn, const Dst *argv) {
@ -193,7 +188,7 @@ static DstSlot namelocal(DstCompiler *c, Dst head, int32_t flags, DstSlot ret) {
ret.index > 0xFF) { ret.index > 0xFF) {
/* Slot is not able to be named */ /* Slot is not able to be named */
DstSlot localslot; DstSlot localslot;
localslot.index = dstc_getreg(c); localslot.index = dstc_allocfar(c);
/* infer type? */ /* infer type? */
localslot.flags = flags; localslot.flags = flags;
localslot.envindex = -1; localslot.envindex = -1;

View File

@ -169,15 +169,8 @@ int dst_core_struct(DstArgs args) {
} }
int dst_core_gensym(DstArgs args) { int dst_core_gensym(DstArgs args) {
DST_MAXARITY(args, 1); DST_FIXARITY(args, 0);
if (args.n == 0) { DST_RETURN_SYMBOL(args, dst_symbol_gen());
DST_RETURN_SYMBOL(args, dst_symbol_gen(NULL, 0));
} else {
const uint8_t *s;
int32_t len;
DST_ARG_BYTES(s, len, args, 0);
DST_RETURN_SYMBOL(args, dst_symbol_gen(s, len));
}
} }
int dst_core_gccollect(DstArgs args) { int dst_core_gccollect(DstArgs args) {

View File

@ -201,48 +201,52 @@ const uint8_t *dst_symbol_from_string(const uint8_t *str) {
return str; return str;
} }
/* Helper for creating a unique string. Increment an integer /* Store counter for genysm to avoid quadratic behavior */
* represented as an array of integer digits. */ DST_THREAD_LOCAL uint8_t gensym_counter[8] = {'_', '0', '0', '0', '0', '0', '0', 0};
static void inc_counter(uint8_t *digits, int base, int len) {
int i; /* Increment the gensym buffer */
uint8_t carry = 1; static void inc_gensym(void) {
for (i = len - 1; i >= 0; --i) { for (int i = sizeof(gensym_counter) - 2; i; i--) {
digits[i] += carry; if (gensym_counter[i] == '9') {
carry = 0; gensym_counter[i] = 'a';
if (digits[i] == base) { } else if (gensym_counter[i] == 'z') {
digits[i] = 0; gensym_counter[i] = 'A';
carry = 1; } else if (gensym_counter[i] == 'Z') {
gensym_counter[i] = '0';
} else {
gensym_counter[i]++;
break;
} }
} }
} }
/* Generate a unique symbol. This is used in the library function gensym. The /* Generate a unique symbol. This is used in the library function gensym. The
* symbol will be of the format prefix_XXXXXX, where X is a base64 digit, and * symbol will be of the format _XXXXXX, where X is a base64 digit, and
* prefix is the argument passed. */ * prefix is the argument passed. No prefix for speed. */
const uint8_t *dst_symbol_gen(const uint8_t *buf, int32_t len) { const uint8_t *dst_symbol_gen(void) {
const uint8_t **bucket = NULL; const uint8_t **bucket = NULL;
uint8_t *sym;
int32_t hash = 0; int32_t hash = 0;
uint8_t counter[6] = {63, 63, 63, 63, 63, 63}; int status;
/* Leave spaces for 6 base 64 digits and two dashes. That means 64^6 possible suffixes, which /* Leave spaces for 6 base 64 digits and two dashes. That means 64^6 possible suffixes, which
* is enough for resolving collisions. */ * is enough for resolving collisions. */
int32_t newlen = len + 7; do {
int32_t newbufsize = newlen + 2 * sizeof(int32_t) + 1; hash = dst_string_calchash(
uint8_t *str = (uint8_t *)dst_gcalloc(DST_MEMORY_SYMBOL, newbufsize) + 2 * sizeof(int32_t); gensym_counter,
dst_string_length(str) = newlen; sizeof(gensym_counter) - 1);
memcpy(str, buf, len); bucket = dst_symcache_findmem(
str[len] = '_'; gensym_counter,
str[newlen] = 0; sizeof(gensym_counter) - 1,
uint8_t *saltbuf = str + len + 1; hash,
int status = 1; &status);
while (status) { } while (status && (inc_gensym(), 1));
int i; sym = (uint8_t *) dst_gcalloc(
inc_counter(counter, 64, 6); DST_MEMORY_SYMBOL,
for (i = 0; i < 6; ++i) 2 * sizeof(int32_t) + sizeof(gensym_counter)) +
saltbuf[i] = dst_base64[counter[i]]; (2 * sizeof(int32_t));
hash = dst_string_calchash(str, newlen); memcpy(sym, gensym_counter, sizeof(gensym_counter));
bucket = dst_symcache_findmem(str, newlen, hash, &status); dst_string_length(sym) = sizeof(gensym_counter) - 1;
} dst_string_hash(sym) = hash;
dst_string_hash(str) = hash; dst_symcache_put((const uint8_t *)sym, bucket);
dst_symcache_put((const uint8_t *)str, bucket); return (const uint8_t *)sym;
return (const uint8_t *)str;
} }

View File

@ -129,7 +129,7 @@ void dst_puts(const uint8_t *str);
const uint8_t *dst_symbol(const uint8_t *str, int32_t len); const uint8_t *dst_symbol(const uint8_t *str, int32_t len);
const uint8_t *dst_symbol_from_string(const uint8_t *str); const uint8_t *dst_symbol_from_string(const uint8_t *str);
const uint8_t *dst_csymbol(const char *str); const uint8_t *dst_csymbol(const char *str);
const uint8_t *dst_symbol_gen(const uint8_t *buf, int32_t len); const uint8_t *dst_symbol_gen();
#define dst_symbolv(str, len) dst_wrap_symbol(dst_symbol((str), (len))) #define dst_symbolv(str, len) dst_wrap_symbol(dst_symbol((str), (len)))
#define dst_csymbolv(cstr) dst_wrap_symbol(dst_csymbol(cstr)) #define dst_csymbolv(cstr) dst_wrap_symbol(dst_csymbol(cstr))

View File

@ -238,12 +238,11 @@
# Gensym tests # Gensym tests
(assert (not= (gensym) (gensym)) "two gensyms not equal") (assert (not= (gensym) (gensym)) "two gensyms not equal")
(assert (not= (gensym 'abc) (gensym 'abc)) "two gensyms with arg not equal")
((fn [] ((fn []
(def syms (table)) (def syms (table))
(var count 0) (var count 0)
(while (< count 128) (while (< count 128)
(put syms (gensym 'beep) true) (put syms (gensym) true)
(:= count (+ 1 count))) (:= count (+ 1 count)))
(assert (= (length syms) 128) "many symbols"))) (assert (= (length syms) 128) "many symbols")))

View File

@ -161,4 +161,10 @@
(testmarsh @{1 2 3 4} "marshal table") (testmarsh @{1 2 3 4} "marshal table")
(testmarsh {1 2 3 4} "marshal struct") (testmarsh {1 2 3 4} "marshal struct")
# Large functions
(def manydefs (for [i :range [0 300]] (tuple 'def (gensym) (string "value_" i))))
(array.push manydefs (tuple * 10000 3 5 7 9))
(def f (compile (tuple.prepend manydefs 'do) *env*))
(assert (= (f) (* 10000 3 5 7 9)) "long function compilation")
(end-suite) (end-suite)