Skip to content

Commit

Permalink
[interp] initial infrastructure for whitebox testing of optimization …
Browse files Browse the repository at this point in the history
…passes (mono/mono#18268)

Commit migrated from mono/mono@05f2651
  • Loading branch information
lewurm authored and akoeplinger committed Jan 14, 2020
1 parent c8d03fb commit d6222a3
Show file tree
Hide file tree
Showing 6 changed files with 513 additions and 171 deletions.
1 change: 1 addition & 0 deletions src/mono/mono/mini/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,4 @@
/buildver-sgen.h
/buildver-boehm.h
/regressiontests.out
/test-mono-interp-whitebox
17 changes: 17 additions & 0 deletions src/mono/mono/mini/Makefile.am.in
Original file line number Diff line number Diff line change
Expand Up @@ -779,6 +779,20 @@ libmonosgen_2_0_la_CFLAGS = $(mono_sgen_CFLAGS) @CXX_ADD_CFLAGS@
libmonosgen_2_0_la_LIBADD = libmini.la $(interp_libs_with_mini) $(dbg_libs_with_mini) $(sgen_libs) $(LIBMONO_DTRACE_OBJECT) $(LLVMMONOF)
libmonosgen_2_0_la_LDFLAGS = $(libmonoldflags) $(monobin_platform_ldflags)

noinst_LIBRARIES += libmaintest.a

libmaintest_a_SOURCES = interp/whitebox.c
libmaintest_a_CFLAGS = $(AM_CFLAGS) @CXX_ADD_CFLAGS@

WHITEBOX_ASSEMBLY=interp/whitebox-snippets.exe
test_mono_interp_whitebox_SOURCES =
test_mono_interp_whitebox_CFLAGS = $(AM_CFLAGS) @CXX_REMOVE_CFLAGS@
test_mono_interp_whitebox_LDADD = interp/libmaintest_a-whitebox.$(OBJEXT) libmini.la $(interp_libs_with_mini) $(dbg_libs_with_mini) $(sgen_libs)
test_mono_interp_whitebox_LDFLAGS = $(libmonoldflags) $(monobin_platform_ldflags)
test_mono_interp_whitebox_DEPENDENCIES = $(WHITEBOX_ASSEMBLY)

check_PROGRAMS = test-mono-interp-whitebox

endif # !ENABLE_MSVC_ONLY

libmonoincludedir = $(includedir)/mono-$(API_VER)/mono/jit
Expand Down Expand Up @@ -900,6 +914,9 @@ rcheck: mono $(regtests)
richeck: mono $(regtests)
$(INTERP_RUNTIME) --regression $(regtests)

interp-whitebox: test-mono-interp-whitebox
MONO_PATH=$(CLASS) ./$< $(WHITEBOX_ASSEMBLY)

mixedcheck: mono mixed.exe
$(MINI_RUNTIME) --interp=jit=JitClass mixed.exe

Expand Down
205 changes: 34 additions & 171 deletions src/mono/mono/mini/interp/transform.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
#include <mono/metadata/marshal.h>
#include <mono/metadata/profiler-private.h>
#include <mono/metadata/tabledefs.h>
#include <mono/metadata/seq-points-data.h>
#include <mono/metadata/mono-basic-block.h>
#include <mono/metadata/abi-details.h>
#include <mono/metadata/reflection-internals.h>
Expand All @@ -31,181 +30,12 @@
#include "mintops.h"
#include "interp-internals.h"
#include "interp.h"

#define INTERP_INST_FLAG_SEQ_POINT_NONEMPTY_STACK 1
#define INTERP_INST_FLAG_SEQ_POINT_METHOD_ENTRY 2
#define INTERP_INST_FLAG_SEQ_POINT_METHOD_EXIT 4
#define INTERP_INST_FLAG_SEQ_POINT_NESTED_CALL 8
#define INTERP_INST_FLAG_RECORD_CALL_PATCH 16

#define INTERP_LOCAL_FLAG_INDIRECT 1
#define INTERP_LOCAL_FLAG_DEAD 2
#include "transform.h"

MonoInterpStats mono_interp_stats;

#define DEBUG 0

typedef struct InterpInst InterpInst;

typedef struct
{
MonoClass *klass;
unsigned char type;
unsigned char flags;
} StackInfo;

#define STACK_VALUE_NONE 0
#define STACK_VALUE_LOCAL 1
#define STACK_VALUE_ARG 2
#define STACK_VALUE_I4 3
#define STACK_VALUE_I8 4

// StackValue contains data to construct an InterpInst that is equivalent with the contents
// of the stack slot / local / argument.
typedef struct {
// Indicates the type of the stored information. It can be a local, argument or a constant
int type;
// Holds the local index or the actual constant value
union {
int local;
int arg;
gint32 i;
gint64 l;
};
} StackValue;

typedef struct
{
// This indicates what is currently stored in this stack slot. This can be a constant
// or the copy of a local / argument.
StackValue val;
// The instruction that pushed this stack slot. If ins is null, we can't remove the usage
// of the stack slot, because we can't clear the instruction that set it.
InterpInst *ins;
} StackContentInfo;

struct InterpInst {
guint16 opcode;
InterpInst *next, *prev;
// If this is -1, this instruction is not logically associated with an IL offset, it is
// part of the IL instruction associated with the previous interp instruction.
int il_offset;
guint32 flags;
guint16 data [MONO_ZERO_LEN_ARRAY];
};

typedef struct {
guint8 *ip;
GSList *preds;
GSList *seq_points;
SeqPoint *last_seq_point;

// This will hold a list of last sequence points of incoming basic blocks
SeqPoint **pred_seq_points;
guint num_pred_seq_points;
} InterpBasicBlock;

typedef enum {
RELOC_SHORT_BRANCH,
RELOC_LONG_BRANCH,
RELOC_SWITCH
} RelocType;

typedef struct {
RelocType type;
/* In the interpreter IR */
int offset;
/* In the IL code */
int target;
} Reloc;

typedef struct {
MonoType *type;
int mt;
int flags;
int offset;
} InterpLocal;

typedef struct
{
MonoMethod *method;
MonoMethod *inlined_method;
MonoMethodHeader *header;
InterpMethod *rtm;
const unsigned char *il_code;
const unsigned char *ip;
const unsigned char *in_start;
InterpInst *last_ins, *first_ins;
int code_size;
int *in_offsets;
int current_il_offset;
StackInfo **stack_state;
int *stack_height;
int *vt_stack_size;
unsigned char *is_bb_start;
unsigned short *new_code;
unsigned short *new_code_end;
unsigned int max_code_size;
StackInfo *stack;
StackInfo *sp;
unsigned int max_stack_height;
unsigned int stack_capacity;
unsigned int vt_sp;
unsigned int max_vt_sp;
unsigned int total_locals_size;
InterpLocal *locals;
unsigned int locals_size;
unsigned int locals_capacity;
int n_data_items;
int max_data_items;
void **data_items;
GHashTable *data_hash;
#ifdef ENABLE_EXPERIMENT_TIERED
GHashTable *patchsite_hash;
#endif
int *clause_indexes;
gboolean gen_sdb_seq_points;
GPtrArray *seq_points;
InterpBasicBlock **offset_to_bb;
InterpBasicBlock *entry_bb;
MonoMemPool *mempool;
GList *basic_blocks;
GPtrArray *relocs;
gboolean verbose_level;
GArray *line_numbers;
} TransformData;

#define STACK_TYPE_I4 0
#define STACK_TYPE_I8 1
#define STACK_TYPE_R4 2
#define STACK_TYPE_R8 3
#define STACK_TYPE_O 4
#define STACK_TYPE_VT 5
#define STACK_TYPE_MP 6
#define STACK_TYPE_F 7

static const char *stack_type_string [] = { "I4", "I8", "R4", "R8", "O ", "VT", "MP", "F " };

#if SIZEOF_VOID_P == 8
#define STACK_TYPE_I STACK_TYPE_I8
#else
#define STACK_TYPE_I STACK_TYPE_I4
#endif

static int stack_type [] = {
STACK_TYPE_I4, /*I1*/
STACK_TYPE_I4, /*U1*/
STACK_TYPE_I4, /*I2*/
STACK_TYPE_I4, /*U2*/
STACK_TYPE_I4, /*I4*/
STACK_TYPE_I8, /*I8*/
STACK_TYPE_R4, /*R4*/
STACK_TYPE_R8, /*R8*/
STACK_TYPE_O, /*O*/
STACK_TYPE_MP, /*P*/
STACK_TYPE_VT
};

#if SIZEOF_VOID_P == 8
#define MINT_NEG_P MINT_NEG_I8
#define MINT_NOT_P MINT_NOT_I8
Expand Down Expand Up @@ -1054,6 +884,21 @@ mono_interp_print_code (InterpMethod *imethod)
dump_mint_code ((const guint16*)start, (const guint16*)(start + jinfo->code_size));
}

/* For debug use */
void
mono_interp_print_td_code (TransformData *td)
{
InterpInst *ins = td->first_ins;

char *name = mono_method_full_name (td->method, TRUE);
g_print ("IR for \"%s\"\n", name);
g_free (name);
while (ins) {
dump_interp_inst_newline (ins);
ins = ins->next;
}
}


static MonoMethodHeader*
interp_method_get_header (MonoMethod* method, MonoError *error)
Expand Down Expand Up @@ -2987,6 +2832,12 @@ interp_method_compute_offsets (TransformData *td, InterpMethod *imethod, MonoMet
td->total_locals_size = offset;
}

void
mono_test_interp_method_compute_offsets (TransformData *td, InterpMethod *imethod, MonoMethodSignature *signature, MonoMethodHeader *header)
{
interp_method_compute_offsets (td, imethod, signature, header);
}

/* Return false is failure to init basic blocks due to being in inline method */
static gboolean
init_bb_start (TransformData *td, MonoMethodHeader *header, gboolean inlining)
Expand Down Expand Up @@ -7328,6 +7179,12 @@ interp_cprop (TransformData *td)
g_free (local_ref_count);
}

void
mono_test_interp_cprop (TransformData *td)
{
interp_cprop (td);
}

static void
interp_super_instructions (TransformData *td)
{
Expand Down Expand Up @@ -7583,6 +7440,12 @@ generate (MonoMethod *method, MonoMethodHeader *header, InterpMethod *rtm, MonoG
mono_mempool_destroy (td->mempool);
}

gboolean
mono_test_interp_generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header, MonoGenericContext *generic_context, MonoError *error)
{
return generate_code (td, method, header, generic_context, error);
}

static mono_mutex_t calc_section;

#ifdef ENABLE_EXPERIMENT_TIERED
Expand Down
Loading

0 comments on commit d6222a3

Please sign in to comment.