2 * Copyright (C) 2003, 2004, 2005, 2006, 2007
3 * Robert Lougher <rob@lougher.org.uk>.
5 * This file is part of JamVM.
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2,
10 * or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23 #include <arpa/inet.h>
35 #include "interp-direct.h"
37 #include <sys/syscall.h>
41 #include <sys/types.h>
42 #include <linux/unistd.h>
44 #include <asm/cachectl.h>
46 #include "arch/avr32_jem.h"
47 #include "interp_jem.h"
60 * Interpreter execution context
66 /* the interpreter execution context */
78 #define GET_THIS(ctx) do { \
79 if (!((ctx)->mb->access_flags & ACC_STATIC) && (ctx)->mb->max_locals && \
80 *(ctx)->lvars_jem) { \
81 uintptr_t *__p = (uintptr_t *)*(ctx)->lvars_jem; \
82 (ctx)->this = JAM_OBJECT(__p); \
85 jam_dprintf("[%s] %smethod with %d vars, assigning %p\n", __func__, \
86 (ctx)->mb->access_flags & ACC_STATIC ? "static " : "", \
87 (ctx)->mb->max_locals, (ctx)->this); \
90 typedef int handler_fn(struct intrp_ctx
*ctx
);
92 static void jem_opcode_rewrite(uint32_t new_opcode
, char *pc
, int argc
, ...)
97 va_start(vargs
, argc
);
99 for (i
= 1; i
<= argc
; i
++)
100 pc
[i
] = (char)va_arg(vargs
, int);
102 syscall(__NR_cacheflush
, CACHE_IFLUSH
, (int)pc
& ~31, 32);
105 #define min(x, y) ({ typeof(x) _x = (x); typeof(y) _y = (y); _x > _y ? _y : _x; })
107 //check if it is an valid object ref (see alloc.c)
108 #define OBJECT_GRAIN 8
109 #define IS_OBJECT(ptr) !(((uintptr_t)(ptr))&(OBJECT_GRAIN-1))
111 #define JEM_THROW_EXCEPTION(excep_name, message) \
113 ctx->frame->last_pc = (CodePntr)ctx->jem.jpc; \
114 signalException(excep_name, message); \
115 jem_throwException(ctx); \
118 #define JEM_NULL_POINTER_CHECK(ref) \
119 if (!ref) JEM_THROW_EXCEPTION("java/lang/NullPointerException", NULL);
121 /*********************************************
122 * JEM Trap Handlers **
123 * *******************************************/
124 static int trap_debug(struct intrp_ctx
*ctx
)
127 struct jem_state
*jem
= &ctx
->jem
;
130 static unsigned long count
;
132 jecr_u
.i
= jem
->jecr
;
134 jam_printf("[%lu] (%u): Trap 0x%08x: ostack 0x%x, opcode 0x%x @ 0x%08x, "
135 "operand 1 0x%x, operand 2 0x%x. Operands:\n",
136 count
++, pthread_self(), jem
->trap_pc
, ctx
->ostack
, jecr_u
.s
.opcode
,
137 jem
->jpc
, jecr_u
.s
.op1
, jecr_u
.s
.op2
);
139 for (i
= 0; i
< jem
->josp
; i
++) {
141 if (ostack_read_u32(ctx
->frame
->ostack
, ctx
->ostack
, i
, &v
) >= 0)
142 jam_printf("\tToS-%d: 0x%x\n", i
, v
);
149 static int jem_throwException(struct intrp_ctx
*ctx
)
151 struct jem_state
*jem
= &ctx
->jem
;
152 ExecEnv
*ee
= ctx
->ee
;
153 Object
*excep
= ee
->exception
;
154 ee
->exception
= NULL
;
156 jem
->jpc
= (unsigned long)findCatchBlock(excep
->class);
157 jam_dprintf("Found exception handler at 0x%08x\n", jem
->jpc
);
159 /* If we didn't find a handler, restore exception and
160 return to previous invocation */
163 ee
->exception
= excep
;
164 /* Original code had a "return NULL" here, which means, end of
166 return JEM_TRAP_HANDLER_FINISH
;
169 /* If we're handling a stack overflow, reduce the stack
170 back past the red zone to enable handling of further
174 ee
->overflow
= FALSE
;
175 ee
->stack_end
-= STACK_RED_ZONE_SIZE
;
178 /* Setup intepreter to run the found catch block */
180 ctx
->frame
= ee
->last_frame
;
181 ctx
->mb
= ctx
->frame
->mb
;
182 ctx
->ostack
= ctx
->frame
->ostack
;
183 ctx
->lvars_jem
= ctx
->frame
->lvars_jem
- 1;
187 ctx
->cp
= &(CLASS_CB(ctx
->mb
->class)->constant_pool
);
189 /* FIXME: don't know if this is correct, depends how we implement
191 ostack_push_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, (uint32_t)excep
);
193 /* Dispatch to the first bytecode */
197 static int opc_return(struct intrp_ctx
*ctx
)
199 ExecEnv
*ee
= ctx
->ee
;
201 /* Set interpreter state to previous frame */
202 if (ctx
->frame
->prev
->mb
== NULL
) {
203 /* The previous frame is a dummy frame - this indicates
204 * top of this Java invocation. */
205 return JEM_TRAP_HANDLER_FINISH
;
208 ctx
->frame
= ctx
->frame
->prev
;
210 jam_dprintf("[%s] return to frame %p mb %p\n", __func__
, ctx
->frame
, ctx
->frame
->mb
);
212 if (ctx
->mb
->access_flags
& ACC_SYNCHRONIZED
) {
213 Object
*sync_ob
= ctx
->mb
->access_flags
& ACC_STATIC
? (Object
*)ctx
->mb
->class : ctx
->this;
214 jam_dprintf("[%s] %smethod unlock obj %p\n", __func__
,
215 ctx
->mb
->access_flags
& ACC_STATIC
? "static " : "", sync_ob
);
216 objectUnlock(sync_ob
);
219 ctx
->ostack
= ctx
->lvars_jem
- ctx
->mb
->max_locals
+ 1 - ctx
->mb
->args_count
;
220 ctx
->mb
= ctx
->frame
->mb
;
221 ctx
->lvars_jem
= ctx
->frame
->lvars_jem
- 1;
225 ctx
->jem
.jpc
= (uint32_t)ctx
->frame
->last_pc
;
226 ctx
->cp
= &(CLASS_CB(ctx
->mb
->class)->constant_pool
);
227 jam_dprintf("[OPC_RETURN] ostack: %p, lvars_jem: %p this: %p class %p\n",
228 ctx
->ostack
, ctx
->lvars_jem
, ctx
->this,
229 ctx
->this ? ctx
->this->class : NULL
);
232 ee
->last_frame
= ctx
->frame
;
237 static int invokeMethod(struct intrp_ctx
*ctx
)
239 ExecEnv
*ee
= ctx
->ee
;
240 /* Seems like the original jamvm reused top of caller's stack for callee's
241 * local variables for passing of method arguments. Our stack and
242 * local variables grow in opposite directions now, so, this is impossible.
243 * ctx->ostack points at the beginning of the free space above ostack.
245 Frame
*new_frame
= (Frame
*)(ctx
->ostack
+ ctx
->new_mb
->max_locals
);
246 Object
*sync_ob
= NULL
;
250 jam_dprintf("[invokeMethod] with args count %d, frame %p\n",
251 ctx
->new_mb
->args_count
, new_frame
);
253 ctx
->frame
->last_pc
= (CodePntr
)ctx
->jem
.jpc
;
254 ctx
->ostack
= (uintptr_t *)(new_frame
+ 1);
256 if (ostack_overflows(ctx
->ostack
, ctx
->new_mb
->max_stack
, (uintptr_t *)ee
->stack_end
)) {
257 if (ee
->overflow
++) {
258 /* Overflow when we're already throwing stack overflow.
259 Stack extension should be enough to throw exception,
260 so something's seriously gone wrong - abort the VM! */
261 jam_printf("Fatal stack overflow! Aborting VM.\n");
264 ee
->stack_end
+= STACK_RED_ZONE_SIZE
;
265 return JEM_THROW_EXCEPTION("java/lang/StackOverflowError", NULL
);
269 new_frame
->mb
= ctx
->new_mb
;
270 //TODO: it seemed lvars is in java stack, but jos[8] should be part of java stack
271 // lvars_jem requires that the highest pointer should refer to the first local variables LV0
272 // Here still not touch the java stack, allocate lvars_jem from native heap
274 new_frame
->lvars_jem
= (uintptr_t *)new_frame
;
276 if (ctx
->new_mb
->max_locals
> 0) {
277 for (i
= 0; i
< ctx
->new_mb
->args_count
; i
++) {
278 *(new_frame
->lvars_jem
- 1 - i
) = *(ctx
->arg1
+ i
);
279 jam_dprintf("arg[%d] = 0x%x@%p\n", i
, *(ctx
->arg1
+ i
), ctx
->arg1
+ i
);
283 jam_dprintf("[invokeMethod] %s::%s() lvars_jem %p\n",
284 CLASS_CB(ctx
->new_mb
->class)->name
, ctx
->new_mb
->name
, new_frame
->lvars_jem
);
286 new_frame
->ostack
= ctx
->ostack
;
287 new_frame
->prev
= ctx
->frame
;
289 ee
->last_frame
= new_frame
;
291 if (ctx
->new_mb
->access_flags
& ACC_SYNCHRONIZED
) {
292 aobj
= (uintptr_t *)*ctx
->arg1
;
293 sync_ob
= ctx
->new_mb
->access_flags
& ACC_STATIC
?
294 (Object
*)ctx
->new_mb
->class : JAM_OBJECT(aobj
);
298 if (ctx
->new_mb
->access_flags
& ACC_NATIVE
) {
299 //FIXME: the object references in JEM are direct pointer to instance variables.
300 // While JamVM requires object references as pointers to Object type.
301 jam_dprintf("[invokeMethod] invoke native method using %p invoker\n",
302 ctx
->new_mb
->native_invoker
);
303 ctx
->ostack
= (*(uintptr_t *(*)(Class
*, MethodBlock
*, uintptr_t*))
304 ctx
->new_mb
->native_invoker
)(ctx
->new_mb
->class, ctx
->new_mb
, ctx
->arg1
);
307 objectUnlock(sync_ob
);
309 ee
->last_frame
= ctx
->frame
;
311 if (exceptionOccured0(ee
)) {
312 jam_dprintf("[invokeMethod] exception occured, goto throwException\n");
313 return jem_throwException(ctx
);
316 jam_dprintf("[invokeMethod] finish native method invoke, return to loop\n");
318 ctx
->frame
= new_frame
;
319 ctx
->mb
= ctx
->new_mb
;
320 ctx
->lvars_jem
= new_frame
->lvars_jem
- 1;
324 ctx
->jem
.jpc
= (unsigned long)ctx
->mb
->code
& ~3;
325 ctx
->cp
= &(CLASS_CB(ctx
->mb
->class)->constant_pool
);
327 jam_dprintf("[invokeMethod] invoke virtual method: mb %x "
328 "lvars %x jpc %x cp %x\n", ctx
->mb
,
329 ctx
->lvars_jem
, ctx
->jem
.jpc
, ctx
->cp
);
335 static int opc_invokesuper_quick(struct intrp_ctx
*ctx
)
337 struct jem_state
*jem
= &ctx
->jem
;
338 Operand
*operand
= &jem
->operand
;
340 jam_dprintf("[OPC_INVOKESUPER_QUICK] method table indx %d\n", operand
->i
);
341 ctx
->new_mb
= CLASS_CB(CLASS_CB(ctx
->mb
->class)->super
)->method_table
[operand
->i
];
342 jam_dprintf("[OPC_INVOKESUPER_QUICK] method args count %d\n", ctx
->new_mb
->args_count
);
344 // set up jem operand stack
345 ctx
->arg1
= ostack_address(ctx
->frame
->ostack
, ctx
->mb
->max_stack
,
346 ctx
->ostack
- ctx
->frame
->ostack
- ctx
->new_mb
->args_count
);
347 JEM_NULL_POINTER_CHECK(*ctx
->arg1
);
348 jam_dprintf("[OP_INVOKESUPER_QUICK] arg1 %x\n", *ctx
->arg1
);
349 return invokeMethod(ctx
);
352 static int opc_invokenonvirtual_quick(struct intrp_ctx
*ctx
)
354 struct jem_state
*jem
= &ctx
->jem
;
355 Operand
*operand
= &jem
->operand
;
357 ctx
->new_mb
= (MethodBlock
*)operand
->pntr
;
358 jam_dprintf("[%s] new methodblock %s (%x) with %d args\n",
359 __func__
, ctx
->new_mb
->name
, ctx
->new_mb
, ctx
->new_mb
->args_count
);
360 ctx
->arg1
= ostack_address(ctx
->frame
->ostack
, ctx
->mb
->max_stack
,
361 ctx
->ostack
- ctx
->frame
->ostack
- ctx
->new_mb
->args_count
);
363 jam_dprintf("[%s] ctx->arg1 %x\n", __func__
, *ctx
->arg1
);
364 JEM_NULL_POINTER_CHECK(*ctx
->arg1
);
365 return invokeMethod(ctx
);
368 static int opc_invokevirtual_quick(struct intrp_ctx
*ctx
)
370 struct jem_state
*jem
= &ctx
->jem
;
372 ctx
->arg1
= ostack_address(ctx
->frame
->ostack
, ctx
->mb
->max_stack
,
373 ctx
->ostack
- ctx
->frame
->ostack
- INV_QUICK_ARGS(jem
));
374 JEM_NULL_POINTER_CHECK(*ctx
->arg1
);
377 //in case of "AALOAD" loads JAM obj from reference array
378 obj
= (Object
*)*ctx
->arg1
;
379 if (!JAM_ON_STACK
|| !IS_JAM_OBJECT(obj
)) {
380 obj
= JAM_OBJECT((uintptr_t *)obj
);
381 //we should ensure ostack contains no JAM object
382 *ctx
->arg1
= (uintptr_t)INST_DATA(obj
);
385 jam_dprintf("[OPC_INVOKEVIRTUAL_QUICK] invoke on object %p from %p class %p\n",
386 obj
, ctx
->arg1
, obj
->class);
387 new_class
= obj
->class;
388 ctx
->new_mb
= CLASS_CB(new_class
)->method_table
[INV_QUICK_IDX(jem
)];
389 jam_dprintf("[OPC_INVOKEVIRTUAL_QUICK] invoke method 0x%08x\n",
391 return invokeMethod(ctx
);
394 static int opc_invokevirtual(struct intrp_ctx
*ctx
)
397 ExecEnv
*ee
= ctx
->ee
;
398 struct jem_state
*jem
= &ctx
->jem
;
400 idx
= jem
->jecr
& 0xffff;
401 ctx
->frame
->last_pc
= (CodePntr
)jem
->jpc
;
402 ctx
->new_mb
= resolveMethod(ctx
->mb
->class, idx
);
404 if (exceptionOccured0(ee
))
405 return jem_throwException(ctx
);
407 jem
->operand
.uu
.u1
= ctx
->new_mb
->args_count
;
408 jem
->operand
.uu
.u2
= ctx
->new_mb
->method_table_index
;
410 jam_dprintf("[OPC_INVOKEVIRTUAL] invoke 0x%08x with args count %d\n",
411 ctx
->new_mb
, ctx
->new_mb
->args_count
);
413 return opc_invokevirtual_quick(ctx
);
416 static int opc_invokespecial(struct intrp_ctx
*ctx
)
419 struct jem_state
*jem
= &ctx
->jem
;
420 Operand
*operand
= &jem
->operand
;
421 ExecEnv
*ee
= ctx
->ee
;
423 /* INVOKESPECIAL's operands represent an index into the Constant Pool */
424 idx
= jem
->jecr
& 0xffff;
426 jam_dprintf("[OPC_INVOKESPECIAL] constant pool index %d\n", idx
);
428 ctx
->new_mb
= resolveMethod(ctx
->mb
->class, idx
);
430 if (exceptionOccured0(ee
))
431 return jem_throwException(ctx
);
433 jam_dprintf("Resolved %s\n", ctx
->new_mb
->name
);
435 /* Check if invoking a super method... */
436 if ((CLASS_CB(ctx
->mb
->class)->access_flags
& ACC_SUPER
) &&
437 ((ctx
->new_mb
->access_flags
& ACC_PRIVATE
) == 0) && (ctx
->new_mb
->name
[0] != '<')) {
439 operand
->i
= ctx
->new_mb
->method_table_index
;
440 return opc_invokesuper_quick(ctx
);
441 #if 0 /* FIXME: verify this whole "pc" chemistry is indeed unneeded */
442 OPCODE_REWRITE(OPC_INVOKESUPER_QUICK
, cache
, operand
);
445 operand
->pntr
= ctx
->new_mb
;
446 return opc_invokenonvirtual_quick(ctx
);
452 static int opc_invokestatic_quick(struct intrp_ctx
*ctx
)
454 struct jem_state
*jem
= &ctx
->jem
;
456 ctx
->new_mb
= RESOLVED_METHOD(jem
);
457 ctx
->arg1
= ostack_address(ctx
->frame
->ostack
, ctx
->mb
->max_stack
,
458 ctx
->ostack
- ctx
->frame
->ostack
- ctx
->new_mb
->args_count
);
459 return invokeMethod(ctx
);
462 static int opc_invokestatic(struct intrp_ctx
*ctx
)
465 struct jem_state
*jem
= &ctx
->jem
;
466 Operand
*operand
= &jem
->operand
;
467 ExecEnv
*ee
= ctx
->ee
;
469 idx
= jem
->jecr
& 0xffff;
471 ctx
->frame
->last_pc
= (CodePntr
)jem
->jpc
;
472 ctx
->new_mb
= resolveMethod(ctx
->mb
->class, idx
);
474 if (exceptionOccured0(ee
))
475 return jem_throwException(ctx
);
477 operand
->pntr
= ctx
->new_mb
;
478 return opc_invokestatic_quick(ctx
);
481 static int opc_new_quick(struct intrp_ctx
*ctx
)
483 struct jem_state
*jem
= &ctx
->jem
;
484 Operand
*operand
= &jem
->operand
;
485 Class
*class = (Class
*)CP_INFO(ctx
->cp
, operand
->uui
.u1
);
488 ctx
->frame
->last_pc
= (CodePntr
)jem
->jpc
;
489 if ((obj
= allocObject(class)) == NULL
)
490 return jem_throwException(ctx
);
491 jam_dprintf("[OPC_NEW_QUICK] push obj ref %x to stack\n", obj
);
492 return ostack_push_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
,
493 (uint32_t)INST_DATA(obj
));
496 static int opc_new(struct intrp_ctx
*ctx
)
498 struct jem_state
*jem
= &ctx
->jem
;
499 Operand
*operand
= &jem
->operand
;
500 int idx
= jem
->jecr
& 0xffff;
501 int opcode
= (jem
->jecr
>> 16) & 0xff;
503 ExecEnv
*ee
= ctx
->ee
;
505 operand
->uui
.u1
= idx
;
506 operand
->uui
.u2
= opcode
;
508 jam_dprintf("[OPC_NEW] opcode: 0x%x, index: 0x%x\n", opcode
, idx
);
510 ctx
->frame
->last_pc
= (CodePntr
)jem
->jpc
;
511 class = resolveClass(ctx
->mb
->class, idx
, opcode
== OPC_NEW
);
512 if (exceptionOccured0(ee
))
513 return jem_throwException(ctx
);
515 if (opcode
== OPC_NEW
) {
516 ClassBlock
*cb
= CLASS_CB(class);
517 if (cb
->access_flags
& (ACC_INTERFACE
| ACC_ABSTRACT
)) {
518 signalException("java/lang/InstantiationError", cb
->name
);
519 return jem_throwException(ctx
);
521 /* rewrite opcode to OPC_NEW_QUICK (0xDD) */
522 jem_opcode_rewrite(0xDD, (char*)jem
->jpc
- 3, 0);
525 return opc_new_quick(ctx
);
528 static int opc_anewarray_quick(struct intrp_ctx
*ctx
)
530 struct jem_state
*jem
= &ctx
->jem
;
531 ConstantPool
*cp
= ctx
->cp
;
532 Class
*class = RESOLVED_CLASS(jem
);
533 char *name
= CLASS_CB(class)->name
;
538 ExecEnv
*ee
= ctx
->ee
;
540 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, count
);
541 ctx
->frame
->last_pc
= (CodePntr
)jem
->jpc
;
543 jam_dprintf("[OPC_ANEWARRAY_QUICK] array %s size %d\n", name
, count
);
545 signalException("java/lang/NegativeArraySizeException", NULL
);
546 return jem_throwException(ctx
);
549 ac_name
= sysMalloc(strlen(name
) + 4);
552 sprintf(ac_name
, "[%s", name
);
554 sprintf(ac_name
, "[L%s;", name
);
556 array_class
= findArrayClassFromClass(ac_name
, ctx
->mb
->class);
559 if (exceptionOccured0(ee
))
560 return jem_throwException(ctx
);
562 if ((obj
= allocArray(array_class
, count
, sizeof(Object
*))) == NULL
)
563 return jem_throwException(ctx
);
565 return ostack_push_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
,
566 (uint32_t)ARRAY_DATA(obj
));
569 static int opc_anewarray(struct intrp_ctx
*ctx
)
571 struct jem_state
*jem
= &ctx
->jem
;
572 Operand
*operand
= &jem
->operand
;
573 int idx
= jem
->jecr
& 0xffff;
574 int opcode
= (jem
->jecr
>> 16) & 0xff;
576 ExecEnv
*ee
= ctx
->ee
;
578 operand
->uui
.u1
= idx
;
579 operand
->uui
.u2
= opcode
;
581 jam_dprintf("[OPC_ANEWARRAY] index: 0x%x\n", idx
);
583 ctx
->frame
->last_pc
= (CodePntr
)jem
->jpc
;
584 //resolve the array class
585 class = resolveClass(ctx
->mb
->class, idx
, FALSE
);
587 if (exceptionOccured0(ee
))
588 return jem_throwException(ctx
);
590 return opc_anewarray_quick(ctx
);
593 static int opc_multianewarray_quick(struct intrp_ctx
*ctx
)
595 struct jem_state
*jem
= &ctx
->jem
;
596 ConstantPool
*cp
= ctx
->cp
;
597 Class
*class = RESOLVED_CLASS(jem
);
598 int i
, dim
= MULTI_ARRAY_DIM(jem
);
601 ExecEnv
*ee
= ctx
->ee
;
603 ctx
->frame
->last_pc
= (CodePntr
)jem
->jpc
;
605 jam_dprintf("[OPC_MULTIANEWARRAY_QUICK]: alloc %d dimensional array for class %s\n", dim
, CLASS_CB(class)->name
);
606 for (i
= 0; i
< dim
; i
++) {
607 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, count
);
608 jam_dprintf("[OPC_MULTIANEWARRAY_QUICK]: elements %d for dim %d\n", count
, i
);
610 signalException("java/lang/NegativeArraySizeException", NULL
);
611 return jem_throwException(ctx
);
615 /* counts are still stored in ostack even after we did pop them out */
616 if ((obj
= allocMultiArray(class, dim
, (intptr_t *)ctx
->ostack
)) == NULL
)
617 return jem_throwException(ctx
);
619 return ostack_push_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
,
620 (uint32_t)ARRAY_DATA(obj
));
623 static int opc_multianewarray(struct intrp_ctx
*ctx
)
625 struct jem_state
*jem
= &ctx
->jem
;
626 Operand
*operand
= &jem
->operand
;
627 int idx
= operand
->uui
.u1
= jem
->jecr
& 0xffff;
630 ExecEnv
*ee
= ctx
->ee
;
633 operand
->uui
.u2
= *(unsigned char*)jem
->jpc
;
634 jem
->jpc
++; /* skip dims */
636 ctx
->frame
->last_pc
= (CodePntr
)jem
->jpc
;
637 /* resolve the array class */
638 class = resolveClass(ctx
->mb
->class, idx
, FALSE
);
640 if (exceptionOccured0(ee
))
641 return jem_throwException(ctx
);
643 return opc_multianewarray_quick(ctx
);
646 static int opc_newarray(struct intrp_ctx
*ctx
)
648 struct jem_state
*jem
= &ctx
->jem
;
649 int type
= (jem
->jecr
>> 8) & 0xff;
653 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, count
);
654 ctx
->frame
->last_pc
= (CodePntr
)jem
->jpc
;
656 jam_dprintf("[OPC_NEWARRAY] alloc array type %d, count %d\n", type
, count
);
657 if ((obj
= allocTypeArray(type
, count
)) == NULL
)
658 return jem_throwException(ctx
);
660 return ostack_push_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
,
661 (uint32_t)ARRAY_DATA(obj
));
664 static int opc_putfield_quick(struct intrp_ctx
*ctx
)
668 struct jem_state
*jem
= &ctx
->jem
;
670 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, arg
);
671 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, obj
);
672 jam_dprintf("[OPC_PUTFIELD_QUICK] put field %x to obj(%d) %x\n", arg
,
673 SINGLE_INDEX(jem
), obj
);
675 JEM_NULL_POINTER_CHECK(obj
);
677 if (JAM_ON_STACK
&& IS_JAM_OBJECT(obj
))
678 obj
= (uint32_t)INST_DATA((Object
*)obj
);
680 ((uint32_t*)obj
)[SINGLE_INDEX(jem
)] = arg
;
685 static int opc_putfield2_quick(struct intrp_ctx
*ctx
)
689 struct jem_state
*jem
= &ctx
->jem
;
691 ostack_pop_u64(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, arg
);
692 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, obj
);
694 JEM_NULL_POINTER_CHECK((uintptr_t*)obj
);
696 if (JAM_ON_STACK
&& IS_JAM_OBJECT(obj
))
697 obj
= (uint32_t)INST_DATA((Object
*)obj
);
699 *(uint64_t *)&(((uint32_t*)obj
)[SINGLE_INDEX(jem
)]) = arg
;
700 jam_dprintf("[OPC_PUTFIELD2_QUICK] put 64 bit %08x to obj %08x\n", arg
, obj
);
705 static int opc_putfield_quick_jem0(struct intrp_ctx
*ctx
)
709 struct jem_state
*jem
= &ctx
->jem
;
711 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, arg
);
712 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, aobj
);
713 jam_dprintf("[OPC_PUTFIELD_QUICK_JEM0] field %x\n", arg
);
715 JEM_NULL_POINTER_CHECK(aobj
);
717 if (JAM_ON_STACK
&& arg
&& !IS_JAM_OBJECT(arg
))
718 arg
= (uint32_t)JAM_OBJECT((uintptr_t *)arg
);
720 if (JAM_ON_STACK
&& IS_JAM_OBJECT(aobj
))
721 aobj
= INST_DATA((Object
*)aobj
);
723 aobj
[SINGLE_INDEX(jem
)] = arg
;
724 jam_dprintf("[OPC_PUTFIELD_QUICK_JEM0] put field %x to obj(%d) %x\n", arg
,
725 SINGLE_INDEX(jem
), aobj
);
730 static int opc_putfield_quick_jem1(struct intrp_ctx
*ctx
)
732 uintptr_t *aobj
, *arg
;
733 struct jem_state
*jem
= &ctx
->jem
;
735 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, arg
);
736 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, aobj
);
737 jam_dprintf("[OPC_PUTFIELD_QUICK_JEM1] field %p\n", arg
);
739 if (JAM_ON_STACK
&& arg
&& !IS_JAM_ARRAY(arg
))
740 arg
= (uintptr_t *)JAM_ARRAY(arg
);
742 if (JAM_ON_STACK
&& IS_JAM_OBJECT(aobj
))
743 aobj
= INST_DATA((Object
*)aobj
);
745 JEM_NULL_POINTER_CHECK(aobj
);
746 aobj
[SINGLE_INDEX(jem
)] = (uintptr_t)arg
;
747 jam_dprintf("[OPC_PUTFIELD_QUICK_JEM1] put field %p to obj(%d) %p\n", arg
,
748 SINGLE_INDEX(jem
), aobj
);
753 static int opc_putfield(struct intrp_ctx
*ctx
)
755 struct jem_state
*jem
= &ctx
->jem
;
756 int idx
= jem
->jecr
& 0xffff;
758 ExecEnv
*ee
= ctx
->ee
;
760 jam_dprintf("[OPC_PUTFIELD] constant pool index %d\n", idx
);
762 ctx
->frame
->last_pc
= (CodePntr
)jem
->jpc
;
763 fb
= resolveField(ctx
->mb
->class, idx
);
764 jam_dprintf("[OPC_PUTFIELD] resolve field 0x%08x, type %c, name %s\n", fb
, *fb
->type
, fb
->name
);
766 if (exceptionOccured0(ee
))
767 return jem_throwException(ctx
);
769 jem
->operand
.i
= fb
->offset
;
773 /* rewrite opc_putfield to opc_putfield2_quick */
774 jem_opcode_rewrite(0xD1, (char*)jem
->jpc
- 3, 2, fb
->offset
>> 8, fb
->offset
);
775 return opc_putfield2_quick(ctx
);
777 jem_opcode_rewrite(0xCF, (char*)jem
->jpc
- 3, 2, fb
->offset
>> 8, fb
->offset
);
778 return opc_putfield_quick_jem0(ctx
);
780 jem_opcode_rewrite(0xCF, (char*)jem
->jpc
- 3, 2, fb
->offset
>> 8, fb
->offset
);
781 return opc_putfield_quick_jem1(ctx
);
783 jem_opcode_rewrite(0xCF, (char*)jem
->jpc
- 3, 2, fb
->offset
>> 8, fb
->offset
);
784 return opc_putfield_quick(ctx
);
788 static int opc_getfield2_quick(struct intrp_ctx
*ctx
)
791 struct jem_state
*jem
= &ctx
->jem
;
792 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, obj
);
793 JEM_NULL_POINTER_CHECK(obj
);
795 if (JAM_ON_STACK
&& IS_JAM_OBJECT(obj
))
796 obj
= (uint32_t*)INST_DATA((Object
*)obj
);
798 jam_dprintf("[OPC_GETFIELD2_QUICK] get 64 bit field %08x from obj %08x\n",
799 *(uint64_t*)(&(obj
[SINGLE_INDEX(jem
)])), obj
);
801 return ostack_push_u64(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
,
802 *(uint64_t*)(&(obj
[SINGLE_INDEX(jem
)])));
805 static int opc_getfield_quick(struct intrp_ctx
*ctx
)
808 struct jem_state
*jem
= &ctx
->jem
;
810 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, aobj
);
811 JEM_NULL_POINTER_CHECK(aobj
);
813 if (JAM_ON_STACK
&& IS_JAM_OBJECT(aobj
))
814 aobj
= (uint32_t*)INST_DATA((Object
*)aobj
);
816 jam_dprintf("[OPC_GETFIELD_QUICK] get field %08x from obj %08x\n",
817 aobj
[SINGLE_INDEX(jem
)], aobj
);
818 return ostack_push_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
,
819 aobj
[SINGLE_INDEX(jem
)]);
822 static int opc_getfield_quick_jem0(struct intrp_ctx
*ctx
)
825 struct jem_state
*jem
= &ctx
->jem
;
827 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, aobj
);
828 JEM_NULL_POINTER_CHECK(aobj
);
830 if (JAM_ON_STACK
&& IS_JAM_OBJECT(aobj
))
831 aobj
= (uint32_t*)INST_DATA((Object
*)aobj
);
833 uint32_t value
= aobj
[SINGLE_INDEX(jem
)];
835 Object
*ref
= (Object
*)value
;
836 if (JAM_ON_STACK
&& IS_JAM_OBJECT(ref
))
838 value
= (uint32_t)INST_DATA(ref
);
839 jam_dprintf("[OPC_GETFIELD_QUICK_JEM0] obj %p ref %x, class %p : %p\n",
840 aobj
, value
, JAM_OBJECT((void *)value
)->class, ref
->class);
842 jam_dprintf("[OPC_GETFIELD_QUICK_JEM0] put obj ref %x\n", value
);
843 return ostack_push_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, value
);
846 static int opc_getfield_quick_jem1(struct intrp_ctx
*ctx
)
849 struct jem_state
*jem
= &ctx
->jem
;
851 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, aobj
);
852 JEM_NULL_POINTER_CHECK(aobj
);
854 //"aaload" would put jamvm obj ref onto the ostack
855 if (JAM_ON_STACK
&& IS_JAM_OBJECT(aobj
))
856 aobj
= (uint32_t*)INST_DATA((Object
*)aobj
);
858 uint32_t value
= aobj
[SINGLE_INDEX(jem
)];
859 jam_dprintf("[OPC_GETFIELD_QUICK_JEM1] array ref %x\n", value
);
861 Object
*ref
= (Object
*)value
;
862 if (JAM_ON_STACK
&& IS_JAM_ARRAY(ref
))
863 value
= (uint32_t)ARRAY_DATA(ref
);
865 jam_dprintf("[OPC_GETFIELD_QUICK_JEM1] put array ref %x\n", value
);
866 return ostack_push_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, value
);
869 static int opc_getfield(struct intrp_ctx
*ctx
)
871 struct jem_state
*jem
= &ctx
->jem
;
872 int idx
= jem
->jecr
& 0xffff;
874 ExecEnv
*ee
= ctx
->ee
;
876 jam_dprintf("[OPC_GETFIELD] constant pool index %d\n", idx
);
878 ctx
->frame
->last_pc
= (CodePntr
)jem
->jpc
;
879 fb
= resolveField(ctx
->mb
->class, idx
);
881 if (exceptionOccured0(ee
))
882 return jem_throwException(ctx
);
884 jem
->operand
.i
= fb
->offset
;
886 jam_dprintf("[OPC_GETFIELD] resolve field %s @ %p, type %c, offset %i, class %p\n",
887 fb
->name
, fb
, *fb
->type
, jem
->operand
.i
, fb
->class);
892 jem_opcode_rewrite(0xD0, (char*)jem
->jpc
- 3, 2, fb
->offset
>> 8, fb
->offset
);
893 return opc_getfield2_quick(ctx
);
895 * Though we assume all objrefs/arrayrefs here should be JEM compliant, but
896 * in case of some JNI code will set field natively, we still handle it
900 jem_opcode_rewrite(0xCE, (char*)jem
->jpc
- 3, 2, fb
->offset
>> 8, fb
->offset
);
901 return opc_getfield_quick_jem0(ctx
);
903 jem_opcode_rewrite(0xCE, (char*)jem
->jpc
- 3, 2, fb
->offset
>> 8, fb
->offset
);
904 return opc_getfield_quick_jem1(ctx
);
906 //jem_opcode_rewrite(0xCE, (char*)jem->jpc - 3, 2, (fb->offset>>8)&0xff, (fb->offset)&0xff);
907 return opc_getfield_quick(ctx
);
911 static int opc_ldc_w_quick_jem(struct intrp_ctx
*ctx
)
913 struct jem_state
*jem
= &ctx
->jem
;
914 //CONSTANT_Class and CONSTANT_String are stored as object reference
915 Object
*cp_info
= (Object
*)CP_INFO(ctx
->cp
, DOUBLE_INDEX(jem
));
916 jam_dprintf("[OPC_LDC_W_QUICK_JEM] push String ref %x to stack\n", cp_info
);
917 return ostack_push_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
,
918 (uint32_t)INST_DATA(cp_info
));
921 static int opc_ldc_w_quick(struct intrp_ctx
*ctx
)
923 struct jem_state
*jem
= &ctx
->jem
;
924 uint32_t cp_info
= CP_INFO(ctx
->cp
, DOUBLE_INDEX(jem
));
925 jam_dprintf("[OPC_LDC_W_QUICK] push constant %08x to stack\n", cp_info
);
926 return ostack_push_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, cp_info
);
929 static int opc_ldc_quick(struct intrp_ctx
*ctx
)
931 struct jem_state
*jem
= &ctx
->jem
;
932 uint32_t constant
= RESOLVED_CONSTANT(jem
);
933 jam_dprintf("[OPC_LDC_QUICK] push constant %x to stack\n", constant
);
934 return ostack_push_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, (uintptr_t)constant
);
937 static int opc_ldc_common(struct intrp_ctx
*ctx
, int idx
)
939 struct jem_state
*jem
= &ctx
->jem
;
940 ExecEnv
*ee
= ctx
->ee
;
941 ctx
->frame
->last_pc
= (CodePntr
)jem
->jpc
;
943 jem
->operand
.u
= resolveSingleConstant(ctx
->mb
->class, idx
);
945 if (exceptionOccured0(ee
))
946 return jem_throwException(ctx
);
948 if (CP_TYPE(ctx
->cp
, idx
) == CONSTANT_ResolvedClass
) {
949 jem
->operand
.i
= idx
;
950 jem_opcode_rewrite(0xCC, (char*)jem
->jpc
- 3, 0);
951 return opc_ldc_w_quick(ctx
);
952 } else if (CP_TYPE(ctx
->cp
, idx
) == CONSTANT_ResolvedString
) {
953 jem
->operand
.i
= idx
;
954 return opc_ldc_w_quick_jem(ctx
);
956 jem_opcode_rewrite(0xCB, (char*)jem
->jpc
- 2, 0);
957 return opc_ldc_quick(ctx
);
961 static int opc_ldc(struct intrp_ctx
*ctx
)
964 ExecEnv
*ee
= ctx
->ee
;
965 struct jem_state
*jem
= &ctx
->jem
;
967 idx
= (jem
->jecr
& 0xff00) >> 8;
969 jam_dprintf("[OPC_LDC] constant pool index %d\n", idx
);
970 return opc_ldc_common(ctx
, idx
);
973 static int opc_ldc_w(struct intrp_ctx
*ctx
)
976 ExecEnv
*ee
= ctx
->ee
;
977 struct jem_state
*jem
= &ctx
->jem
;
979 idx
= (jem
->jecr
& 0xffff);
981 jam_dprintf("[OPC_LDC_W] constant pool index %d\n", idx
);
982 return opc_ldc_common(ctx
, idx
);
985 static int opc_monitorenter(struct intrp_ctx
*ctx
)
989 struct jem_state
*jem
= &ctx
->jem
;
990 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, ptr
);
992 obj
= JAM_OBJECT(ptr
);
994 /* is an array ref */
995 obj
= JAM_ARRAY(ptr
);
996 jam_dprintf("[OPC_MONITORENTER] lock %x\n", obj
);
997 JEM_NULL_POINTER_CHECK(obj
);
1002 static int opc_monitorexit(struct intrp_ctx
*ctx
)
1006 struct jem_state
*jem
= &ctx
->jem
;
1007 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, ptr
);
1009 obj
= JAM_OBJECT(ptr
);
1010 if (!IS_OBJECT(obj
))
1011 /* is an array ref */
1012 obj
= JAM_ARRAY(ptr
);
1013 jam_dprintf("[OPC_MONITOREXIT] unlock %x\n", obj
);
1014 JEM_NULL_POINTER_CHECK(obj
);
1019 static int opc_getstatic_quick(struct intrp_ctx
*ctx
)
1021 struct jem_state
*jem
= &ctx
->jem
;
1022 return ostack_push_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
,
1023 RESOLVED_FIELD(jem
)->static_value
);
1026 static int opc_getstatic2_quick(struct intrp_ctx
*ctx
)
1028 struct jem_state
*jem
= &ctx
->jem
;
1029 return ostack_push_u64(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
,
1030 RESOLVED_FIELD(jem
)->static_value
);
1033 static int opc_getstatic_quick_jem0(struct intrp_ctx
*ctx
)
1035 struct jem_state
*jem
= &ctx
->jem
;
1036 uintptr_t value
= RESOLVED_FIELD(jem
)->static_value
;
1038 jam_dprintf("[OPC_GETSTATIC_QUICK_JEM0] obj ref %x\n", value
);
1040 Object
*ref
= (Object
*)value
;
1041 if (!JAM_ON_STACK
|| IS_JAM_OBJECT(ref
))
1043 value
= (uintptr_t)INST_DATA(ref
);
1045 jam_dprintf("[OPC_GETSTATIC_QUICK_JEM0] put obj ref %x\n", value
);
1046 return ostack_push_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, value
);
1049 static int opc_getstatic_quick_jem1(struct intrp_ctx
*ctx
)
1051 struct jem_state
*jem
= &ctx
->jem
;
1052 uintptr_t value
= RESOLVED_FIELD(jem
)->static_value
;
1053 jam_dprintf("[OPC_GETSTATIC_QUICK_JEM1] array ref %x\n", value
);
1055 Object
*ref
= (Object
*)value
;
1056 if (!JAM_ON_STACK
|| IS_JAM_ARRAY(ref
))
1058 value
= (uintptr_t)ARRAY_DATA(ref
);
1060 jam_dprintf("[OPC_GETSTATIC_QUICK_JEM1] put array ref %x\n", value
);
1061 return ostack_push_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, value
);
1064 static int opc_getstatic(struct intrp_ctx
*ctx
)
1069 ExecEnv
*ee
= ctx
->ee
;
1070 struct jem_state
*jem
= &ctx
->jem
;
1072 idx
= (int)(jem
->jecr
& 0xffff);
1073 jam_dprintf("[OPC_GETSTATIC] constant pool index %d class %s\n",idx
,CLASS_CB(ctx
->mb
->class)->name
);
1075 ctx
->frame
->last_pc
= (CodePntr
)jem
->jpc
;
1076 fb
= resolveField(ctx
->mb
->class, idx
);
1078 if (exceptionOccured0(ee
))
1079 return jem_throwException(ctx
);
1081 jam_dprintf("[OPC_GETSTATIC] get static for field %08x, type %c\n", fb
, *fb
->type
);
1082 jem
->operand
.pntr
= fb
;
1083 switch (*fb
->type
) {
1086 return opc_getstatic2_quick(ctx
);
1091 return opc_getstatic_quick_jem0(ctx
);
1093 return opc_getstatic_quick_jem1(ctx
);
1095 return opc_getstatic_quick(ctx
);
1099 static int opc_putstatic2_quick(struct intrp_ctx
*ctx
)
1101 struct jem_state
*jem
= &ctx
->jem
;
1102 return ostack_pop_u64(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
,
1103 *(u8
*)&RESOLVED_FIELD(jem
)->static_value
);
1106 static int opc_putstatic_quick(struct intrp_ctx
*ctx
)
1108 struct jem_state
*jem
= &ctx
->jem
;
1109 return ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
,
1110 RESOLVED_FIELD(jem
)->static_value
);
1113 static int opc_putstatic_quick_jem0(struct intrp_ctx
*ctx
)
1116 struct jem_state
*jem
= &ctx
->jem
;
1117 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, value
);
1119 jam_dprintf("[OPC_PUTSTATIC_QUICK_JEM0] obj %x\n", value
);
1120 if (value
&& (!JAM_ON_STACK
|| !IS_JAM_OBJECT(value
)))
1121 value
= (uintptr_t)JAM_OBJECT((uintptr_t *)value
);
1122 jam_dprintf("[OPC_PUTSTATIC_QUICK_JEM0] put obj %x\n", value
);
1123 RESOLVED_FIELD(jem
)->static_value
= value
;
1127 static int opc_putstatic_quick_jem1(struct intrp_ctx
*ctx
)
1130 struct jem_state
*jem
= &ctx
->jem
;
1131 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, value
);
1133 jam_dprintf("[OPC_PUTSTATIC_QUICK_JEM1] array %p\n", value
);
1134 if (value
&& (!JAM_ON_STACK
|| !IS_JAM_ARRAY(value
)))
1135 value
= (uintptr_t*)JAM_ARRAY(value
);
1136 jam_dprintf("[OPC_PUTSTATIC_QUICK_JEM1] put array %p\n", value
);
1137 RESOLVED_FIELD(jem
)->static_value
= (uintptr_t)value
;
1141 static int opc_putstatic(struct intrp_ctx
*ctx
)
1146 ExecEnv
*ee
= ctx
->ee
;
1147 struct jem_state
*jem
= &ctx
->jem
;
1149 idx
= (int)(jem
->jecr
& 0xffff);
1151 ctx
->frame
->last_pc
= (CodePntr
)jem
->jpc
;
1152 fb
= resolveField(ctx
->mb
->class, idx
);
1154 if (exceptionOccured0(ee
))
1155 return jem_throwException(ctx
);
1157 jam_dprintf("[OPC_PUTSTATIC] put static for field %08x, type %c\n", fb
, *fb
->type
);
1158 jem
->operand
.pntr
= fb
;
1159 switch (*fb
->type
) {
1162 //jem_opcode_rewrite(0xD5, (char*)jem->jpc - 3);
1163 return opc_putstatic2_quick(ctx
);
1165 return opc_putstatic_quick_jem0(ctx
);
1167 return opc_putstatic_quick_jem1(ctx
);
1169 return opc_putstatic_quick(ctx
);
1173 static int opc_checkcast_quick(struct intrp_ctx
*ctx
)
1175 struct jem_state
*jem
= &ctx
->jem
;
1176 ConstantPool
*cp
= ctx
->cp
;
1177 Class
*class = RESOLVED_CLASS(jem
);
1181 ostack_read_u32(ctx
->frame
->ostack
, ctx
->ostack
, 0, &ptr
);
1182 jam_dprintf("[OPC_CHECKCAST_QUICK] check cast for JEM type %x (class %s)\n", ptr
, CLASS_CB(class)->name
);
1184 #warning Does not look right!
1185 if (!JAM_ON_STACK
|| !IS_JAM_OBJECT(ptr
) || !IS_JAM_ARRAY(ptr
)) {
1186 obj
= JAM_OBJECT(ptr
);
1187 if (!IS_OBJECT(obj
)) {
1188 jam_dprintf("[OPC_CHECKCAST_QUICK] check cast for array\n");
1189 //should be array ref
1190 obj
= JAM_ARRAY(ptr
);
1192 jam_dprintf("[OPC_CHECKCAST_QUICK] check cast for object %x\n", obj
);
1196 jam_dprintf("[OPC_CHECKCAST_QUICK] check class %p (%s) for obj %p (%s)\n",
1197 class, CLASS_CB(class)->name
, obj
->class, CLASS_CB(obj
->class)->name
);
1198 if (!isInstanceOf(class, obj
->class))
1199 return JEM_THROW_EXCEPTION("java/lang/ClassCastException", CLASS_CB(obj
->class)->name
);
1205 static int opc_checkcast(struct intrp_ctx
*ctx
)
1207 struct jem_state
*jem
= &ctx
->jem
;
1208 Operand
*operand
= &jem
->operand
;
1209 int idx
= jem
->jecr
& 0xffff;
1210 int opcode
= (jem
->jecr
>> 16) & 0xff;
1212 ExecEnv
*ee
= ctx
->ee
;
1214 operand
->uui
.u1
= idx
;
1215 operand
->uui
.u2
= opcode
;
1217 jam_dprintf("[OPC_CHECKCAST] index: 0x%x\n", idx
);
1219 ctx
->frame
->last_pc
= (CodePntr
)jem
->jpc
;
1220 //resolve the cast class
1221 class = resolveClass(ctx
->mb
->class, idx
, FALSE
);
1223 if (exceptionOccured0(ee
))
1224 return jem_throwException(ctx
);
1226 return opc_checkcast_quick(ctx
);
1229 static int opc_invokeinterface_quick(struct intrp_ctx
*ctx
)
1234 int cache
= ctx
->jem
.operand
.uu
.u2
;
1236 ctx
->new_mb
= (MethodBlock
*)CP_INFO(ctx
->cp
, ctx
->jem
.operand
.uu
.u1
);
1237 ctx
->arg1
= ostack_address(ctx
->frame
->ostack
, ctx
->mb
->max_stack
,
1238 ctx
->ostack
- ctx
->frame
->ostack
- ctx
->new_mb
->args_count
);
1240 jam_dprintf("[OPC_INVOKEINTERFACE_QUICK] newmb %x (name %s) (args count %d) objref(jem) %x\n",
1241 ctx
->new_mb
, ctx
->new_mb
->name
, ctx
->new_mb
->args_count
, ctx
->arg1
);
1243 objref
= (Object
*)*ctx
->arg1
;
1244 #warning Does not look right!
1245 if (!JAM_ON_STACK
|| !IS_JAM_OBJECT(objref
) || !IS_JAM_ARRAY(objref
)) {
1246 objref
= JAM_OBJECT((uintptr_t *)objref
);
1247 if (!IS_OBJECT(objref
))
1248 objref
= JAM_ARRAY((uintptr_t *)*ctx
->arg1
);
1250 //turn type in the stack to JEM type ref
1251 *ctx
->arg1
= (uintptr_t)INST_DATA(objref
);
1253 JEM_NULL_POINTER_CHECK(objref
);
1255 cb
= CLASS_CB(objref
->class);
1257 if ((cache
>= cb
->imethod_table_size
) ||
1258 (ctx
->new_mb
->class != cb
->imethod_table
[cache
].interface
)) {
1259 for (cache
= 0; (cache
< cb
->imethod_table_size
) &&
1260 (ctx
->new_mb
->class != cb
->imethod_table
[cache
].interface
); cache
++);
1262 if (cache
== cb
->imethod_table_size
)
1263 return JEM_THROW_EXCEPTION("java/lang/IncompatibleClassChangeError",
1264 "unimplemented interface");
1267 mtbl_idx
= cb
->imethod_table
[cache
].offsets
[ctx
->new_mb
->method_table_index
];
1268 jam_dprintf("[OPC_INVOKEINTERFACE_QUICK] find method at %d\n", mtbl_idx
);
1269 ctx
->new_mb
= cb
->method_table
[mtbl_idx
];
1270 jam_dprintf("[OPC_INVOKEINTERFACE_QUICK] invoking method at %d\n", mtbl_idx
);
1271 return invokeMethod(ctx
);
1274 static int opc_invokeinterface(struct intrp_ctx
*ctx
)
1276 struct jem_state
*jem
= &ctx
->jem
;
1277 Operand
*operand
= &jem
->operand
;
1278 ExecEnv
*ee
= ctx
->ee
;
1280 int idx
= operand
->uu
.u1
= jem
->jecr
& 0xffff;
1281 /*NOTES: invokeinterface opcode is supposed to take 4 operands.
1282 * For JEM, two index bytes has been processed before trap,
1283 * so offset jpc 4 operands for next opcode
1284 *FIXME: ? not know why JEM does not handle this */
1285 ctx
->frame
->last_pc
= (CodePntr
)(jem
->jpc
+= 2);
1286 ctx
-> new_mb
= resolveInterfaceMethod(ctx
->mb
->class, idx
);
1288 jam_dprintf("[OPC_INVOKEINTERFACE] constant pool index %d\n", idx
);
1289 if (exceptionOccured0(ee
))
1290 return jem_throwException(ctx
);
1292 if (CLASS_CB(ctx
->new_mb
->class)->access_flags
& ACC_INTERFACE
) {
1294 return opc_invokeinterface_quick(ctx
);
1296 operand
->uu
.u1
= ctx
->new_mb
->args_count
;
1297 operand
->uu
.u2
= ctx
->new_mb
->method_table_index
;
1298 return opc_invokevirtual_quick(ctx
);
1302 static int opc_instanceof_quick(struct intrp_ctx
*ctx
)
1304 struct jem_state
*jem
= &ctx
->jem
;
1305 ConstantPool
*cp
= ctx
->cp
;
1306 Class
*class = RESOLVED_CLASS(jem
);
1310 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, ptr
);
1312 obj
= JAM_OBJECT(ptr
);
1313 if (!IS_OBJECT(obj
)) {
1314 jam_dprintf("[OPC_INSTANCEOF_QUICK] instanceof for array\n");
1315 //should be array ref
1316 obj
= JAM_ARRAY(ptr
);
1319 jam_dprintf("[OPC_INSTANCEOF_QUICK] check instanceof class %s for obj(%s)\n",
1320 CLASS_CB(class)->name
, CLASS_CB(obj
->class)->name
);
1322 ostack_push_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
,
1323 (uint32_t)isInstanceOf(class, obj
->class));
1328 static int opc_instanceof(struct intrp_ctx
*ctx
)
1330 struct jem_state
*jem
= &ctx
->jem
;
1331 Operand
*operand
= &jem
->operand
;
1332 int idx
= jem
->jecr
& 0xffff;
1333 int opcode
= (jem
->jecr
>> 16) & 0xff;
1335 ExecEnv
*ee
= ctx
->ee
;
1337 operand
->uui
.u1
= idx
;
1338 operand
->uui
.u2
= opcode
;
1340 jam_dprintf("[OPC_INSTANCEOF] index: 0x%x\n", idx
);
1342 ctx
->frame
->last_pc
= (CodePntr
)jem
->jpc
;
1343 //resolve the cast class
1344 class = resolveClass(ctx
->mb
->class, idx
, FALSE
);
1346 if (exceptionOccured0(ee
))
1347 return jem_throwException(ctx
);
1349 return opc_instanceof_quick(ctx
);
1352 static int opc_aastore(struct intrp_ctx
*ctx
)
1359 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, aobj
);
1360 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, idx
);
1361 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, array
);
1363 jam_dprintf("[OPC_AASTORE] obj %x, idx %x, array %x\n", aobj
, idx
, array
);
1365 /* aobj does point to an object, but we do not know if that's an array or
1366 * not, and we need to know that for the arrayStoreCheck() check below */
1367 #warning Does not look right!
1368 if (aobj
&& (!JAM_ON_STACK
|| !IS_JAM_OBJECT(aobj
) || !IS_JAM_ARRAY(aobj
))) {
1369 if (!IS_OBJECT(JAM_OBJECT(aobj
))) {
1370 //in case of storing an array to another array
1371 obj
= JAM_ARRAY(aobj
);
1373 obj
= JAM_OBJECT(aobj
);
1376 obj
= (Object
*)aobj
;
1377 array
= JAM_ARRAY((uintptr_t *)array
);
1379 jam_dprintf("[OPC_AASTORE] store obj ref %x to array %x in index %d\n", obj
, array
, idx
);
1380 JEM_NULL_POINTER_CHECK(array
);
1382 if (idx
>= ARRAY_LEN(array
)) {
1383 char buff
[MAX_INT_DIGITS
];
1384 snprintf(buff
, MAX_INT_DIGITS
, "%d", idx
);
1385 JEM_THROW_EXCEPTION("java/lang/ArrayIndexOutOfBoundsException", buff
);
1388 if ((obj
!= NULL
) && !arrayStoreCheck(array
->class, obj
->class))
1389 JEM_THROW_EXCEPTION("java/lang/ArrayStoreException", NULL
);
1391 //FIXME: If we set JEM ref here, it is very likely that some native jamvm code would directly offset
1392 // the array to get the non jamvm refs to use, which then causes segfault.
1394 ((Object
**)ARRAY_DATA(array
))[idx
] = obj
;
1396 ((uintptr_t**)ARRAY_DATA(array
))[idx
] = aobj
;
1401 static int do_javaExceptions(struct intrp_ctx
*ctx
)
1404 struct jem_state
*jem
= &ctx
->jem
;
1406 /* deliberate segfault */
1407 /* *(int *)0 = 0; */
1409 jecr_u
.i
= jem
->jecr
;
1410 /* This should not happen, because we don't use the "Java Handle" (H)
1411 * bit in the Status Register and we set JBCR to 0x80000000 - still
1412 * it does happen, but seems to be harmless so far. Just ignore. */
1413 if (jecr_u
.s
.opcode
== OPC_AASTORE
)
1414 return opc_aastore(ctx
);
1419 static int opc_afireturn(struct intrp_ctx
*ctx
)
1423 struct jem_state
*jem
= &ctx
->jem
;
1425 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, val
);
1427 jam_dprintf("[OPC_AFIRETURN] return 0x%08x @ %p, this %p\n",
1428 val
, ctx
->lvars_jem
, ctx
->this);
1430 ret
= opc_return(ctx
);
1432 ret
= ostack_push_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, val
);
1434 /* Function returning a value must have local variables */
1435 *ctx
->lvars_jem
= val
;
1440 static int opc_ldreturn(struct intrp_ctx
*ctx
)
1445 struct jem_state
*jem
= &ctx
->jem
;
1446 ostack_pop_u64(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, val
);
1448 jam_dprintf("[OPC_LDRETURN] return %lld\n", val
);
1450 ret
= opc_return(ctx
);
1453 ret
= ostack_push_u64(ctx
->frame
->ostack
, ctx
->mb
->max_stack
,
1456 /* Function returning a value must have local variables */
1457 *(uint64_t*)ctx
->lvars_jem
= val
;
1462 static int opc_fcmpg(struct intrp_ctx
*ctx
)
1466 struct jem_state
*jem
= &ctx
->jem
;
1467 ostack_pop_f32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, v2
);
1468 ostack_pop_f32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, v1
);
1476 res
= 1; /* isNaN */
1477 jam_dprintf("[OPC_FCMPG] result %d\n", res
);
1478 ostack_push_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, res
);
1482 static int opc_fcmpl(struct intrp_ctx
*ctx
)
1486 struct jem_state
*jem
= &ctx
->jem
;
1487 ostack_pop_f32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, v2
);
1488 ostack_pop_f32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, v1
);
1497 jam_dprintf("[OPC_FCMPL] result %d\n", res
);
1498 ostack_push_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, res
);
1502 static int opc_i2f(struct intrp_ctx
*ctx
)
1505 struct jem_state
*jem
= &ctx
->jem
;
1506 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, i
);
1509 jam_dprintf("[OPC_I2F] convert to %f\n", f
);
1510 ostack_push_f32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, f
);
1514 static int opc_i2d(struct intrp_ctx
*ctx
)
1516 return JEM_TRAP_HANDLER_FINISH
;
1519 static int opc_fmul(struct intrp_ctx
*ctx
)
1523 struct jem_state
*jem
= &ctx
->jem
;
1524 ostack_pop_f32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, v2
);
1525 ostack_pop_f32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, v1
);
1527 jam_dprintf("[OPC_FMUL] result %f\n", ret
);
1528 ostack_push_f32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, ret
);
1532 static int opc_fadd(struct intrp_ctx
*ctx
)
1536 struct jem_state
*jem
= &ctx
->jem
;
1537 ostack_pop_f32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, v2
);
1538 ostack_pop_f32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, v1
);
1540 jam_dprintf("[OPC_FADD] result %f\n", ret
);
1541 ostack_push_f32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, ret
);
1545 static int opc_fsub(struct intrp_ctx
*ctx
)
1549 struct jem_state
*jem
= &ctx
->jem
;
1550 ostack_pop_f32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, v2
);
1551 ostack_pop_f32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, v1
);
1553 jam_dprintf("[OPC_FSUB] result %f\n", ret
);
1554 ostack_push_f32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, ret
);
1558 static int opc_f2i(struct intrp_ctx
*ctx
)
1562 struct jem_state
*jem
= &ctx
->jem
;
1563 ostack_pop_f32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, value
);
1564 jam_dprintf("[OPC_F2I] float value %f\n", value
);
1565 if (value
>= (float)INT_MAX
)
1567 else if (value
<= (float)INT_MIN
)
1569 else if (value
!= value
)
1573 jam_dprintf("[OPC_F2I] int value %d\n", res
);
1574 ostack_push_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, res
);
1578 static int opc_iinc(struct intrp_ctx
*ctx
)
1581 jecr_u
.i
= ctx
->jem
.jecr
;
1582 int index
= (int)jecr_u
.s
.op1
;
1583 int con
= (int)jecr_u
.s
.op2
;
1584 uintptr_t *ptr
= ctx
->lvars_jem
;
1586 jam_dprintf("[OPC_IINC] add %d to local var %x at %d (%d)\n",
1587 con
, ptr
[-index
], index
, ctx
->mb
->max_locals
);
1588 ptr
[-index
] = ptr
[-index
] + con
;
1590 jam_dprintf("[OPC_IINC] local var is %x now\n", ptr
[-index
]);
1594 static int opc_athrow(struct intrp_ctx
*ctx
)
1597 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, obj
);
1598 ctx
->frame
->last_pc
= (CodePntr
)ctx
->jem
.jpc
;
1599 ExecEnv
*ee
= ctx
->ee
;
1601 JEM_NULL_POINTER_CHECK(obj
);
1603 if (!JAM_ON_STACK
|| !IS_JAM_OBJECT(obj
))
1604 obj
= JAM_OBJECT((uintptr_t *)obj
);
1606 jam_dprintf("[OPC_ATHROW] throw exception %s\n", CLASS_CB(obj
->class)->name
);
1607 ee
->exception
= obj
;
1608 return jem_throwException(ctx
);
1611 static int do_stackOverflow(struct intrp_ctx
*ctx
)
1613 jam_dprintf("[TRAP] STACK OVERFLOW XXXXXXXX\n");
1617 static int do_stackUnderflow(struct intrp_ctx
*ctx
)
1619 jam_dprintf("[TRAP] STACK UNDERFLOW XXXXXXXX\n");
1623 static int do_stackOverflow1(struct intrp_ctx
*ctx
)
1625 jam_dprintf("[TRAP] STACK OVERFLOW1XXXXXXXX\n");
1629 static int do_stackUnderflow1(struct intrp_ctx
*ctx
)
1631 jam_dprintf("[TRAP] STACK UNDERFLOW1XXXXXXXX\n");
1635 static handler_fn
*trap_handler_f
[256] = {
1636 [OPC_INVOKEINTERFACE
] = opc_invokeinterface
,
1637 [OPC_INVOKESPECIAL
] = opc_invokespecial
,
1638 [OPC_INVOKESUPER_QUICK
] = opc_invokesuper_quick
,
1639 [OPC_INVOKENONVIRTUAL_QUICK
] = opc_invokenonvirtual_quick
,
1640 [OPC_INVOKEVIRTUAL
] = opc_invokevirtual
,
1641 [OPC_INVOKEVIRTUAL_QUICK
] = opc_invokevirtual_quick
,
1642 [OPC_INVOKESTATIC
] = opc_invokestatic
,
1643 // [OPC_INVOKESTATIC_QUICK] = opc_invokestatic_quick,
1644 [OPC_NEW
] = opc_new
,
1645 [0xDD] = opc_new
, /* JEM: NEW_QUICK */
1646 [OPC_RETURN
] = opc_return
,
1647 [OPC_ARETURN
] = opc_afireturn
,
1648 [OPC_IRETURN
] = opc_afireturn
,
1649 [OPC_FRETURN
] = opc_afireturn
,
1650 [OPC_PUTFIELD
] = opc_putfield
,
1651 // [OPC_PUTFIELD_QUICK] = opc_putfield_quick,
1652 // [OPC_PUTFIELD2_QUICK] = opc_putfield2_quick,
1653 // [OPC_LDC_W_QUICK] = opc_ldc_w_quick,
1654 // [OPC_LDC_QUICK] = opc_ldc_quick,
1655 [OPC_LDC_W
] = opc_ldc_w
,
1656 [OPC_LDC
] = opc_ldc
,
1657 [OPC_MONITORENTER
] = opc_monitorenter
,
1658 [OPC_MONITOREXIT
] = opc_monitorexit
,
1659 [OPC_GETSTATIC
] = opc_getstatic
,
1660 // [OPC_GETSTATIC_QUICK] = opc_getstatic_quick,
1661 // [OPC_GETSTATIC2_QUICK] = opc_getstatic2_quick,
1662 [OPC_PUTSTATIC
] = opc_putstatic
,
1663 [OPC_PUTSTATIC_QUICK
] = opc_putstatic_quick
,
1664 [OPC_PUTSTATIC2_QUICK
] = opc_putstatic2_quick
,
1665 [OPC_ANEWARRAY
] = opc_anewarray
,
1666 [OPC_ANEWARRAY_QUICK
] = opc_anewarray_quick
,
1667 [OPC_MULTIANEWARRAY
] = opc_multianewarray
,
1668 [OPC_NEWARRAY
] = opc_newarray
,
1669 [OPC_CHECKCAST
] = opc_checkcast
,
1670 [OPC_CHECKCAST_QUICK
] = opc_checkcast_quick
,
1671 [OPC_GETFIELD
] = opc_getfield
,
1672 // [OPC_GETFIELD_QUICK] = opc_getfield_quick,
1673 // [OPC_GETFIELD2_QUICK] = opc_getfield2_quick,
1674 [OPC_FCMPL
] = opc_fcmpl
,
1675 [OPC_FCMPG
] = opc_fcmpg
,
1676 [OPC_I2F
] = opc_i2f
,
1677 [OPC_I2D
] = opc_i2d
,
1678 [OPC_FMUL
] = opc_fmul
,
1679 // [OPC_FADD] = opc_fadd,
1680 // [OPC_FSUB] = opc_fsub,
1681 [OPC_F2I
] = opc_f2i
,
1682 [OPC_IINC
] = opc_iinc
,
1683 [OPC_INSTANCEOF
] = opc_instanceof
,
1684 [OPC_ATHROW
] = opc_athrow
,
1685 [OPC_LRETURN
] = opc_ldreturn
,
1688 static handler_fn
*exception_handler_f
[] = {
1689 [0] = do_javaExceptions
,
1690 [1] = do_stackOverflow
,
1691 [2] = do_stackUnderflow
,
1692 [3] = do_stackOverflow1
,
1693 [4] = do_stackUnderflow1
,
1696 struct jem_profile
{
1701 static struct jem_profile prof
[256];
1703 /******************************/
1704 uintptr_t *executeJava(void)
1707 * load trap entries to JEM trap table set when initializing JamVM
1713 static struct timeval tv1
, tv2
;
1715 ExecEnv
*ee
= getExecEnv();
1717 /* Initialize interpreter's static environment */
1718 struct intrp_ctx ctx
;
1719 struct jem_state
*jem
= &ctx
.jem
;
1722 ctx
.frame
= ee
->last_frame
;
1723 ctx
.mb
= ctx
.frame
->mb
;
1725 * We use ostack to save overflowing Java Operand Stack elements. On a stack
1726 * overflow we free a half of the stack (4 elements) to avoid an immediate
1727 * next overflow. When entering a trap, the Operand Stack is saved in a
1728 * temporary array in the reverse order:
1729 * ATTENTION: Looks like ToS is really in r0, not in r7, as JEM manual says
1732 * jos[7 - N] = rN (ToS - N)
1735 * UPDATE (27.06.2008)
1736 * I think, actually, the manual is right in some way... If you access
1737 * registers individually _when_ JOSP == N + 1 != 0. If they are read out
1738 * with an ldm, you get this:
1741 * jos[7 - N] = rN (ToS)
1743 * jos[7] = r0 (ToS - N)
1744 * on an overflow we push r3..r0, i.e., jos[4..7] to the frame stack, and
1745 * set saved JOSP to 4.
1747 unsigned long jos
[8];
1749 ctx
.ostack
= ctx
.frame
->ostack
;
1750 ctx
.cp
= &(CLASS_CB(ctx
.mb
->class)->constant_pool
);
1751 /* End enterpreter's static environment */
1753 //fetch the original pc before prepare direct mb
1755 /* I think, mb->code is indeed a copy of the original code[] array from the
1756 * class object. See class.c::defineClass():390 */
1758 if (ctx
.frame
->lvars_jem
) {
1759 ctx
.lvars_jem
= ctx
.frame
->lvars_jem
- 1;
1763 jam_printf("BUG: lvars_jem == NULL!!!");
1767 jam_dprintf("[executeJava] ostack %08x locals %d lvars_jem %08x\n",
1768 ctx
.ostack
, ctx
.mb
->max_locals
, ctx
.lvars_jem
);
1769 jam_dprintf("[executeJava] execute method %s on class %s\n",
1770 ctx
.mb
->name
, CLASS_CB(ctx
.mb
->class)->name
);
1773 /* Don't think we need it, at least, not in the direct.c form. There the code
1774 * is converted into an internal representation, which is useless for JEM */
1775 PREPARE_MB(ctx
.mb
);//see direct.c (prepare)
1778 jem
->jpc
= (unsigned long)ctx
.mb
->code
& ~3;
1779 jam_dprintf("[executeJava] begin on opcode %04x (%04x)\n",
1780 *(char*)jem
->jpc
, *((char*)jem
->jpc
+ 1));
1784 /* This is not thread-safe. Have to use TLS. */
1790 jam_dprintf("About to enter JEM at 0x%08x, this = %p, class = %p. Code:",
1791 jem
->jpc
, ctx
.this, ctx
.this ? ctx
.this->class : NULL
);
1792 for (i
= 0; i
< 32 && jem
->jpc
+ i
< (unsigned long)(ctx
.mb
->code
+ ctx
.mb
->code_size
); i
++) {
1794 jam_dprintf("\n0x%04x:", i
);
1795 jam_dprintf(" 0x%02x", ((char*)jem
->jpc
)[i
]);
1798 jam_dprintf("\nUp to 8 first Local Variables out of %d:\n", ctx
.mb
->max_locals
);
1799 for (i
= 0; i
< min(8, ctx
.mb
->max_locals
); i
++)
1800 jam_dprintf("LVAR_%d: 0x%08x\n", i
, *(ctx
.lvars_jem
- i
), ctx
.lvars_jem
- i
);
1803 /* On entry we need last Java Operand Stack depth, set it not deeper
1804 * than half hardware stack */
1805 jem
->josp
= min(5, ostack_depth(ctx
.frame
->ostack
, ctx
.ostack
));
1806 jam_dprintf("Pop %d words to JEM stack from %p:%p\n", jem
->josp
,
1807 ctx
.frame
->ostack
, ctx
.ostack
);
1808 /* As long as we are in asm, top jem.josp stack elements belong JEM */
1809 for (i
= 0; i
< jem
->josp
; i
++)
1810 ostack_pop_u32(ctx
.frame
->ostack
, ctx
.mb
->max_stack
, ctx
.ostack
,
1811 jos
[7 - jem
->josp
+ 1 + i
]);
1815 gettimeofday(&tv2
, NULL
);
1816 prof
[opcode
].time
+= (tv2
.tv_sec
- tv1
.tv_sec
) * 1000000 +
1817 tv2
.tv_usec
- tv1
.tv_usec
;
1822 __asm__
__volatile__(
1823 ".globl debug_jem_enter\n"
1824 "debug_jem_enter:\n"
1825 " pushm r0-r7,r10-r11\n"
1829 " mov r12, %[josp]\n" /* Cannot use %[josp] ... */
1830 " mov r11, %[ostack]\n"
1831 " pushm r11\n" /* Need ostack below */
1832 " ldm r11, r0-r7\n" /* Restore Java Operands */
1833 " cp.w r12, 0\n" /* Test josp == 0 */
1835 "5: incjosp 1\n" /* ... for loop counter, */
1836 " sub r12, 1\n" /* because it can be */
1837 " brne 5b\n" /* one of r0-r7 */
1838 "4: popjc\n" /* Restore Local Variables */
1839 " sub r10, pc, . - trap\n" /* These 3 instructions */
1840 " retj\n" /* have to stay */
1841 "trap: pushjc\n" /* together */
1842 " mfsr r11, 0x58\n" /* JOSP */
1843 " lsl r11, 28\n" /* Clear r11[31:3] using */
1844 " lsr r11, 28\n" /* one register */
1850 "2: popm r11\n" /* ostack */
1851 " stm r11, r0-r7\n" /* Save Java Operands */
1852 " popm r0-r7,r10-r11\n"
1853 " mov %[tpc], r12\n"
1854 " mov %[jpc], lr\n" /* Resume address */
1855 " mfsr %[jecr], 0x54\n" /* JECR */
1856 " mov %[josp], r8\n" /* JOSP */
1857 " .globl debug_jem_exit\n"
1859 : [jecr
] "=r" (jem
->jecr
), [tpc
] "=r" (jem
->trap_pc
),
1860 [josp
] "+r" (jem
->josp
), [jpc
] "+r" (jem
->jpc
)
1861 : [cp
] "r" (ctx
.cp
->info
), [lv0
] "r" (ctx
.lvars_jem
),
1863 : "r8", "r9", "lr", "r12", "memory"
1866 * trap_pc now holds trap pc, describing which trap has been entered,
1867 * jecr holds JECR with the trapping bytecode at bits 23..16, possibly
1868 * arguments at bits 7..0 and 15..8,
1869 * josp holds JOSP (JOSP & 0xf),
1870 * jos holds stored registers r7-r0 (note order!) - Java Operand Stack
1871 * jpc points at the trapping opcode, in case of exceptions and stack
1872 * over- and underflows, and at the next opcode, in case of a trap
1876 gettimeofday(&tv1
, NULL
);
1879 for (i
= 0; i
< jem
->josp
; i
++)
1880 ostack_push_u32(ctx
.frame
->ostack
, ctx
.mb
->max_stack
, ctx
.ostack
,
1883 opcode
= (jem
->jecr
>> 16) & 0xff;
1885 jep
= jem
->trap_pc
& 0xfff;
1889 done
= exception_handler_f
[jep
>> 7](&ctx
);
1890 else if (trap_handler_f
[opcode
])
1891 done
= trap_handler_f
[opcode
](&ctx
);
1894 jam_printf("Unimplemented Java Opcode 0x%02x\n", opcode
);
1901 } while (done
!= JEM_TRAP_HANDLER_FINISH
);
1907 jam_dprintf("Unknown Java Opcodes\n");
1912 void initialiseInterpreter(InitArgs
*args
) {
1913 initialiseDirect(args
);
1917 void dump_profile(void)
1922 for (i
= 0; i
< 256; i
++)
1924 jam_printf("0x%x:\t%u times,\t%lu usec\n", i
, prof
[i
].n
, prof
[i
].time
);