Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--man/mono.113
-rw-r--r--mono/mini/aot-compiler.c102
-rw-r--r--mono/mini/method-to-ir.c8
-rw-r--r--mono/mini/mini.h1
4 files changed, 121 insertions, 3 deletions
diff --git a/man/mono.1 b/man/mono.1
index 857f3913577..37e96045e56 100644
--- a/man/mono.1
+++ b/man/mono.1
@@ -192,6 +192,19 @@ Same for the llvm tools 'opt' and 'llc'.
.TP
.I stats
Print various stats collected during AOT compilation.
+.TP
+.I readonly-value=namespace.typename.fieldname=type/value
+Override the value of a static readonly field. Usually, during JIT
+compilation, the static constructor is ran eagerly, so the value of
+a static readonly field is known at compilation time and the compiler
+can do a number of optimizations based on it. During AOT, instead, the static
+constructor can't be ran, so this option can be used to set the value of such
+a field and enable the same set of optimizations.
+Type can be any of i1, i2, i4 for integers of the respective sizes (in bytes).
+Note that signed/unsigned numbers do not matter here, just the storage size.
+This option can be specified multiple times and it doesn't prevent the static
+constructor for the type defining the field to execute with the usual rules
+at runtime (hence possibly computing a different value for the field).
.PP
For more information about AOT, see: http://www.mono-project.com/AOT
diff --git a/mono/mini/aot-compiler.c b/mono/mini/aot-compiler.c
index d7e78d83cc7..f07368eb76c 100644
--- a/mono/mini/aot-compiler.c
+++ b/mono/mini/aot-compiler.c
@@ -92,6 +92,22 @@
#define ALIGN_PTR_TO(ptr,align) (gpointer)((((gssize)(ptr)) + (align - 1)) & (~(align - 1)))
#define ROUND_DOWN(VALUE,SIZE) ((VALUE) & ~((SIZE) - 1))
+/* predefined values for static readonly fields without needed to run the .cctor */
+typedef struct _ReadOnlyValue ReadOnlyValue;
+struct _ReadOnlyValue {
+ ReadOnlyValue *next;
+ char *name;
+ int type; /* to be used later for typechecking to prevent user errors */
+ union {
+ guint8 i1;
+ guint16 i2;
+ guint32 i4;
+ guint64 i8;
+ gpointer ptr;
+ } value;
+};
+static ReadOnlyValue *readonly_values = NULL;
+
typedef struct MonoAotOptions {
char *outfile;
gboolean save_temps;
@@ -4620,6 +4636,83 @@ str_begins_with (const char *str1, const char *str2)
return strncmp (str1, str2, len) == 0;
}
+void*
+mono_aot_readonly_field_override (MonoClassField *field)
+{
+ ReadOnlyValue *rdv;
+ for (rdv = readonly_values; rdv; rdv = rdv->next) {
+ char *p = rdv->name;
+ int len;
+ len = strlen (field->parent->name_space);
+ if (strncmp (p, field->parent->name_space, len))
+ continue;
+ p += len;
+ if (*p++ != '.')
+ continue;
+ len = strlen (field->parent->name);
+ if (strncmp (p, field->parent->name, len))
+ continue;
+ p += len;
+ if (*p++ != '.')
+ continue;
+ if (strcmp (p, field->name))
+ continue;
+ switch (rdv->type) {
+ case MONO_TYPE_I1:
+ return &rdv->value.i1;
+ case MONO_TYPE_I2:
+ return &rdv->value.i2;
+ case MONO_TYPE_I4:
+ return &rdv->value.i4;
+ default:
+ break;
+ }
+ }
+ return NULL;
+}
+
+static void
+add_readonly_value (MonoAotOptions *opts, const char *val)
+{
+ ReadOnlyValue *rdv;
+ const char *fval;
+ const char *tval;
+ /* the format of val is:
+ * namespace.typename.fieldname=type/value
+ * type can be i1 for uint8/int8/boolean, i2 for uint16/int16/char, i4 for uint32/int32
+ */
+ fval = strrchr (val, '/');
+ if (!fval) {
+ fprintf (stderr, "AOT : invalid format for readonly field '%s', missing /.\n", val);
+ exit (1);
+ }
+ tval = strrchr (val, '=');
+ if (!tval) {
+ fprintf (stderr, "AOT : invalid format for readonly field '%s', missing =.\n", val);
+ exit (1);
+ }
+ rdv = g_new0 (ReadOnlyValue, 1);
+ rdv->name = g_malloc0 (tval - val + 1);
+ memcpy (rdv->name, val, tval - val);
+ tval++;
+ fval++;
+ if (strncmp (tval, "i1", 2) == 0) {
+ rdv->value.i1 = atoi (fval);
+ rdv->type = MONO_TYPE_I1;
+ } else if (strncmp (tval, "i2", 2) == 0) {
+ rdv->value.i2 = atoi (fval);
+ rdv->type = MONO_TYPE_I2;
+ } else if (strncmp (tval, "i4", 2) == 0) {
+ rdv->value.i4 = atoi (fval);
+ rdv->type = MONO_TYPE_I4;
+ } else {
+ fprintf (stderr, "AOT : unsupported type for readonly field '%s'.\n", tval);
+ exit (1);
+ }
+ rdv->next = readonly_values;
+ readonly_values = rdv;
+}
+
static void
mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts)
{
@@ -4676,6 +4769,8 @@ mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts)
opts->mtriple = g_strdup (arg + strlen ("mtriple="));
} else if (str_begins_with (arg, "llvm-path=")) {
opts->llvm_path = g_strdup (arg + strlen ("llvm-path="));
+ } else if (str_begins_with (arg, "readonly-value=")) {
+ add_readonly_value (opts, arg + strlen ("readonly-value="));
} else if (str_begins_with (arg, "info")) {
printf ("AOT target setup: %s.\n", AOT_TARGET_STR);
exit (0);
@@ -4698,6 +4793,7 @@ mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts)
printf (" nimt-trampolines=\n");
printf (" autoreg\n");
printf (" tool-prefix=\n");
+ printf (" readonly-value=\n");
printf (" soft-debug\n");
printf (" print-skipped\n");
printf (" stats\n");
@@ -7209,6 +7305,12 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
/* AOT disabled */
+void*
+mono_aot_readonly_field_override (MonoClassField *field)
+{
+ return NULL;
+}
+
int
mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
{
diff --git a/mono/mini/method-to-ir.c b/mono/mini/method-to-ir.c
index ebf6dabbf1a..c92b081ecd7 100644
--- a/mono/mini/method-to-ir.c
+++ b/mono/mini/method-to-ir.c
@@ -8965,15 +8965,17 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
} else {
gboolean is_const = FALSE;
MonoVTable *vtable = NULL;
+ gpointer addr = NULL;
if (!context_used) {
vtable = mono_class_vtable (cfg->domain, klass);
CHECK_TYPELOAD (klass);
}
- if (!context_used && !((cfg->opt & MONO_OPT_SHARED) || cfg->compile_aot) &&
- vtable->initialized && (ftype->attrs & FIELD_ATTRIBUTE_INIT_ONLY)) {
- gpointer addr = (char*)mono_vtable_get_static_field_data (vtable) + field->offset;
+ if ((ftype->attrs & FIELD_ATTRIBUTE_INIT_ONLY) && (((addr = mono_aot_readonly_field_override (field)) != NULL) ||
+ (!context_used && !((cfg->opt & MONO_OPT_SHARED) || cfg->compile_aot) && vtable->initialized))) {
int ro_type = ftype->type;
+ if (!addr)
+ addr = (char*)mono_vtable_get_static_field_data (vtable) + field->offset;
if (ro_type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
ro_type = mono_class_enum_basetype (ftype->data.klass)->type;
}
diff --git a/mono/mini/mini.h b/mono/mini/mini.h
index e3d5e54e1c5..474cb4a0128 100644
--- a/mono/mini/mini.h
+++ b/mono/mini/mini.h
@@ -1836,6 +1836,7 @@ void mono_aot_set_make_unreadable (gboolean unreadable) MONO_INTERNAL;
gboolean mono_aot_is_pagefault (void *ptr) MONO_INTERNAL;
void mono_aot_handle_pagefault (void *ptr) MONO_INTERNAL;
void mono_aot_register_jit_icall (const char *name, gpointer addr) MONO_INTERNAL;
+void* mono_aot_readonly_field_override (MonoClassField *field) MONO_INTERNAL;
/* This is an exported function */
void mono_aot_register_globals (gpointer *globals);