1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2 * This source file is part of SableVM. *
3 * *
4 * See the file "LICENSE" for the copyright information and for *
5 * the terms and conditions for copying, distribution and *
6 * modification of this source file. *
7 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
8
9 #include "gc_gencopy.h"
10
11 /*
12 ----------------------------------------------------------------------
13 _svmf_bytes_to_u16
14 ----------------------------------------------------------------------
15 */
16
17 inline svm_static _svmt_u16
_svmf_bytes_to_u16(_svmt_u8 * bytes)18 _svmf_bytes_to_u16 (_svmt_u8 *bytes)
19 {
20 jint i;
21 _svmt_u16 result = 0;
22
23 for (i = 0; i < 2; i++)
24 {
25 result = (result << 8) | bytes[i];
26 }
27
28 return result;
29 }
30
31 /*
32 ----------------------------------------------------------------------
33 _svmf_bytes_to_s32
34 ----------------------------------------------------------------------
35 */
36
37 inline svm_static _svmt_s32
_svmf_bytes_to_s32(_svmt_u8 * bytes)38 _svmf_bytes_to_s32 (_svmt_u8 *bytes)
39 {
40 jint i;
41 _svmt_s32 result = 0;
42
43 for (i = 0; i < 4; i++)
44 {
45 result = (result << 8) | bytes[i];
46 }
47
48 return result;
49 }
50
51 /*
52 ----------------------------------------------------------------------
53 _svmf_bytes_to_s16
54 ----------------------------------------------------------------------
55 */
56
57 inline svm_static _svmt_s16
_svmf_bytes_to_s16(_svmt_u8 * bytes)58 _svmf_bytes_to_s16 (_svmt_u8 *bytes)
59 {
60 jint i;
61 _svmt_s16 result = 0;
62
63 for (i = 0; i < 2; i++)
64 {
65 result = (result << 8) | bytes[i];
66 }
67
68 return result;
69 }
70
71 /*
72 ----------------------------------------------------------------------
73 _svmf_aligned_size_t
74 ----------------------------------------------------------------------
75 */
76
77 inline static size_t
_svmf_aligned_size_t(size_t size)78 _svmf_aligned_size_t (size_t size)
79 {
80 return (size + (SVM_ALIGNMENT - 1)) & ~((size_t) (SVM_ALIGNMENT - 1));
81 }
82
83 /*
84 ----------------------------------------------------------------------
85 _svmf_max_jint
86 ----------------------------------------------------------------------
87 */
88
89 inline static jint
_svmf_max_jint(jint value1,jint value2)90 _svmf_max_jint (jint value1, jint value2)
91 {
92 return (value1 >= value2) ? value1 : value2;
93 }
94
95 /*
96 ----------------------------------------------------------------------
97 _svmf_min_jint
98 ----------------------------------------------------------------------
99 */
100
101 inline static jint
_svmf_min_jint(jint value1,jint value2)102 _svmf_min_jint (jint value1, jint value2)
103 {
104 return (value1 <= value2) ? value1 : value2;
105 }
106
107 /*
108 ----------------------------------------------------------------------
109 _svmf_get_bit
110 ----------------------------------------------------------------------
111 */
112
113 inline static jboolean
_svmf_get_bit(_svmt_u8 * bytes,jint index)114 _svmf_get_bit (_svmt_u8 *bytes, jint index)
115 {
116 return (bytes[index / 8] >> (index % 8)) & 1;
117 }
118
119 /*
120 ----------------------------------------------------------------------
121 _svmf_set_bit
122 ----------------------------------------------------------------------
123 */
124
125 inline static void
_svmf_set_bit(_svmt_u8 * bytes,jint index)126 _svmf_set_bit (_svmt_u8 *bytes, jint index)
127 {
128 bytes[index / 8] |= ((_svmt_u8) 1) << (index % 8);
129 }
130
131 /*
132 ----------------------------------------------------------------------
133 _svmf_clear_bit
134 ----------------------------------------------------------------------
135 */
136
137 inline static void
_svmf_clear_bit(_svmt_u8 * bytes,jint index)138 _svmf_clear_bit (_svmt_u8 *bytes, jint index)
139 {
140 bytes[index / 8] &= ~(((_svmt_u8) 1) << (index % 8));
141 }
142
143 /*
144 ----------------------------------------------------------------------
145 _svmf_is_set_flag
146 ----------------------------------------------------------------------
147 */
148
149 inline static jboolean
_svmf_is_set_flag(jint value,jint flag)150 _svmf_is_set_flag (jint value, jint flag)
151 {
152 return (value & flag) == flag;
153 }
154
155 /*
156 ----------------------------------------------------------------------
157 _svmh_set_flag
158 ----------------------------------------------------------------------
159 */
160
161 inline static void
_svmh_set_flag(jint * pvalue,jint flag)162 _svmh_set_flag (jint *pvalue, jint flag)
163 {
164 *pvalue |= flag;
165 }
166
167 /*
168 ----------------------------------------------------------------------
169 _svmh_clear_flag
170 ----------------------------------------------------------------------
171 */
172
173 inline static void
_svmh_clear_flag(jint * pvalue,jint flag)174 _svmh_clear_flag (jint *pvalue, jint flag)
175 {
176 *pvalue &= ~flag;
177 }
178
179 /*
180 ----------------------------------------------------------------------
181 _svmf_is_interface
182 ----------------------------------------------------------------------
183 */
184
185 inline static jboolean
_svmf_is_interface(_svmt_class_info * class)186 _svmf_is_interface (_svmt_class_info *class)
187 {
188 return _svmf_is_set_flag (class->access_flags, SVM_ACC_INTERFACE);
189 }
190
191 /*
192 ----------------------------------------------------------------------
193 _svmf_aligned_to_increment
194 ----------------------------------------------------------------------
195 */
196
197 inline static size_t
_svmf_aligned_to_increment(size_t size,size_t increment)198 _svmf_aligned_to_increment (size_t size, size_t increment)
199 {
200 return ((size + (increment - 1)) / increment) * increment;
201 }
202
203 /*
204 ----------------------------------------------------------------------
205 _svmh_validate_min_max_increment
206 ----------------------------------------------------------------------
207 */
208
209 svm_static jint
_svmh_validate_min_max_increment(size_t * pmin,size_t * pmax,size_t * pincr)210 _svmh_validate_min_max_increment (size_t *pmin, size_t *pmax, size_t *pincr)
211 {
212 *pmin = _svmf_aligned_size_t (*pmin);
213 *pmax = _svmf_aligned_size_t (*pmax);
214 *pincr = _svmf_aligned_size_t (*pincr);
215
216 /* Allow shortcut for specifying fixed size */
217 if (*pmin == *pmax)
218 {
219 *pincr = 0;
220 }
221 else if (*pincr == 0)
222 {
223 *pmax = *pmin;
224 }
225
226 /* min must be positive */
227 if (*pmin == 0)
228 {
229 return JNI_ERR;
230 }
231
232 /* max size of 0 means no maximum */
233 if (*pmax == 0 && *pincr == 0)
234 {
235 return JNI_ERR;
236 }
237
238 /* if not 0, max size must be >= the min size */
239 if (*pmax > 0 && *pmax < *pmin)
240 {
241 return JNI_ERR;
242 }
243
244 /* incr should be zero for fixed size, non-zero otherwise */
245 if ((*pmax == *pmin && *pincr != 0) || (*pmax != *pmin && *pincr == 0))
246 {
247 return JNI_ERR;
248 }
249
250 /* make (max - min) a multiple of incr */
251 if (*pmax > *pmin)
252 {
253 *pmax = *pmin + _svmf_aligned_to_increment (*pmax - *pmin, *pincr);
254
255 if (*pmax <= *pmin)
256 {
257 return JNI_ERR;
258 }
259 }
260
261 return JNI_OK;
262 }
263
264 /*
265 ----------------------------------------------------------------------
266 _svmf_get_boolean_array_element
267 ----------------------------------------------------------------------
268 */
269
270 inline static jboolean
_svmf_get_boolean_array_element(_svmt_array_instance * array,jint indx)271 _svmf_get_boolean_array_element (_svmt_array_instance *array, jint indx)
272 {
273 _svmt_u8 *elements;
274
275 #ifndef _SABLEVM_INLINED_THREADED_INTERPRETER
276 assert (array != NULL);
277 assert (array->vtable->type->is_array);
278 assert (indx >= 0 && indx < array->size);
279 #endif
280
281 elements = (_svmt_u8 *)
282 (((char *) array) + _svmf_aligned_size_t (sizeof (_svmt_array_instance)));
283
284 return _svmf_get_bit (elements, indx);
285 }
286
287 /*
288 ----------------------------------------------------------------------
289 _svmf_set_boolean_array_element
290 ----------------------------------------------------------------------
291 */
292
293 inline svm_static void
_svmf_set_boolean_array_element(_svmt_array_instance * array,jint indx,jboolean value)294 _svmf_set_boolean_array_element (_svmt_array_instance *array, jint indx,
295 jboolean value)
296 {
297 _svmt_u8 *elements;
298
299 #ifndef _SABLEVM_INLINED_THREADED_INTERPRETER
300 assert (array != NULL);
301 assert (array->vtable->type->is_array);
302 assert (indx >= 0 && indx < array->size);
303 #endif
304
305 elements = (_svmt_u8 *)
306 (((char *) array) + _svmf_aligned_size_t (sizeof (_svmt_array_instance)));
307
308 if (value)
309 {
310 _svmf_set_bit (elements, indx);
311 }
312 else
313 {
314 _svmf_clear_bit (elements, indx);
315 }
316 }
317
318 /*
319 ----------------------------------------------------------------------
320 _svmf_get_reference_array_element
321 ----------------------------------------------------------------------
322 */
323
324 inline svm_static _svmt_object_instance *
_svmf_get_reference_array_element(_svmt_array_instance * array,jint indx)325 _svmf_get_reference_array_element (_svmt_array_instance *array, jint indx)
326 {
327 _svmt_object_instance **elements;
328
329 #ifndef _SABLEVM_INLINED_THREADED_INTERPRETER
330 assert (array != NULL);
331 assert (array->vtable->type->is_array);
332 assert (indx >= 0 && indx < array->size);
333 #endif
334
335 #if defined (_SABLEVM_BIDIRECTIONAL_OBJECT_LAYOUT)
336
337 elements = (_svmt_object_instance **) array;
338 return elements[(-1) - indx];
339
340 #else
341
342 elements = (_svmt_object_instance **)
343 (((char *) array) + _svmf_aligned_size_t (sizeof (_svmt_array_instance)));
344
345 return elements[indx];
346
347 #endif
348 }
349
350 /*
351 ----------------------------------------------------------------------
352 _svmf_printf
353 ----------------------------------------------------------------------
354 */
355
356 svm_static void
_svmf_printf(_svmt_JNIEnv * env,FILE * stream,const char * format,...)357 _svmf_printf (_svmt_JNIEnv *env, FILE *stream, const char *format, ...)
358 {
359 _svmt_JavaVM *vm = env->vm;
360 va_list ap;
361
362 va_start (ap, format);
363
364 (*(vm->vfprintf)) (stream, format, ap);
365
366 #if (!defined(NDEBUG)) || defined(_SABLEVM_INLINABILITY_TESTING)
367 fflush (NULL);
368 #endif
369
370 va_end (ap);
371 }
372
373 /*
374 ----------------------------------------------------------------------
375 _svmf_parse_size_t
376 ----------------------------------------------------------------------
377 */
378
379 svm_static jint
_svmf_parse_size_t(size_t * size,const char * value)380 _svmf_parse_size_t (size_t *size, const char *value)
381 {
382 size_t result = 0;
383
384 if (*value == 0)
385 {
386 return JNI_ERR;
387 }
388
389 do
390 {
391 char c = *value++;
392
393 if (c >= '0' && c <= '9')
394 {
395 size_t old = result;
396 result = (result * 10) + (c - '0');
397 if (result < old)
398 {
399 return JNI_ERR;
400 }
401 }
402 else if (c == 0)
403 {
404 *size = result;
405 return JNI_OK;
406 }
407 else
408 {
409 return JNI_ERR;
410 }
411 }
412 while (1);
413 }
414
415 /*
416 ----------------------------------------------------------------------
417 _svmf_get_BOOLEAN_field
418 ----------------------------------------------------------------------
419 */
420
421 inline static jboolean
_svmf_get_BOOLEAN_field(_svmt_object_instance * instance,size_t offset)422 _svmf_get_BOOLEAN_field (_svmt_object_instance *instance, size_t offset)
423 {
424 return _svmf_get_bit ((_svmt_u8 *) instance, offset);
425 }
426
427 /*
428 ----------------------------------------------------------------------
429 _svmf_put_BOOLEAN_field
430 ----------------------------------------------------------------------
431 */
432
433 inline static void
_svmf_put_BOOLEAN_field(_svmt_object_instance * instance,size_t offset,jboolean value)434 _svmf_put_BOOLEAN_field (_svmt_object_instance *instance, size_t offset,
435 jboolean value)
436 {
437 if (value)
438 {
439 _svmf_set_bit ((_svmt_u8 *) instance, offset);
440 }
441 else
442 {
443 _svmf_clear_bit ((_svmt_u8 *) instance, offset);
444 }
445 }
446
447 /*
448 ----------------------------------------------------------------------
449 _svmf_get_REFERENCE_field
450 ----------------------------------------------------------------------
451 */
452
453 inline static _svmt_object_instance *
_svmf_get_REFERENCE_field(_svmt_object_instance * instance,size_t offset)454 _svmf_get_REFERENCE_field (_svmt_object_instance *instance, size_t offset)
455 {
456 _svmt_object_instance *result =
457 *((_svmt_object_instance **) (void *) (((char *) instance) + offset));
458
459 #if defined (MAGIC) && !defined (_SABLEVM_INLINED_THREADED_INTERPRETER)
460 assert (result == NULL || strcmp (result->magic, "SableVM") == 0);
461 #endif
462
463 return result;
464 }
465
466 /*
467 ----------------------------------------------------------------------
468 _svmf_put_REFERENCE_field
469 ----------------------------------------------------------------------
470 */
471
472 inline static void
_svmf_put_REFERENCE_field(_svmt_JNIEnv * env SVM_UNUSED,_svmt_object_instance * instance,size_t offset,_svmt_object_instance * value)473 _svmf_put_REFERENCE_field (_svmt_JNIEnv *env SVM_UNUSED,
474 _svmt_object_instance *instance, size_t offset,
475 _svmt_object_instance *value)
476 {
477 *((_svmt_object_instance **) (void *) (((char *) instance) + offset)) =
478 value;
479 #if defined (_SABLEVM_GC_WRITE_BARRIER)
480 _svmf_write_barrier
481 (env, (_svmt_object_instance **) (void *) ((char *) instance + offset));
482 #endif /* _SABLEVM_GC_WRITE_BARRIER */
483 }
484
485 /*
486 ----------------------------------------------------------------------
487 _svmf_get_REFERENCE_static
488 ----------------------------------------------------------------------
489 */
490
491 inline static _svmt_object_instance *
_svmf_get_REFERENCE_static(jvalue * pvalue)492 _svmf_get_REFERENCE_static (jvalue *pvalue)
493 {
494 _svmt_object_instance *result = *(pvalue->l);
495
496 #if defined (MAGIC) && !defined (_SABLEVM_INLINED_THREADED_INTERPRETER)
497 assert (result == NULL || strcmp (result->magic, "SableVM") == 0);
498 #endif
499
500 return result;
501 }
502
503 /*
504 ----------------------------------------------------------------------
505 _svmf_put_REFERENCE_static
506 ----------------------------------------------------------------------
507 */
508
509 inline static void
_svmf_put_REFERENCE_static(jvalue * pvalue,_svmt_object_instance * value)510 _svmf_put_REFERENCE_static (jvalue *pvalue, _svmt_object_instance *value)
511 {
512 *(pvalue->l) = value;
513 }
514
515 /*
516 ----------------------------------------------------------------------
517 _svmf_dump_stack_trace
518 ----------------------------------------------------------------------
519 */
520
521 svm_static void
_svmf_dump_stack_trace(_svmt_JNIEnv * env)522 _svmf_dump_stack_trace (_svmt_JNIEnv *env)
523 {
524 _svmt_JavaVM *vm = env->vm;
525 _svmt_stack_frame *frame = env->stack.current_frame;
526 _svmt_method_info *method = frame->method;
527
528 jint lineNumber = -1;
529 jboolean isNative = JNI_FALSE;
530
531 _svmf_printf (env, stderr, "--- stack trace dump (begin) ---\n");
532 _svmf_printf (env, stderr, "Thread ID: %d, Posix ID: %d\n", env->thread.id,
533 env->thread.pthread);
534
535 while (method != &vm->stack_bottom_method)
536 {
537 _svmt_class_info *class;
538
539 /* skip internal frames */
540 if (_svmf_is_set_flag (method->access_flags, SVM_ACC_INTERNAL))
541 {
542 _svmf_printf (env, stderr, "(internal frame)\n");
543
544 frame = (_svmt_stack_frame *) (void *)
545 (((char *) frame) - frame->previous_offset);
546 method = frame->method;
547 continue;
548 }
549
550 isNative = _svmf_is_set_flag (method->access_flags, SVM_ACC_NATIVE);
551
552 class = method->class_info;
553
554 if ((!isNative) && method->data.code_attribute->line_numbers != NULL)
555 {
556 jint table_length =
557 method->data.code_attribute->line_numbers->
558 line_number_table_length;
559 _svmt_line_number_table *table =
560 method->data.code_attribute->line_numbers->line_number_table;
561 _svmt_code *pc = frame->pc;
562 jint i;
563
564 for (i = 0; i < table_length; i++)
565 {
566 if ((pc >= table[i].normal_start && pc <= table[i].normal_end)
567 || (pc >= table[i].prepare_start
568 && pc <= table[i].prepare_end))
569 {
570 lineNumber = table[i].line_number;
571 break;
572 }
573 }
574 }
575
576 _svmf_printf (env, stderr, "(%s:%d) %s.%s %c\n", class->file_name,
577 lineNumber, class->name, DREF (method->name, value),
578 (jint) (isNative ? 'n' : ' '));
579
580 lineNumber = -1;
581 isNative = JNI_FALSE;
582
583 frame = (_svmt_stack_frame *) (void *)
584 (((char *) frame) - frame->previous_offset);
585 method = frame->method;
586 }
587
588 _svmf_printf (env, stderr, "--- stack trace dump (end) ---\n");
589
590 }
591
592
593
594
595
596
597 #ifdef COMMENT
598
599 #include "includes.h"
600
601 static jboolean have_identical_package_name
602 (const char *name1, const char *name2);
603
604
605 /*
606 ----------------------------------------------------------------------
607 have_identical_package_name
608 ----------------------------------------------------------------------
609 */
610
611 svm_static jboolean
have_identical_package_name(const char * name1,const char * name2)612 have_identical_package_name (const char *name1, const char *name2)
613 {
614 size_t i, j;
615 size_t length;
616 size_t len1 = strlen (name1);
617 size_t len2 = strlen (name2);
618
619 length = (len1 >= len2) ? len1 : len2;
620
621 /* skip common prefix */
622 for (i = 0; i < length; i++)
623 {
624 if (name1[i] != name2[i])
625 {
626 break;
627 }
628 }
629
630 /* if the remaining of name1 or name2 contains a '/', then the packages differ */
631 for (j = i; j < len1; j++)
632 {
633 if (name1[j] == '/')
634 {
635 return JNI_FALSE;
636 }
637 }
638
639 for (j = i; j < len2; j++)
640 {
641 if (name2[j] == '/')
642 {
643 return JNI_FALSE;
644 }
645 }
646
647 return JNI_TRUE;
648 }
649
650 /*
651 ----------------------------------------------------------------------
652 _svmf_has_same_runtime_package
653 ----------------------------------------------------------------------
654 */
655
656 jboolean
_svmf_have_same_runtime_package(_svmt_type_info * type1,_svmt_type_info * type2)657 _svmf_have_same_runtime_package (_svmt_type_info *type1,
658 _svmt_type_info *type2)
659 {
660 return
661 (type1->class_loader_info == type2->class_loader_info &&
662 have_identical_package_name (type1->name, type2->name))
663 ? JNI_TRUE : JNI_FALSE;
664 }
665
666 /*
667 ----------------------------------------------------------------------
668 _svmf_debug_print_stack_trace
669 ----------------------------------------------------------------------
670 */
671
672 void
_svmf_debug_print_stack_trace(_svmt_JNIEnv * env)673 _svmf_debug_print_stack_trace (_svmt_JNIEnv *env)
674 {
675 _svmt_stack_frame *frame = env->stack.current_frame;
676
677 /* if (strcmp(DREF(frame->method->name, value), "loadLibrary") == 0)
678 {
679 printf ("gotcha!\n");
680 } */
681
682 printf ("--------------------\n");
683 while (1)
684 {
685 _svmt_method_info *method = frame->method;
686
687 if (IS_SET (method->access_flags, SVM_ACC_DUMMY))
688 {
689 printf (" -- \n");
690 }
691 else if (IS_SET (method->access_flags, SVM_ACC_NATIVE))
692 {
693 printf
694 ("%s.%s %s (native)\n",
695 method->class_info->name,
696 DREF (method->name, value), DREF (method->descriptor, value));
697 }
698 else if (method->code != method->code_attribute->prepared_code)
699 {
700 printf
701 ("%s.%s %s (being prepared)\n",
702 method->class_info->name,
703 DREF (method->name, value), DREF (method->descriptor, value));
704 }
705 else
706 {
707 _svmt_bytecode_info *bc_info = method->code_attribute->bc_info;
708 jint attributes_count = method->code_attribute->attributes_count;
709 jint i;
710 _svmt_LineNumberTable_attribute *attribute = NULL;
711 size_t offset = frame->pc - method->code;
712 jint table_length;
713 _svmt_line_number_table *table;
714 jboolean printed = JNI_FALSE;
715
716 for (i = 0; i < attributes_count; i++)
717 {
718 if (strcmp
719 (DREF (method->code_attribute->attributes[i]->name, value),
720 "LineNumberTable") == 0)
721 {
722 attribute = (_svmt_LineNumberTable_attribute *)
723 method->code_attribute->attributes[i];
724 }
725 }
726
727 if (attribute != NULL)
728 {
729 table_length = attribute->line_number_table_length;
730 table = attribute->line_number_table;
731
732 for (i = table_length - 1; i >= 0; i--)
733 {
734 if (offset >=
735 bc_info[table[i].start_pc].code_offset +
736 bc_info[table[i].start_pc].code_length)
737 {
738 printf
739 ("%s.%s %s (line %d)\n",
740 method->class_info->name,
741 DREF (method->name, value),
742 DREF (method->descriptor, value),
743 table[i].line_number);
744 printed = JNI_TRUE;
745 break;
746 }
747 }
748 }
749
750 if (!printed)
751 {
752 jint bc_length = method->code_attribute->code_length;
753 for (i = 0; i < bc_length; i++)
754 {
755 if (offset ==
756 bc_info[i].code_offset + bc_info[i].code_length)
757 {
758 printf
759 ("%s.%s %s (at bytecode # %d)\n",
760 method->class_info->name,
761 DREF (method->name, value),
762 DREF (method->descriptor, value), i);
763 printed = JNI_TRUE;
764 break;
765 }
766 }
767 }
768
769 if (!printed)
770 {
771 printf
772 ("%s.%s %s (unknown)\n",
773 method->class_info->name,
774 DREF (method->name, value),
775 DREF (method->descriptor, value));
776 break;
777 }
778 }
779
780 if (frame->previous_offset == 0)
781 {
782 break;
783 }
784
785 frame =
786 (_svmt_stack_frame *) (((char *) frame) - frame->previous_offset);
787 }
788 }
789
790
791 #endif /* COMMENT */
792