OSDN Git Service

b0d2b2184b92f80d719676be74ea3f91393503f6
[nxt-jsp/lejos_nxj.git] / nxtOSEK / lejos_nxj / src / nxtvm / javavm / language.c
1 /**
2  * Runtime data structures for loaded program.
3  */
4
5 #include "types.h"
6 #include "trace.h"
7 #include "constants.h"
8 #include "specialsignatures.h"
9 #include "specialclasses.h"
10 #include "memory.h"
11 #include "threads.h"
12 #include "classes.h"
13 #include "language.h"
14 #include "configure.h"
15 #include "interpreter.h"
16 #include "exceptions.h"
17 #include "stack.h"
18 #include "platform_hooks.h"
19
20 #if 0
21 #define get_stack_object(MREC_)  ((Object *) get_ref_at ((MREC_)->numParameters - 1))
22 #endif
23
24 // Reliable globals:
25
26 void *installedBinary;
27
28 // Temporary globals:
29
30 // (Gotta be careful with these; a lot of stuff
31 // is not reentrant because of globals like these).
32
33 static ClassRecord *tempClassRecord;
34 static MethodRecord *tempMethodRecord;
35
36 // Methods:
37
38 byte get_class_index (Object *obj)
39 {
40   byte f;
41
42   f = obj->flags.all;
43   if (f & IS_ARRAY_MASK)
44     return JAVA_LANG_OBJECT;
45   return (f & CLASS_MASK);
46 }
47
48 /**
49  * @return Method record or null.
50  */
51 MethodRecord *find_method (ClassRecord *classRecord, TWOBYTES methodSignature)
52 {
53   tempByte = classRecord->numMethods;
54   while (tempByte--)
55   {
56     tempMethodRecord = get_method_record (classRecord, tempByte);
57     if (tempMethodRecord->signatureId == methodSignature)
58       return tempMethodRecord;
59   }
60   return null;
61 }
62
63 boolean dispatch_static_initializer (ClassRecord *aRec, byte *retAddr)
64 {
65   if (is_initialized (aRec))
66     return false;
67   set_initialized (aRec);
68   if (!has_clinit (aRec))
69     return false;
70   #if DEBUG_METHODS
71   printf ("dispatch_static_initializer: has clinit: %d, %d\n",
72           (int) aRec, (int) retAddr);
73   #endif
74   dispatch_special (find_method (aRec, _6clinit_7_4_5V), retAddr);
75   return true;
76 }
77
78 void dispatch_virtual (Object *ref, TWOBYTES signature, byte *retAddr)
79 {
80   MethodRecord *auxMethodRecord;
81   byte auxByte;
82
83 #if DEBUG_METHODS
84   printf("dispatch_virtual %d\n", signature);
85 #endif
86   if (ref == JNULL)
87   {
88     throw_exception (nullPointerException);
89     return;
90   }
91
92   auxByte = get_class_index(ref);
93  LABEL_METHODLOOKUP:
94   tempClassRecord = get_class_record (auxByte);
95   auxMethodRecord = find_method (tempClassRecord, signature);
96   if (auxMethodRecord == null)
97   {
98     #if SAFE
99     if (auxByte == JAVA_LANG_OBJECT)
100     {
101       throw_exception (noSuchMethodError);
102       return;
103     }
104     #endif
105     auxByte = tempClassRecord->parentClass;
106     goto LABEL_METHODLOOKUP;
107   }
108
109   if (dispatch_special (auxMethodRecord, retAddr))
110   {
111     if (is_synchronized(auxMethodRecord))
112     {
113       current_stackframe()->monitor = ref;
114       enter_monitor (currentThread, ref);
115     }
116   }
117 }
118
119 /**
120  * Calls static initializer if necessary before
121  * dispatching with dispatch_special().
122  * @param retAddr Return bytecode address.
123  * @param btAddr Backtrack bytecode address (in case
124  *               static initializer is executed).
125  */
126 void dispatch_special_checked (byte classIndex, byte methodIndex,
127                                byte *retAddr, byte *btAddr)
128 {
129   ClassRecord *classRecord;
130
131   #if DEBUG_METHODS
132   printf ("dispatch_special_checked: %d, %d, %d, %d\n",
133           classIndex, methodIndex, (int) retAddr, (int) btAddr);
134   #endif
135
136   classRecord = get_class_record (classIndex);
137   if (dispatch_static_initializer (classRecord, btAddr))
138     return;
139   dispatch_special (get_method_record (classRecord, methodIndex), retAddr);
140 }
141
142 /**
143  * @param classRecord Record for method class.
144  * @param methodRecord Calle's method record.
145  * @param retAddr What the PC should be upon return.
146  * @return true iff the stack frame was pushed.
147  */
148 boolean dispatch_special (MethodRecord *methodRecord, byte *retAddr)
149 {
150   #if DEBUG_METHODS
151   int debug_ctr;
152   #endif
153
154   StackFrame *stackFrame;
155   byte newStackFrameIndex;
156
157   #if DEBUG_BYTECODE
158   printf ("\n------ dispatch special - %d ------------------\n\n",
159           methodRecord->signatureId);
160   #endif
161
162   #if DEBUG_METHODS
163   printf ("dispatch_special: %d, %d\n", 
164           (int) methodRecord, (int) retAddr);
165   printf ("-- signature id = %d\n", methodRecord->signatureId);
166   printf ("-- code offset  = %d\n", methodRecord->codeOffset);
167   printf ("-- flags        = %d\n", methodRecord->mflags);
168   printf ("-- num params   = %d\n", methodRecord->numParameters);
169   printf ("-- stack ptr    = %d\n", (int) get_stack_ptr());
170   printf ("-- max stack ptr= %d\n", (int) (currentThread->stackArray + (get_array_size(currentThread->stackArray))*2));
171   #endif
172
173   pop_words (methodRecord->numParameters);
174   pc = retAddr;
175
176   if (is_native (methodRecord))
177   {
178   #if DEBUG_METHODS
179   printf ("-- native\n");
180   #endif 
181     dispatch_native (methodRecord->signatureId, get_stack_ptr() + 1);
182     // Stack frame not pushed
183     return false;
184   }
185
186   newStackFrameIndex = currentThread->stackFrameArraySize;
187   
188   if (newStackFrameIndex >= get_array_length((Object *) word2ptr (currentThread->stackFrameArray)))
189   {
190 #if !FIXED_STACK_SIZE
191         // int len = get_array_length((Object *) word2ptr (currentThread->stackFrameArray));
192         int newlen = get_array_length((Object *) word2ptr (currentThread->stackFrameArray)) * 3 / 2;
193         JINT newStackFrameArray = JNULL;
194
195         // Stack frames are indexed by a byte value so limit the size.          
196         if (newlen <= 255)
197         {
198             // increase the stack frame size
199                 newStackFrameArray = ptr2word(reallocate_array(word2ptr(currentThread->stackFrameArray), newlen));
200         }
201         
202         // If can't allocate new stack, give in!
203     if (newStackFrameArray == JNULL)
204     {
205 #endif
206       throw_exception (stackOverflowError);
207       return false;
208 #if !FIXED_STACK_SIZE
209     }
210         
211         // Assign new array
212         currentThread->stackFrameArray = newStackFrameArray;
213 #endif
214   }
215   
216   if (newStackFrameIndex == 0)
217   {
218     // Assign NEW stack frame
219     stackFrame = stackframe_array();
220   }
221   else
222   {
223     #if DEBUG_METHODS
224     for (debug_ctr = 0; debug_ctr < methodRecord->numParameters; debug_ctr++)
225       printf ("-- param[%d]    = %ld\n", debug_ctr, (long) get_stack_ptr()[debug_ctr+1]);  
226     #endif
227
228     // Save OLD stackFrame state
229     stackFrame = stackframe_array() + (newStackFrameIndex - 1);
230     update_stack_frame (stackFrame);
231     // Push NEW stack frame
232     stackFrame++;
233   }
234   // Increment size of stack frame array
235   currentThread->stackFrameArraySize++;
236   // Initialize rest of new stack frame
237   stackFrame->methodRecord = methodRecord;
238   stackFrame->monitor = null;
239   stackFrame->localsBase = get_stack_ptr() + 1;
240   // Initialize auxiliary global variables (registers)
241   pc = get_code_ptr(methodRecord);
242
243   #if DEBUG_METHODS
244   printf ("pc set to 0x%X\n", (int) pc);
245   #endif
246
247   init_sp (stackFrame, methodRecord);
248   update_constant_registers (stackFrame);
249   
250   //printf ("m %d stack = %d\n", (int) methodRecord->signatureId, (int) (localsBase - stack_array())); 
251   
252   // Check for stack overflow
253   // (stackTop + methodRecord->maxOperands) >= (stack_array() + STACK_SIZE);
254   if (is_stack_overflow (methodRecord))
255   {
256 #if !FIXED_STACK_SIZE
257     StackFrame *stackBase;
258     int i;
259     
260     // Need at least this many bytes
261     // int len = (int)(stackTop + methodRecord->maxOperands) - (int)(stack_array()) - HEADER_SIZE;
262     
263     // Need to compute new array size (as distinct from number of bytes in array).
264         int newlen = (((int)(stackTop + methodRecord->maxOperands) - (int)(stack_array()) - HEADER_SIZE + 1) / 4) * 3 / 2;
265         JINT newStackArray = ptr2word(reallocate_array(word2ptr(currentThread->stackArray), newlen));
266         
267         // If can't allocate new stack, give in!
268     if (newStackArray == JNULL)
269     {
270 #endif
271       throw_exception (stackOverflowError);
272       return false;
273 #if !FIXED_STACK_SIZE
274     }
275         
276     // Adjust pointers.
277     newlen = newStackArray - currentThread->stackArray;
278     stackBase = stackframe_array();
279     stackTop = word2ptr(ptr2word(stackTop) + newlen);
280     localsBase = word2ptr(ptr2word(localsBase) + newlen);
281 #if DEBUG_MEMORY
282         printf("thread=%d, stackTop(%d), localsBase(%d)=%d\n", currentThread->threadId, (int)stackTop, (int)localsBase, (int)(*localsBase));
283 #endif
284     for (i=currentThread->stackFrameArraySize-1;
285          i >= 0;
286          i--)
287     {
288         stackBase[i].localsBase = word2ptr(ptr2word(stackBase[i].localsBase) + newlen);
289                 stackBase[i].stackTop = word2ptr(ptr2word(stackBase[i].stackTop) + newlen);
290 #if DEBUG_MEMORY
291         printf("stackBase[%d].localsBase(%d) = %d\n", i, (int)stackBase[i].localsBase, (int)(*stackBase[i].localsBase));
292 #endif
293     }
294     
295         // Assign new array
296         currentThread->stackArray = newStackArray;
297 #endif
298   } 
299   return true;
300 }
301
302 /**
303  */
304 void do_return (byte numWords)
305 {
306   StackFrame *stackFrame;
307   STACKWORD *fromStackPtr;
308
309   stackFrame = current_stackframe();
310
311   #if DEBUG_BYTECODE
312   printf ("\n------ return ----- %d ------------------\n\n",
313           stackFrame->methodRecord->signatureId);
314   #endif
315
316   #if DEBUG_METHODS
317   printf ("do_return: method: %d  #  num. words: %d\n", 
318           stackFrame->methodRecord->signatureId, numWords);
319   #endif
320
321   #ifdef VERIFY
322   assert (stackFrame != null, LANGUAGE3);
323   #endif
324   if (stackFrame->monitor != null)
325     exit_monitor (currentThread, stackFrame->monitor);
326
327   #if DEBUG_THREADS || DEBUG_METHODS
328   printf ("do_return: stack frame array size: %d\n", currentThread->stackFrameArraySize);
329   #endif
330
331   if (currentThread->stackFrameArraySize == 1)
332   {
333     #if DEBUG_METHODS
334     printf ("do_return: thread is done: %d\n", (int) currentThread);
335     #endif
336     currentThread->state = DEAD;
337     schedule_request (REQUEST_SWITCH_THREAD);
338     return;
339   }
340
341   // Place source ptr below data to be copied up the stack
342   fromStackPtr = get_stack_ptr_at (numWords);
343   // Pop stack frame
344   currentThread->stackFrameArraySize--;
345   stackFrame--;
346   // Assign registers
347   update_registers (stackFrame);
348
349   #if DEBUG_METHODS
350   printf ("do_return: stack reset to:\n");
351   printf ("-- stack ptr = %d\n", (int) get_stack_ptr());
352   #endif
353
354   while (numWords--)
355   {
356     push_word (*(++fromStackPtr));
357   }  
358 }
359
360 /**
361  * @return 1 or 0.
362  */
363 STACKWORD instance_of (Object *obj, byte classIndex)
364 {
365   byte rtType;
366
367   if (obj == null)
368     return 0;
369   rtType = get_class_index(obj);
370   // TBD: support for interfaces
371   if (is_interface (get_class_record(classIndex)))
372     return 1;
373  LABEL_INSTANCE:
374   if (rtType == classIndex)
375     return 1;
376   if (rtType == JAVA_LANG_OBJECT)
377     return 0;
378   rtType = get_class_record(rtType)->parentClass;
379   goto LABEL_INSTANCE;
380 }
381
382
383
384
385