Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Mon Sep 24 18:49:01 CEST 2001 Paolo Molaro <lupus@ximian.com>

	* x86/tramp.c: don't change a MONO_TYPE_STRING to a char*
	when it's an argument to an internalcall.


Mon Sep 24 18:56:59 CEST 2001 Paolo Molaro <lupus@ximian.com>

	* object.c, object.h: added mono_ldstr (), mono_string_is_interned () and
	mono_string_intern () to implement the semantics of the ldstr opcode
	and the interning of System.Strings.
	* icall.c: provide hooks to make String::IsIntern and String::Intern
	internalcalls.


Mon Sep 24 18:50:25 CEST 2001 Paolo Molaro <lupus@ximian.com>

	* interp.c: catch a few more error conditions with exceptions instead of
	erroring out.
	Don't use g_print() in stack traces because it doesn't work with
	some float values.
	When we call an instance method of a valuetype class, unbox the 'this'
	argument if it is an object.
	Use mono_ldstr () to implement the ldstr opcode: it takes care of
	interning the string if necessary.
	Implemented new opcodes: ckfinite, cgt.un, clt.un, ldvirtftn, ldarga.
	Fixes to handle NaNs when comparing doubles.
	Make sure the loaded assembly has an entry point defined.
	Fixed portability bugs in neg and not opcodes.

svn path=/trunk/mono/; revision=943
  • Loading branch information...
commit 78550fa962237d4fbb8a84ce2540d7d995bb15c0 1 parent f8fddf0
@illupus illupus authored
View
5 mono/arch/ChangeLog
@@ -1,4 +1,9 @@
+Mon Sep 24 18:49:01 CEST 2001 Paolo Molaro <lupus@ximian.com>
+
+ * x86/tramp.c: don't change a MONO_TYPE_STRING to a char*
+ when it's an argument to an internalcall.
+
Sun Sep 23 13:44:57 CEST 2001 Paolo Molaro <lupus@ximian.com>
* x86/tramp.c: handle MONO_TYPE_CLASS in trampolines.
View
25 mono/arch/x86/tramp.c
@@ -10,6 +10,7 @@
#include "config.h"
#include "x86-codegen.h"
#include "mono/metadata/class.h"
+#include "mono/metadata/tabledefs.h"
#include "mono/interpreter/interp.h"
/*
@@ -149,10 +150,12 @@ mono_create_trampoline (MonoMethod *method)
continue;
}
switch (sig->params [i - 1]->type) {
+ case MONO_TYPE_BOOLEAN:
case MONO_TYPE_I1:
case MONO_TYPE_U1:
case MONO_TYPE_I2:
case MONO_TYPE_U2:
+ case MONO_TYPE_CHAR:
case MONO_TYPE_I4:
case MONO_TYPE_U4:
case MONO_TYPE_I:
@@ -170,6 +173,14 @@ mono_create_trampoline (MonoMethod *method)
x86_fst_membase (p, X86_ESP, 0, TRUE, TRUE);
break;
case MONO_TYPE_STRING:
+ /*
+ * If it is an internalcall we assume it's the object we want.
+ * Yet another reason why MONO_TYPE_STRING should not be used to indicate char*.
+ */
+ if (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
+ x86_push_membase (p, X86_EDX, arg_pos);
+ break;
+ }
/*if (frame->method->flags & PINVOKE_ATTRIBUTE_CHAR_SET_ANSI*/
x86_push_membase (p, X86_EDX, arg_pos);
x86_mov_reg_imm (p, X86_EDX, mono_get_ansi_string);
@@ -190,8 +201,6 @@ mono_create_trampoline (MonoMethod *method)
x86_push_membase (p, X86_EDX, arg_pos + 4);
x86_push_membase (p, X86_EDX, arg_pos);
break;
- case MONO_TYPE_BOOLEAN:
- case MONO_TYPE_CHAR:
default:
g_error ("Can't trampoline 0x%x", sig->params [i - 1]->type);
}
@@ -256,11 +265,13 @@ mono_create_trampoline (MonoMethod *method)
/*
* free the allocated strings.
*/
- if (local_size)
- x86_mov_reg_imm (p, X86_EDX, g_free);
- for (i = 1; i <= local_size; ++i) {
- x86_push_membase (p, X86_EBP, LOC_POS * i);
- x86_call_reg (p, X86_EDX);
+ if (!(method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL)) {
+ if (local_size)
+ x86_mov_reg_imm (p, X86_EDX, g_free);
+ for (i = 1; i <= local_size; ++i) {
+ x86_push_membase (p, X86_EBP, LOC_POS * i);
+ x86_call_reg (p, X86_EDX);
+ }
}
/*
* Standard epilog.
View
16 mono/interpreter/ChangeLog
@@ -1,3 +1,19 @@
+
+Mon Sep 24 18:50:25 CEST 2001 Paolo Molaro <lupus@ximian.com>
+
+ * interp.c: catch a few more error conditions with exceptions instead of
+ erroring out.
+ Don't use g_print() in stack traces because it doesn't work with
+ some float values.
+ When we call an instance method of a valuetype class, unbox the 'this'
+ argument if it is an object.
+ Use mono_ldstr () to implement the ldstr opcode: it takes care of
+ interning the string if necessary.
+ Implemented new opcodes: ckfinite, cgt.un, clt.un, ldvirtftn, ldarga.
+ Fixes to handle NaNs when comparing doubles.
+ Make sure the loaded assembly has an entry point defined.
+ Fixed portability bugs in neg and not opcodes.
+
2001-09-24 Dietmar Maurer <dietmar@ximian.com>
* interp.c (ves_exec_method): LDC_I4: 8bit constants are signed
View
220 mono/interpreter/interp.c
@@ -206,48 +206,28 @@ newobj (MonoImage *image, guint32 token)
#undef DEBUG_VM_DISPATCH
static MonoMethod*
-get_virtual_method (MonoImage *image, guint32 token, stackval *args)
+get_virtual_method (MonoImage *image, MonoMethod *m, stackval *objs)
{
- MonoMethod *m;
MonoObject *obj;
MonoClass *klass;
- stackval *objs;
int i;
- switch (mono_metadata_token_table (token)) {
- case MONO_TABLE_METHOD:
- case MONO_TABLE_MEMBERREF:
- m = mono_get_method (image, token, NULL);
- objs = &args [-(m->signature->param_count + 1)];
- obj = objs->data.p;
- klass = objs->data.vt.klass ? objs->data.vt.klass: obj->klass;
-#ifdef DEBUG_VM_DISPATCH
- g_print ("%s%smethod lookup %s.%s::%s (cast class %s; real class %s)\n",
- m->flags & METHOD_ATTRIBUTE_VIRTUAL ? "virtual ": "",
- m->flags & METHOD_ATTRIBUTE_FINAL ? "final ": "",
- m->klass->name_space, m->klass->name, m->name, klass->name, obj->klass->name);
-#endif
- if ((m->flags & METHOD_ATTRIBUTE_FINAL) || !(m->flags & METHOD_ATTRIBUTE_VIRTUAL))
+ if ((m->flags & METHOD_ATTRIBUTE_FINAL) || !(m->flags & METHOD_ATTRIBUTE_VIRTUAL))
return m;
- if (!(m->klass->flags & TYPE_ATTRIBUTE_INTERFACE))
- klass = obj->klass;
- for (; klass && klass != m->klass; klass = klass->parent) {
- for (i = 0; i < klass->method.count; ++i) {
- if (!klass->methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
- continue;
- if (!strcmp(m->name, klass->methods [i]->name) && mono_metadata_signature_equal (m->signature, klass->methods [i]->signature)) {
-#ifdef DEBUG_VM_DISPATCH
- g_print ("\tfound %s%s.%s::%s\n", klass->methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL ? "virtual ": "",
- klass->name_space, klass->name, klass->methods [i]->name);
-#endif
- return klass->methods [i];
- }
+ obj = objs->data.p;
+ klass = objs->data.vt.klass ? objs->data.vt.klass: obj->klass;
+ if (!(m->klass->flags & TYPE_ATTRIBUTE_INTERFACE))
+ klass = obj->klass;
+ for (; klass && klass != m->klass; klass = klass->parent) {
+ for (i = 0; i < klass->method.count; ++i) {
+ if (!klass->methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
+ continue;
+ if (!strcmp(m->name, klass->methods [i]->name) && mono_metadata_signature_equal (m->signature, klass->methods [i]->signature)) {
+ return klass->methods [i];
}
}
- return m;
}
- g_error ("got virtual method: 0x%x\n", token);
- return NULL;
+ return m;
}
static MonoObject*
@@ -371,6 +351,16 @@ get_exception_array_type_mismatch ()
return ex;
}
+static MonoObject*
+get_exception_missing_method ()
+{
+ static MonoObject *ex = NULL;
+ if (ex)
+ return ex;
+ ex = get_named_exception ("MissingMethodException");
+ return ex;
+}
+
void inline
stackval_from_data (MonoType *type, stackval *result, const char *data)
{
@@ -652,11 +642,11 @@ dump_stack (stackval *stack, stackval *sp)
while (s < sp) {
switch (s->type) {
- case VAL_I32: g_print ("[%d] ", s->data.i); break;
- case VAL_I64: g_print ("[%lld] ", s->data.l); break;
- case VAL_DOUBLE: g_print ("[%0.5f] ", s->data.f); break;
- case VAL_VALUET: g_print ("[vt: %p] ", s->data.vt.vt); break;
- default: g_print ("[%p] ", s->data.p); break;
+ case VAL_I32: printf ("[%d] ", s->data.i); break;
+ case VAL_I64: printf ("[%lld] ", s->data.l); break;
+ case VAL_DOUBLE: printf ("[%0.5f] ", s->data.f); break;
+ case VAL_VALUET: printf ("[vt: %p] ", s->data.vt.vt); break;
+ default: printf ("[%p] ", s->data.p); break;
}
++s;
}
@@ -1129,13 +1119,19 @@ ves_exec_method (MonoInvocation *frame)
/* check the signature we put in mono_create_method_pointer () */
g_assert (code [2] == 'M' && code [3] == 'o');
child_frame.method = *(gpointer*)(code + sizeof (gpointer));
+ csignature = child_frame.method->signature;
} else {
- if (virtual)
- child_frame.method = get_virtual_method (image, token, sp);
- else
- child_frame.method = mono_get_method (image, token, NULL);
+ child_frame.method = mono_get_method (image, token, NULL);
+ if (!child_frame.method)
+ THROW_EX (get_exception_missing_method (), ip -5);
+ csignature = child_frame.method->signature;
+ if (virtual) {
+ stackval *this_arg = &sp [-csignature->param_count-1];
+ if (!this_arg->data.p)
+ THROW_EX (get_exception_null_reference(), ip - 5);
+ child_frame.method = get_virtual_method (image, child_frame.method, this_arg);
+ }
}
- csignature = child_frame.method->signature;
g_assert (csignature->call_convention == MONO_CALL_DEFAULT);
/* decrement by the actual number of args */
if (csignature->param_count) {
@@ -1148,7 +1144,10 @@ ves_exec_method (MonoInvocation *frame)
g_assert (sp >= frame->stack);
--sp;
g_assert (sp->type == VAL_OBJ || sp->type == VAL_VALUETA);
- child_frame.obj = sp->data.p;
+ if (sp->type == VAL_OBJ && child_frame.method->klass->valuetype) /* unbox it */
+ child_frame.obj = (char*)sp->data.p + sizeof (MonoObject);
+ else
+ child_frame.obj = sp->data.p;
} else {
child_frame.obj = NULL;
}
@@ -1685,7 +1684,7 @@ ves_exec_method (MonoInvocation *frame)
sp [-1].data.l %= sp [0].data.l;
} else if (sp->type == VAL_DOUBLE) {
/* FIXME: what do we actually do here? */
- sp [-1].data.f = 0;
+ sp [-1].data.f = fmod (sp [-1].data.f, sp [0].data.f);
} else {
if (GET_NATI (sp [0]) == 0)
THROW_EX (get_exception_divide_by_zero (), ip - 1);
@@ -1773,7 +1772,7 @@ ves_exec_method (MonoInvocation *frame)
BREAK;
CASE (CEE_NEG)
++ip;
- --sp;
+ --sp;
if (sp->type == VAL_I32)
sp->data.i = - sp->data.i;
else if (sp->type == VAL_I64)
@@ -1781,19 +1780,19 @@ ves_exec_method (MonoInvocation *frame)
else if (sp->type == VAL_DOUBLE)
sp->data.f = - sp->data.f;
else if (sp->type == VAL_NATI)
- sp->data.p = (gpointer)(- (int)sp->data.p);
+ sp->data.p = (gpointer)(- (mono_i)sp->data.p);
++sp;
BREAK;
CASE (CEE_NOT)
++ip;
- --sp;
+ --sp;
if (sp->type == VAL_I32)
sp->data.i = ~ sp->data.i;
else if (sp->type == VAL_I64)
sp->data.l = ~ sp->data.l;
else if (sp->type == VAL_NATI)
- sp->data.p = (gpointer)(~ (int)sp->data.p);
- ++sp;
+ sp->data.p = (gpointer)(~ (mono_i)sp->data.p);
+ ++sp;
BREAK;
CASE (CEE_CONV_U1) /* fall through */
CASE (CEE_CONV_I1) {
@@ -1960,18 +1959,13 @@ ves_exec_method (MonoInvocation *frame)
}
CASE (CEE_LDSTR) {
MonoObject *o;
- const char *name;
- int len;
guint32 index;
ip++;
index = mono_metadata_token_index (read32 (ip));
ip += 4;
- name = mono_metadata_user_string (image, index);
- len = mono_metadata_decode_blob_size (name, &name);
-
- o = mono_new_utf16_string (name, len >> 1);
+ o = mono_ldstr (image, index);
sp->type = VAL_OBJ;
sp->data.p = o;
sp->data.vt.klass = NULL;
@@ -1994,6 +1988,8 @@ ves_exec_method (MonoInvocation *frame)
/* call the contructor */
child_frame.method = mono_get_method (image, token, o->klass);
+ if (!child_frame.method)
+ THROW_EX (get_exception_missing_method (), ip -5);
csig = child_frame.method->signature;
/*
@@ -2640,7 +2636,11 @@ ves_exec_method (MonoInvocation *frame)
CASE (CEE_UNUSED22)
CASE (CEE_UNUSED23) ves_abort(); BREAK;
CASE (CEE_REFANYVAL) ves_abort(); BREAK;
- CASE (CEE_CKFINITE) ves_abort(); BREAK;
+ CASE (CEE_CKFINITE)
+ if (!finite(sp [-1].data.f))
+ THROW_EX (get_exception_arithmetic (), ip);
+ ++ip;
+ BREAK;
CASE (CEE_UNUSED24) ves_abort(); BREAK;
CASE (CEE_UNUSED25) ves_abort(); BREAK;
CASE (CEE_MKREFANY) ves_abort(); BREAK;
@@ -2654,7 +2654,6 @@ ves_exec_method (MonoInvocation *frame)
CASE (CEE_UNUSED66)
CASE (CEE_UNUSED67) ves_abort(); BREAK;
CASE (CEE_LDTOKEN)
- /*CASE (CEE_CONV_I) ves_abort(); BREAK; */
CASE (CEE_CONV_OVF_I) ves_abort(); BREAK;
CASE (CEE_CONV_OVF_U) ves_abort(); BREAK;
CASE (CEE_ADD_OVF) ves_abort(); BREAK;
@@ -2746,9 +2745,12 @@ ves_exec_method (MonoInvocation *frame)
result = sp [0].data.i == (gint)GET_NATI (sp [1]);
else if (sp->type == VAL_I64)
result = sp [0].data.l == sp [1].data.l;
- else if (sp->type == VAL_DOUBLE)
- result = sp [0].data.f == sp [1].data.f;
- else
+ else if (sp->type == VAL_DOUBLE) {
+ if (isnan (sp [0].data.f) || isnan (sp [1].data.f))
+ result = 0;
+ else
+ result = sp [0].data.f == sp [1].data.f;
+ } else
result = GET_NATI (sp [0]) == GET_NATI (sp [1]);
sp->type = VAL_I32;
sp->data.i = result;
@@ -2765,17 +2767,38 @@ ves_exec_method (MonoInvocation *frame)
result = sp [0].data.i > (gint)GET_NATI (sp [1]);
else if (sp->type == VAL_I64)
result = sp [0].data.l > sp [1].data.l;
+ else if (sp->type == VAL_DOUBLE) {
+ if (isnan (sp [0].data.f) || isnan (sp [1].data.f))
+ result = 0;
+ else
+ result = sp [0].data.f > sp [1].data.f;
+ } else
+ result = (gint)GET_NATI (sp [0]) > (gint)GET_NATI (sp [1]);
+ sp->type = VAL_I32;
+ sp->data.i = result;
+
+ sp++;
+ break;
+ }
+ case CEE_CGT_UN: {
+ gint32 result;
+ ++ip;
+ sp -= 2;
+
+ if (sp->type == VAL_I32)
+ result = (guint32)sp [0].data.i > (mono_u)GET_NATI (sp [1]);
+ else if (sp->type == VAL_I64)
+ result = (guint64)sp [0].data.l > (guint64)sp [1].data.l;
else if (sp->type == VAL_DOUBLE)
- result = sp [0].data.f > sp [1].data.f;
+ result = isnan (sp [0].data.f) || isnan (sp [1].data.f);
else
- result = (gint)GET_NATI (sp [0]) > (gint)GET_NATI (sp [1]);
+ result = (mono_u)GET_NATI (sp [0]) > (mono_u)GET_NATI (sp [1]);
sp->type = VAL_I32;
sp->data.i = result;
sp++;
break;
}
- case CEE_CGT_UN: ves_abort(); break;
case CEE_CLT: {
gint32 result;
++ip;
@@ -2785,29 +2808,61 @@ ves_exec_method (MonoInvocation *frame)
result = sp [0].data.i < (gint)GET_NATI (sp [1]);
else if (sp->type == VAL_I64)
result = sp [0].data.l < sp [1].data.l;
+ else if (sp->type == VAL_DOUBLE) {
+ if (isnan (sp [0].data.f) || isnan (sp [1].data.f))
+ result = 0;
+ else
+ result = sp [0].data.f < sp [1].data.f;
+ } else
+ result = (gint)GET_NATI (sp [0]) < (gint)GET_NATI (sp [1]);
+ sp->type = VAL_I32;
+ sp->data.i = result;
+
+ sp++;
+ break;
+ }
+ case CEE_CLT_UN: {
+ gint32 result;
+ ++ip;
+ sp -= 2;
+
+ if (sp->type == VAL_I32)
+ result = (guint32)sp [0].data.i < (mono_u)GET_NATI (sp [1]);
+ else if (sp->type == VAL_I64)
+ result = (guint64)sp [0].data.l < (guint64)sp [1].data.l;
else if (sp->type == VAL_DOUBLE)
- result = sp [0].data.f < sp [1].data.f;
+ result = isnan (sp [0].data.f) || isnan (sp [1].data.f);
else
- result = (gint)GET_NATI (sp [0]) < (gint)GET_NATI (sp [1]);
+ result = (mono_u)GET_NATI (sp [0]) < (mono_u)GET_NATI (sp [1]);
sp->type = VAL_I32;
sp->data.i = result;
sp++;
break;
}
- case CEE_CLT_UN: ves_abort(); break;
- case CEE_LDFTN: {
+ case CEE_LDFTN:
+ case CEE_LDVIRTFTN: {
+ int virtual = *ip == CEE_LDVIRTFTN;
+ MonoMethod *m;
guint32 token;
++ip;
token = read32 (ip);
ip += 4;
+ m = mono_get_method (image, token, NULL);
+ if (!m)
+ THROW_EX (get_exception_missing_method (), ip - 5);
+ if (virtual) {
+ stackval *objs = &sp [-m->signature->param_count - 1];
+ if (!objs->data.p)
+ THROW_EX (get_exception_null_reference (), ip - 5);
+ m = get_virtual_method (image, m, objs);
+ }
sp->type = VAL_NATI;
- sp->data.p = mono_create_method_pointer (mono_get_method (image, token, NULL));
+ sp->data.p = mono_create_method_pointer (m);
sp->data.vt.klass = NULL;
++sp;
break;
}
- case CEE_LDVIRTFTN: ves_abort(); break;
case CEE_UNUSED56: ves_abort(); break;
case CEE_LDARG: {
guint32 arg_pos;
@@ -2819,7 +2874,28 @@ ves_exec_method (MonoInvocation *frame)
++sp;
break;
}
- case CEE_LDARGA: ves_abort(); break;
+ case CEE_LDARGA: {
+ MonoType *t;
+ MonoClass *c;
+ guint32 anum;
+
+ ++ip;
+ anum = read32 (ip);
+ ip += 4;
+ t = ARG_TYPE (signature, anum);
+ c = mono_class_from_mono_type (t);
+ sp->data.vt.klass = c;
+ sp->data.vt.vt = ARG_POS (anum);
+
+ if (c->valuetype)
+ sp->type = VAL_VALUETA;
+ else
+ sp->type = VAL_TP;
+
+ ++sp;
+ ++ip;
+ break;
+ }
case CEE_STARG: {
guint32 arg_pos;
++ip;
@@ -3086,6 +3162,8 @@ ves_exec (MonoAssembly *assembly, int argc, char *argv[])
iinfo = image->image_info;
method = mono_get_method (image, iinfo->cli_cli_header.ch_entry_point, NULL);
+ if (!method)
+ g_error ("No entry point method found in %s", image->name);
if (method->signature->param_count) {
int i;
View
9 mono/metadata/ChangeLog
@@ -1,3 +1,12 @@
+
+Mon Sep 24 18:56:59 CEST 2001 Paolo Molaro <lupus@ximian.com>
+
+ * object.c, object.h: added mono_ldstr (), mono_string_is_interned () and
+ mono_string_intern () to implement the semantics of the ldstr opcode
+ and the interning of System.Strings.
+ * icall.c: provide hooks to make String::IsIntern and String::Intern
+ internalcalls.
+
2001-09-23 Dick Porter <dick@ximian.com>
* threads-dummy.c:
View
6 mono/metadata/icall.c
@@ -201,6 +201,12 @@ static gpointer icall_map [] = {
"System.Object::MemberwiseClone", ves_icall_System_Object_MemberwiseClone,
/*
+ * System.String
+ */
+ "System.String::IsInterned", mono_string_is_interned,
+ "System.String::Intern", mono_string_intern,
+
+ /*
* System.Threading
*/
"System.Threading.Thread::Start_internal", ves_icall_System_Threading_Thread_Start_internal,
View
110 mono/metadata/object.c
@@ -238,3 +238,113 @@ mono_object_isinst (MonoObject *obj, MonoClass *klass)
return FALSE;
}
+static GHashTable *ldstr_table = NULL;
+
+static int
+ldstr_hash (const char* str)
+{
+ guint len, h;
+ const char *end;
+ len = mono_metadata_decode_blob_size (str, &str);
+ end = str + len;
+ h = *str;
+ /*
+ * FIXME: The distribution may not be so nice with lots of
+ * null chars in the string.
+ */
+ for (str += 1; str < end; str++)
+ h = (h << 5) - h + *str;
+ return h;
+}
+
+static gboolean
+ldstr_equal (const char *str1, const char *str2) {
+ int len;
+ if ((len=mono_metadata_decode_blob_size (str1, &str1)) !=
+ mono_metadata_decode_blob_size (str2, &str2))
+ return 0;
+ return memcmp (str1, str2, len) == 0;
+}
+
+typedef struct {
+ MonoObject *obj;
+ MonoObject *found;
+} InternCheck;
+
+static void
+check_interned (gpointer key, MonoObject *value, InternCheck *check)
+{
+ if (value == check->obj)
+ check->found = value;
+}
+
+MonoObject*
+mono_string_is_interned (MonoObject *o)
+{
+ InternCheck check;
+ check.obj = o;
+ check.found = NULL;
+ /*
+ * Yes, this is slow. Our System.String implementation needs to be redone.
+ * And GLib needs foreach() methods that can be stopped halfway.
+ */
+ g_hash_table_foreach (ldstr_table, (GHFunc)check_interned, &check);
+ return check.found;
+}
+
+MonoObject*
+mono_string_intern (MonoObject *o)
+{
+ MonoObject *res;
+ MonoStringObject *str = (MonoStringObject*) o;
+ char *ins = g_malloc (4 + str->length * 2);
+ char *p;
+
+ /* Encode the length */
+ p = ins;
+ if (str->length <= 127)
+ *p++ = 127;
+ else if (str->length <= 16384) {
+ p [0] = 0x80 | (str->length >> 8);
+ p [1] = str->length & 0xff;
+ p += 2;
+ } else {
+ guint32 l = str->length;
+ p [0] = (l >> 24) | 0xc0;
+ p [1] = (l >> 16) & 0xff;
+ p [2] = (l >> 8) & 0xff;
+ p [3] = l & 0xff;
+ p += 4;
+ }
+ memcpy (p, str->c_str->vector, str->length * 2);
+
+ if ((res = g_hash_table_lookup (ldstr_table, str))) {
+ g_free (ins);
+ return res;
+ }
+ g_hash_table_insert (ldstr_table, ins, str);
+ return (MonoObject*)str;
+}
+
+MonoObject*
+mono_ldstr (MonoImage *image, guint32 index)
+{
+ const char *str, *sig;
+ MonoObject *o;
+ guint len;
+
+ if (!ldstr_table)
+ ldstr_table = g_hash_table_new ((GHashFunc)ldstr_hash, (GCompareFunc)ldstr_equal);
+
+ sig = str = mono_metadata_user_string (image, index);
+
+ if ((o = g_hash_table_lookup (ldstr_table, str)))
+ return o;
+
+ len = mono_metadata_decode_blob_size (str, &str);
+ o = mono_new_utf16_string (str, len >> 1);
+ g_hash_table_insert (ldstr_table, sig, o);
+
+ return o;
+}
+
View
9 mono/metadata/object.h
@@ -36,6 +36,15 @@ mono_new_szarray (MonoClass *eclass, guint32 n);
MonoObject *
mono_new_utf16_string (const char *text, gint32 len);
+MonoObject*
+mono_ldstr (MonoImage *image, guint32 index);
+
+MonoObject*
+mono_string_is_interned (MonoObject *o);
+
+MonoObject*
+mono_string_intern (MonoObject *o);
+
MonoObject *
mono_new_string (const char *text);
View
1  mono/tests/Makefile.am
@@ -26,6 +26,7 @@ TESTSRC= \
interface.cs \
virtual-method.cs \
intptrcast.cs \
+ indexer.cs \
stream.cs \
stream-writer.cs \
console.cs \
View
32 mono/tests/indexer.cs
@@ -0,0 +1,32 @@
+namespace Test {
+public class Patient {
+ int id;
+ double age;
+ bool dead;
+ public object this[string name] {
+ get {
+ switch (name) {
+ case "id": return id;
+ case "age": return age;
+ case "dead": return dead;
+ default: return null;
+ }
+ }
+ set {
+ switch (name) {
+ case "id": id = (int)value; break;
+ case "age": age = (double)value; break;
+ case "dead": dead = (bool)value; break;
+ }
+ }
+ }
+ public static int Main() {
+ Patient bob = new Patient();
+ bob["age"] = 32.0;
+ if ((bool)bob["dead"])
+ return 1;
+ return 0;
+ }
+}
+}
+
Please sign in to comment.
Something went wrong with that request. Please try again.