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 /*
10 ----------------------------------------------------------------------
11 _svmm_identity_hashcode
12 ----------------------------------------------------------------------
13 */
14 
15 #define _svmm_identity_hashcode(env, obj, hashcode) \
16 _svmh_identity_hashcode (env, obj, &hashcode)
17 
18 svm_static jint
_svmh_identity_hashcode(_svmt_JNIEnv * env,jobject obj,jint * phashcode)19 _svmh_identity_hashcode (_svmt_JNIEnv *env, jobject obj, jint *phashcode)
20 {
21   _svmt_JavaVM *vm = env->vm;
22   jboolean monitor_acquired = JNI_FALSE;
23   _svmt_JNIEnv *owner = NULL;
24 
25   /* is it an array? */
26   if (_svmf_lockword_is_array ((*obj)->lockword))
27     {
28       assert (!monitor_acquired);
29 
30       *phashcode = (*(_svmf_cast_jarray (obj)))->hashcode;
31       return JNI_OK;
32     }
33 
34 retry:
35   {
36     _svmt_object_instance *instance = *obj;
37     _svmt_word state = _svmf_lockword_get_hashstate (instance->lockword);
38 
39     switch (state)
40       {
41       case SVM_HASH_NONE:
42 	{
43 	  /* The untold story in the 2 bits hashcode within a thin
44 	     lock is that it cannot be modified unless a) the current
45 	     thread owns the lock, or b) the owning thread is
46 	     suspended.
47 	   */
48 
49 	  if (!monitor_acquired)
50 	    {
51 	      jboolean succeeded = JNI_FALSE;	/* init just to keep compiler happy */
52 
53 	      if (_svmm_enter_object_monitor_non_blocking
54 		  (env, instance, succeeded))
55 		{
56 		  return JNI_ERR;
57 		}
58 
59 	      if (succeeded)
60 		{
61 		  monitor_acquired = JNI_TRUE;
62 		  goto retry;
63 		}
64 
65 	      /* refresh values, in case GC happened in enter_monitor call */
66 	      instance = *obj;
67 
68 	      /* contention: another thread owns the lock.  Suspend it. */
69 	      {
70 		_svmt_word lockword = instance->lockword;
71 
72 		if (_svmf_lockword_is_thin (lockword))
73 		  {
74 		    jint owner_id = _svmf_lockword_get_thread_id (lockword);
75 
76 		    assert (owner_id != env->thread.id);
77 
78 		    owner = vm->threads.array[owner_id];
79 
80 		    /* If the lock has been released, retry. */
81 		    if (owner == NULL)
82 		      {
83 			goto retry;
84 		      }
85 
86 		    _svmm_mutex_lock (vm->global_mutex);
87 
88 		    assert (env != owner);
89 
90 		    /* suspend owner thread */
91 		    _svmf_suspend_thread (env, owner);
92 
93 		    _svmm_mutex_unlock ();
94 
95 		    /* refresh values */
96 		    instance = *obj;
97 		    lockword = instance->lockword;
98 
99 		    if (_svmf_lockword_is_thin (lockword))
100 		      {
101 			owner_id = _svmf_lockword_get_thread_id (lockword);
102 		      }
103 		    else
104 		      {
105 			owner_id = 0;	/* so that we retry */
106 		      }
107 
108 		    /* make sure it is still owner */
109 		    if (owner != vm->threads.array[owner_id])
110 		      {
111 			_svmm_mutex_lock (vm->global_mutex);
112 
113 			/* resume owner thread */
114 			_svmf_resume_thread (env, owner);
115 
116 			_svmm_mutex_unlock ();
117 
118 			owner = NULL;
119 			goto retry;
120 		      }
121 		  }
122 		else
123 		  {
124 		    /* it is a fat lock */
125 
126 		    _svmt_word fat_index =
127 		      _svmf_lockword_get_fatlock_index (lockword);
128 		    _svmt_fat_lock *fat_lock = vm->fat_locks.array[fat_index];
129 
130 		    _svmm_mutex_lock (fat_lock->mutex);
131 
132 		    if (fat_lock->recursive_count != 0)
133 		      {
134 			owner = fat_lock->owner;
135 		      }
136 
137 		    _svmm_mutex_unlock ();
138 
139 		    /* If the lock has been released, retry. */
140 		    if (owner == NULL)
141 		      {
142 			goto retry;
143 		      }
144 
145 		    _svmm_mutex_lock (vm->global_mutex);
146 
147 		    assert (env != owner);
148 
149 		    /* suspend owner thread */
150 		    _svmf_suspend_thread (env, owner);
151 
152 		    _svmm_mutex_unlock ();
153 
154 		    /* refresh values */
155 		    instance = *obj;
156 		    lockword = instance->lockword;
157 
158 		    {
159 		      jboolean changed = JNI_FALSE;
160 
161 		      if (!_svmf_lockword_is_thin (lockword))
162 			{
163 			  fat_index =
164 			    _svmf_lockword_get_fatlock_index (lockword);
165 			  fat_lock = vm->fat_locks.array[fat_index];
166 
167 			  _svmm_mutex_lock (fat_lock->mutex);
168 
169 			  if (fat_lock->recursive_count == 0
170 			      || owner != fat_lock->owner)
171 			    {
172 			      changed = JNI_TRUE;
173 			    }
174 
175 			  _svmm_mutex_unlock ();
176 			}
177 		      else
178 			{
179 			  changed = JNI_TRUE;
180 			}
181 
182 		      /* make sure it is still owner */
183 		      if (changed)
184 			{
185 			  _svmm_mutex_lock (vm->global_mutex);
186 
187 			  /* resume owner thread */
188 			  _svmf_resume_thread (env, owner);
189 
190 			  _svmm_mutex_unlock ();
191 
192 			  owner = NULL;
193 			  goto retry;
194 			}
195 		    }
196 		  }
197 	      }
198 	    }
199 
200 #if defined (_SABLEVM_COPY_GC) || defined (_SABLEVM_GENCOPY_GC)
201 
202 	  /* we must make sure there will be enough space to store the hashcode at gc time */
203 	  {
204 	    jint end_of_heap, status = JNI_OK;
205 
206 	    _svmm_mutex_lock (vm->global_mutex);
207 
208 	    /* remember that allocation is made in multiples of SVM_ALIGNMENT */
209 	    if (vm->heap.alloc == vm->heap.end)
210 	      end_of_heap = JNI_TRUE;
211 	    else
212 	      end_of_heap = JNI_FALSE;
213 
214 	    if (end_of_heap == JNI_TRUE)
215 	      {
216 #if defined (_SABLEVM_COPY_GC)
217 		status = _svmf_copy_gc_no_exception (env, SVM_ALIGNMENT);
218 #elif defined (_SABLEVM_GENCOPY_GC)
219 		status = _svmf_gencopy_gc_no_exception (env, SVM_ALIGNMENT);
220 #endif
221 	      }
222 
223 	    if ((end_of_heap == JNI_FALSE) || (status == JNI_OK))
224 	      {
225 #if defined (_SABLEVM_GENCOPY_GC)
226 		if (_svmf_in_nursery (env, *obj))
227 		  vm->heap.hashed_notmoved_nursery++;
228 #endif
229 		vm->heap.hashed_notmoved++;
230 		vm->heap.end = ((char *) vm->heap.end) - SVM_ALIGNMENT;
231 	      }
232 
233 	    _svmm_mutex_unlock ();
234 
235 	    if (status != JNI_OK)
236 	      {
237 		if (monitor_acquired)
238 		  {
239 		    assert (owner == NULL);
240 
241 		    if (_svmf_exit_object_monitor (env, *obj) != JNI_OK)
242 		      {
243 			return JNI_ERR;
244 		      }
245 		  }
246 		else
247 		  {
248 		    assert (owner != NULL);
249 
250 		    _svmm_mutex_lock (vm->global_mutex);
251 
252 		    /* resume owner thread */
253 		    _svmf_resume_thread (env, owner);
254 
255 		    _svmm_mutex_unlock ();
256 		  }
257 
258 		_svmf_error_OutOfMemoryError (env);
259 		return JNI_ERR;
260 	      }
261 
262 	    /* in case gc moved things around */
263 	    instance = *obj;
264 	  }
265 #endif
266 
267 	  _svmm_lockword_set_hashstate (instance->lockword,
268 					SVM_HASH_NOT_MOVED);
269 
270 #if defined (_SABLEVM_NO_GC) || defined (_SABLEVM_COPY_GC)
271 
272 	  *phashcode = vm->heap.hashcode_base + (size_t) instance;
273 
274 #elif defined (_SABLEVM_GENCOPY_GC)
275 
276 	  if (_svmf_in_nursery (env, instance))
277 	    *phashcode = vm->heap.hashcode_base_nursery + (size_t) instance;
278 	  else
279 	    *phashcode = vm->heap.hashcode_base - (size_t) instance;
280 
281 #else
282 #error todo
283 #endif
284 	}
285 	break;
286 
287       case SVM_HASH_NOT_MOVED:
288 	{
289 #if defined (_SABLEVM_NO_GC)  || defined (_SABLEVM_COPY_GC)
290 
291 	  *phashcode = vm->heap.hashcode_base + (size_t) instance;
292 
293 #elif defined (_SABLEVM_GENCOPY_GC)
294 
295 	  if (_svmf_in_nursery (env, instance))
296 	    *phashcode = vm->heap.hashcode_base_nursery + (size_t) instance;
297 	  else
298 	    *phashcode = vm->heap.hashcode_base - (size_t) instance;
299 
300 #else
301 #error todo
302 #endif
303 	}
304 	break;
305 
306       case SVM_HASH_MOVED:
307 	{
308 	  *phashcode =
309 	    _svmf_get_INT_field (instance, instance->vtable->hashcode_offset);
310 	}
311 	break;
312 
313       default:
314 	{
315 	  _svmm_fatal_error ("impossible control flow");
316 	}
317 	break;
318       }
319   }
320 
321   if (monitor_acquired)
322     {
323       monitor_acquired = JNI_FALSE;
324 
325       if (_svmf_exit_object_monitor (env, *obj) != JNI_OK)
326 	{
327 	  return JNI_ERR;
328 	}
329     }
330   else if (owner != NULL)
331     {
332       _svmm_mutex_lock (vm->global_mutex);
333 
334       /* resume owner thread */
335       _svmf_resume_thread (env, owner);
336 
337       _svmm_mutex_unlock ();
338     }
339 
340   return JNI_OK;
341 }
342 
343 /*
344 ----------------------------------------------------------------------
345 _svmf_is_assignable_from
346 ----------------------------------------------------------------------
347 */
348 
349 inline svm_static jboolean
_svmf_is_assignable_from(_svmt_JNIEnv * env,_svmt_type_info * from,_svmt_type_info * to)350 _svmf_is_assignable_from (_svmt_JNIEnv *env, _svmt_type_info *from,
351 			  _svmt_type_info *to)
352 {
353   _svmt_JavaVM *vm = env->vm;
354   _svmt_type_info *S = from;
355   _svmt_type_info *T = to;
356 
357 #ifndef _SABLEVM_INLINED_THREADED_INTERPRETER
358   assert (S != NULL);
359   assert (T != NULL);
360 #endif
361 
362 loop:
363   if (!(S->is_array))
364     {
365       _svmt_class_info *cS = _svmf_cast_class (S);
366 
367       if (!_svmf_is_set_flag (cS->access_flags, SVM_ACC_INTERFACE))
368 	{
369 	  /* S is a class */
370 	  if (!(T->is_array))
371 	    {
372 	      _svmt_class_info *cT = _svmf_cast_class (T);
373 
374 	      if (!_svmf_is_set_flag (cT->access_flags, SVM_ACC_INTERFACE))
375 		{
376 		  /* T is a class */
377 		  jint s = cS->data.noninterface.super_classes_size;
378 		  jint t = cT->data.noninterface.super_classes_size;
379 
380 		  if ((s < t)
381 		      || (cS->data.noninterface.super_classes[t - 1] != cT))
382 		    {
383 		      return JNI_FALSE;
384 		    }
385 		  else
386 		    {
387 		      return JNI_TRUE;
388 		    }
389 		}
390 	      else
391 		{
392 		  /* T is an interface */
393 		  jint s = cS->data.noninterface.max_interface_id;
394 		  jint t = cT->data.interface.interface_id;
395 
396 		  if ((s < t) ||
397 		      (_svmf_get_bit
398 		       (cS->data.noninterface.super_interfaces, t) == 0))
399 		    {
400 		      return JNI_FALSE;
401 		    }
402 		  else
403 		    {
404 		      return JNI_TRUE;
405 		    }
406 		}
407 	    }
408 	  else
409 	    {
410 	      /* T is an array */
411 	      return JNI_FALSE;
412 	    }
413 	}
414       else
415 	{
416 	  /* S is an interface */
417 	  if (!(T->is_array))
418 	    {
419 	      _svmt_class_info *cT = _svmf_cast_class (T);
420 
421 	      if (!_svmf_is_set_flag (cT->access_flags, SVM_ACC_INTERFACE))
422 		{
423 		  /* T is a class */
424 		  if (cT == vm->class_loading.boot_loader.classes.jlobject)
425 		    {
426 		      return JNI_TRUE;
427 		    }
428 		  else
429 		    {
430 		      return JNI_FALSE;
431 		    }
432 		}
433 	      else
434 		{
435 		  /* T is an interface */
436 		  jint s = cS->data.interface.interface_id;
437 		  jint t = cT->data.interface.interface_id;
438 
439 		  if ((s < t) ||
440 		      (_svmf_get_bit (cS->data.interface.super_interfaces, t)
441 		       == 0))
442 		    {
443 		      return JNI_FALSE;
444 		    }
445 		  else
446 		    {
447 		      return JNI_TRUE;
448 		    }
449 		}
450 	    }
451 	  else
452 	    {
453 	      /* T is an array */
454 	      return JNI_FALSE;
455 	    }
456 	}
457     }
458   else
459     {
460       /* S is an array */
461       _svmt_array_info *aS = _svmf_cast_array (S);
462 
463       if (!(T->is_array))
464 	{
465 	  _svmt_class_info *cT = _svmf_cast_class (T);
466 
467 	  if (!_svmf_is_set_flag (cT->access_flags, SVM_ACC_INTERFACE))
468 	    {
469 	      /* T is a class */
470 	      if (cT == vm->class_loading.boot_loader.classes.jlobject)
471 		{
472 		  return JNI_TRUE;
473 		}
474 	      else
475 		{
476 		  return JNI_FALSE;
477 		}
478 	    }
479 	  else
480 	    {
481 	      /* T is an interface */
482 	      if ((cT == vm->class_loading.boot_loader.classes.jlcloneable) ||
483 		  (cT ==
484 		   vm->class_loading.boot_loader.classes.jiserializable))
485 		{
486 		  return JNI_TRUE;
487 		}
488 	      else
489 		{
490 		  return JNI_FALSE;
491 		}
492 	    }
493 	}
494       else
495 	{
496 	  /* T is an array */
497 	  _svmt_array_info *aT = _svmf_cast_array (T);
498 
499 	  if ((aS->dimensions == 1 && aS->base_type != SVM_TYPE_REFERENCE) ||
500 	      (aT->dimensions == 1 && aT->base_type != SVM_TYPE_REFERENCE))
501 	    {
502 	      /* S or T is an array of primitive type */
503 	      if (aS->dimensions == aT->dimensions &&
504 		  aS->base_type == aT->base_type)
505 		{
506 		  return JNI_TRUE;
507 		}
508 	      else
509 		{
510 		  return JNI_FALSE;
511 		}
512 	    }
513 
514 	  /* redo with element types */
515 
516 	  if (aS->dimensions == 1)
517 	    {
518 #ifndef _SABLEVM_INLINED_THREADED_INTERPRETER
519 	      assert (aS->base_type == SVM_TYPE_REFERENCE);
520 	      assert (aS->base_class != NULL);
521 #endif
522 
523 	      S = _svmf_cast_type_class (aS->base_class);
524 	    }
525 	  else
526 	    {
527 #ifndef _SABLEVM_INLINED_THREADED_INTERPRETER
528 	      assert (aS->array_element != NULL);
529 #endif
530 
531 	      S = _svmf_cast_type_array (aS->array_element);
532 	    }
533 
534 	  if (aT->dimensions == 1)
535 	    {
536 #ifndef _SABLEVM_INLINED_THREADED_INTERPRETER
537 	      assert (aT->base_type == SVM_TYPE_REFERENCE);
538 	      assert (aT->base_class != NULL);
539 #endif
540 
541 	      T = _svmf_cast_type_class (aT->base_class);
542 	    }
543 	  else
544 	    {
545 #ifndef _SABLEVM_INLINED_THREADED_INTERPRETER
546 	      assert (aT->array_element != NULL);
547 #endif
548 
549 	      T = _svmf_cast_type_array (aT->array_element);
550 	    }
551 
552 	  goto loop;
553 	}
554     }
555 
556 #ifndef _SABLEVM_INLINED_THREADED_INTERPRETER
557   _svmm_fatal_error ("impossible control flow");
558 #endif
559 }
560 
561 /*
562 ----------------------------------------------------------------------
563 _svmf_set_reference_array_element_no_exception
564 ----------------------------------------------------------------------
565 */
566 
567 inline svm_static jint
_svmf_set_reference_array_element_no_exception(_svmt_JNIEnv * env,_svmt_array_instance * array,jint indx,_svmt_object_instance * value)568 _svmf_set_reference_array_element_no_exception (_svmt_JNIEnv *env,
569 						_svmt_array_instance *array,
570 						jint indx,
571 						_svmt_object_instance *value)
572 {
573   _svmt_object_instance **elements;
574 
575 #ifndef _SABLEVM_INLINED_THREADED_INTERPRETER
576   assert (array != NULL);
577   assert (array->vtable->type->is_array);
578   assert (indx >= 0 && indx < array->size);
579   assert (array->vtable->type->is_array == JNI_TRUE);
580 #endif
581 
582   /* check that value is of appropriate type */
583   if (value != NULL)
584     {
585       _svmt_array_info *array_type = _svmf_cast_array (array->vtable->type);
586       _svmt_type_info *element_type;
587 
588       if (array_type->dimensions > 1)
589 	{
590 #ifndef _SABLEVM_INLINED_THREADED_INTERPRETER
591 	  assert (array_type->array_element != NULL);
592 #endif
593 
594 	  element_type = _svmf_cast_type_array (array_type->array_element);
595 	}
596       else
597 	{
598 #ifndef _SABLEVM_INLINED_THREADED_INTERPRETER
599 	  assert (array_type->dimensions == 1);
600 	  assert (array_type->base_type == SVM_TYPE_REFERENCE);
601 	  assert (array_type->base_class != NULL);
602 #endif
603 
604 	  element_type = _svmf_cast_type_class (array_type->base_class);
605 	}
606 
607       if (!_svmf_is_assignable_from (env, value->vtable->type, element_type))
608 	{
609 	  return JNI_ERR;
610 	}
611     }
612 
613 #if defined (_SABLEVM_BIDIRECTIONAL_OBJECT_LAYOUT)
614 
615   elements = (_svmt_object_instance **) array;
616   elements[(-1) - indx] = value;
617 #if defined (_SABLEVM_GC_WRITE_BARRIER)
618   _svmf_write_barrier
619     (env, (_svmt_object_instance **) &elements[(-1) - indx]);
620 #endif /* _SABLEVM_GC_WRITE_BARRIER */
621 
622 #else
623 
624   elements = (_svmt_object_instance **)
625     (((char *) array) + _svmf_aligned_size_t (sizeof (_svmt_array_instance)));
626 
627   elements[indx] = value;
628 #if defined (_SABLEVM_GC_WRITE_BARRIER)
629   _svmf_write_barrier (env, (_svmt_object_instance **) &elements[indx]);
630 #endif /* _SABLEVM_GC_WRITE_BARRIER */
631 
632 #endif
633 
634   return JNI_OK;
635 }
636 
637 /*
638 ----------------------------------------------------------------------
639 _svmf_tree_compare_type
640 ----------------------------------------------------------------------
641 */
642 
643 inline svm_static jint
_svmf_tree_compare_type(_svmt_type_node * value1,_svmt_type_node * value2)644 _svmf_tree_compare_type (_svmt_type_node *value1, _svmt_type_node *value2)
645 {
646   assert (value1 != NULL);
647   assert (value2 != NULL);
648 
649   return strcmp (value1->name, value2->name);
650 }
651 
652 /*
653 ----------------------------------------------------------------------
654 _svmf_tree_compare_interface_method_signature
655 ----------------------------------------------------------------------
656 */
657 
658 inline svm_static jint
_svmf_tree_compare_imethod_signature(_svmt_imethod_signature_node * value1,_svmt_imethod_signature_node * value2)659 _svmf_tree_compare_imethod_signature (_svmt_imethod_signature_node *value1,
660 				      _svmt_imethod_signature_node *value2)
661 {
662   jint diff = strcmp (value1->name, value2->name);
663 
664   if (diff == 0)
665     {
666       diff = strcmp (value1->descriptor, value2->descriptor);
667     }
668 
669   return diff;
670 }
671 
672 /*
673 ----------------------------------------------------------------------
674 _svmf_tree_compare_gc_map
675 ----------------------------------------------------------------------
676 */
677 
678 inline svm_static jint
_svmf_tree_compare_gc_map(_svmt_gc_map_node * value1,_svmt_gc_map_node * value2)679 _svmf_tree_compare_gc_map (_svmt_gc_map_node *value1,
680 			   _svmt_gc_map_node *value2)
681 {
682   jint diff;
683   jint i;
684   jint size;
685 
686   assert (value1 != NULL);
687   assert (value2 != NULL);
688 
689   diff = value1->size - value2->size;
690   i = 0;
691   size = value1->size;
692 
693   while (diff == 0 && i < size)
694     {
695       diff =
696 	_svmf_get_bit (value1->bits, i) - _svmf_get_bit (value2->bits, i);
697       i++;
698     }
699 
700   return diff;
701 }
702 
703 /*
704 ----------------------------------------------------------------------
705 _svmf_tree_compare_sequence
706 ----------------------------------------------------------------------
707 */
708 
709 inline svm_static jint
_svmf_tree_compare_sequence(_svmt_sequence_node * value1,_svmt_sequence_node * value2)710 _svmf_tree_compare_sequence (_svmt_sequence_node *value1,
711 			     _svmt_sequence_node *value2)
712 {
713   jint diff;
714   jint i;
715   jint size;
716 
717   assert (value1 != NULL);
718   assert (value2 != NULL);
719 
720   diff = value1->instructions_length - value2->instructions_length;
721   i = 0;
722   size = value1->instructions_length;
723 
724   while (diff == 0 && i < size)
725     {
726       diff = value1->instructions[i] - value2->instructions[i];
727       i++;
728     }
729 
730   return diff;
731 }
732 
733 /*
734 ----------------------------------------------------------------------
735 _svmf_tree_compare_internal_method
736 ----------------------------------------------------------------------
737 */
738 
739 inline svm_static jint
_svmf_tree_compare_internal_method(_svmt_internal_method_node * value1,_svmt_internal_method_node * value2)740 _svmf_tree_compare_internal_method (_svmt_internal_method_node *value1,
741 				    _svmt_internal_method_node *value2)
742 {
743   assert (value1 != NULL);
744   assert (value2 != NULL);
745 
746   return strcmp (value1->name, value2->name);
747 }
748 
749 /*
750 ----------------------------------------------------------------------
751 _svmh_global_copy_jobject
752 ----------------------------------------------------------------------
753 */
754 
755 inline svm_static jint
_svmh_global_copy_jobject(_svmt_JNIEnv * env,jobject src,jobject * dest)756 _svmh_global_copy_jobject (_svmt_JNIEnv *env, jobject src, jobject *dest)
757 {
758   assert (src != NULL);
759 
760   if (_svmm_new_native_global (env, *dest) != JNI_OK)
761     {
762       return JNI_ERR;
763     }
764 
765   **dest = *src;
766   return JNI_OK;
767 }
768 
769 /*
770 ----------------------------------------------------------------------
771 _svmh_galloc_copy_str_no_exception
772 ----------------------------------------------------------------------
773 */
774 
775 #define _svmm_galloc_copy_str_no_exception(dst, src) \
776 _svmh_galloc_copy_str_no_exception (&dst, src)
777 
778 svm_static jint
_svmh_galloc_copy_str_no_exception(char ** dest,const char * src)779 _svmh_galloc_copy_str_no_exception (char **dest, const char *src)
780 {
781   char *tmp;
782 
783   assert (src != NULL);
784 
785   tmp = _svmf_malloc (strlen (src) + 1);
786 
787   if (tmp == NULL)
788     {
789       return JNI_ERR;
790     }
791 
792   strcpy (tmp, src);
793 
794   *dest = tmp;
795   return JNI_OK;
796 }
797 
798 /*
799 ----------------------------------------------------------------------
800 _svmh_gfree_str_no_exception
801 ----------------------------------------------------------------------
802 */
803 
804 #define _svmm_gfree_str_no_exception(str) \
805 _svmh_gfree_str_no_exception (&str)
806 
807 svm_static void
_svmh_gfree_str_no_exception(char ** str)808 _svmh_gfree_str_no_exception (char **str)
809 {
810   assert (*str != NULL);
811 
812   _svmf_free (*str);
813   *str = NULL;
814 }
815 
816 /*
817 ----------------------------------------------------------------------
818 _svmh_galloc_copy_str
819 ----------------------------------------------------------------------
820 */
821 
822 #define _svmm_galloc_copy_str(env, dst, src) \
823 _svmh_galloc_copy_str (env, &dst, src)
824 
825 svm_static jint
_svmh_galloc_copy_str(_svmt_JNIEnv * env,char ** dest,const char * src)826 _svmh_galloc_copy_str (_svmt_JNIEnv *env, char **dest, const char *src)
827 {
828   char *tmp;
829 
830   assert (src != NULL);
831 
832   tmp = _svmf_malloc (strlen (src) + 1);
833 
834   if (tmp == NULL)
835     {
836       _svmf_error_OutOfMemoryError (env);
837       return JNI_ERR;
838     }
839 
840   strcpy (tmp, src);
841 
842   *dest = tmp;
843   return JNI_OK;
844 }
845 
846 /*
847 ----------------------------------------------------------------------
848 _svmh_gfree_str
849 ----------------------------------------------------------------------
850 */
851 
852 #define _svmm_gfree_str(str) \
853 _svmh_gfree_str (&str)
854 
855 svm_static void
_svmh_gfree_str(char ** str)856 _svmh_gfree_str (char **str)
857 {
858   assert (*str != NULL);
859 
860   _svmf_free (*str);
861   *str = NULL;
862 }
863 
864 /*
865 ----------------------------------------------------------------------
866 _svmh_new_native_global_array
867 ----------------------------------------------------------------------
868 */
869 
870 #ifdef COMMENT
871 
872 static jint
_svmh_new_native_global_array(_svmt_JNIEnv * env,jarray * array)873 _svmh_new_native_global_array (_svmt_JNIEnv *env, jarray *array)
874 {
875   return _svmh_new_native_global (env, (jobject *) array);
876 }
877 
878 #endif /* COMMENT */
879 
880 /*
881 ----------------------------------------------------------------------
882 _svmh_free_native_global_array
883 ----------------------------------------------------------------------
884 */
885 
886 #ifdef COMMENT
887 
888 static void
_svmh_free_native_global_array(_svmt_JNIEnv * env,jarray * pglobal_arrayref)889 _svmh_free_native_global_array (_svmt_JNIEnv *env, jarray *pglobal_arrayref)
890 {
891   _svmh_free_native_global (env, (jobject *) pglobal_arrayref);
892 }
893 
894 #endif /* COMMENT */
895 
896 /*
897 ----------------------------------------------------------------------
898 _svmh_new_native_local_array
899 ----------------------------------------------------------------------
900 */
901 
902 static jint
_svmh_new_native_local_array(_svmt_JNIEnv * env,jarray * array)903 _svmh_new_native_local_array (_svmt_JNIEnv *env, jarray *array)
904 {
905   return _svmh_new_native_local (env, (jobject *) array);
906 }
907 
908 /*
909 ----------------------------------------------------------------------
910 _svmh_free_native_local_array
911 ----------------------------------------------------------------------
912 */
913 
914 static void
_svmh_free_native_local_array(_svmt_JNIEnv * env,jarray * pglobal_arrayref)915 _svmh_free_native_local_array (_svmt_JNIEnv *env, jarray *pglobal_arrayref)
916 {
917   _svmh_free_native_local (env, (jobject *) pglobal_arrayref);
918 }
919 
920 /*
921 ----------------------------------------------------------------------
922 _svmh_local_wrap_pointer
923 ----------------------------------------------------------------------
924 */
925 
926 svm_static jint
_svmh_local_wrap_pointer(_svmt_JNIEnv * env,void * pointer,jbyteArray * pwrapper)927 _svmh_local_wrap_pointer (_svmt_JNIEnv *env, void *pointer,
928 			  jbyteArray *pwrapper)
929 {
930   _svmt_JavaVM *vm = env->vm;
931   jbyteArray wrapper = NULL;
932 
933   if (_svmm_new_native_local_array (env, wrapper) != JNI_OK)
934     {
935       return JNI_ERR;
936     }
937 
938   if (_svmm_new_array_instance
939       (env, vm->class_loading.boot_loader.classes.byte_array, sizeof (void *),
940        *wrapper) != JNI_OK)
941     {
942       _svmm_free_native_local_array (env, wrapper);
943       return JNI_ERR;
944     }
945 
946   /* put "pointer" into the "wrapper" array */
947   *((void **) (void *)
948     (((char *) *wrapper) + _svmf_aligned_size_t
949      (sizeof (_svmt_array_instance)))) = pointer;
950 
951   *pwrapper = wrapper;
952 
953   return JNI_OK;
954 }
955 
956 /*
957 ----------------------------------------------------------------------
958 _svmf_wrap_pointer
959 ----------------------------------------------------------------------
960 */
961 
962 svm_static jint
_svmf_wrap_pointer(_svmt_JNIEnv * env,void * pointer,jbyteArray wrapper)963 _svmf_wrap_pointer (_svmt_JNIEnv *env, void *pointer, jbyteArray wrapper)
964 {
965   _svmt_JavaVM *vm = env->vm;
966 
967   if (_svmm_new_array_instance
968       (env, vm->class_loading.boot_loader.classes.byte_array, sizeof (void *),
969        *wrapper) != JNI_OK)
970     {
971       return JNI_ERR;
972     }
973 
974   /* put "pointer" into the "wrapper" array */
975   *((void **) (void *)
976     (((char *) *wrapper) + _svmf_aligned_size_t
977      (sizeof (_svmt_array_instance)))) = pointer;
978 
979   return JNI_OK;
980 }
981 
982 /*
983 ----------------------------------------------------------------------
984 _svmf_unwrap_pointer
985 ----------------------------------------------------------------------
986 */
987 
988 static void *
_svmf_unwrap_pointer(_svmt_array_instance * wrapper)989 _svmf_unwrap_pointer (_svmt_array_instance *wrapper)
990 {
991   return *((void **) (void *)
992 	   (((char *) wrapper) +
993 	    _svmf_aligned_size_t (sizeof (_svmt_array_instance))));
994 }
995 
996 /*
997 ----------------------------------------------------------------------
998 _svmf_unwrap_class_instance
999 ----------------------------------------------------------------------
1000 */
1001 
1002 svm_static _svmt_type_info *
_svmf_unwrap_class_instance(_svmt_JNIEnv * env,jclass class)1003 _svmf_unwrap_class_instance (_svmt_JNIEnv *env, jclass class)
1004 {
1005   _svmt_JavaVM *vm = env->vm;
1006   _svmt_array_instance *vmdata;
1007 
1008   vmdata = _svmf_cast_array_instance
1009     (_svmf_get_REFERENCE_field (*class,
1010 				vm->class_loading.boot_loader.fields.
1011 				jlclass_vmdata->data.instance_field.offset));
1012 
1013   return (_svmt_type_info *) _svmf_unwrap_pointer (vmdata);
1014 }
1015 
1016 /*
1017 ----------------------------------------------------------------------
1018 _svmf_unwrap_field_instance
1019 ----------------------------------------------------------------------
1020 */
1021 
1022 svm_static _svmt_field_info *
_svmf_unwrap_field_instance(_svmt_JNIEnv * env,jobject obj)1023 _svmf_unwrap_field_instance (_svmt_JNIEnv *env, jobject obj)
1024 {
1025   _svmt_JavaVM *vm = env->vm;
1026   _svmt_array_instance *vmdata;
1027 
1028   vmdata = _svmf_cast_array_instance
1029     (_svmf_get_REFERENCE_field (*obj,
1030 				vm->class_loading.boot_loader.fields.
1031 				jlrfield_vmdata->data.instance_field.offset));
1032 
1033   return (_svmt_field_info *) _svmf_unwrap_pointer (vmdata);
1034 }
1035 
1036 /*
1037 ----------------------------------------------------------------------
1038 _svmf_unwrap_method_instance
1039 ----------------------------------------------------------------------
1040 */
1041 
1042 svm_static _svmt_method_info *
_svmf_unwrap_method_instance(_svmt_JNIEnv * env,jobject obj)1043 _svmf_unwrap_method_instance (_svmt_JNIEnv *env, jobject obj)
1044 {
1045   _svmt_JavaVM *vm = env->vm;
1046   _svmt_array_instance *vmdata;
1047 
1048   vmdata = _svmf_cast_array_instance
1049     (_svmf_get_REFERENCE_field (*obj,
1050 				vm->class_loading.boot_loader.fields.
1051 				jlrmethod_vmdata->data.instance_field.
1052 				offset));
1053 
1054   return (_svmt_method_info *) _svmf_unwrap_pointer (vmdata);
1055 }
1056 
1057 /*
1058 ----------------------------------------------------------------------
1059 _svmf_unwrap_constructor_instance
1060 ----------------------------------------------------------------------
1061 */
1062 
1063 svm_static _svmt_method_info *
_svmf_unwrap_constructor_instance(_svmt_JNIEnv * env,jobject obj)1064 _svmf_unwrap_constructor_instance (_svmt_JNIEnv *env, jobject obj)
1065 {
1066   _svmt_JavaVM *vm = env->vm;
1067   _svmt_array_instance *vmdata;
1068 
1069   vmdata = _svmf_cast_array_instance
1070     (_svmf_get_REFERENCE_field (*obj,
1071 				vm->class_loading.boot_loader.fields.
1072 				jlrconstructor_vmdata->data.instance_field.
1073 				offset));
1074 
1075   return (_svmt_method_info *) _svmf_unwrap_pointer (vmdata);
1076 }
1077 
1078 /*
1079 ----------------------------------------------------------------------
1080 _svmf_new_class
1081 ----------------------------------------------------------------------
1082 */
1083 
1084 svm_static jint
_svmf_new_class_pd(_svmt_JNIEnv * env,_svmt_type_info * type,jobject protection_domain)1085 _svmf_new_class_pd (_svmt_JNIEnv *env, _svmt_type_info *type,
1086 		    jobject protection_domain)
1087 {
1088   _svmt_JavaVM *vm = env->vm;
1089   jbyteArray data = NULL;
1090   jclass class_instance = NULL;
1091 
1092   if (_svmm_local_wrap_pointer (env, type, data) != JNI_OK)
1093     {
1094       return JNI_ERR;
1095     }
1096 
1097   if (_svmm_new_native_global (env, class_instance) != JNI_OK)
1098     {
1099       _svmm_free_native_local_array (env, data);
1100       return JNI_ERR;
1101     }
1102 
1103   if (_svmm_new_object_instance
1104       (env, vm->class_loading.boot_loader.classes.jlclass,
1105        *class_instance) != JNI_OK)
1106     {
1107       _svmm_free_native_local_array (env, data);
1108       _svmm_free_native_global (env, class_instance);
1109       return JNI_ERR;
1110     }
1111 
1112   if (_svmm_invoke_nonvirtual_jlclass_init
1113       (env, class_instance, _svmf_cast_jobject (data),
1114        protection_domain) != JNI_OK)
1115     {
1116       _svmm_free_native_local_array (env, data);
1117       _svmm_free_native_global (env, class_instance);
1118       return JNI_ERR;
1119     }
1120 
1121   _svmm_free_native_local_array (env, data);
1122 
1123   type->class_instance = class_instance;
1124 
1125   return JNI_OK;
1126 }
1127 
1128 svm_static jint
_svmf_new_class(_svmt_JNIEnv * env,_svmt_type_info * type)1129 _svmf_new_class (_svmt_JNIEnv *env, _svmt_type_info *type)
1130 {
1131   return _svmf_new_class_pd (env, type, (jobject) (NULL));
1132 }
1133 
1134 /*
1135 ----------------------------------------------------------------------
1136 _svmf_find_method_in_class
1137 ----------------------------------------------------------------------
1138 */
1139 
1140 /*
1141 inline static _svmt_method_info *
1142 _svmf_find_method_in_class (_svmt_class_info *class, const char *name,
1143 			    const char *descriptor)
1144 {
1145   jint methods_count = class->methods_count;
1146   _svmt_method_info *methods = class->methods;
1147   jint i;
1148 
1149   for (i = 0; i < methods_count; i++)
1150     {
1151       _svmt_method_info *method = &methods[i];
1152 
1153       if (strcmp (name, DREF (method->name, value)) == 0 &&
1154 	  strcmp (descriptor, DREF (method->descriptor, value)) == 0)
1155 	{
1156 	  return method;
1157 	}
1158     }
1159 
1160   return NULL;
1161 }
1162 */
1163 
1164 /*
1165 ----------------------------------------------------------------------
1166 _svmf_get_string
1167 ----------------------------------------------------------------------
1168 */
1169 
1170 svm_static jint
_svmf_get_string(_svmt_JNIEnv * env,const char * value,jstring str)1171 _svmf_get_string (_svmt_JNIEnv *env, const char *value, jstring str)
1172 {
1173   _svmt_JavaVM *vm = env->vm;
1174   jbyteArray data = NULL;
1175   jint length = strlen (value);
1176   jint status;
1177 
1178   if (_svmm_new_native_local_array (env, data) != JNI_OK)
1179     {
1180       return JNI_ERR;
1181     }
1182 
1183   if (_svmm_new_array_instance
1184       (env, vm->class_loading.boot_loader.classes.byte_array, length,
1185        *data) != JNI_OK)
1186     {
1187       _svmm_free_native_local_array (env, data);
1188       return JNI_ERR;
1189     }
1190 
1191   /* put the string characters into the "wrapper" array without
1192      including the end-of-string '\0' marker */
1193   strncpy (((char *) *data) +
1194 	   _svmf_aligned_size_t (sizeof (_svmt_array_instance)), value,
1195 	   length);
1196 
1197   status =
1198     _svmm_invoke_static_stringcreator_createstring
1199     (env, _svmf_cast_jobject (data), str);
1200 
1201   _svmm_free_native_local_array (env, data);
1202 
1203   return status;
1204 }
1205 
1206 /*
1207 ----------------------------------------------------------------------
1208 _svmf_get_interned_string
1209 ----------------------------------------------------------------------
1210 */
1211 
1212 svm_static jint
_svmf_get_interned_string(_svmt_JNIEnv * env,const char * value,jstring str)1213 _svmf_get_interned_string (_svmt_JNIEnv *env, const char *value, jstring str)
1214 {
1215   _svmt_JavaVM *vm = env->vm;
1216   jbyteArray data = NULL;
1217   jint length = strlen (value);
1218   jint status;
1219 
1220   if (_svmm_new_native_local_array (env, data) != JNI_OK)
1221     {
1222       return JNI_ERR;
1223     }
1224 
1225   if (_svmm_new_array_instance
1226       (env, vm->class_loading.boot_loader.classes.byte_array, length,
1227        *data) != JNI_OK)
1228     {
1229       _svmm_free_native_local_array (env, data);
1230       return JNI_ERR;
1231     }
1232 
1233   /* put the string characters into the "wrapper" array without
1234      including the end-of-string '\0' marker */
1235   strncpy (((char *) *data) +
1236 	   _svmf_aligned_size_t (sizeof (_svmt_array_instance)), value,
1237 	   length);
1238 
1239   status =
1240     _svmm_invoke_static_stringcreator_createinternedstring
1241     (env, _svmf_cast_jobject (data), str);
1242 
1243   _svmm_free_native_local_array (env, data);
1244 
1245   return status;
1246 }
1247 
1248 /*
1249 ----------------------------------------------------------------------
1250 _svmf_get_current_working_directory
1251 ----------------------------------------------------------------------
1252 */
1253 
1254 svm_static const char *
_svmf_get_current_working_directory(void)1255 _svmf_get_current_working_directory (void)
1256 {
1257   size_t size = 1024;
1258   char *buffer = _svmf_malloc (size);
1259 
1260   while (buffer != NULL)
1261     {
1262       if (getcwd (buffer, size) != NULL)
1263 	{
1264 	  return buffer;
1265 	}
1266 
1267       _svmf_free (buffer);
1268 
1269       {
1270 	size_t old_size = size;
1271 
1272 	size *= 2;
1273 
1274 	if (size <= old_size)
1275 	  {
1276 	    return NULL;
1277 	  }
1278       }
1279 
1280       buffer = _svmf_malloc (size);
1281     }
1282 
1283   return NULL;
1284 }
1285 
1286 /*
1287 ----------------------------------------------------------------------
1288 _svmm_galloc_utf_chars
1289 ----------------------------------------------------------------------
1290 */
1291 
1292 #define _svmm_galloc_utf_chars(env, src, dst) \
1293 _svmh_galloc_utf_chars (env, src, &dst)
1294 
1295 #define _svmm_gfree_utf_chars(str) \
1296 _svmm_gfree_str(str)
1297 
1298 svm_static jint
_svmh_galloc_utf_chars(_svmt_JNIEnv * env,jstring src,char ** pdst)1299 _svmh_galloc_utf_chars (_svmt_JNIEnv *env, jstring src, char **pdst)
1300 {
1301   jbyteArray bytes;
1302   char *result;
1303 
1304   if (_svmm_new_native_local_array (env, bytes) != JNI_OK)
1305     {
1306       return JNI_ERR;
1307     }
1308 
1309   if (_svmm_invoke_static_stringcreator_getutfchars
1310       (env, src, _svmf_cast_jobject (bytes)) != JNI_OK)
1311     {
1312       _svmm_free_native_local_array (env, bytes);
1313       return JNI_ERR;
1314     }
1315 
1316   {
1317     char *str =
1318       ((char *) *bytes) +
1319       _svmf_aligned_size_t (sizeof (_svmt_array_instance));
1320 
1321     if (_svmm_galloc_copy_str (env, result, str) != JNI_OK)
1322       {
1323 	_svmm_free_native_local_array (env, bytes);
1324 	return JNI_ERR;
1325       }
1326 
1327     _svmm_free_native_local_array (env, bytes);
1328     *pdst = result;
1329     return JNI_OK;
1330   }
1331 }
1332 
1333 /*
1334 ----------------------------------------------------------------------
1335 _svmf_is_super_class
1336 ----------------------------------------------------------------------
1337 */
1338 
1339 svm_static jboolean
_svmf_is_super_class(_svmt_class_info * class1,_svmt_class_info * class2)1340 _svmf_is_super_class (_svmt_class_info *class1, _svmt_class_info *class2)
1341 {
1342   _svmt_class_info *current;
1343 
1344   if (CAN_DREF (class2->super_class))
1345     {
1346       current = _svmf_cast_class (DREF (class2->super_class, type));
1347     }
1348   else
1349     {
1350       current = NULL;
1351     }
1352 
1353   while (current != NULL)
1354     {
1355       if (current == class1)
1356 	{
1357 	  return JNI_TRUE;
1358 	}
1359 
1360       if (CAN_DREF (current->super_class))
1361 	{
1362 	  current = _svmf_cast_class (DREF (current->super_class, type));
1363 	}
1364       else
1365 	{
1366 	  current = NULL;
1367 	}
1368     }
1369 
1370   return JNI_FALSE;
1371 }
1372 
1373 /*
1374 ----------------------------------------------------------------------
1375 _svmf_get_current_class_loader
1376 ----------------------------------------------------------------------
1377 */
1378 
1379 svm_static _svmt_class_loader_info *
_svmf_get_current_class_loader(_svmt_JNIEnv * env)1380 _svmf_get_current_class_loader (_svmt_JNIEnv *env)
1381 {
1382   _svmt_JavaVM *vm = env->vm;
1383   _svmt_stack_frame *frame = env->stack.current_frame;
1384   _svmt_method_info *method = frame->method;
1385 
1386   while (method != &vm->stack_bottom_method &&
1387 	 method != &vm->vm_initiated_call_method)
1388     {
1389       if ((!_svmf_is_set_flag (method->access_flags, SVM_ACC_INTERNAL)) &&
1390 	  method->class_info->class_loader_info->class_loader != NULL)
1391 	{
1392 	  return method->class_info->class_loader_info;
1393 	}
1394 
1395       frame = (_svmt_stack_frame *) (void *)
1396 	(((char *) frame) - frame->previous_offset);
1397       method = frame->method;
1398     }
1399 
1400   return vm->class_loading.boot_loader.class_loader_info;
1401 }
1402 
1403 /*
1404 ----------------------------------------------------------------------
1405 _svmf_enter_class_loader_monitor
1406 ----------------------------------------------------------------------
1407 */
1408 
1409 svm_static jint
_svmf_enter_class_loader_monitor(_svmt_JNIEnv * env,_svmt_class_loader_info * class_loader_info)1410 _svmf_enter_class_loader_monitor (_svmt_JNIEnv *env,
1411 				  _svmt_class_loader_info *class_loader_info)
1412 {
1413   if (class_loader_info->class_loader == NULL)
1414     {
1415       _svmt_JavaVM *vm = env->vm;
1416       assert (class_loader_info ==
1417 	      vm->class_loading.boot_loader.class_loader_info);
1418 
1419       if (_svmf_enter_object_monitor
1420 	  (env,
1421 	   *(vm->class_loading.boot_loader.classes.virtualmachine->
1422 	     class_instance)) != JNI_OK)
1423 	{
1424 	  return JNI_ERR;
1425 	}
1426     }
1427   else
1428     {
1429       if (_svmf_enter_object_monitor (env, *(class_loader_info->class_loader))
1430 	  != JNI_OK)
1431 	{
1432 	  return JNI_ERR;
1433 	}
1434     }
1435 
1436   return JNI_OK;
1437 }
1438 
1439 /*
1440 ----------------------------------------------------------------------
1441 _svmf_exit_class_loader_monitor
1442 ----------------------------------------------------------------------
1443 */
1444 
1445 svm_static jint
_svmf_exit_class_loader_monitor(_svmt_JNIEnv * env,_svmt_class_loader_info * class_loader_info)1446 _svmf_exit_class_loader_monitor (_svmt_JNIEnv *env,
1447 				 _svmt_class_loader_info *class_loader_info)
1448 {
1449   if (class_loader_info->class_loader == NULL)
1450     {
1451       _svmt_JavaVM *vm = env->vm;
1452       assert (class_loader_info ==
1453 	      vm->class_loading.boot_loader.class_loader_info);
1454 
1455       if (_svmf_exit_object_monitor
1456 	  (env,
1457 	   *(vm->class_loading.boot_loader.classes.virtualmachine->
1458 	     class_instance)) != JNI_OK)
1459 	{
1460 	  return JNI_ERR;
1461 	}
1462     }
1463   else
1464     {
1465       if (_svmf_exit_object_monitor (env, *(class_loader_info->class_loader))
1466 	  != JNI_OK)
1467 	{
1468 	  return JNI_ERR;
1469 	}
1470     }
1471 
1472   return JNI_OK;
1473 }
1474 
1475 /*
1476 ----------------------------------------------------------------------
1477 _svmf_wrap_exception_in_invocationte
1478 ----------------------------------------------------------------------
1479 */
1480 
1481 /* This function wraps the "current_exception" parameter into a new
1482    InvocationTargetException instance, then throws it. */
1483 
1484 svm_static int
_svmf_wrap_exception_in_invocationte(_svmt_JNIEnv * env,jobject current_exception)1485 _svmf_wrap_exception_in_invocationte (_svmt_JNIEnv *env,
1486 				      jobject current_exception)
1487 {
1488   _svmt_JavaVM *vm = env->vm;
1489   jobject invocationte = NULL;
1490   jint status;
1491 
1492   if (_svmm_new_native_local (env, invocationte) != JNI_OK)
1493     {
1494       return JNI_ERR;
1495     }
1496 
1497   if (_svmm_new_object_instance
1498       (env,
1499        vm->class_loading.boot_loader.classes.jlrinvocationtargetexception,
1500        *invocationte) != JNI_OK)
1501     {
1502       _svmm_free_native_local (env, invocationte);
1503       return JNI_ERR;
1504     }
1505 
1506   status =
1507     _svmm_invoke_nonvirtual_jlrinvocationtargetexception_init (env,
1508 							       invocationte,
1509 							       current_exception);
1510 
1511   /* if no exception was raised, throw InvocationTargetException
1512      instance */
1513   if (status == JNI_OK)
1514     {
1515       *(env->throwable) = *invocationte;
1516     }
1517 
1518   _svmm_free_native_local (env, invocationte);
1519 
1520   return JNI_ERR;
1521 }
1522 
1523 /*
1524 ----------------------------------------------------------------------
1525 _svmf_verbose_methods_enter
1526 ----------------------------------------------------------------------
1527 */
1528 
1529 #ifndef NDEBUG
1530 
1531 inline svm_static void
_svmf_verbose_methods_enter(_svmt_JNIEnv * env)1532 _svmf_verbose_methods_enter (_svmt_JNIEnv *env)
1533 {
1534   if (env->vm->verbose_methods == JNI_TRUE)
1535     {
1536       _svmt_method_info *method = env->stack.current_frame->method;
1537 
1538       _svmf_printf (env, stderr,
1539 		    "T%d: [verbose methods: entering method %s.%s%s]\n",
1540 		    env->thread.id,
1541 		    method->class_info->name,
1542 		    DREF (method->name, value),
1543 		    DREF (method->descriptor, value));
1544     }
1545 }
1546 
1547 #endif /* !NDEBUG */
1548 
1549 /*
1550 ----------------------------------------------------------------------
1551 _svmf_verbose_methods_exit
1552 ----------------------------------------------------------------------
1553 */
1554 
1555 #ifndef NDEBUG
1556 
1557 inline svm_static void
_svmf_verbose_methods_exit(_svmt_JNIEnv * env)1558 _svmf_verbose_methods_exit (_svmt_JNIEnv *env)
1559 {
1560   if (env->vm->verbose_methods == JNI_TRUE)
1561     {
1562       _svmt_method_info *method = env->stack.current_frame->method;
1563 
1564       _svmf_printf (env, stderr,
1565 		    "T%d: [verbose methods: exiting  method %s.%s%s]\n",
1566 		    env->thread.id,
1567 		    method->class_info->name,
1568 		    DREF (method->name, value),
1569 		    DREF (method->descriptor, value));
1570 
1571       {
1572 	_svmt_method_info *caller_method;
1573 	_svmt_stack_frame *caller_frame = env->stack.current_frame;
1574 	caller_frame = (_svmt_stack_frame *) (void *)
1575 	  (((char *) caller_frame) - caller_frame->previous_offset);
1576 	caller_method = caller_frame->method;
1577 
1578 	while (_svmf_is_set_flag
1579 	       (caller_method->access_flags, SVM_ACC_INTERNAL)
1580 	       && caller_method != &env->vm->stack_bottom_method)
1581 	  {
1582 	    caller_frame = (_svmt_stack_frame *) (void *)
1583 	      (((char *) caller_frame) - caller_frame->previous_offset);
1584 	    caller_method = caller_frame->method;
1585 	  }
1586 
1587 	if (!_svmf_is_set_flag
1588 	    (caller_method->access_flags, SVM_ACC_INTERNAL))
1589 	  {
1590 	    _svmf_printf (env, stderr,
1591 			  "T%d: [                   returning to %s.%s%s]\n",
1592 			  env->thread.id,
1593 			  caller_method->class_info->name,
1594 			  DREF (caller_method->name, value),
1595 			  DREF (caller_method->descriptor, value));
1596 	  }
1597       }
1598     }
1599 }
1600 
1601 #endif /* !NDEBUG */
1602 
1603 /*
1604 ----------------------------------------------------------------------
1605 _svmm_get_type_from_within_descriptor
1606 ----------------------------------------------------------------------
1607 */
1608 
1609 #ifndef NDEBUG
1610 
1611 #define _svmm_get_type_from_within_descriptor(env, method_info, current, index) \
1612 _svmh_get_type_from_within_descriptor (env, method_info, &current, &index)
1613 
1614 svm_static _svmt_type_info *
_svmh_get_type_from_within_descriptor(_svmt_JNIEnv * env,_svmt_method_info * method_info,const char ** pcurrent,jint * pindex)1615 _svmh_get_type_from_within_descriptor (_svmt_JNIEnv *env,
1616 				       _svmt_method_info *method_info,
1617 				       const char **pcurrent, jint *pindex)
1618 {
1619   const char *current = *pcurrent;
1620   _svmt_type_info *result = NULL;
1621 
1622   switch (*current)
1623     {
1624     case 'B':
1625     case 'C':
1626     case 'F':
1627     case 'I':
1628     case 'S':
1629     case 'Z':
1630     case 'V':
1631       {
1632 	current++;
1633 	(*pindex)++;
1634       }
1635       break;
1636 
1637     case 'D':
1638     case 'J':
1639       {
1640 	current++;
1641 	(*pindex) += 2;
1642       }
1643       break;
1644 
1645     case 'L':
1646       {
1647 	jint length = 0;
1648 	char *p = (char *) current;
1649 	_svmt_u8 *name;
1650 
1651 	while (*++p != ';')
1652 	  {
1653 	    length++;
1654 	  }
1655 
1656 	if (_svmm_gzmalloc_ubytes (env, length + 1, name) != JNI_OK)
1657 	  {
1658 	    _svmm_fatal_error ("unsupported failure while debugging");
1659 	  }
1660 
1661 	p = (char *) name;
1662 	while (*++current != ';')
1663 	  {
1664 	    *(p++) = *current;
1665 	  }
1666 
1667 	current++;
1668 	(*pindex)++;
1669 
1670 	if (_svmm_create_type
1671 	    (env, method_info->class_info->class_loader_info,
1672 	     (const char *) name, result) != JNI_OK)
1673 	  {
1674 	    _svmm_fatal_error ("unsupported failure while debugging");
1675 	  }
1676 
1677 	_svmm_gzmfree_ubytes (name);
1678       }
1679       break;
1680 
1681     case '[':
1682       {
1683 	jint length = 0;
1684 	char *p = (char *) current;
1685 	_svmt_u8 *name;
1686 
1687 	while (*p == '[')
1688 	  {
1689 	    p++;
1690 	    length++;
1691 	  }
1692 
1693 	if (*p == 'L')
1694 	  {
1695 	    while (*p != ';')
1696 	      {
1697 		p++;
1698 		length++;
1699 	      }
1700 	    length++;
1701 	  }
1702 	else
1703 	  {
1704 	    length++;
1705 	  }
1706 
1707 	if (_svmm_gzmalloc_ubytes (env, length + 1, name) != JNI_OK)
1708 	  {
1709 	    _svmm_fatal_error ("unsupported failure while debugging");
1710 	  }
1711 
1712 	p = (char *) name;
1713 	while (*current == '[')
1714 	  {
1715 	    *(p++) = *current++;
1716 	  }
1717 
1718 	if (*current == 'L')
1719 	  {
1720 	    while (*current != ';')
1721 	      {
1722 		*(p++) = *current++;
1723 	      }
1724 	    *(p++) = *current++;
1725 	  }
1726 	else
1727 	  {
1728 	    *(p++) = *current++;
1729 	  }
1730 
1731 	(*pindex)++;
1732 
1733 	if (_svmm_create_type
1734 	    (env, method_info->class_info->class_loader_info,
1735 	     (const char *) name, result) != JNI_OK)
1736 	  {
1737 	    _svmm_fatal_error ("unsupported failure while debugging");
1738 	  }
1739 
1740 	if (_svmf_link_type (env, result) != JNI_OK)
1741 	  {
1742 	    _svmm_fatal_error ("unsupported failure while debugging");
1743 	  }
1744 
1745 	_svmm_gzmfree_ubytes (name);
1746       }
1747       break;
1748 
1749     default:
1750       {
1751 	_svmm_fatal_error ("impossible control flow");
1752       }
1753     }
1754 
1755   *pcurrent = current;
1756   return result;
1757 }
1758 
1759 #endif /* !NDEBUG */
1760 
1761 /*
1762 ----------------------------------------------------------------------
1763 _svmm_skip_type_within_descriptor
1764 ----------------------------------------------------------------------
1765 */
1766 
1767 #ifndef NDEBUG
1768 
1769 #define _svmm_skip_type_within_descriptor(current, index) \
1770 _svmh_skip_type_within_descriptor (&current, &index)
1771 
1772 svm_static void
_svmh_skip_type_within_descriptor(const char ** pcurrent,jint * pindex)1773 _svmh_skip_type_within_descriptor (const char **pcurrent, jint *pindex)
1774 {
1775   const char *current = *pcurrent;
1776 
1777   switch (*current++)
1778     {
1779     case 'B':
1780     case 'C':
1781     case 'F':
1782     case 'I':
1783     case 'S':
1784     case 'Z':
1785     case 'V':
1786       {
1787 	(*pindex)++;
1788       }
1789       break;
1790 
1791     case 'D':
1792     case 'J':
1793       {
1794 	(*pindex) += 2;
1795       }
1796       break;
1797 
1798     case 'L':
1799       {
1800 	while (*current++ != ';');
1801 
1802 	(*pindex)++;
1803       }
1804       break;
1805 
1806     case '[':
1807       {
1808 	while (*current == '[')
1809 	  {
1810 	    current++;
1811 	  }
1812 
1813 	if (*current++ == 'L')
1814 	  {
1815 	    while (*current++ != ';');
1816 	  }
1817 
1818 	(*pindex)++;
1819       }
1820       break;
1821 
1822     default:
1823       {
1824 	_svmm_fatal_error ("impossible control flow");
1825       }
1826     }
1827 
1828   *pcurrent = current;
1829 }
1830 
1831 #endif /* !NDEBUG */
1832 
1833 /*
1834 ----------------------------------------------------------------------
1835 _svmf_print_statistics
1836 ----------------------------------------------------------------------
1837 */
1838 #ifdef STATISTICS
1839 svm_static void
_svmf_print_statistics(_svmt_JNIEnv * env)1840 _svmf_print_statistics (_svmt_JNIEnv *env)
1841 {
1842   _svmt_JavaVM *vm = env->vm;
1843 
1844   _svmf_printf (env, stderr, "\nSTATS: Number of prepared classes: %d\n",
1845 		vm->class_count);
1846   _svmf_printf (env, stderr, "STATS: Number of prepared interfaces: %d\n",
1847 		vm->interface_count);
1848   _svmf_printf (env, stderr, "STATS: Number of prepared arrays: %d\n",
1849 		vm->array_count);
1850   _svmf_printf (env, stderr, "STATS: Number of prepared methods: %d\n",
1851 		vm->method_count);
1852   _svmf_printf (env, stderr,
1853 		"STATS: Number of prepared bytecode instructions: %d\n",
1854 		vm->bytecode_instruction_count);
1855   _svmf_printf (env, stderr,
1856 		"STATS: Number of prepared bytecodes: %d\n",
1857 		vm->bytecode_count);
1858   _svmf_printf (env, stderr, "STATS: Code array size: %d\n\n", vm->code_size);
1859 
1860   _svmf_printf (env, stderr,
1861 		"STATS: Maximum stack size: %d\n", vm->max_stack_size);
1862   _svmf_printf (env, stderr,
1863 		"STATS: Number of locals on stack: %d\n",
1864 		vm->stack_local_count);
1865   _svmf_printf (env, stderr,
1866 		"STATS: Number of split locals on stack: %d\n\n",
1867 		vm->stack_local_split_count);
1868 
1869   _svmf_printf (env, stderr,
1870 		"STATS: Total sparse interface virtual tables size: %d\n",
1871 		vm->total_ivtables);
1872   _svmf_printf (env, stderr,
1873 		"STATS: Total interface virtual table holes size: %d\n",
1874 		vm->total_holes);
1875   _svmf_printf (env, stderr, "STATS: Total wasted holes size: %d\n\n",
1876 		vm->total_lost_holes);
1877 
1878   _svmf_printf (env, stderr, "STATS: Total GC maps size: %d\n",
1879 		vm->total_gc_maps_size);
1880   _svmf_printf (env, stderr, "STATS: GC maps count: %d\n",
1881 		vm->total_gc_maps_count);
1882   _svmf_printf (env, stderr, "STATS: GC points count: %d\n\n",
1883 		vm->check_points_count);
1884 
1885   _svmf_printf (env, stderr, "STATS: Original locals count: %d\n",
1886 		vm->total_orig_locals_count);
1887   _svmf_printf (env, stderr, "STATS: Unused locals count: %d\n",
1888 		vm->total_unused_locals_count);
1889   _svmf_printf (env, stderr, "STATS: Added locals count: %d\n\n",
1890 		vm->total_added_locals_count);
1891 
1892 #if defined (_SABLEVM_INLINED_THREADED_INTERPRETER)
1893 
1894   _svmf_printf (env, stderr,
1895 		"STATS: Number of distinct (inlined) threads:: %d\n",
1896 		vm->distinct_inlined_threads_count);
1897   _svmf_printf (env, stderr,
1898 		"STATS: Total bytecode count of distinct threads: %d\n",
1899 		vm->total_distinct_thread_bc_length);
1900   _svmf_printf (env, stderr,
1901 		"STATS: Total inlined size of distinct threads: %d\n\n",
1902 		vm->total_distinct_thread_inlined_length);
1903 
1904   _svmf_printf (env, stderr, "STATS: Number of (inlined) threads:: %d\n",
1905 		vm->inlined_threads_count);
1906   _svmf_printf (env, stderr, "STATS: Total bytecode count of threads: %d\n",
1907 		vm->total_thread_bc_length);
1908   _svmf_printf (env, stderr, "STATS: Total inlined size of threads: %d\n\n",
1909 		vm->total_thread_inlined_length);
1910 
1911   _svmf_printf (env, stderr, "STATS: Maximum thread bytecode count: %d\n",
1912 		vm->max_thread_bc_length);
1913   _svmf_printf (env, stderr, "STATS: Maximum thread inlined size: %d\n\n",
1914 		vm->max_thread_inlined_length);
1915 
1916 #endif
1917 
1918 }
1919 #endif /* STATISTICS */
1920