unbreak JIT and check limits

Repairs a problem with ce9894c8bf, where a large "inlined" vector
allocation is not actually inlined, but other parts of the JIT
assume that it will behave as inlined --- which implies that the
runstack will be left unchanged after the call.

Closes #1868
This commit is contained in:
Matthew Flatt 2017-10-25 17:35:20 -06:00
parent 55c1685526
commit dfa5d48092
9 changed files with 61 additions and 16 deletions

View File

@ -934,12 +934,17 @@
;; a vector allocation that is too large
(parameterize ([current-namespace (make-base-namespace)])
(let loop ([i 10])
((eval `(lambda (x) (vector x ,@(for/list ([j (in-range i)])
j))))
i)
(when (i . < . 100000)
(loop (floor (* i #e1.25))))))
(for ([tail? '(#t #f)])
(let loop ([i 10])
((eval `(lambda (f x)
,(let ([e `(vector x ,@(for/list ([j (in-range i)])
j))])
(if tail?
e
`(f ,e)))))
values i)
(when (i . < . 10000)
(loop (floor (* i #e1.25)))))))
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -298,6 +298,11 @@ GC2_EXTERN int GC_allocate_phantom_bytes(void *pb, intptr_t);
Returns 0 if allocation should fail due to a memory limit,
1 otherwise. The representative `pb` determines who is charged. */
GC2_EXTERN intptr_t GC_max_nursery_object_size();
/*
Returns a lower bound on the maximum size allowed for allocation
in the nursery. */
/***************************************************************************/
/* Memory tracing */
/***************************************************************************/
@ -581,7 +586,7 @@ GC2_EXTERN intptr_t GC_is_place();
Otherwise returns 0;
*/
GC2_EXTERN int GC_message_small_objects_size(void *msg_memory, intptr_t up_to);
GC2_EXTERN int GC_message_small_objects_size(void *msg_memory, intptr_t up_to);
/*
Determines whether the message qualifies as short and whether the
total size of all objects allocated by the message allocator is less

View File

@ -1774,6 +1774,8 @@ intptr_t GC_alloc_alignment()
intptr_t GC_malloc_stays_put_threshold() { return MAX_OBJECT_SIZE; }
intptr_t GC_max_nursery_object_size() { return MAX_OBJECT_SIZE - OBJHEAD_SIZE; }
/*****************************************************************************/
/* Nursery (a.k.a. generation 0) and generation 1/2 */
/*****************************************************************************/

View File

@ -256,6 +256,9 @@ Scheme_Env *scheme_engine_instance_init()
scheme_init_resolve();
scheme_init_sfs();
scheme_init_validate();
#ifdef MZ_USE_JIT
scheme_init_jit();
#endif
scheme_init_process_globals();
@ -492,7 +495,7 @@ static Scheme_Env *place_instance_init(void *stack_base, int initial_main_os_thr
scheme_init_stack_check();
scheme_init_overflow();
scheme_init_thread_lwc();
scheme_init_compenv_places();

View File

@ -266,6 +266,9 @@ typedef struct Apply_LWC_Args {
typedef Scheme_Object *(*Continuation_Apply_Indirect)(Apply_LWC_Args *, intptr_t);
typedef Scheme_Object *(*Continuation_Apply_Finish)(Apply_LWC_Args *args, void *stack, void *frame);
#define JIT_MAX_VECTOR_INLINE_SIZE 256
#define JIT_MAX_STRUCT_FIELD_INLINE_COUNT 256
#ifdef MZ_LONG_DOUBLE
# define JIT_NUM_FL_KINDS 2
#else

View File

@ -150,7 +150,7 @@ static int check_val_struct_prim(Scheme_Object *p, int arity)
Scheme_Struct_Type *t;
t = (Scheme_Struct_Type *)SCHEME_PRIM_CLOSURE_ELS(p)[0];
if ((arity == t->num_islots)
&& (arity < 100)) {
&& (arity < JIT_MAX_STRUCT_FIELD_INLINE_COUNT)) {
return INLINE_STRUCT_PROC_CONSTR;
}
return 0;
@ -5288,9 +5288,18 @@ static int generate_vector_alloc(mz_jit_state *jitter, Scheme_Object *rator,
c = 2;
} else {
c = app->num_args;
if (c > 256) {
if (c > JIT_MAX_VECTOR_INLINE_SIZE) {
/* Too big for inline alloc */
return scheme_generate_app(app, NULL, c, c, jitter, 0, 0, 0, 0);
i = scheme_generate_app(app, NULL, c, c, jitter, 0, 0, 0, 0);
CHECK_LIMIT();
if (dest != JIT_R0)
jit_movr_p(dest, JIT_R0);
/* since we're called in inline mode, need to manually pop: */
jit_addi_l(JIT_RUNSTACK, JIT_RUNSTACK, WORDS_TO_BYTES(c));
mz_runstack_popped(jitter, c);
return i;
} else if (c)
scheme_generate_app(app, NULL, c, c, jitter, 0, 0, 0, 2); /* sync'd below */
}

View File

@ -29,6 +29,22 @@
/* Used by vector-set-performance-stats!: */
int scheme_jit_malloced;
void scheme_init_jit()
{
#ifdef CAN_INLINE_ALLOC
intptr_t max_alloc;
max_alloc = GC_max_nursery_object_size();
if ((sizeof(Scheme_Vector) + (JIT_MAX_VECTOR_INLINE_SIZE - mzFLEX_DELTA) * sizeof(Scheme_Object *)) > max_alloc) {
scheme_log_abort("Misconfigured: inlined vector size is greater than maximum allowed by GC");
abort();
}
if ((sizeof(Scheme_Structure) + ((JIT_MAX_STRUCT_FIELD_INLINE_COUNT - mzFLEX_DELTA) * sizeof(Scheme_Object *))) > max_alloc) {
scheme_log_abort("Misconfigured: inlined struct size is greater than maximum allowed by GC");
abort();
}
#endif
}
/*========================================================================*/
/* JIT buffer */
/*========================================================================*/

View File

@ -304,6 +304,9 @@ void scheme_init_finalization(void);
void scheme_init_portable_case(void);
void scheme_init_stack_check(void);
void scheme_init_overflow(void);
#ifdef MZ_USE_JIT
void scheme_init_jit(void);
#endif
#ifdef MZ_PRECISE_GC
void scheme_register_traversers(void);
void scheme_init_hash_key_procs(void);
@ -532,7 +535,6 @@ extern Scheme_Object *scheme_make_vector_proc;
extern Scheme_Object *scheme_vector_immutable_proc;
extern Scheme_Object *scheme_vector_ref_proc;
extern Scheme_Object *scheme_vector_set_proc;
extern Scheme_Object *scheme_vector_cas_proc;
extern Scheme_Object *scheme_list_to_vector_proc;
extern Scheme_Object *scheme_unsafe_vector_length_proc;
extern Scheme_Object *scheme_unsafe_struct_ref_proc;
@ -1075,6 +1077,9 @@ typedef struct Scheme_Structure
Scheme_Object *slots[mzFLEX_ARRAY_DECL];
} Scheme_Structure;
#define MAX_STRUCT_FIELD_COUNT 32768
#define MAX_STRUCT_FIELD_COUNT_STR "32768"
#ifdef MZ_USE_PLACES
typedef struct Scheme_Serialized_Structure
{

View File

@ -2839,7 +2839,7 @@ static int parse_pos(const char *who, Scheme_Object *prim, Scheme_Object **args,
if (!SCHEME_INTP(args[1]) || (SCHEME_INT_VAL(args[1]) < 0)) {
if (SCHEME_BIGNUMP(args[1]) && SCHEME_BIGPOS(args[1])) {
pos = 32769; /* greater than max field count */
pos = (MAX_STRUCT_FIELD_COUNT + 1);
} else {
if (!who)
who = extract_field_proc_name(prim);
@ -3482,9 +3482,6 @@ static Scheme_Object *make_prefab_struct(int argc, Scheme_Object *argv[])
return scheme_make_prefab_struct_instance(stype, vec);
}
#define MAX_STRUCT_FIELD_COUNT 32768
#define MAX_STRUCT_FIELD_COUNT_STR "32768"
static Scheme_Object *prefab_key_struct_type(int argc, Scheme_Object *argv[])
{
Scheme_Struct_Type *stype;