Skip to content

Commit

Permalink
kernel: change coding of integers, strings, eager floats
Browse files Browse the repository at this point in the history
When coding GAP function bodies, we now have an (optional) plist in the
function body of (immutable) values. Instead of storing the raw data
for an integer or string within the respective expression, we instead
store the integer resp. string in that values plist, and retrieve it
from there when printing or evaluation such expressions (for strings,
evaluation returns a shallow copy of the stored string constant, to
preserve semantics). For eager floats, the values plist is used instead
of `EAGER_FLOAT_LITERAL_CACHE`, which is removed by this patch (thus
resolving part of issue gap-system#1993).

These changes have several advantages:
* we avoid a possible GC crash when compiling (large) string expressions
* a function like `f := x -> 12345678901234567890` used to return a new
  integer object with each call; now it always returns the same integer,
  i.e., `IsIdenticalObj(f(1), f(2));` now returns true
* floats benefit from avoiding use of a global "cache" which never is
  emptied (thus these eager float literals now are garbage collected if
  the function referencing them is garbage collected)
* the cache simplifies future optimizations: e.g. we could convert
  expressions like `-2^100` by evaluating them and storing the result
  in the values list; we could also store permutations precomputed, that
  is, replace a `T_PERM_EXPR` and the `T_PERM_CYCLE` expressions nested
  in it by a single "constant expression" that references the immutable
  permutation described by these expressions (at least in the case these
  expressions were explicitly defined, i.e., `(1,2)` would work but not
  `(i,j)`
  • Loading branch information
fingolfin committed Jan 11, 2019
1 parent c76376b commit c22de8e
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 75 deletions.
79 changes: 34 additions & 45 deletions src/code.c
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,12 @@ void SET_ENDLINE_BODY(Obj body, UInt val)
BODY_HEADER(body)->endline = val ? INTOBJ_INT(val) : 0;
}

Obj GET_VALUE_FROM_CURRENT_BODY(Int ix)
{
Obj values = ((BodyHeader *)STATE(PtrBody))->values;
return ELM_PLIST(values, ix);
}


/****************************************************************************
**
Expand Down Expand Up @@ -491,6 +497,22 @@ void PushBinaryOp (
}


/****************************************************************************
**
*F PushValue( <val> ) . . . . . . . . . . . . . . store value in values list
**
** 'PushValue' pushes a value into the value list of the body, and returns
** the index at which the value was inserted.
*/
static Int PushValue(Obj val)
{
BodyHeader * header = (BodyHeader *)STATE(PtrBody);
if (!header->values)
header->values = NEW_PLIST(T_PLIST, 4);
return PushPlist(header->values, val);
}


/****************************************************************************
**
*F * * * * * * * * * * * * * coder functions * * * * * * * * * * * * * * * *
Expand Down Expand Up @@ -823,6 +845,11 @@ void CodeFuncExprEnd(UInt nr)
// make the function expression list immutable
MakeImmutable( FEXS_FUNC( fexp ) );

// make the body values list (if any) immutable
Obj values = ((BodyHeader *)STATE(PtrBody))->values;
if (values)
MakeImmutable(values);

/* make the body smaller */
ResizeBag(BODY_FUNC(fexp), CS(OffsBody));
SET_ENDLINE_BODY(BODY_FUNC(fexp), GetInputLineNumber());
Expand Down Expand Up @@ -1537,9 +1564,8 @@ void CodeIntExpr(Obj val)
/* otherwise stuff the value into the values list */
else {
GAP_ASSERT(TNUM_OBJ(val) == T_INTPOS || TNUM_OBJ(val) == T_INTNEG);
expr = NewExpr( T_INT_EXPR, sizeof(UInt) + SIZE_OBJ(val) );
WRITE_EXPR(expr, 0, TNUM_OBJ(val));
memcpy((UInt *)ADDR_EXPR(expr)+1, CONST_ADDR_OBJ(val), (size_t)SIZE_OBJ(val));
expr = NewExpr( T_INT_EXPR, sizeof(UInt) );
WRITE_EXPR(expr, 0, PushValue(val));
}

/* push the expression */
Expand Down Expand Up @@ -1734,16 +1760,10 @@ void CodeListExprEnd (
void CodeStringExpr (
Obj str )
{
Expr string; /* string, result */

/* allocate the string expression */
string = NewExpr( T_STRING_EXPR, SIZEBAG_STRINGLEN(GET_LEN_STRING(str)) );
GAP_ASSERT(IS_STRING_REP(str));

/* copy the string */
memcpy( ADDR_EXPR(string), CONST_ADDR_OBJ(str),
SIZEBAG_STRINGLEN(GET_LEN_STRING(str)) );

/* push the string */
Expr string = NewExpr( T_STRING_EXPR, sizeof(UInt) );
WRITE_EXPR(string, 0, PushValue(str));
PushExpr( string );
}

Expand All @@ -1758,7 +1778,6 @@ enum {
};
static UInt NextFloatExprNumber = 3;

Obj EAGER_FLOAT_LITERAL_CACHE = 0;
static Obj CONVERT_FLOAT_LITERAL_EAGER;


Expand Down Expand Up @@ -1843,15 +1862,7 @@ static void CodeEagerFloatExpr(Obj str, Char mark)
UInt l = GET_LEN_STRING(str);
Expr fl = NewExpr(T_FLOAT_EXPR_EAGER, sizeof(UInt) * 3 + l + 1);
Obj v = CALL_2ARGS(CONVERT_FLOAT_LITERAL_EAGER, str, ObjsChar[(Int)mark]);
UInt ix;
assert(EAGER_FLOAT_LITERAL_CACHE);
#ifdef HPCGAP
assert(TNUM_OBJ(EAGER_FLOAT_LITERAL_CACHE) == T_ALIST);
ix = AddAList(EAGER_FLOAT_LITERAL_CACHE, v);
#else
assert(IS_PLIST(EAGER_FLOAT_LITERAL_CACHE));
ix = PushPlist(EAGER_FLOAT_LITERAL_CACHE, v);
#endif
UInt ix = PushValue(v);
WRITE_EXPR(fl, 0, ix);
WRITE_EXPR(fl, 1, l);
WRITE_EXPR(fl, 2, (UInt)mark);
Expand Down Expand Up @@ -3176,7 +3187,7 @@ static Int InitKernel (
InitBagNamesFromTable( BagNames );

/* install the marking functions for function body bags */
InitMarkFuncBags( T_BODY, MarkThreeSubBags );
InitMarkFuncBags( T_BODY, MarkFourSubBags );

SaveObjFuncs[ T_BODY ] = SaveBody;
LoadObjFuncs[ T_BODY ] = LoadBody;
Expand All @@ -3196,7 +3207,6 @@ static Int InitKernel (
InitGlobalBag(&CS(StackExpr), "CS(StackExpr)");

/* some functions and globals needed for float conversion */
InitGlobalBag( &EAGER_FLOAT_LITERAL_CACHE, "EAGER_FLOAT_LITERAL_CACHE" );
InitFopyGVar( "CONVERT_FLOAT_LITERAL_EAGER", &CONVERT_FLOAT_LITERAL_EAGER);

ImportGVarFromLibrary( "TYPE_KERNEL_OBJECT", &TYPE_KERNEL_OBJECT );
Expand All @@ -3206,26 +3216,6 @@ static Int InitKernel (
}


/****************************************************************************
**
*F InitLibrary( <module> ) . . . . . . . initialise library data structures
*/
static Int InitLibrary (
StructInitInfo * module )
{
Obj cache;

#ifdef HPCGAP
cache = NewAtomicList(T_ALIST, 1);
#else
cache = NEW_PLIST_IMM(T_PLIST, 1000L);
#endif
EAGER_FLOAT_LITERAL_CACHE = cache;

/* return success */
return 0;
}

/****************************************************************************
**
*F PostRestore( <module> ) . . . . . . . recover
Expand Down Expand Up @@ -3292,7 +3282,6 @@ static StructInitInfo module = {
.type = MODULE_BUILTIN,
.name = "code",
.initKernel = InitKernel,
.initLibrary = InitLibrary,
.preSave = PreSave,
.postRestore = PostRestore,

Expand Down
8 changes: 8 additions & 0 deletions src/code.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,11 @@ typedef struct {
// if non-zero, this is an immediate integer encoding the line
// number where a function ends
Obj endline;

// if non-zero, this points to a dense plist containing constant values
// referenced by the code in this function body
Obj values;

} BodyHeader;

EXPORT_INLINE BodyHeader *BODY_HEADER(Obj body)
Expand All @@ -94,6 +99,9 @@ void SET_STARTLINE_BODY(Obj body, UInt val);
UInt GET_ENDLINE_BODY(Obj body);
void SET_ENDLINE_BODY(Obj body, UInt val);

extern Obj GET_VALUE_FROM_CURRENT_BODY(Int ix);


/****************************************************************************
**
*V OFFSET_FIRST_STAT . . . . . . . . . . offset of first statement in a body
Expand Down
16 changes: 9 additions & 7 deletions src/compiler.c
Original file line number Diff line number Diff line change
Expand Up @@ -2279,10 +2279,13 @@ CVar CompIntExpr (
return CVAR_INTG( INT_INTEXPR(expr) );
}
else {
// get the actual integer
Obj obj = EVAL_EXPR(expr);

val = CVAR_TEMP( NewTemp( "val" ) );
siz = SIZE_EXPR(expr) - sizeof(UInt);
typ = READ_EXPR(expr, 0);
Emit( "%c = C_MAKE_INTEGER_BAG(%d, %d);\n",val, siz, typ);
siz = SIZE_OBJ(obj);
typ = TNUM_OBJ(obj);
Emit( "%c = C_MAKE_INTEGER_BAG(%d, %d);\n", val, siz, typ);
if ( typ == T_INTPOS ) {
SetInfoCVar(val, W_INT_POS);
}
Expand All @@ -2291,12 +2294,11 @@ CVar CompIntExpr (
}

for ( i = 0; i < siz/INTEGER_UNIT_SIZE; i++ ) {
UInt limb = CONST_ADDR_INT(obj)[i];
#if INTEGER_UNIT_SIZE == 4
Emit("C_SET_LIMB4( %c, %d, %dL);\n", val, i,
((UInt4 *)((const UInt *)CONST_ADDR_EXPR(expr) + 1))[i]);
Emit("C_SET_LIMB4( %c, %d, %dL);\n", val, i, limb);
#elif INTEGER_UNIT_SIZE == 8
Emit("C_SET_LIMB8( %c, %d, %dLL);\n", val, i,
((UInt8 *)((const UInt *)CONST_ADDR_EXPR(expr) + 1))[i]);
Emit("C_SET_LIMB8( %c, %d, %dLL);\n", val, i, limb);
#else
#error unsupported INTEGER_UNIT_SIZE
#endif
Expand Down
33 changes: 10 additions & 23 deletions src/exprs.c
Original file line number Diff line number Diff line change
Expand Up @@ -721,15 +721,8 @@ Obj EvalPow (
Obj EvalIntExpr (
Expr expr )
{
Obj val; /* integer, result */

/* allocate the integer */
val = NewBag(READ_EXPR(expr, 0), SIZE_EXPR(expr) - sizeof(UInt));
memcpy(ADDR_OBJ(val), ((const UInt *)CONST_ADDR_EXPR(expr)) + 1,
SIZE_EXPR(expr) - sizeof(UInt));

/* return the value */
return val;
UInt ix = READ_EXPR(expr, 0);
return GET_VALUE_FROM_CURRENT_BODY(ix);
}

/****************************************************************************
Expand Down Expand Up @@ -1107,15 +1100,9 @@ Obj EvalRangeExpr (
Obj EvalStringExpr (
Expr expr )
{
Obj string; /* string value, result */
UInt len; /* size of expression */

len = READ_EXPR(expr, 0);
string = NEW_STRING(len);
memcpy(ADDR_OBJ(string), CONST_ADDR_EXPR(expr), SIZEBAG_STRINGLEN(len));

/* return the string */
return string;
UInt ix = READ_EXPR(expr, 0);
Obj string = GET_VALUE_FROM_CURRENT_BODY(ix);
return SHALLOW_COPY_OBJ(string);
}

/****************************************************************************
Expand Down Expand Up @@ -1171,13 +1158,10 @@ Obj EvalFloatExprLazy (
** 'EvalFloatExpr' evaluates the float expression <expr> to a float
** value.
*/
extern Obj EAGER_FLOAT_LITERAL_CACHE;

Obj EvalFloatExprEager(Expr expr)
{
UInt ix = READ_EXPR(expr, 0);
Obj fl = ELM_LIST(EAGER_FLOAT_LITERAL_CACHE, ix);
return fl;
return GET_VALUE_FROM_CURRENT_BODY(ix);
}


Expand Down Expand Up @@ -1684,7 +1668,10 @@ void PrintRangeExpr (
void PrintStringExpr (
Expr expr )
{
PrintString(EvalStringExpr(expr));
UInt ix = READ_EXPR(expr, 0);
Obj string = GET_VALUE_FROM_CURRENT_BODY(ix);

PrintString(string);
}

/****************************************************************************
Expand Down

0 comments on commit c22de8e

Please sign in to comment.