classinfo: changed type of super and interfaces to classref_or_classinfo
[cacao.git] / src / native / native.c
1 /* src/native/native.c - table of native functions
2
3    Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4    R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5    C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6    Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
23    02111-1307, USA.
24
25    Contact: cacao@complang.tuwien.ac.at
26
27    Authors: Reinhard Grafl
28             Roman Obermaisser
29             Andreas Krall
30
31    Changes: Christian Thalinger
32
33    $Id: native.c 2186 2005-04-02 00:43:25Z edwin $
34
35 */
36
37
38 #include <stdlib.h>
39 #include <unistd.h>
40 #include <time.h>
41 #include <math.h>
42 #include <string.h>
43 #include <assert.h>
44 #include <sys/time.h>
45 #include <utime.h>
46
47 /* Include files for IO functions */
48
49 #include <fcntl.h>
50 #include <dirent.h>
51 #include <sys/types.h>
52 #ifdef _OSF_SOURCE 
53 #include <sys/mode.h>
54 #endif
55 #include <sys/stat.h>
56
57 #include "config.h"
58 #include "cacao/cacao.h"
59 #include "mm/memory.h"
60 #include "native/jni.h"
61 #include "native/native.h"
62 #include "native/include/java_lang_Throwable.h"
63 #include "toolbox/logging.h"
64 #include "vm/builtin.h"
65 #include "vm/exceptions.h"
66 #include "vm/global.h"
67 #include "vm/loader.h"
68 #include "vm/options.h"
69 #include "vm/stringlocal.h"
70 #include "vm/tables.h"
71 #include "vm/jit/asmpart.h"
72 #include "vm/jit/jit.h"
73 #include "vm/resolve.h"
74
75
76 /* include table of native functions ******************************************/
77
78 #include "nativetable.inc"
79
80
81 /************* use classinfo structure as java.lang.Class object **************/
82
83 void use_class_as_object(classinfo *c) 
84 {
85         if (!c->classvftbl) {
86                 /* is the class loaded */
87                 if (!c->loaded)
88 /*                      if (!class_load(c)) */
89 /*                              throw_exception_exit(); */
90                         panic("use_class_as_object: class_load should not happen");
91
92                 /* is the class linked */
93                 if (!c->linked)
94                         if (!link_class(c))
95                                 throw_exception_exit();
96
97                 /*if (class_java_lang_Class ==0) panic("java/lang/Class not loaded in use_class_as_object");
98                 if (class_java_lang_Class->vftbl ==0) panic ("vftbl == 0 in use_class_as_object");*/
99                 c->header.vftbl = class_java_lang_Class->vftbl;
100                 c->classvftbl = true;
101         }
102 }
103
104
105 /************************** tables for methods ********************************/
106
107 #undef JOWENN_DEBUG
108 #undef JOWENN_DEBUG1
109
110 #ifdef STATIC_CLASSPATH
111 #define NATIVETABLESIZE  (sizeof(nativetable)/sizeof(struct nativeref))
112
113 /* table for fast string comparison */
114 static nativecompref nativecomptable[NATIVETABLESIZE];
115
116 /* string comparsion table initialized */
117 static bool nativecompdone = false;
118 #endif
119
120
121 /* XXX don't define this in a header file!!! */
122
123 static struct nativeCall nativeCalls[] =
124 {
125 #include "nativecalls.inc"
126 };
127
128 #define NATIVECALLSSIZE    (sizeof(nativeCalls) / sizeof(struct nativeCall))
129
130 struct nativeCompCall nativeCompCalls[NATIVECALLSSIZE];
131
132
133 /* native_loadclasses **********************************************************
134
135    Load classes required for native methods.
136
137 *******************************************************************************/
138
139 bool native_init(void)
140 {
141 #if !defined(STATIC_CLASSPATH)
142         void *p;
143
144         /* We need to access the dummy native table, not only to remove a warning */
145         /* but to be sure that the table is not optimized away (gcc does this     */
146         /* since 3.4).                                                            */
147         p = &dummynativetable;
148 #endif
149
150         /* everything's ok */
151
152         return true;
153 }
154
155
156 /*********************** Function: native_findfunction *************************
157
158         Looks up a method (must have the same class name, method name, descriptor
159         and 'static'ness) and returns a function pointer to it.
160         Returns: function pointer or NULL (if there is no such method)
161
162         Remark: For faster operation, the names/descriptors are converted from C
163                 strings to Unicode the first time this function is called.
164
165 *******************************************************************************/
166
167 functionptr native_findfunction(utf *cname, utf *mname, 
168                                                                 utf *desc, bool isstatic)
169 {
170 #ifdef STATIC_CLASSPATH
171         int i;
172         /* entry of table for fast string comparison */
173         struct nativecompref *n;
174         /* for warning message if no function is found */
175         char *buffer;                   
176         int buffer_len;
177
178         isstatic = isstatic ? true : false;
179         
180         if (!nativecompdone) {
181                 for (i = 0; i < NATIVETABLESIZE; i++) {
182                         nativecomptable[i].classname  = 
183                                 utf_new_char(nativetable[i].classname);
184                         nativecomptable[i].methodname = 
185                                 utf_new_char(nativetable[i].methodname);
186                         nativecomptable[i].descriptor = 
187                                 utf_new_char(nativetable[i].descriptor);
188                         nativecomptable[i].isstatic   = 
189                                 nativetable[i].isstatic;
190                         nativecomptable[i].func       = 
191                                 nativetable[i].func;
192                 }
193                 nativecompdone = true;
194         }
195
196 #ifdef JOWENN_DEBUG
197         buffer_len = 
198                 utf_strlen(cname) + utf_strlen(mname) + utf_strlen(desc) + 64;
199         
200         buffer = MNEW(char, buffer_len);
201
202         strcpy(buffer, "searching matching function in native table:");
203         utf_sprint(buffer+strlen(buffer), mname);
204         strcpy(buffer+strlen(buffer), ": ");
205         utf_sprint(buffer+strlen(buffer), desc);
206         strcpy(buffer+strlen(buffer), " for class ");
207         utf_sprint(buffer+strlen(buffer), cname);
208
209         log_text(buffer);       
210
211         MFREE(buffer, char, buffer_len);
212 #endif
213                 
214         for (i = 0; i < NATIVETABLESIZE; i++) {
215                 n = &(nativecomptable[i]);
216
217                 if (cname == n->classname && mname == n->methodname &&
218                     desc == n->descriptor && isstatic == n->isstatic)
219                         return n->func;
220 #ifdef JOWENN_DEBUG
221                         else {
222                                 if (cname == n->classname && mname == n->methodname )  log_text("static and descriptor mismatch");
223                         
224                                 else {
225                                         buffer_len = 
226                                           utf_strlen(n->classname) + utf_strlen(n->methodname) + utf_strlen(n->descriptor) + 64;
227         
228                                         buffer = MNEW(char, buffer_len);
229
230                                         strcpy(buffer, "comparing with:");
231                                         utf_sprint(buffer+strlen(buffer), n->methodname);
232                                         strcpy (buffer+strlen(buffer), ": ");
233                                         utf_sprint(buffer+strlen(buffer), n->descriptor);
234                                         strcpy(buffer+strlen(buffer), " for class ");
235                                         utf_sprint(buffer+strlen(buffer), n->classname);
236
237                                         log_text(buffer);       
238
239                                         MFREE(buffer, char, buffer_len);
240                                 }
241                         } 
242 #endif
243         }
244
245                 
246         /* no function was found, display warning */
247
248         buffer_len = 
249                 utf_strlen(cname) + utf_strlen(mname) + utf_strlen(desc) + 64;
250
251         buffer = MNEW(char, buffer_len);
252
253         strcpy(buffer, "warning: native function ");
254         utf_sprint(buffer + strlen(buffer), mname);
255         strcpy(buffer + strlen(buffer), ": ");
256         utf_sprint(buffer + strlen(buffer), desc);
257         strcpy(buffer + strlen(buffer), " not found in class ");
258         utf_sprint(buffer + strlen(buffer), cname);
259
260         log_text(buffer);       
261
262         MFREE(buffer, char, buffer_len);
263
264 /*      exit(1); */
265
266         /* keep compiler happy */
267         return NULL;
268 #else
269 /* dynamic classpath */
270   return 0;
271 #endif
272 }
273
274
275 /****************** function class_findfield_approx ****************************
276         
277         searches in 'classinfo'-structure for a field with the
278         specified name
279
280 *******************************************************************************/
281  
282 fieldinfo *class_findfield_approx(classinfo *c, utf *name)
283 {
284         s4 i;
285
286         for (i = 0; i < c->fieldscount; i++) {
287                 /* compare field names */
288                 if ((c->fields[i].name == name))
289                         return &(c->fields[i]);
290         }
291
292         /* field was not found, raise exception */      
293         *exceptionptr = new_exception(string_java_lang_NoSuchFieldException);
294
295         return NULL;
296 }
297
298
299 s4 class_findfield_index_approx(classinfo *c, utf *name)
300 {
301         s4 i;
302
303         for (i = 0; i < c->fieldscount; i++) {
304                 /* compare field names */
305                 if ((c->fields[i].name == name))
306                         return i;
307         }
308
309         /* field was not found, raise exception */      
310         *exceptionptr = new_exception(string_java_lang_NoSuchFieldException);
311
312         return -1;
313 }
314
315
316 /* native_new_and_init *********************************************************
317
318    Creates a new object on the heap and calls the initializer.
319    Returns the object pointer or NULL if memory is exhausted.
320                         
321 *******************************************************************************/
322
323 java_objectheader *native_new_and_init(classinfo *c)
324 {
325         methodinfo *m;
326         java_objectheader *o;
327
328         if (!c)
329                 return *exceptionptr;
330
331         /* create object */
332
333         o = builtin_new(c);
334         
335         if (!o)
336                 return NULL;
337
338         /* find initializer */
339
340         m = class_findmethod(c, utf_init, utf_void__void);
341                                                       
342         /* initializer not found */
343
344         if (!m)
345                 return o;
346
347         /* call initializer */
348
349         asm_calljavafunction(m, o, NULL, NULL, NULL);
350
351         return o;
352 }
353
354
355 java_objectheader *native_new_and_init_string(classinfo *c, java_lang_String *s)
356 {
357         methodinfo *m;
358         java_objectheader *o;
359
360         if (!c)
361                 return *exceptionptr;
362
363         /* create object */
364
365         o = builtin_new(c);
366
367         if (!o)
368                 return NULL;
369
370         /* find initializer */
371
372         m = class_resolveclassmethod(c,
373                                                                  utf_init,
374                                                                  utf_java_lang_String__void,
375                                                                  NULL,
376                                                                  true);
377
378         /* initializer not found */
379
380         if (!m)
381                 return NULL;
382
383         /* call initializer */
384
385         asm_calljavafunction(m, o, s, NULL, NULL);
386
387         return o;
388 }
389
390
391 java_objectheader *native_new_and_init_int(classinfo *c, s4 i)
392 {
393         methodinfo *m;
394         java_objectheader *o;
395
396         if (!c)
397                 return *exceptionptr;
398
399         /* create object */
400
401         o = builtin_new(c);
402         
403         if (!o)
404                 return NULL;
405
406         /* find initializer */
407
408         m = class_resolveclassmethod(c, utf_init, utf_int__void, NULL, true);
409
410         /* initializer not found  */
411
412         if (!m)
413                 return NULL;
414
415         /* call initializer */
416
417         asm_calljavafunction(m, o, (void *) (ptrint) i, NULL, NULL);
418
419         return o;
420 }
421
422
423 java_objectheader *native_new_and_init_throwable(classinfo *c, java_lang_Throwable *t)
424 {
425         methodinfo *m;
426         java_objectheader *o;
427
428         if (!c)
429                 return *exceptionptr;
430
431         /* create object */
432
433         o = builtin_new(c);
434         
435         if (!o)
436                 return NULL;
437
438         /* find initializer */
439
440         m = class_findmethod(c, utf_init, utf_java_lang_Throwable__void);
441                                                       
442         /* initializer not found */
443
444         if (!m)
445                 return NULL;
446
447         /* call initializer */
448
449         asm_calljavafunction(m, o, t, NULL, NULL);
450
451         return o;
452 }
453
454
455 void copy_vftbl(vftbl_t **dest, vftbl_t *src)
456 {
457     *dest = src;
458 #if 0
459     /* XXX this kind of copying does not work (in the general
460      * case). The interface tables would have to be copied, too. I
461      * don't see why we should make a copy anyway. -Edwin
462      */
463         *dest = mem_alloc(sizeof(vftbl) + sizeof(methodptr)*(src->vftbllength-1));
464         memcpy(*dest, src, sizeof(vftbl) - sizeof(methodptr));
465         memcpy(&(*dest)->table, &src->table, src->vftbllength * sizeof(methodptr));
466 #endif
467 }
468
469
470 /******************************************************************************************                                                                                                             
471
472         creates method signature (excluding return type) from array of 
473         class-objects representing the parameters of the method 
474
475 *******************************************************************************************/
476
477
478 utf *create_methodsig(java_objectarray* types, char *retType)
479 {
480     char *buffer;       /* buffer for building the desciptor */
481     char *pos;          /* current position in buffer */
482     utf *result;        /* the method signature */
483     u4 buffer_size = 3; /* minimal size=3: room for parenthesis and returntype */
484     u4 i, j;
485  
486     if (!types) return NULL;
487
488     /* determine required buffer-size */    
489     for (i = 0; i < types->header.size; i++) {
490                 classinfo *c = (classinfo *) types->data[i];
491                 buffer_size  = buffer_size + c->name->blength + 2;
492     }
493
494     if (retType) buffer_size += strlen(retType);
495
496     /* allocate buffer */
497     buffer = MNEW(char, buffer_size);
498     pos    = buffer;
499     
500     /* method-desciptor starts with parenthesis */
501     *pos++ = '(';
502
503     for (i = 0; i < types->header.size; i++) {
504                 char ch;           
505
506                 /* current argument */
507             classinfo *c = (classinfo *) types->data[i];
508
509             /* current position in utf-text */
510             char *utf_ptr = c->name->text; 
511             
512             /* determine type of argument */
513             if ((ch = utf_nextu2(&utf_ptr)) == '[') {
514                 /* arrayclass */
515                 for (utf_ptr--; utf_ptr < utf_end(c->name); utf_ptr++) {
516                                 *pos++ = *utf_ptr; /* copy text */
517                         }
518
519             } else {            
520                         /* check for primitive types */
521                         for (j = 0; j < PRIMITIVETYPE_COUNT; j++) {
522                                 char *utf_pos   = utf_ptr - 1;
523                                 char *primitive = primitivetype_table[j].wrapname;
524
525                                 /* compare text */
526                                 while (utf_pos < utf_end(c->name)) {
527                                         if (*utf_pos++ != *primitive++) goto nomatch;
528                                 }
529
530                                 /* primitive type found */
531                                 *pos++ = primitivetype_table[j].typesig;
532                                 goto next_type;
533
534                         nomatch:
535                                 ;
536                         }
537
538                         /* no primitive type and no arrayclass, so must be object */
539                         *pos++ = 'L';
540
541                         /* copy text */
542                         for (utf_ptr--; utf_ptr < utf_end(c->name); utf_ptr++) {
543                                 *pos++ = *utf_ptr;
544                         }
545
546                         *pos++ = ';';
547
548                 next_type:
549                         ;
550                 }  
551     }       
552
553     *pos++ = ')';
554
555     if (retType) {
556                 for (i = 0; i < strlen(retType); i++) {
557                         *pos++ = retType[i];
558                 }
559     }
560
561     /* create utf-string */
562     result = utf_new(buffer, (pos - buffer));
563     MFREE(buffer, char, buffer_size);
564
565     return result;
566 }
567
568
569 /* get_parametertypes **********************************************************
570
571    use the descriptor of a method to generate a java/lang/Class array
572    which contains the classes of the parametertypes of the method
573
574 *******************************************************************************/
575
576 java_objectarray* get_parametertypes(methodinfo *m) 
577 {
578     methoddesc *descr =  m->parseddesc;    /* method-descriptor */ 
579     java_objectarray* result;
580     int parametercount = descr->paramcount;
581     int i;
582
583     /* create class-array */
584     result = builtin_anewarray(parametercount, class_java_lang_Class);
585
586     /* get classes */
587     for (i = 0; i < parametercount; i++) {
588                 if (!resolve_class_from_typedesc(descr->paramtypes + i,false,
589                                         (classinfo **) (result->data + i)))
590                         return NULL; /* exception */
591                 use_class_as_object((classinfo*) result->data[i]);
592         }
593
594     return result;
595 }
596
597
598 /* get_exceptiontypes **********************************************************
599
600    get the exceptions which can be thrown by a method
601
602 *******************************************************************************/
603
604 java_objectarray* get_exceptiontypes(methodinfo *m)
605 {
606     u2 excount;
607     u2 i;
608     java_objectarray *result;
609
610         excount = m->thrownexceptionscount;
611
612     /* create class-array */
613     result = builtin_anewarray(excount, class_java_lang_Class);
614
615     for (i = 0; i < excount; i++) {
616                 java_objectheader *o = (java_objectheader *) (m->thrownexceptions[i]);
617                 use_class_as_object((classinfo *) o);
618                 result->data[i] = o;
619     }
620
621     return result;
622 }
623
624
625 /******************************************************************************************
626
627         get the returntype class of a method
628
629 *******************************************************************************************/
630
631 classinfo *get_returntype(methodinfo *m) 
632 {
633         classinfo *cls;
634
635         if (!resolve_class_from_typedesc(&(m->parseddesc->returntype),false,&cls))
636                 return NULL; /* exception */
637
638         use_class_as_object(cls);
639         return cls;
640 }
641
642
643 /*****************************************************************************/
644 /*****************************************************************************/
645
646
647 /*--------------------------------------------------------*/
648 void printNativeCall(nativeCall nc) {
649   int i,j;
650
651   printf("\n%s's Native Methods call:\n",nc.classname); fflush(stdout);
652   for (i=0; i<nc.methCnt; i++) {  
653       printf("\tMethod=%s %s\n",nc.methods[i].methodname, nc.methods[i].descriptor);fflush(stdout);
654
655     for (j=0; j<nc.callCnt[i]; j++) {  
656         printf("\t\t<%i,%i>aCalled = %s %s %s\n",i,j,
657         nc.methods[i].methodCalls[j].classname, 
658         nc.methods[i].methodCalls[j].methodname, 
659         nc.methods[i].methodCalls[j].descriptor);fflush(stdout);
660       }
661     }
662   printf("-+++++--------------------\n");fflush(stdout);
663 }
664
665 /*--------------------------------------------------------*/
666 void printCompNativeCall(nativeCompCall nc) {
667   int i,j;
668   printf("printCompNativeCall BEGIN\n");fflush(stdout); 
669   printf("\n%s's Native Comp Methods call:\n",nc.classname->text);fflush(stdout);
670   utf_display(nc.classname); fflush(stdout);
671   
672   for (i=0; i<nc.methCnt; i++) {  
673     printf("\tMethod=%s %s\n",nc.methods[i].methodname->text,nc.methods[i].descriptor->text);fflush(stdout);
674     utf_display(nc.methods[i].methodname); fflush(stdout);
675     utf_display(nc.methods[i].descriptor);fflush(stdout);
676     printf("\n");fflush(stdout);
677
678     for (j=0; j<nc.callCnt[i]; j++) {  
679       printf("\t\t<%i,%i>bCalled = ",i,j);fflush(stdout);
680         utf_display(nc.methods[i].methodCalls[j].classname);fflush(stdout);
681         utf_display(nc.methods[i].methodCalls[j].methodname); fflush(stdout);
682         utf_display(nc.methods[i].methodCalls[j].descriptor);fflush(stdout);
683         printf("\n");fflush(stdout);
684       }
685     }
686 printf("---------------------\n");fflush(stdout);
687 }
688
689
690 /*--------------------------------------------------------*/
691 classMeth findNativeMethodCalls(utf *c, utf *m, utf *d ) 
692 {
693     int i = 0;
694     int j = 0;
695     int cnt = 0;
696     classMeth mc;
697     mc.i_class = i;
698     mc.j_method = j;
699     mc.methCnt = cnt;
700
701     return mc;
702 }
703
704 /*--------------------------------------------------------*/
705 nativeCall* findNativeClassCalls(char *aclassname ) {
706 int i;
707
708 for (i=0;i<NATIVECALLSSIZE; i++) {
709    /* convert table to utf later to speed up search */ 
710    if (strcmp(nativeCalls[i].classname, aclassname) == 0) 
711         return &nativeCalls[i];
712    }
713
714 return NULL;
715 }
716 /*--------------------------------------------------------*/
717 /*--------------------------------------------------------*/
718 void utfNativeCall(nativeCall nc, nativeCompCall *ncc) {
719   int i,j;
720
721
722   ncc->classname = utf_new_char(nc.classname); 
723   ncc->methCnt = nc.methCnt;
724   
725   for (i=0; i<nc.methCnt; i++) {  
726     ncc->methods[i].methodname = utf_new_char(nc.methods[i].methodname);
727     ncc->methods[i].descriptor = utf_new_char(nc.methods[i].descriptor);
728     ncc->callCnt[i] = nc.callCnt[i];
729
730     for (j=0; j<nc.callCnt[i]; j++) {  
731
732         ncc->methods[i].methodCalls[j].classname  = utf_new_char(nc.methods[i].methodCalls[j].classname);
733
734         if (strcmp("", nc.methods[i].methodCalls[j].methodname) != 0) {
735           ncc->methods[i].methodCalls[j].methodname = utf_new_char(nc.methods[i].methodCalls[j].methodname);
736           ncc->methods[i].methodCalls[j].descriptor = utf_new_char(nc.methods[i].methodCalls[j].descriptor);
737           }
738         else {
739           ncc->methods[i].methodCalls[j].methodname = NULL;
740           ncc->methods[i].methodCalls[j].descriptor = NULL;
741           }
742       }
743     }
744 }
745
746
747
748 /*--------------------------------------------------------*/
749
750 bool natcall2utf(bool natcallcompdone) {
751 int i;
752
753 if (natcallcompdone) 
754         return true;
755
756 for (i=0;i<NATIVECALLSSIZE; i++) {
757    utfNativeCall  (nativeCalls[i], &nativeCompCalls[i]);  
758    }
759
760 return true;
761 }
762
763 /*--------------------------------------------------------*/
764
765
766 java_objectarray *builtin_asm_createclasscontextarray(classinfo **end, classinfo **start)
767 {
768 #if defined(__GNUC__)
769 #warning platform dependend
770 #endif
771         java_objectarray *tmpArray;
772         int i;
773         classinfo **current;
774         classinfo *c;
775         size_t size;
776
777         size = (((size_t) start) - ((size_t) end)) / sizeof(classinfo*);
778
779         /*printf("end %p, start %p, size %ld\n",end,start,size);*/
780         if (!class_java_lang_Class)
781                 class_java_lang_Class = class_new(utf_new_char("java/lang/Class"));
782
783         if (!class_java_lang_SecurityManager)
784                 class_java_lang_SecurityManager =
785                         class_new(utf_new_char("java/lang/SecurityManager"));
786
787         if (size > 0) {
788                 if (*start == class_java_lang_SecurityManager) {
789                         size--;
790                         start--;
791                 }
792         }
793
794         tmpArray = (java_objectarray*)
795                 builtin_newarray(size, class_array_of(class_java_lang_Class)->vftbl);
796
797         for(i = 0, current = start; i < size; i++, current--) {
798                 c = *current;
799                 /*              printf("%d\n",i);
800                 utf_display(c->name);*/
801                 use_class_as_object(c);
802                 tmpArray->data[i] = (java_objectheader *) c;
803         }
804
805         return tmpArray;
806 }
807
808
809 java_lang_ClassLoader *builtin_asm_getclassloader(classinfo **end, classinfo **start)
810 {
811 #if defined(__GNUC__)
812 #warning platform dependend
813 #endif
814         int i;
815         classinfo **current;
816         classinfo *c;
817         classinfo *privilegedAction;
818         size_t size;
819
820         size = (((size_t) start) - ((size_t) end)) / sizeof(classinfo*);
821
822         /*      log_text("builtin_asm_getclassloader");
823         printf("end %p, start %p, size %ld\n",end,start,size);*/
824
825         if (!class_java_lang_SecurityManager)
826                 class_java_lang_SecurityManager =
827                         class_new(utf_new_char("java/lang/SecurityManager"));
828
829         if (size > 0) {
830                 if (*start == class_java_lang_SecurityManager) {
831                         size--;
832                         start--;
833                 }
834         }
835
836         privilegedAction=class_new(utf_new_char("java/security/PrivilegedAction"));
837
838         for(i = 0, current = start; i < size; i++, current--) {
839                 c = *current;
840
841                 if (c == privilegedAction)
842                         return NULL;
843
844                 if (c->classloader)
845                         return (java_lang_ClassLoader *) c->classloader;
846         }
847
848         return NULL;
849 }
850
851
852 /*
853  * These are local overrides for various environment variables in Emacs.
854  * Please do not remove this and leave it at the end of the file, where
855  * Emacs will automagically detect them.
856  * ---------------------------------------------------------------------
857  * Local variables:
858  * mode: c
859  * indent-tabs-mode: t
860  * c-basic-offset: 4
861  * tab-width: 4
862  * End:
863  */