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)
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;
191 mono_raise_exception (mono_get_exception_overflow ());
196 mono_lldiv (gint64 a, gint64 b)
204 mono_llrem (gint64 a, gint64 b)
212 mono_lldiv_un (guint64 a, guint64 b)
220 mono_llrem_un (guint64 a, guint64 b)
228 mono_lshl (guint64 a, gint32 shamt)
235 /*printf ("TESTL %lld << %d = %lld\n", a, shamt, res);*/
241 mono_lshr_un (guint64 a, gint32 shamt)
248 /*printf ("TESTR %lld >> %d = %lld\n", a, shamt, res);*/
254 mono_lshr (gint64 a, gint32 shamt)
261 /*printf ("TESTR %lld >> %d = %lld\n", a, shamt, res);*/
267 * ves_array_element_address:
268 * @this: a pointer to the array object
270 * Returns: the address of an array element.
273 ves_array_element_address (MonoArray *this, ...)
277 int i, ind, esize, realidx;
282 g_assert (this != NULL);
286 class = this->obj.vtable->klass;
288 g_assert (this->bounds != NULL);
290 esize = mono_array_element_size (class);
291 ind = va_arg(ap, int);
292 ind -= (int)this->bounds [0].lower_bound;
293 if ((guint32)ind >= (guint32)this->bounds [0].length)
294 mono_raise_exception (mono_get_exception_index_out_of_range ());
295 for (i = 1; i < class->rank; i++) {
296 realidx = va_arg(ap, int) - (int)this->bounds [i].lower_bound;
297 if ((guint32)realidx >= (guint32)this->bounds [i].length)
298 mono_raise_exception (mono_get_exception_index_out_of_range ());
299 ind *= this->bounds [i].length;
304 ea = (gpointer*)((char*)this->vector + esize);
312 mono_array_new_va (MonoMethod *cm, ...)
314 MonoDomain *domain = mono_domain_get ();
317 guint32 *lower_bounds;
324 pcount = cm->signature->param_count;
325 rank = cm->klass->rank;
329 lengths = alloca (sizeof (guint32) * pcount);
330 for (i = 0; i < pcount; ++i)
331 lengths [i] = d = va_arg(ap, int);
333 if (rank == pcount) {
334 /* Only lengths provided. */
337 g_assert (pcount == (rank * 2));
338 /* lower bounds are first. */
339 lower_bounds = lengths;
344 return mono_array_new_full (domain, cm->klass, lengths, lower_bounds);
348 mono_class_static_field_address (MonoDomain *domain, MonoClassField *field)
355 //printf ("SFLDA0 %s.%s::%s %d\n", field->parent->name_space, field->parent->name, field->name, field->offset, field->parent->inited);
357 mono_class_init (field->parent);
359 vtable = mono_class_vtable (domain, field->parent);
361 //printf ("SFLDA1 %p\n", (char*)vtable->data + field->offset);
363 if (!domain->thread_static_fields || !(addr = g_hash_table_lookup (domain->thread_static_fields, field)))
364 addr = (char*)vtable->data + field->offset;
366 addr = mono_threads_get_static_data (GPOINTER_TO_UINT (addr));
372 mono_ldtoken_wrapper (MonoImage *image, int token)
374 MonoClass *handle_class;
378 res = mono_ldtoken (image, token, &handle_class);
379 mono_class_init (handle_class);
385 mono_fconv_u8 (double v)
392 mono_fconv_u4 (double v)
399 mono_fconv_ovf_i8 (double v)
407 if (isnan(v) || v != res) {
408 mono_raise_exception (mono_get_exception_overflow ());
414 mono_fconv_ovf_u8 (double v)
422 if (isnan(v) || v != res) {
423 mono_raise_exception (mono_get_exception_overflow ());