2 * jit-icalls.c: internal calls used by the JIT
5 * Dietmar Maurer (dietmar@ximian.com)
6 * Paolo Molaro (lupus@ximian.com)
8 * (C) 2002 Ximian, Inc.
14 mono_ldftn (MonoMethod *method)
20 EnterCriticalSection (metadata_section);
21 addr = mono_compile_method (method);
22 LeaveCriticalSection (metadata_section);
28 mono_ldvirtfn (MonoObject *obj, MonoMethod *method)
32 method = mono_object_get_virtual_method (obj, method);
33 if (method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)
34 method = mono_marshal_get_synchronized_wrapper (method);
36 return mono_ldftn (method);
40 helper_initobj (void *addr, int size)
44 memset (addr, 0, size);
48 helper_memcpy (void *addr, void *src, int size)
52 memcpy (addr, src, size);
56 helper_memset (void *addr, int val, int size)
60 memset (addr, val, size);
64 helper_stelem_ref (MonoArray *array, int index, MonoObject *val)
68 if (index >= array->max_length)
69 mono_raise_exception (mono_get_exception_index_out_of_range ());
71 if (val && !mono_object_isinst (val, array->obj.vtable->klass->element_class))
72 mono_raise_exception (mono_get_exception_array_type_mismatch ());
74 mono_array_set (array, gpointer, index, val);
78 mono_llmult (gint64 a, gint64 b)
80 /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
85 mono_llmult_ovf_un (guint32 al, guint32 ah, guint32 bl, guint32 bh)
91 // fixme: this is incredible slow
96 res = (guint64)al * (guint64)bl;
98 t1 = (guint64)ah * (guint64)bl + (guint64)al * (guint64)bh;
101 goto raise_exception;
103 res += ((guint64)t1) << 32;
108 mono_raise_exception (mono_get_exception_overflow ());
114 mono_llmult_ovf (guint32 al, gint32 ah, guint32 bl, gint32 bh)
117 Use Karatsuba algorithm where:
118 a*b is: AhBh(R^2+R)+(Ah-Al)(Bl-Bh)R+AlBl(R+1)
119 where Ah is the "high half" (most significant 32 bits) of a and
120 where Al is the "low half" (least significant 32 bits) of a and
121 where Bh is the "high half" of b and Bl is the "low half" and
122 where R is the Radix or "size of the half" (in our case 32 bits)
124 Note, for the product of two 64 bit numbers to fit into a 64
125 result, ah and/or bh must be 0. This will save us from doing
126 the AhBh term at all.
128 Also note that we refactor so that we don't overflow 64 bits with
129 intermediate results. So we use [(Ah-Al)(Bl-Bh)+AlBl]R+AlBl
137 /* need to work with absoulte values, so find out what the
138 resulting sign will be and convert any negative numbers
139 from two's complement
143 /* flip the bits and add 1 */
154 /* flip the bits and add 1 */
164 /* we overflow for sure if both upper halves are greater
165 than zero because we would need to shift their
166 product 64 bits to the left and that will not fit
167 in a 64 bit result */
169 goto raise_exception;
171 /* do the AlBl term first */
172 t1 = (gint64)al * (gint64)bl;
176 /* now do the [(Ah-Al)(Bl-Bh)+AlBl]R term */
177 t1 += (gint64)(ah - al) * (gint64)(bl - bh);
179 /* check for overflow */
180 if (t1 > (0x7FFFFFFFFFFFFFFF - res))
181 goto raise_exception;
186 goto raise_exception;
194 mono_raise_exception (mono_get_exception_overflow ());
199 mono_lldiv (gint64 a, gint64 b)
207 mono_llrem (gint64 a, gint64 b)
215 mono_lldiv_un (guint64 a, guint64 b)
223 mono_llrem_un (guint64 a, guint64 b)
231 mono_lshl (guint64 a, gint32 shamt)
235 /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
238 /*printf ("TESTL %lld << %d = %lld\n", a, shamt, res);*/
244 mono_lshr_un (guint64 a, gint32 shamt)
248 /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
251 /*printf ("TESTR %lld >> %d = %lld\n", a, shamt, res);*/
257 mono_lshr (gint64 a, gint32 shamt)
261 /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
264 /*printf ("TESTR %lld >> %d = %lld\n", a, shamt, res);*/
270 * ves_array_element_address:
271 * @this: a pointer to the array object
273 * Returns: the address of an array element.
276 ves_array_element_address (MonoArray *this, ...)
280 int i, ind, esize, realidx;
285 g_assert (this != NULL);
289 class = this->obj.vtable->klass;
291 g_assert (this->bounds != NULL);
293 esize = mono_array_element_size (class);
294 ind = va_arg(ap, int);
295 ind -= (int)this->bounds [0].lower_bound;
296 if ((guint32)ind >= (guint32)this->bounds [0].length)
297 mono_raise_exception (mono_get_exception_index_out_of_range ());
298 for (i = 1; i < class->rank; i++) {
299 realidx = va_arg(ap, int) - (int)this->bounds [i].lower_bound;
300 if ((guint32)realidx >= (guint32)this->bounds [i].length)
301 mono_raise_exception (mono_get_exception_index_out_of_range ());
302 ind *= this->bounds [i].length;
307 ea = (gpointer*)((char*)this->vector + esize);
315 mono_array_new_va (MonoMethod *cm, ...)
317 MonoDomain *domain = mono_domain_get ();
320 guint32 *lower_bounds;
327 pcount = cm->signature->param_count;
328 rank = cm->klass->rank;
332 lengths = alloca (sizeof (guint32) * pcount);
333 for (i = 0; i < pcount; ++i)
334 lengths [i] = d = va_arg(ap, int);
336 if (rank == pcount) {
337 /* Only lengths provided. */
340 g_assert (pcount == (rank * 2));
341 /* lower bounds are first. */
342 lower_bounds = lengths;
347 return mono_array_new_full (domain, cm->klass, lengths, lower_bounds);
351 mono_class_static_field_address (MonoDomain *domain, MonoClassField *field)
358 //printf ("SFLDA0 %s.%s::%s %d\n", field->parent->name_space, field->parent->name, field->name, field->offset, field->parent->inited);
360 mono_class_init (field->parent);
362 vtable = mono_class_vtable (domain, field->parent);
363 if (!vtable->initialized)
364 mono_runtime_class_init (vtable);
366 //printf ("SFLDA1 %p\n", (char*)vtable->data + field->offset);
368 if (!domain->thread_static_fields || !(addr = g_hash_table_lookup (domain->thread_static_fields, field)))
369 addr = (char*)vtable->data + field->offset;
371 addr = mono_threads_get_static_data (GPOINTER_TO_UINT (addr));
377 mono_ldtoken_wrapper (MonoImage *image, int token)
379 MonoClass *handle_class;
383 res = mono_ldtoken (image, token, &handle_class);
384 mono_class_init (handle_class);
390 mono_fconv_u8 (double v)
392 /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
397 mono_fconv_u4 (double v)
399 /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
404 mono_fconv_ovf_i8 (double v)
412 if (isnan(v) || v != res) {
413 mono_raise_exception (mono_get_exception_overflow ());
419 mono_fconv_ovf_u8 (double v)
427 if (isnan(v) || v != res) {
428 mono_raise_exception (mono_get_exception_overflow ());