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"
38 #include <sys/syscall.h>
42 #include "arch/avr32_jem.h"
43 #include "interp_jem.h"
56 * Interpreter execution context
62 /* the interpreter execution context */
74 typedef int handler_fn(struct intrp_ctx
*ctx
);
76 static void jem_opcode_rewrite(uint32_t new_opcode
, char *pc
, int argc
, ...)
81 va_start(vargs
, argc
);
83 for (i
= 1; i
<= argc
; i
++)
84 pc
[i
] = (char)va_arg(vargs
, int);
88 #define min(x, y) ({ typeof(x) _x = (x); typeof(y) _y = (y); _x > _y ? _y : _x; })
90 //check if it is an valid object ref (see alloc.c)
91 #define OBJECT_GRAIN 8
92 #define IS_OBJECT(ptr) !(((uintptr_t)(ptr))&(OBJECT_GRAIN-1))
94 #define JEM_THROW_EXCEPTION(excep_name, message) \
96 ctx->frame->last_pc = (CodePntr)ctx->jem.jpc; \
97 signalException(excep_name, message); \
98 jem_throwException(ctx); \
101 #define JEM_NULL_POINTER_CHECK(ref) \
102 if (!ref) JEM_THROW_EXCEPTION("java/lang/NullPointerException", NULL);
104 /*********************************************
105 * JEM Trap Handlers **
106 * *******************************************/
107 static int trap_debug(struct intrp_ctx
*ctx
)
110 struct jem_state
*jem
= &ctx
->jem
;
113 static unsigned long count
;
115 jecr_u
.i
= jem
->jecr
;
117 jam_printf("[%lu]: Trap 0x%08x: ostack 0x%x, opcode 0x%x @ 0x%08x, "
118 "operand 1 0x%x, operand 2 0x%x. Operands:\n",
119 count
++, jem
->trap_pc
, ctx
->ostack
, jecr_u
.s
.opcode
,
120 jem
->jpc
, jecr_u
.s
.op1
, jecr_u
.s
.op2
);
122 for (i
= 0; i
< jem
->josp
; i
++) {
124 if (ostack_read_u32(ctx
->frame
->ostack
, ctx
->ostack
, i
, &v
) >= 0)
125 jam_printf("\tToS-%d: 0x%x\n", i
, v
);
132 static int jem_throwException(struct intrp_ctx
*ctx
)
134 struct jem_state
*jem
= &ctx
->jem
;
135 ExecEnv
*ee
= ctx
->ee
;
136 Object
*excep
= ee
->exception
;
137 ee
->exception
= NULL
;
139 jem
->jpc
= (unsigned long)findCatchBlock(excep
->class);
140 jam_dprintf("Found exception handler at 0x%08x\n", jem
->jpc
);
142 /* If we didn't find a handler, restore exception and
143 return to previous invocation */
146 ee
->exception
= excep
;
147 /* Original code had a "return NULL" here, which means, end of
149 return JEM_TRAP_HANDLER_FINISH
;
152 /* If we're handling a stack overflow, reduce the stack
153 back past the red zone to enable handling of further
157 ee
->overflow
= FALSE
;
158 ee
->stack_end
-= STACK_RED_ZONE_SIZE
;
161 /* Setup intepreter to run the found catch block */
163 ctx
->frame
= ee
->last_frame
;
164 ctx
->mb
= ctx
->frame
->mb
;
165 ctx
->ostack
= ctx
->frame
->ostack
;
166 ctx
->lvars_jem
= ctx
->frame
->lvars_jem
? ctx
->frame
->lvars_jem
- 1 : NULL
;
167 if (ctx
->lvars_jem
) {
168 uintptr_t *aobj
= (uintptr_t *)*ctx
->lvars_jem
;
169 ctx
->this = JAM_OBJECT(aobj
);
172 ctx
->cp
= &(CLASS_CB(ctx
->mb
->class)->constant_pool
);
174 /* FIXME: don't know if this is correct, depends how we implement
176 ostack_push_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, (uint32_t)excep
);
178 /* Dispatch to the first bytecode */
182 static int opc_return(struct intrp_ctx
*ctx
)
184 ExecEnv
*ee
= ctx
->ee
;
186 /* Set interpreter state to previous frame */
187 if (ctx
->frame
->prev
->mb
== NULL
) {
188 /* The previous frame is a dummy frame - this indicates
189 * top of this Java invocation. */
193 ctx
->frame
= ctx
->frame
->prev
;
195 if (ctx
->mb
->access_flags
& ACC_SYNCHRONIZED
) {
196 Object
*sync_ob
= ctx
->mb
->access_flags
& ACC_STATIC
? (Object
*)ctx
->mb
->class : ctx
->this;
197 objectUnlock(sync_ob
);
200 ctx
->ostack
= ctx
->lvars_jem
- ctx
->mb
->max_locals
+ 1 - ctx
->mb
->args_count
;
201 ctx
->mb
= ctx
->frame
->mb
;
202 ctx
->lvars_jem
= ctx
->frame
->lvars_jem
? ctx
->frame
->lvars_jem
- 1 : 0;
203 if (ctx
->lvars_jem
) {
204 uintptr_t *aobj
= (uintptr_t *)*ctx
->lvars_jem
;
205 ctx
->this = JAM_OBJECT(aobj
);
208 ctx
->jem
.jpc
= (uint32_t)ctx
->frame
->last_pc
;
209 ctx
->cp
= &(CLASS_CB(ctx
->mb
->class)->constant_pool
);
210 jam_dprintf("[OPC_RETURN] ostack : %08x, lvars_jem :%08x this %08x\n",
211 ctx
->ostack
, ctx
->lvars_jem
, ctx
->this);
214 ee
->last_frame
= ctx
->frame
;
219 static int invokeMethod(struct intrp_ctx
*ctx
)
221 ExecEnv
*ee
= ctx
->ee
;
222 /* Seems like the original jamvm reused top of caller's stack for callee's
223 * local variables for passing of method arguments. Our stack and
224 * local variables grow in opposite directions now, so, this is impossible.
225 * ctx->ostack points at the beginning of the free space above ostack.
227 Frame
*new_frame
= (Frame
*)(ctx
->ostack
+ ctx
->new_mb
->max_locals
);
228 Object
*sync_ob
= NULL
;
232 jam_dprintf("[invokeMethod] with args count %d\n", ctx
->new_mb
->args_count
);
233 jam_dprintf("[invokeMethod] new frame start %x\n", new_frame
);
235 ctx
->frame
->last_pc
= (CodePntr
)ctx
->jem
.jpc
;
236 ctx
->ostack
= (uintptr_t *)(new_frame
+ 1);
238 if (ostack_overflows(ctx
->ostack
, ctx
->new_mb
->max_stack
, (uintptr_t *)ee
->stack_end
)) {
239 if (ee
->overflow
++) {
240 /* Overflow when we're already throwing stack overflow.
241 Stack extension should be enough to throw exception,
242 so something's seriously gone wrong - abort the VM! */
243 jam_printf("Fatal stack overflow! Aborting VM.\n");
246 ee
->stack_end
+= STACK_RED_ZONE_SIZE
;
247 return JEM_THROW_EXCEPTION("java/lang/StackOverflowError", NULL
);
251 new_frame
->mb
= ctx
->new_mb
;
252 //TODO: it seemed lvars is in java stack, but jos[8] should be part of java stack
253 // lvars_jem requires that the highest pointer should refer to the first local variables LV0
254 // Here still not touch the java stack, allocate lvars_jem from native heap
256 new_frame
->lvars_jem
= (uintptr_t *)new_frame
;
258 if (ctx
->new_mb
->max_locals
> 0) {
260 for (i
= 0; i
< ctx
->new_mb
->args_count
; i
++) {
261 *(new_frame
->lvars_jem
- 1 - i
) = *(ctx
->arg1
+ i
);
262 jam_dprintf("arg[%d] = 0x%x@%p\n", i
, *(ctx
->arg1
+ i
), ctx
->arg1
+ i
);
265 jam_dprintf("[invokeMethod] new_frame -> lvars_jem %x\n", new_frame
->lvars_jem
);
267 new_frame
->ostack
= ctx
->ostack
;
268 new_frame
->prev
= ctx
->frame
;
270 ee
->last_frame
= new_frame
;
272 if (ctx
->new_mb
->access_flags
& ACC_SYNCHRONIZED
) {
273 aobj
= (uintptr_t *)*ctx
->arg1
;
274 sync_ob
= ctx
->new_mb
->access_flags
& ACC_STATIC
?
275 (Object
*)ctx
->new_mb
->class : JAM_OBJECT(aobj
);
279 if (ctx
->new_mb
->access_flags
& ACC_NATIVE
) {
280 //FIXME: the object references in JEM are direct pointer to instance variables.
281 // While JamVM requires object references as pointers to Object type.
282 jam_dprintf("[invokeMethod] invoke native method\n");
283 ctx
->ostack
= (*(uintptr_t *(*)(Class
*, MethodBlock
*, uintptr_t*))
284 ctx
->new_mb
->native_invoker
)(ctx
->new_mb
->class, ctx
->new_mb
, ctx
->arg1
);
287 objectUnlock(sync_ob
);
289 ee
->last_frame
= ctx
->frame
;
291 if (exceptionOccured0(ee
)) {
292 jam_dprintf("[invokeMethod] exception occured, goto throwException\n");
293 return jem_throwException(ctx
);
296 jam_dprintf("[invokeMethod] finish native method invoke, return to loop\n");
298 ctx
->frame
= new_frame
;
299 ctx
->mb
= ctx
->new_mb
;
300 ctx
->lvars_jem
= new_frame
->lvars_jem
? new_frame
->lvars_jem
- 1 : NULL
;
302 if (ctx
->lvars_jem
) {
303 aobj
= (uintptr_t *)*ctx
->lvars_jem
;
304 ctx
->this = JAM_OBJECT(aobj
);
308 ctx
->jem
.jpc
= (unsigned long)ctx
->mb
->code
& ~3;
309 ctx
->cp
= &(CLASS_CB(ctx
->mb
->class)->constant_pool
);
311 jam_dprintf("[invokeMethod] invoke virtual method: frame %x mb %x "
312 "lvars %x jpc %x cp %x\n", ctx
->frame
, ctx
->mb
,
313 ctx
->lvars_jem
, ctx
->jem
.jpc
, ctx
->cp
);
314 jam_dprintf("[invokeMethod] finish virtual method invoke, return to loop\n");
320 static int opc_invokesuper_quick(struct intrp_ctx
*ctx
)
322 struct jem_state
*jem
= &ctx
->jem
;
323 Operand
*operand
= &jem
->operand
;
325 jam_dprintf("[OPC_INVOKESUPER_QUICK] method table indx %d\n", operand
->i
);
326 ctx
->new_mb
= CLASS_CB(CLASS_CB(ctx
->mb
->class)->super
)->method_table
[operand
->i
];
327 jam_dprintf("[OPC_INVOKESUPER_QUICK] method args count %d\n", ctx
->new_mb
->args_count
);
329 // set up jem operand stack
330 ctx
->arg1
= ostack_address(ctx
->frame
->ostack
, ctx
->mb
->max_stack
,
331 ctx
->ostack
- ctx
->frame
->ostack
- ctx
->new_mb
->args_count
);
332 JEM_NULL_POINTER_CHECK(*ctx
->arg1
);
333 jam_dprintf("[OP_INVOKESUPER_QUICK] arg1 %x\n", *ctx
->arg1
);
334 return invokeMethod(ctx
);
337 static int opc_invokenonvirtual_quick(struct intrp_ctx
*ctx
)
339 struct jem_state
*jem
= &ctx
->jem
;
340 Operand
*operand
= &jem
->operand
;
342 ctx
->new_mb
= (MethodBlock
*)operand
->pntr
;
343 jam_dprintf("[%s] new methodblock %s (%x) with %d args\n",
344 __func__
, ctx
->new_mb
->name
, ctx
->new_mb
, ctx
->new_mb
->args_count
);
345 ctx
->arg1
= ostack_address(ctx
->frame
->ostack
, ctx
->mb
->max_stack
,
346 ctx
->ostack
- ctx
->frame
->ostack
- ctx
->new_mb
->args_count
);
348 jam_dprintf("[%s] ctx->arg1 %x\n", __func__
, *ctx
->arg1
);
349 JEM_NULL_POINTER_CHECK(*ctx
->arg1
);
350 return invokeMethod(ctx
);
353 static int opc_invokevirtual_quick(struct intrp_ctx
*ctx
)
355 struct jem_state
*jem
= &ctx
->jem
;
357 ctx
->arg1
= ostack_address(ctx
->frame
->ostack
, ctx
->mb
->max_stack
,
358 ctx
->ostack
- ctx
->frame
->ostack
- INV_QUICK_ARGS(jem
));
359 JEM_NULL_POINTER_CHECK(*ctx
->arg1
);
362 //in case of "AALOAD" loads JAM obj from reference array
363 obj
= (Object
*)*ctx
->arg1
;
364 if (!JAM_ON_STACK
|| !IS_JAM_OBJECT(obj
))
365 obj
= JAM_OBJECT((uintptr_t *)obj
);
367 //we should ensure ostack constains no JAM object
368 *ctx
->arg1
= (uintptr_t)INST_DATA(obj
);
370 jam_dprintf("[OPC_INVOKEVIRTUAL_QUICK] invoke on object 0x%08x (0x%08x)\n", obj
, ctx
->arg1
);
371 new_class
= obj
->class;
372 ctx
->new_mb
= CLASS_CB(new_class
)->method_table
[INV_QUICK_IDX(jem
)];
373 jam_dprintf("[OPC_INVOKEVIRTUAL_QUICK] invoke method 0x%08x on class %x\n",
374 ctx
->new_mb
, new_class
);
375 return invokeMethod(ctx
);
378 static int opc_invokevirtual(struct intrp_ctx
*ctx
)
381 ExecEnv
*ee
= ctx
->ee
;
382 struct jem_state
*jem
= &ctx
->jem
;
384 idx
= jem
->jecr
& 0xffff;
385 ctx
->frame
->last_pc
= (CodePntr
)jem
->jpc
;
386 ctx
->new_mb
= resolveMethod(ctx
->mb
->class, idx
);
388 if (exceptionOccured0(ee
))
389 return jem_throwException(ctx
);
391 jem
->operand
.uu
.u1
= ctx
->new_mb
->args_count
;
392 jem
->operand
.uu
.u2
= ctx
->new_mb
->method_table_index
;
394 jam_dprintf("[OPC_INVOKEVIRTUAL] invoke 0x%08x with args count %d\n",
395 ctx
->new_mb
,ctx
->new_mb
->args_count
);
397 return opc_invokevirtual_quick(ctx
);
400 static int opc_invokespecial(struct intrp_ctx
*ctx
)
403 struct jem_state
*jem
= &ctx
->jem
;
404 Operand
*operand
= &jem
->operand
;
405 ExecEnv
*ee
= ctx
->ee
;
407 /* INVOKESPECIAL's operands represent an index into the Constant Pool */
408 idx
= jem
->jecr
& 0xffff;
410 jam_dprintf("[OPC_INVOKESPECIAL] constant pool index %d\n", idx
);
412 ctx
->new_mb
= resolveMethod(ctx
->mb
->class, idx
);
414 if (exceptionOccured0(ee
))
415 return jem_throwException(ctx
);
417 jam_dprintf("Resolved %s\n", ctx
->new_mb
->name
);
419 /* Check if invoking a super method... */
420 if ((CLASS_CB(ctx
->mb
->class)->access_flags
& ACC_SUPER
) &&
421 ((ctx
->new_mb
->access_flags
& ACC_PRIVATE
) == 0) && (ctx
->new_mb
->name
[0] != '<')) {
423 operand
->i
= ctx
->new_mb
->method_table_index
;
424 return opc_invokesuper_quick(ctx
);
425 #if 0 /* FIXME: verify this whole "pc" chemistry is indeed unneeded */
426 OPCODE_REWRITE(OPC_INVOKESUPER_QUICK
, cache
, operand
);
429 operand
->pntr
= ctx
->new_mb
;
430 return opc_invokenonvirtual_quick(ctx
);
436 static int opc_invokestatic_quick(struct intrp_ctx
*ctx
)
438 struct jem_state
*jem
= &ctx
->jem
;
440 ctx
->new_mb
= RESOLVED_METHOD(jem
);
441 ctx
->arg1
= ostack_address(ctx
->frame
->ostack
, ctx
->mb
->max_stack
,
442 ctx
->ostack
- ctx
->frame
->ostack
- ctx
->new_mb
->args_count
);
443 return invokeMethod(ctx
);
446 static int opc_invokestatic(struct intrp_ctx
*ctx
)
449 struct jem_state
*jem
= &ctx
->jem
;
450 Operand
*operand
= &jem
->operand
;
451 ExecEnv
*ee
= ctx
->ee
;
453 idx
= jem
->jecr
& 0xffff;
455 ctx
->frame
->last_pc
= (CodePntr
)jem
->jpc
;
456 ctx
->new_mb
= resolveMethod(ctx
->mb
->class, idx
);
458 if (exceptionOccured0(ee
))
459 return jem_throwException(ctx
);
461 operand
->pntr
= ctx
->new_mb
;
462 return opc_invokestatic_quick(ctx
);
465 static int opc_new_quick(struct intrp_ctx
*ctx
)
467 struct jem_state
*jem
= &ctx
->jem
;
468 Operand
*operand
= &jem
->operand
;
469 Class
*class = (Class
*)CP_INFO(ctx
->cp
, operand
->uui
.u1
);
472 ctx
->frame
->last_pc
= (CodePntr
)jem
->jpc
;
473 if ((obj
= allocObject(class)) == NULL
)
474 return jem_throwException(ctx
);
475 jam_dprintf("[OPC_NEW_QUICK] push obj ref %x to stack\n", obj
);
476 return ostack_push_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
,
477 (uint32_t)INST_DATA(obj
));
480 static int opc_new(struct intrp_ctx
*ctx
)
482 struct jem_state
*jem
= &ctx
->jem
;
483 Operand
*operand
= &jem
->operand
;
484 int idx
= operand
->uui
.u1
= jem
->jecr
& 0xffff;
485 int opcode
= operand
->uui
.u2
= (jem
->jecr
>> 16) & 0xff;
487 ExecEnv
*ee
= ctx
->ee
;
489 jam_dprintf("[OPC_NEW] opcode: %x\n", opcode
);
491 ctx
->frame
->last_pc
= (CodePntr
)jem
->jpc
;
492 class = resolveClass(ctx
->mb
->class, idx
, opcode
== OPC_NEW
);
493 if (exceptionOccured0(ee
))
494 return jem_throwException(ctx
);
496 if (opcode
== OPC_NEW
) {
497 ClassBlock
*cb
= CLASS_CB(class);
498 if (cb
->access_flags
& (ACC_INTERFACE
| ACC_ABSTRACT
)) {
499 signalException("java/lang/InstantiationError", cb
->name
);
500 return jem_throwException(ctx
);
502 /* rewrite opcode to OPC_NEW_QUICK (0xDD) */
503 jem_opcode_rewrite(0xDD, (char*)jem
->jpc
- 3, 0);
506 return opc_new_quick(ctx
);
509 static int opc_anewarray_quick(struct intrp_ctx
*ctx
)
511 struct jem_state
*jem
= &ctx
->jem
;
512 ConstantPool
*cp
= ctx
->cp
;
513 Class
*class = RESOLVED_CLASS(jem
);
514 char *name
= CLASS_CB(class)->name
;
519 ExecEnv
*ee
= ctx
->ee
;
521 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, count
);
522 ctx
->frame
->last_pc
= (CodePntr
)jem
->jpc
;
524 jam_dprintf("[OPC_ANEWARRAY_QUICK] array %s size %d\n", name
, count
);
526 signalException("java/lang/NegativeArraySizeException", NULL
);
527 return jem_throwException(ctx
);
530 ac_name
= sysMalloc(strlen(name
) + 4);
533 sprintf(ac_name
, "[%s", name
);
535 sprintf(ac_name
, "[L%s;", name
);
537 array_class
= findArrayClassFromClass(ac_name
, ctx
->mb
->class);
540 if (exceptionOccured0(ee
))
541 return jem_throwException(ctx
);
543 if ((obj
= allocArray(array_class
, count
, sizeof(Object
*))) == NULL
)
544 return jem_throwException(ctx
);
546 return ostack_push_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
,
547 (uint32_t)ARRAY_DATA(obj
));
550 static int opc_anewarray(struct intrp_ctx
*ctx
)
552 struct jem_state
*jem
= &ctx
->jem
;
553 Operand
*operand
= &jem
->operand
;
554 int idx
= operand
->uui
.u1
= jem
->jecr
& 0xffff;
555 int opcode
= operand
->uui
.u2
= (jem
->jecr
>> 16) & 0xff;
557 ExecEnv
*ee
= ctx
->ee
;
559 jam_dprintf("[OPC_NEW/OPC_ANEWARRAY/OPC_CHECKCAST/OPC_INSTANCEOF] opcode : %x\n", opcode
);
561 ctx
->frame
->last_pc
= (CodePntr
)jem
->jpc
;
562 //resolve the array class
563 class = resolveClass(ctx
->mb
->class, idx
, opcode
== OPC_NEW
);
565 if (exceptionOccured0(ee
))
566 return jem_throwException(ctx
);
568 return opc_anewarray_quick(ctx
);
571 static int opc_multianewarray_quick(struct intrp_ctx
*ctx
)
573 struct jem_state
*jem
= &ctx
->jem
;
574 ConstantPool
*cp
= ctx
->cp
;
575 Class
*class = RESOLVED_CLASS(jem
);
576 int i
, dim
= MULTI_ARRAY_DIM(jem
);
579 ExecEnv
*ee
= ctx
->ee
;
581 ctx
->frame
->last_pc
= (CodePntr
)jem
->jpc
;
583 jam_dprintf("[OPC_MULTIANEWARRAY_QUICK]: alloc %d dimensional array for class %s\n", dim
, CLASS_CB(class)->name
);
584 for (i
= 0; i
< dim
; i
++) {
585 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, count
);
586 jam_dprintf("[OPC_MULTIANEWARRAY_QUICK]: elements %d for dim %d\n", count
, i
);
588 signalException("java/lang/NegativeArraySizeException", NULL
);
589 return jem_throwException(ctx
);
593 /* counts are still stored in ostack even after we did pop them out */
594 if ((obj
= allocMultiArray(class, dim
, (intptr_t *)ctx
->ostack
)) == NULL
)
595 return jem_throwException(ctx
);
597 return ostack_push_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
,
598 (uint32_t)ARRAY_DATA(obj
));
601 static int opc_multianewarray(struct intrp_ctx
*ctx
)
603 struct jem_state
*jem
= &ctx
->jem
;
604 Operand
*operand
= &jem
->operand
;
605 int idx
= operand
->uui
.u1
= jem
->jecr
& 0xffff;
608 ExecEnv
*ee
= ctx
->ee
;
611 operand
->uui
.u2
= *(unsigned char*)jem
->jpc
;
612 jem
->jpc
++; /* skip dims */
614 ctx
->frame
->last_pc
= (CodePntr
)jem
->jpc
;
615 /* resolve the array class */
616 class = resolveClass(ctx
->mb
->class, idx
, FALSE
);
618 if (exceptionOccured0(ee
))
619 return jem_throwException(ctx
);
621 return opc_multianewarray_quick(ctx
);
624 static int opc_newarray(struct intrp_ctx
*ctx
)
626 struct jem_state
*jem
= &ctx
->jem
;
627 int type
= (jem
->jecr
>> 8) & 0xff;
631 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, count
);
632 ctx
->frame
->last_pc
= (CodePntr
)jem
->jpc
;
634 jam_dprintf("[OPC_NEWARRAY] alloc array type %d, count %d\n", type
, count
);
635 if ((obj
= allocTypeArray(type
, count
)) == NULL
)
636 return jem_throwException(ctx
);
638 return ostack_push_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
,
639 (uint32_t)ARRAY_DATA(obj
));
642 static int opc_putfield_quick(struct intrp_ctx
*ctx
)
646 struct jem_state
*jem
= &ctx
->jem
;
648 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, arg
);
649 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, obj
);
650 jam_dprintf("[OPC_PUTFIELD_QUICK] put field %x to obj(%d) %x\n", arg
,
651 SINGLE_INDEX(jem
), obj
);
653 JEM_NULL_POINTER_CHECK(obj
);
655 if (JAM_ON_STACK
&& IS_JAM_OBJECT(obj
))
656 obj
= (uint32_t)INST_DATA((Object
*)obj
);
658 ((uint32_t*)obj
)[SINGLE_INDEX(jem
)] = arg
;
663 static int opc_putfield2_quick(struct intrp_ctx
*ctx
)
667 struct jem_state
*jem
= &ctx
->jem
;
669 ostack_pop_u64(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, arg
);
670 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, obj
);
672 JEM_NULL_POINTER_CHECK((uintptr_t*)obj
);
674 if (JAM_ON_STACK
&& IS_JAM_OBJECT(obj
))
675 obj
= (uint32_t)INST_DATA((Object
*)obj
);
677 *(uint64_t *)&(((uint32_t*)obj
)[SINGLE_INDEX(jem
)]) = arg
;
678 jam_dprintf("[OPC_PUTFIELD2_QUICK] put 64 bit %08x to obj %08x\n", arg
, obj
);
683 static int opc_putfield_quick_jem0(struct intrp_ctx
*ctx
)
687 struct jem_state
*jem
= &ctx
->jem
;
689 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, arg
);
690 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, aobj
);
691 jam_dprintf("[OPC_PUTFIELD_QUICK_JEM0] field %x\n", arg
);
693 JEM_NULL_POINTER_CHECK(aobj
);
695 if (JAM_ON_STACK
&& arg
&& !IS_JAM_OBJECT(arg
))
696 arg
= (uint32_t)JAM_OBJECT((uintptr_t *)arg
);
698 if (JAM_ON_STACK
&& IS_JAM_OBJECT(aobj
))
699 aobj
= INST_DATA((Object
*)aobj
);
701 aobj
[SINGLE_INDEX(jem
)] = arg
;
702 jam_dprintf("[OPC_PUTFIELD_QUICK_JEM0] put field %x to obj(%d) %x\n", arg
,
703 SINGLE_INDEX(jem
), aobj
);
708 static int opc_putfield_quick_jem1(struct intrp_ctx
*ctx
)
710 uintptr_t *aobj
, *arg
;
711 struct jem_state
*jem
= &ctx
->jem
;
713 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, arg
);
714 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, aobj
);
715 jam_dprintf("[OPC_PUTFIELD_QUICK_JEM1] field %p\n", arg
);
717 if (JAM_ON_STACK
&& arg
&& !IS_JAM_ARRAY(arg
))
718 arg
= (uintptr_t *)JAM_ARRAY(arg
);
720 if (JAM_ON_STACK
&& IS_JAM_OBJECT(aobj
))
721 aobj
= INST_DATA((Object
*)aobj
);
723 JEM_NULL_POINTER_CHECK(aobj
);
724 aobj
[SINGLE_INDEX(jem
)] = (uintptr_t)arg
;
725 jam_dprintf("[OPC_PUTFIELD_QUICK_JEM1] put field %p to obj(%d) %p\n", arg
,
726 SINGLE_INDEX(jem
), aobj
);
731 static int opc_putfield(struct intrp_ctx
*ctx
)
733 struct jem_state
*jem
= &ctx
->jem
;
734 int idx
= jem
->jecr
& 0xffff;
736 ExecEnv
*ee
= ctx
->ee
;
738 jam_dprintf("[OPC_PUTFIELD] constant pool index %d\n", idx
);
740 ctx
->frame
->last_pc
= (CodePntr
)jem
->jpc
;
741 fb
= resolveField(ctx
->mb
->class, idx
);
742 jam_dprintf("[OPC_PUTFIELD] resolve field 0x%08x, type %c\n", fb
, *fb
->type
);
744 if (exceptionOccured0(ee
))
745 return jem_throwException(ctx
);
747 jem
->operand
.i
= fb
->offset
;
751 /* rewrite opc_putfield to opc_putfield2_quick */
752 jem_opcode_rewrite(0xD1, (char*)jem
->jpc
- 3, 2, fb
->offset
>> 8, fb
->offset
);
753 return opc_putfield2_quick(ctx
);
755 jem_opcode_rewrite(0xCF, (char*)jem
->jpc
- 3, 2, fb
->offset
>> 8, fb
->offset
);
756 return opc_putfield_quick_jem0(ctx
);
758 jem_opcode_rewrite(0xCF, (char*)jem
->jpc
- 3, 2, fb
->offset
>> 8, fb
->offset
);
759 return opc_putfield_quick_jem1(ctx
);
761 jem_opcode_rewrite(0xCF, (char*)jem
->jpc
- 3, 2, fb
->offset
>> 8, fb
->offset
);
762 return opc_putfield_quick(ctx
);
766 static int opc_getfield2_quick(struct intrp_ctx
*ctx
)
769 struct jem_state
*jem
= &ctx
->jem
;
770 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, obj
);
771 JEM_NULL_POINTER_CHECK(obj
);
773 if (JAM_ON_STACK
&& IS_JAM_OBJECT(obj
))
774 obj
= (uint32_t*)INST_DATA((Object
*)obj
);
776 jam_dprintf("[OPC_GETFIELD2_QUICK] get 64 bit field %08x from obj %08x\n",
777 *(uint64_t*)(&(obj
[SINGLE_INDEX(jem
)])), obj
);
779 return ostack_push_u64(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
,
780 *(uint64_t*)(&(obj
[SINGLE_INDEX(jem
)])));
783 static int opc_getfield_quick(struct intrp_ctx
*ctx
)
786 struct jem_state
*jem
= &ctx
->jem
;
788 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, aobj
);
789 JEM_NULL_POINTER_CHECK(aobj
);
791 if (JAM_ON_STACK
&& IS_JAM_OBJECT(aobj
))
792 aobj
= (uint32_t*)INST_DATA((Object
*)aobj
);
794 jam_dprintf("[OPC_GETFIELD_QUICK] get field %08x from obj %08x\n",
795 aobj
[SINGLE_INDEX(jem
)], aobj
);
796 return ostack_push_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
,
797 aobj
[SINGLE_INDEX(jem
)]);
800 static int opc_getfield_quick_jem0(struct intrp_ctx
*ctx
)
803 struct jem_state
*jem
= &ctx
->jem
;
804 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, aobj
);
805 JEM_NULL_POINTER_CHECK(aobj
);
807 if (JAM_ON_STACK
&& IS_JAM_OBJECT(aobj
))
808 aobj
= (uint32_t*)INST_DATA((Object
*)aobj
);
810 uint32_t value
= aobj
[SINGLE_INDEX(jem
)];
811 jam_dprintf("[OPC_GETFIELD_QUICK_JEM0] obj ref %x\n", value
);
813 Object
*ref
= (Object
*)value
;
814 if (JAM_ON_STACK
&& IS_JAM_OBJECT(ref
))
816 value
= (uint32_t)INST_DATA(ref
);
818 jam_dprintf("[OPC_GETFIELD_QUICK_JEM0] put obj ref %x\n", value
);
819 return ostack_push_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, value
);
823 static int opc_getfield_quick_jem1(struct intrp_ctx
*ctx
)
826 struct jem_state
*jem
= &ctx
->jem
;
828 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, aobj
);
829 JEM_NULL_POINTER_CHECK(aobj
);
831 //"aaload" would put jamvm obj ref onto the ostack
832 if (JAM_ON_STACK
&& IS_JAM_OBJECT(aobj
))
833 aobj
= (uint32_t*)INST_DATA((Object
*)aobj
);
835 uint32_t value
= aobj
[SINGLE_INDEX(jem
)];
836 jam_dprintf("[OPC_GETFIELD_QUICK_JEM1] array ref %x\n", value
);
838 Object
*ref
= (Object
*)value
;
839 if (JAM_ON_STACK
&& IS_JAM_ARRAY(ref
))
840 value
= (uint32_t)ARRAY_DATA(ref
);
842 jam_dprintf("[OPC_GETFIELD_QUICK_JEM1] put array ref %x\n", value
);
843 return ostack_push_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, value
);
846 static int opc_getfield(struct intrp_ctx
*ctx
)
848 struct jem_state
*jem
= &ctx
->jem
;
849 int idx
= jem
->jecr
& 0xffff;
851 ExecEnv
*ee
= ctx
->ee
;
853 jam_dprintf("[OPC_GETFIELD] constant pool index %d\n", idx
);
855 ctx
->frame
->last_pc
= (CodePntr
)jem
->jpc
;
856 fb
= resolveField(ctx
->mb
->class, idx
);
857 jam_dprintf("[OPC_GETFIELD] resolve field 0x%08x, type %c\n", fb
, *fb
->type
);
859 if (exceptionOccured0(ee
))
860 return jem_throwException(ctx
);
862 jem
->operand
.i
= fb
->offset
;
866 jem_opcode_rewrite(0xD0, (char*)jem
->jpc
- 3, 2, fb
->offset
>> 8, fb
->offset
);
867 return opc_getfield2_quick(ctx
);
869 * Though we assume all objrefs/arrayrefs here should be JEM compliant, but
870 * in case of some JNI code will set field natively, we still handle it
874 jem_opcode_rewrite(0xCE, (char*)jem
->jpc
- 3, 2, fb
->offset
>> 8, fb
->offset
);
875 return opc_getfield_quick_jem0(ctx
);
877 jem_opcode_rewrite(0xCE, (char*)jem
->jpc
- 3, 2, fb
->offset
>> 8, fb
->offset
);
878 return opc_getfield_quick_jem1(ctx
);
880 //jem_opcode_rewrite(0xCE, (char*)jem->jpc - 3, 2, (fb->offset>>8)&0xff, (fb->offset)&0xff);
881 return opc_getfield_quick(ctx
);
885 static int opc_ldc_w_quick_jem(struct intrp_ctx
*ctx
)
887 struct jem_state
*jem
= &ctx
->jem
;
888 //CONSTANT_Class and CONSTANT_String are stored as object reference
889 Object
*cp_info
= (Object
*)CP_INFO(ctx
->cp
, DOUBLE_INDEX(jem
));
890 jam_dprintf("[OPC_LDC_W_QUICK_JEM] push String ref %x to stack\n", cp_info
);
891 return ostack_push_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
,
892 (uint32_t)INST_DATA(cp_info
));
895 static int opc_ldc_w_quick(struct intrp_ctx
*ctx
)
897 struct jem_state
*jem
= &ctx
->jem
;
898 uint32_t cp_info
= CP_INFO(ctx
->cp
, DOUBLE_INDEX(jem
));
899 jam_dprintf("[OPC_LDC_W_QUICK] push constant %08x to stack\n", cp_info
);
900 return ostack_push_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, cp_info
);
903 static int opc_ldc_quick(struct intrp_ctx
*ctx
)
905 struct jem_state
*jem
= &ctx
->jem
;
906 uint32_t constant
= RESOLVED_CONSTANT(jem
);
907 jam_dprintf("[OPC_LDC_QUICK] push constant %x to stack\n", constant
);
908 return ostack_push_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, (uintptr_t)constant
);
911 static int opc_ldc_common(struct intrp_ctx
*ctx
, int idx
)
913 struct jem_state
*jem
= &ctx
->jem
;
914 ExecEnv
*ee
= ctx
->ee
;
915 ctx
->frame
->last_pc
= (CodePntr
)jem
->jpc
;
917 jem
->operand
.u
= resolveSingleConstant(ctx
->mb
->class, idx
);
919 if (exceptionOccured0(ee
))
920 return jem_throwException(ctx
);
922 if (CP_TYPE(ctx
->cp
, idx
) == CONSTANT_ResolvedClass
) {
923 jem
->operand
.i
= idx
;
924 jem_opcode_rewrite(0xCC, (char*)jem
->jpc
- 3, 0);
925 return opc_ldc_w_quick(ctx
);
926 } else if (CP_TYPE(ctx
->cp
, idx
) == CONSTANT_ResolvedString
) {
927 jem
->operand
.i
= idx
;
928 return opc_ldc_w_quick_jem(ctx
);
930 jem_opcode_rewrite(0xCB, (char*)jem
->jpc
- 2, 0);
931 return opc_ldc_quick(ctx
);
935 static int opc_ldc(struct intrp_ctx
*ctx
)
938 ExecEnv
*ee
= ctx
->ee
;
939 struct jem_state
*jem
= &ctx
->jem
;
941 idx
= (jem
->jecr
& 0xff00) >> 8;
943 jam_dprintf("[OPC_LDC] constant pool index %d\n", idx
);
944 return opc_ldc_common(ctx
, idx
);
947 static int opc_ldc_w(struct intrp_ctx
*ctx
)
950 ExecEnv
*ee
= ctx
->ee
;
951 struct jem_state
*jem
= &ctx
->jem
;
953 idx
= (jem
->jecr
& 0xffff);
955 jam_dprintf("[OPC_LDC_W] constant pool index %d\n", idx
);
956 return opc_ldc_common(ctx
, idx
);
959 static int opc_monitorenter(struct intrp_ctx
*ctx
)
963 struct jem_state
*jem
= &ctx
->jem
;
964 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, ptr
);
966 obj
= JAM_OBJECT(ptr
);
968 /* is an array ref */
969 obj
= JAM_ARRAY(ptr
);
970 jam_dprintf("[OPC_MONITORENTER] lock %x\n", obj
);
971 JEM_NULL_POINTER_CHECK(obj
);
976 static int opc_monitorexit(struct intrp_ctx
*ctx
)
980 struct jem_state
*jem
= &ctx
->jem
;
981 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, ptr
);
983 obj
= JAM_OBJECT(ptr
);
985 /* is an array ref */
986 obj
= JAM_ARRAY(ptr
);
987 jam_dprintf("[OPC_MONITOREXIT] unlock %x\n", obj
);
988 JEM_NULL_POINTER_CHECK(obj
);
993 static int opc_getstatic_quick(struct intrp_ctx
*ctx
)
995 struct jem_state
*jem
= &ctx
->jem
;
996 return ostack_push_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
,
997 RESOLVED_FIELD(jem
)->static_value
);
1000 static int opc_getstatic2_quick(struct intrp_ctx
*ctx
)
1002 struct jem_state
*jem
= &ctx
->jem
;
1003 return ostack_push_u64(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
,
1004 RESOLVED_FIELD(jem
)->static_value
);
1007 static int opc_getstatic_quick_jem0(struct intrp_ctx
*ctx
)
1009 struct jem_state
*jem
= &ctx
->jem
;
1010 uintptr_t value
= RESOLVED_FIELD(jem
)->static_value
;
1012 jam_dprintf("[OPC_GETSTATIC_QUICK_JEM0] obj ref %x\n", value
);
1014 Object
*ref
= (Object
*)value
;
1015 if (!JAM_ON_STACK
|| IS_JAM_OBJECT(ref
))
1017 value
= (uintptr_t)INST_DATA(ref
);
1019 jam_dprintf("[OPC_GETSTATIC_QUICK_JEM0] put obj ref %x\n", value
);
1020 return ostack_push_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, value
);
1023 static int opc_getstatic_quick_jem1(struct intrp_ctx
*ctx
)
1025 struct jem_state
*jem
= &ctx
->jem
;
1026 uintptr_t value
= RESOLVED_FIELD(jem
)->static_value
;
1027 jam_dprintf("[OPC_GETSTATIC_QUICK_JEM1] array ref %x\n", value
);
1029 Object
*ref
= (Object
*)value
;
1030 if (!JAM_ON_STACK
|| IS_JAM_ARRAY(ref
))
1032 value
= (uintptr_t)ARRAY_DATA(ref
);
1034 jam_dprintf("[OPC_GETSTATIC_QUICK_JEM1] put array ref %x\n", value
);
1035 return ostack_push_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, value
);
1038 static int opc_getstatic(struct intrp_ctx
*ctx
)
1043 ExecEnv
*ee
= ctx
->ee
;
1044 struct jem_state
*jem
= &ctx
->jem
;
1046 idx
= (int)(jem
->jecr
& 0xffff);
1047 jam_dprintf("[OPC_GETSTATIC] constant pool index %d class %s\n",idx
,CLASS_CB(ctx
->mb
->class)->name
);
1049 ctx
->frame
->last_pc
= (CodePntr
)jem
->jpc
;
1050 fb
= resolveField(ctx
->mb
->class, idx
);
1052 if (exceptionOccured0(ee
))
1053 return jem_throwException(ctx
);
1055 jam_dprintf("[OPC_GETSTATIC] get static for field %08x, type %c\n", fb
, *fb
->type
);
1056 jem
->operand
.pntr
= fb
;
1057 switch (*fb
->type
) {
1060 return opc_getstatic2_quick(ctx
);
1065 return opc_getstatic_quick_jem0(ctx
);
1067 return opc_getstatic_quick_jem1(ctx
);
1069 return opc_getstatic_quick(ctx
);
1073 static int opc_putstatic2_quick(struct intrp_ctx
*ctx
)
1075 struct jem_state
*jem
= &ctx
->jem
;
1076 return ostack_pop_u64(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
,
1077 *(u8
*)&RESOLVED_FIELD(jem
)->static_value
);
1080 static int opc_putstatic_quick(struct intrp_ctx
*ctx
)
1082 struct jem_state
*jem
= &ctx
->jem
;
1083 return ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
,
1084 RESOLVED_FIELD(jem
)->static_value
);
1087 static int opc_putstatic_quick_jem0(struct intrp_ctx
*ctx
)
1090 struct jem_state
*jem
= &ctx
->jem
;
1091 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, value
);
1093 jam_dprintf("[OPC_PUTSTATIC_QUICK_JEM0] obj %x\n", value
);
1094 if (value
&& (!JAM_ON_STACK
|| !IS_JAM_OBJECT(value
)))
1095 value
= (uintptr_t)JAM_OBJECT((uintptr_t *)value
);
1096 jam_dprintf("[OPC_PUTSTATIC_QUICK_JEM0] put obj %x\n", value
);
1097 RESOLVED_FIELD(jem
)->static_value
= value
;
1101 static int opc_putstatic_quick_jem1(struct intrp_ctx
*ctx
)
1104 struct jem_state
*jem
= &ctx
->jem
;
1105 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, value
);
1107 jam_dprintf("[OPC_PUTSTATIC_QUICK_JEM1] array %p\n", value
);
1108 if (value
&& (!JAM_ON_STACK
|| !IS_JAM_ARRAY(value
)))
1109 value
= (uintptr_t*)JAM_ARRAY(value
);
1110 jam_dprintf("[OPC_PUTSTATIC_QUICK_JEM1] put array %p\n", value
);
1111 RESOLVED_FIELD(jem
)->static_value
= (uintptr_t)value
;
1115 static int opc_putstatic(struct intrp_ctx
*ctx
)
1120 ExecEnv
*ee
= ctx
->ee
;
1121 struct jem_state
*jem
= &ctx
->jem
;
1123 idx
= (int)(jem
->jecr
& 0xffff);
1125 ctx
->frame
->last_pc
= (CodePntr
)jem
->jpc
;
1126 fb
= resolveField(ctx
->mb
->class, idx
);
1128 if (exceptionOccured0(ee
))
1129 return jem_throwException(ctx
);
1131 jam_dprintf("[OPC_PUTSTATIC] put static for field %08x, type %c\n", fb
, *fb
->type
);
1132 jem
->operand
.pntr
= fb
;
1133 switch (*fb
->type
) {
1136 //jem_opcode_rewrite(0xD5, (char*)jem->jpc - 3);
1137 return opc_putstatic2_quick(ctx
);
1139 return opc_putstatic_quick_jem0(ctx
);
1141 return opc_putstatic_quick_jem1(ctx
);
1143 return opc_putstatic_quick(ctx
);
1147 static int opc_checkcast_quick(struct intrp_ctx
*ctx
)
1149 struct jem_state
*jem
= &ctx
->jem
;
1150 ConstantPool
*cp
= ctx
->cp
;
1151 Class
*class = RESOLVED_CLASS(jem
);
1155 ostack_read_u32(ctx
->frame
->ostack
, ctx
->ostack
, 0, &ptr
);
1156 jam_dprintf("[OPC_CHECKCAST_QUICK] check cast for JEM type %x (class %s)\n", ptr
, CLASS_CB(class)->name
);
1158 #warning Does not look right!
1159 if (!JAM_ON_STACK
|| !IS_JAM_OBJECT(ptr
) || !IS_JAM_ARRAY(ptr
)) {
1160 obj
= JAM_OBJECT(ptr
);
1161 if (!IS_OBJECT(obj
)) {
1162 jam_dprintf("[OPC_CHECKCAST_QUICK] check cast for array\n");
1163 //should be array ref
1164 obj
= JAM_ARRAY(ptr
);
1166 jam_dprintf("[OPC_CHECKCAST_QUICK] check cast for object %x\n", obj
);
1170 jam_dprintf("[OPC_CHECKCAST_QUICK] check class %s for obj(%s)\n", CLASS_CB(class)->name
, CLASS_CB(obj
->class)->name
);
1171 if ((obj
!= NULL
) && !isInstanceOf(class, obj
->class))
1172 return JEM_THROW_EXCEPTION("java/lang/ClassCastException", CLASS_CB(obj
->class)->name
);
1178 static int opc_checkcast(struct intrp_ctx
*ctx
)
1180 struct jem_state
*jem
= &ctx
->jem
;
1181 Operand
*operand
= &jem
->operand
;
1182 int idx
= operand
->uui
.u1
= jem
->jecr
& 0xffff;
1183 int opcode
= operand
->uui
.u2
= (jem
->jecr
>> 16) & 0xff;
1185 ExecEnv
*ee
= ctx
->ee
;
1187 jam_dprintf("[OPC_NEW/OPC_ANEWARRAY/OPC_CHECKCAST/OPC_INSTANCEOF] opcode : %x\n", opcode
);
1189 ctx
->frame
->last_pc
= (CodePntr
)jem
->jpc
;
1190 //resolve the cast class
1191 class = resolveClass(ctx
->mb
->class, idx
, opcode
== OPC_NEW
);
1193 if (exceptionOccured0(ee
))
1194 return jem_throwException(ctx
);
1196 return opc_checkcast_quick(ctx
);
1199 static int opc_invokeinterface_quick(struct intrp_ctx
*ctx
)
1204 int cache
= ctx
->jem
.operand
.uu
.u2
;
1206 ctx
->new_mb
= (MethodBlock
*)CP_INFO(ctx
->cp
, ctx
->jem
.operand
.uu
.u1
);
1207 ctx
->arg1
= ostack_address(ctx
->frame
->ostack
, ctx
->mb
->max_stack
,
1208 ctx
->ostack
- ctx
->frame
->ostack
- ctx
->new_mb
->args_count
);
1210 jam_dprintf("[OPC_INVOKEINTERFACE_QUICK] newmb %x (name %s) (args count %d) objref(jem) %x\n",
1211 ctx
->new_mb
, ctx
->new_mb
->name
, ctx
->new_mb
->args_count
, ctx
->arg1
);
1213 objref
= (Object
*)*ctx
->arg1
;
1214 #warning Does not look right!
1215 if (!JAM_ON_STACK
|| !IS_JAM_OBJECT(objref
) || !IS_JAM_ARRAY(objref
)) {
1216 objref
= JAM_OBJECT((uintptr_t *)objref
);
1217 if (!IS_OBJECT(objref
))
1218 objref
= JAM_ARRAY((uintptr_t *)*ctx
->arg1
);
1220 //turn type in the stack to JEM type ref
1221 *ctx
->arg1
= (uintptr_t)INST_DATA(objref
);
1223 JEM_NULL_POINTER_CHECK(objref
);
1225 cb
= CLASS_CB(objref
->class);
1227 if ((cache
>= cb
->imethod_table_size
) ||
1228 (ctx
->new_mb
->class != cb
->imethod_table
[cache
].interface
)) {
1229 for (cache
= 0; (cache
< cb
->imethod_table_size
) &&
1230 (ctx
->new_mb
->class != cb
->imethod_table
[cache
].interface
); cache
++);
1232 if (cache
== cb
->imethod_table_size
)
1233 return JEM_THROW_EXCEPTION("java/lang/IncompatibleClassChangeError",
1234 "unimplemented interface");
1237 mtbl_idx
= cb
->imethod_table
[cache
].offsets
[ctx
->new_mb
->method_table_index
];
1238 jam_dprintf("[OPC_INVOKEINTERFACE_QUICK] find method at %d\n", mtbl_idx
);
1239 ctx
->new_mb
= cb
->method_table
[mtbl_idx
];
1240 jam_dprintf("[OPC_INVOKEINTERFACE_QUICK] invoking method at %d\n", mtbl_idx
);
1241 return invokeMethod(ctx
);
1244 static int opc_invokeinterface(struct intrp_ctx
*ctx
)
1246 struct jem_state
*jem
= &ctx
->jem
;
1247 Operand
*operand
= &jem
->operand
;
1248 ExecEnv
*ee
= ctx
->ee
;
1250 int idx
= operand
->uu
.u1
= jem
->jecr
& 0xffff;
1251 /*NOTES: invokeinterface opcode is supposed to take 4 operands.
1252 * For JEM, two index bytes has been processed before trap,
1253 * so offset jpc 4 operands for next opcode
1254 *FIXME: ? not know why JEM does not handle this */
1255 ctx
->frame
->last_pc
= (CodePntr
)(jem
->jpc
+= 2);
1256 ctx
-> new_mb
= resolveInterfaceMethod(ctx
->mb
->class, idx
);
1258 jam_dprintf("[OPC_INVOKEINTERFACE] constant pool index %d\n", idx
);
1259 if (exceptionOccured0(ee
))
1260 return jem_throwException(ctx
);
1262 if (CLASS_CB(ctx
->new_mb
->class)->access_flags
& ACC_INTERFACE
) {
1264 return opc_invokeinterface_quick(ctx
);
1266 operand
->uu
.u1
= ctx
->new_mb
->args_count
;
1267 operand
->uu
.u2
= ctx
->new_mb
->method_table_index
;
1268 return opc_invokevirtual_quick(ctx
);
1272 static int opc_instanceof_quick(struct intrp_ctx
*ctx
)
1274 struct jem_state
*jem
= &ctx
->jem
;
1275 ConstantPool
*cp
= ctx
->cp
;
1276 Class
*class = RESOLVED_CLASS(jem
);
1280 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, ptr
);
1282 obj
= JAM_OBJECT(ptr
);
1283 if (!IS_OBJECT(obj
)) {
1284 jam_dprintf("[OPC_INSTANCEOF_QUICK] instanceof for array\n");
1285 //should be array ref
1286 obj
= JAM_ARRAY(ptr
);
1289 jam_dprintf("[OPC_INSTANCEOF_QUICK] check instanceof class %s for obj(%s)\n", CLASS_CB(class)->name
, CLASS_CB(obj
->class)->name
);
1291 ostack_push_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
,isInstanceOf(class, obj
->class));
1296 static int opc_instanceof(struct intrp_ctx
*ctx
)
1298 struct jem_state
*jem
= &ctx
->jem
;
1299 Operand
*operand
= &jem
->operand
;
1300 int idx
= operand
->uui
.u1
= jem
->jecr
& 0xffff;
1301 int opcode
= operand
->uui
.u2
= (jem
->jecr
>> 16) & 0xff;
1303 ExecEnv
*ee
= ctx
->ee
;
1305 jam_dprintf("[OPC_INSTANCEOF] opcode : %x\n", opcode
);
1307 ctx
->frame
->last_pc
= (CodePntr
)jem
->jpc
;
1308 //resolve the cast class
1309 class = resolveClass(ctx
->mb
->class, idx
, opcode
== OPC_NEW
);
1311 if (exceptionOccured0(ee
))
1312 return jem_throwException(ctx
);
1314 return opc_instanceof_quick(ctx
);
1317 static int opc_aastore(struct intrp_ctx
*ctx
)
1324 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, aobj
);
1325 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, idx
);
1326 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, array
);
1328 jam_dprintf("[OPC_AASTORE] obj %x, idx %x, array %x\n", aobj
, idx
, array
);
1330 /* aobj does point to an object, but we do not know if that's an array or
1331 * not, and we need to know that for the arrayStoreCheck() check below */
1332 #warning Does not look right!
1333 if (aobj
&& (!JAM_ON_STACK
|| !IS_JAM_OBJECT(aobj
) || !IS_JAM_ARRAY(aobj
))) {
1334 if (!IS_OBJECT(JAM_OBJECT(aobj
))) {
1335 //in case of storing an array to another array
1336 obj
= JAM_ARRAY(aobj
);
1338 obj
= JAM_OBJECT(aobj
);
1341 obj
= (Object
*)aobj
;
1342 array
= JAM_ARRAY((uintptr_t *)array
);
1344 jam_dprintf("[OPC_AASTORE] store obj ref %x to array %x in index %d\n", obj
, array
, idx
);
1345 JEM_NULL_POINTER_CHECK(array
);
1347 if (idx
>= ARRAY_LEN(array
)) {
1348 char buff
[MAX_INT_DIGITS
];
1349 snprintf(buff
, MAX_INT_DIGITS
, "%d", idx
);
1350 JEM_THROW_EXCEPTION("java/lang/ArrayIndexOutOfBoundsException", buff
);
1353 if ((obj
!= NULL
) && !arrayStoreCheck(array
->class, obj
->class))
1354 JEM_THROW_EXCEPTION("java/lang/ArrayStoreException", NULL
);
1356 //FIXME: If we set JEM ref here, it is very likely that some native jamvm code would directly offset
1357 // the array to get the non jamvm refs to use, which then causes segfault.
1359 ((Object
**)ARRAY_DATA(array
))[idx
] = obj
;
1361 ((uintptr_t**)ARRAY_DATA(array
))[idx
] = aobj
;
1366 static int do_javaExceptions(struct intrp_ctx
*ctx
)
1369 struct jem_state
*jem
= &ctx
->jem
;
1371 /* deliberate segfault */
1372 /* *(int *)0 = 0; */
1374 jecr_u
.i
= jem
->jecr
;
1375 /* This should not happen, because we don't use the "Java Handle" (H)
1376 * bit in the Status Register and we set JBCR to 0x80000000 - still
1377 * it does happen, but seems to be harmless so far. Just ignore. */
1378 if (jecr_u
.s
.opcode
== OPC_AASTORE
)
1379 return opc_aastore(ctx
);
1384 static int opc_afireturn(struct intrp_ctx
*ctx
)
1388 struct jem_state
*jem
= &ctx
->jem
;
1390 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, val
);
1392 jam_dprintf("[OPC_AFIRETURN] return %08x @ %p\n", val
, ctx
->lvars_jem
);
1394 ret
= opc_return(ctx
);
1396 ret
= ostack_push_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, val
);
1398 *ctx
->lvars_jem
= val
;
1403 static int opc_ldreturn(struct intrp_ctx
*ctx
)
1408 struct jem_state
*jem
= &ctx
->jem
;
1409 ostack_pop_u64(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, val
);
1411 jam_dprintf("[OPC_LDRETURN] return %lld\n", val
);
1413 ret
= opc_return(ctx
);
1416 ret
= ostack_push_u64(ctx
->frame
->ostack
, ctx
->mb
->max_stack
,
1419 *(uint64_t*)ctx
->lvars_jem
= val
;
1424 static int opc_fcmpg(struct intrp_ctx
*ctx
)
1428 struct jem_state
*jem
= &ctx
->jem
;
1429 ostack_pop_f32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, v2
);
1430 ostack_pop_f32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, v1
);
1438 res
= 1; /* isNaN */
1439 jam_dprintf("[OPC_FCMPG] result %d\n", res
);
1440 ostack_push_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, res
);
1444 static int opc_fcmpl(struct intrp_ctx
*ctx
)
1448 struct jem_state
*jem
= &ctx
->jem
;
1449 ostack_pop_f32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, v2
);
1450 ostack_pop_f32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, v1
);
1459 jam_dprintf("[OPC_FCMPL] result %d\n", res
);
1460 ostack_push_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, res
);
1464 static int opc_i2f(struct intrp_ctx
*ctx
)
1467 struct jem_state
*jem
= &ctx
->jem
;
1468 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, i
);
1471 jam_dprintf("[OPC_I2F] convert to %f\n", f
);
1472 ostack_push_f32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, f
);
1476 static int opc_i2d(struct intrp_ctx
*ctx
)
1478 return JEM_TRAP_HANDLER_FINISH
;
1481 static int opc_fmul(struct intrp_ctx
*ctx
)
1485 struct jem_state
*jem
= &ctx
->jem
;
1486 ostack_pop_f32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, v2
);
1487 ostack_pop_f32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, v1
);
1489 jam_dprintf("[OPC_FMUL] result %f\n", ret
);
1490 ostack_push_f32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, ret
);
1494 static int opc_fadd(struct intrp_ctx
*ctx
)
1498 struct jem_state
*jem
= &ctx
->jem
;
1499 ostack_pop_f32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, v2
);
1500 ostack_pop_f32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, v1
);
1502 jam_dprintf("[OPC_FADD] result %f\n", ret
);
1503 ostack_push_f32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, ret
);
1507 static int opc_fsub(struct intrp_ctx
*ctx
)
1511 struct jem_state
*jem
= &ctx
->jem
;
1512 ostack_pop_f32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, v2
);
1513 ostack_pop_f32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, v1
);
1515 jam_dprintf("[OPC_FSUB] result %f\n", ret
);
1516 ostack_push_f32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, ret
);
1520 static int opc_f2i(struct intrp_ctx
*ctx
)
1524 struct jem_state
*jem
= &ctx
->jem
;
1525 ostack_pop_f32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, value
);
1526 jam_dprintf("[OPC_F2I] float value %f\n", value
);
1527 if (value
>= (float)INT_MAX
)
1529 else if (value
<= (float)INT_MIN
)
1531 else if (value
!= value
)
1535 jam_dprintf("[OPC_F2I] int value %d\n", res
);
1536 ostack_push_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, res
);
1540 static int opc_iinc(struct intrp_ctx
*ctx
)
1543 jecr_u
.i
= ctx
->jem
.jecr
;
1544 int index
= (int)jecr_u
.s
.op1
;
1545 int con
= (int)jecr_u
.s
.op2
;
1546 uintptr_t *ptr
= ctx
->lvars_jem
;
1548 jam_dprintf("[OPC_IINC] add %d to local var %x at %d (%d)\n",
1549 con
, ptr
[-index
], index
, ctx
->mb
->max_locals
);
1550 ptr
[-index
] = ptr
[-index
] + con
;
1552 jam_dprintf("[OPC_IINC] local var is %x now\n", ptr
[-index
]);
1556 static int opc_athrow(struct intrp_ctx
*ctx
)
1559 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, obj
);
1560 ctx
->frame
->last_pc
= (CodePntr
)ctx
->jem
.jpc
;
1561 ExecEnv
*ee
= ctx
->ee
;
1563 JEM_NULL_POINTER_CHECK(obj
);
1565 if (!JAM_ON_STACK
|| !IS_JAM_OBJECT(obj
))
1566 obj
= JAM_OBJECT((uintptr_t *)obj
);
1568 jam_dprintf("[OPC_ATHROW] throw exception %s\n", CLASS_CB(obj
->class)->name
);
1569 ee
->exception
= obj
;
1570 return jem_throwException(ctx
);
1573 static int do_stackOverflow(struct intrp_ctx
*ctx
)
1575 jam_dprintf("[TRAP] STACK OVERFLOW XXXXXXXX\n");
1580 static int do_stackUnderflow(struct intrp_ctx
*ctx
)
1582 jam_dprintf("[TRAP] STACK UNDERFLOW XXXXXXXX\n");
1587 static int do_stackOverflow1(struct intrp_ctx
*ctx
)
1589 jam_dprintf("[TRAP] STACK OVERFLOW1XXXXXXXX\n");
1594 static int do_stackUnderflow1(struct intrp_ctx
*ctx
)
1596 jam_dprintf("[TRAP] STACK UNDERFLOW1XXXXXXXX\n");
1601 static handler_fn
*trap_handler_f
[256] = {
1602 [OPC_INVOKEINTERFACE
] = opc_invokeinterface
,
1603 [OPC_INVOKESPECIAL
] = opc_invokespecial
,
1604 [OPC_INVOKESUPER_QUICK
] = opc_invokesuper_quick
,
1605 [OPC_INVOKENONVIRTUAL_QUICK
] = opc_invokenonvirtual_quick
,
1606 [OPC_INVOKEVIRTUAL
] = opc_invokevirtual
,
1607 [OPC_INVOKEVIRTUAL_QUICK
] = opc_invokevirtual_quick
,
1608 [OPC_INVOKESTATIC
] = opc_invokestatic
,
1609 // [OPC_INVOKESTATIC_QUICK] = opc_invokestatic_quick,
1610 [OPC_NEW
] = opc_new
,
1611 [0xDD] = opc_new
, /* JEM: NEW_QUICK */
1612 [OPC_RETURN
] = opc_return
,
1613 [OPC_ARETURN
] = opc_afireturn
,
1614 [OPC_IRETURN
] = opc_afireturn
,
1615 [OPC_FRETURN
] = opc_afireturn
,
1616 [OPC_PUTFIELD
] = opc_putfield
,
1617 // [OPC_PUTFIELD_QUICK] = opc_putfield_quick,
1618 // [OPC_PUTFIELD2_QUICK] = opc_putfield2_quick,
1619 // [OPC_LDC_W_QUICK] = opc_ldc_w_quick,
1620 // [OPC_LDC_QUICK] = opc_ldc_quick,
1621 [OPC_LDC_W
] = opc_ldc_w
,
1622 [OPC_LDC
] = opc_ldc
,
1623 [OPC_MONITORENTER
] = opc_monitorenter
,
1624 [OPC_MONITOREXIT
] = opc_monitorexit
,
1625 [OPC_GETSTATIC
] = opc_getstatic
,
1626 // [OPC_GETSTATIC_QUICK] = opc_getstatic_quick,
1627 // [OPC_GETSTATIC2_QUICK] = opc_getstatic2_quick,
1628 [OPC_PUTSTATIC
] = opc_putstatic
,
1629 [OPC_PUTSTATIC_QUICK
] = opc_putstatic_quick
,
1630 [OPC_PUTSTATIC2_QUICK
] = opc_putstatic2_quick
,
1631 [OPC_ANEWARRAY
] = opc_anewarray
,
1632 [OPC_ANEWARRAY_QUICK
] = opc_anewarray_quick
,
1633 [OPC_MULTIANEWARRAY
] = opc_multianewarray
,
1634 [OPC_NEWARRAY
] = opc_newarray
,
1635 [OPC_CHECKCAST
] = opc_checkcast
,
1636 [OPC_CHECKCAST_QUICK
] = opc_checkcast_quick
,
1637 [OPC_GETFIELD
] = opc_getfield
,
1638 // [OPC_GETFIELD_QUICK] = opc_getfield_quick,
1639 // [OPC_GETFIELD2_QUICK] = opc_getfield2_quick,
1640 [OPC_FCMPL
] = opc_fcmpl
,
1641 [OPC_FCMPG
] = opc_fcmpg
,
1642 [OPC_I2F
] = opc_i2f
,
1643 [OPC_I2D
] = opc_i2d
,
1644 [OPC_FMUL
] = opc_fmul
,
1645 // [OPC_FADD] = opc_fadd,
1646 // [OPC_FSUB] = opc_fsub,
1647 [OPC_F2I
] = opc_f2i
,
1648 [OPC_IINC
] = opc_iinc
,
1649 [OPC_INSTANCEOF
] = opc_instanceof
,
1650 [OPC_ATHROW
] = opc_athrow
,
1651 [OPC_LRETURN
] = opc_ldreturn
,
1654 static handler_fn
*exception_handler_f
[] = {
1655 [0] = do_javaExceptions
,
1656 [1] = do_stackOverflow
,
1657 [2] = do_stackUnderflow
,
1658 [3] = do_stackOverflow1
,
1659 [4] = do_stackUnderflow1
,
1662 struct jem_profile
{
1667 static struct jem_profile prof
[256];
1669 /******************************/
1670 uintptr_t *executeJava(void)
1673 * load trap entries to JEM trap table set when initializing JamVM
1679 static struct timeval tv1
, tv2
;
1681 ExecEnv
*ee
= getExecEnv();
1683 /* Initialize interpreter's static environment */
1684 struct intrp_ctx ctx
;
1685 struct jem_state
*jem
= &ctx
.jem
;
1688 ctx
.frame
= ee
->last_frame
;
1689 ctx
.mb
= ctx
.frame
->mb
;
1691 * We use ostack to save overflowing Java Operand Stack elements. On a stack
1692 * overflow we free a half of the stack (4 elements) to avoid an immediate
1693 * next overflow. When entering a trap, the Operand Stack is saved in a
1694 * temporary array in the reverse order:
1695 * ATTENTION: Looks like ToS is really in r0, not in r7, as JEM manual says
1698 * jos[7 - N] = rN (ToS - N)
1701 * UPDATE (27.06.2008)
1702 * I think, actually, the manual is right in some way... If you access
1703 * registers individually _when_ JOSP == N + 1 != 0. If they are read out
1704 * with an ldm, you get this:
1707 * jos[7 - N] = rN (ToS)
1709 * jos[7] = r0 (ToS - N)
1710 * on an overflow we push r3..r0, i.e., jos[4..7] to the frame stack, and
1711 * set saved JOSP to 4.
1713 unsigned long jos
[8];
1715 ctx
.ostack
= ctx
.frame
->ostack
;
1716 ctx
.cp
= &(CLASS_CB(ctx
.mb
->class)->constant_pool
);
1717 /* End enterpreter's static environment */
1719 //fetch the original pc before prepare direct mb
1721 /* I think, mb->code is indeed a copy of the original code[] array from the
1722 * class object. See class.c::defineClass():390 */
1724 if (ctx
.frame
->lvars_jem
) {
1726 ctx
.lvars_jem
= ctx
.frame
->lvars_jem
- 1;
1727 ptr
= (uintptr_t *)*ctx
.lvars_jem
;
1728 ctx
.this = JAM_OBJECT(ptr
);
1730 /* FIXME: do not know how to set it when there're none local var */
1731 ctx
.lvars_jem
= NULL
;
1735 jam_dprintf("[executeJava] ostack %08x locals %d lvars_jem %08x\n",
1736 ctx
.ostack
, ctx
.mb
->max_locals
, ctx
.lvars_jem
);
1737 jam_dprintf("[executeJava] execute method %s on class %s\n",
1738 ctx
.mb
->name
, CLASS_CB(ctx
.mb
->class)->name
);
1741 /* Don't think we need it, at least, not in the direct.c form. There the code
1742 * is converted into an internal representation, which is useless for JEM */
1743 PREPARE_MB(ctx
.mb
);//see direct.c (prepare)
1746 jem
->jpc
= (unsigned long)ctx
.mb
->code
& ~3;
1747 jam_dprintf("[executeJava] begin on opcode %04x (%04x)\n",
1748 *(char*)jem
->jpc
, *((char*)jem
->jpc
+ 1));
1754 jam_dprintf("About to enter JEM at 0x%08x, this = %p. Code:", jem
->jpc
, ctx
.this);
1755 for (i
= 0; i
< 32 && jem
->jpc
+ i
< (unsigned long)(ctx
.mb
->code
+ ctx
.mb
->code_size
); i
++) {
1757 jam_dprintf("\n0x%04x:", i
);
1758 jam_dprintf(" 0x%02x", ((char*)jem
->jpc
)[i
]);
1761 jam_dprintf("\nUp to 8 first Local Variables out of %d:\n", ctx
.mb
->max_locals
);
1762 for (i
= 0; i
< min(8, ctx
.mb
->max_locals
); i
++)
1763 jam_dprintf("LVAR_%d: 0x%08x\n", i
, *(ctx
.lvars_jem
- i
), ctx
.lvars_jem
- i
);
1766 /* On entry we need last Java Operand Stack depth, set it not deeper
1767 * than half hardware stack */
1768 jem
->josp
= min(5, ostack_depth(ctx
.frame
->ostack
, ctx
.ostack
));
1769 jam_dprintf("Pop %d words to JEM stack from %p:%p\n", jem
->josp
,
1770 ctx
.frame
->ostack
, ctx
.ostack
);
1771 /* As long as we are in asm, top jem.josp stack elements belong JEM */
1772 for (i
= 0; i
< jem
->josp
; i
++)
1773 ostack_pop_u32(ctx
.frame
->ostack
, ctx
.mb
->max_stack
, ctx
.ostack
,
1774 jos
[7 - jem
->josp
+ 1 + i
]);
1778 gettimeofday(&tv2
, NULL
);
1779 prof
[opcode
].time
+= (tv2
.tv_sec
- tv1
.tv_sec
) * 1000000 +
1780 tv2
.tv_usec
- tv1
.tv_usec
;
1785 __asm__
__volatile__(
1786 ".globl debug_jem_enter\n"
1787 "debug_jem_enter:\n"
1788 " pushm r0-r7,r10-r11\n"
1792 " mov r12, %[josp]\n" /* Cannot use %[josp] ... */
1793 " mov r11, %[ostack]\n"
1794 " pushm r11\n" /* Need ostack below */
1795 " ldm r11, r0-r7\n" /* Restore Java Operands */
1796 " cp.w r12, 0\n" /* Test josp == 0 */
1798 "5: incjosp 1\n" /* ... for loop counter, */
1799 " sub r12, 1\n" /* because it can be */
1800 " brne 5b\n" /* one of r0-r7 */
1801 "4: popjc\n" /* Restore Local Variables */
1802 " sub r10, pc, . - trap\n" /* These 3 instructions */
1803 " retj\n" /* have to stay */
1804 "trap: pushjc\n" /* together */
1805 " mfsr r11, 0x58\n" /* JOSP */
1806 " lsl r11, 28\n" /* Clear r11[31:3] using */
1807 " lsr r11, 28\n" /* one register */
1813 "2: popm r11\n" /* ostack */
1814 " stm r11, r0-r7\n" /* Save Java Operands */
1815 " popm r0-r7,r10-r11\n"
1816 " mov %[tpc], r12\n"
1817 " mov %[jpc], lr\n" /* Resume address */
1818 " mfsr %[jecr], 0x54\n" /* JECR */
1819 " mov %[josp], r8\n" /* JOSP */
1820 " .globl debug_jem_exit\n"
1822 : [jecr
] "=r" (jem
->jecr
), [tpc
] "=r" (jem
->trap_pc
),
1823 [josp
] "+r" (jem
->josp
), [jpc
] "+r" (jem
->jpc
)
1824 : [cp
] "r" (ctx
.cp
->info
), [lv0
] "r" (ctx
.lvars_jem
),
1826 : "r8", "r9", "lr", "r12", "memory"
1829 * trap_pc now holds trap pc, describing which trap has been entered,
1830 * jecr holds JECR with the trapping bytecode at bits 23..16, possibly
1831 * arguments at bits 7..0 and 15..8,
1832 * josp holds JOSP (JOSP & 0xf),
1833 * jos holds stored registers r7-r0 (note order!) - Java Operand Stack
1834 * jpc points at the trapping opcode, in case of exceptions and stack
1835 * over- and underflows, and at the next opcode, in case of a trap
1839 gettimeofday(&tv1
, NULL
);
1842 for (i
= 0; i
< jem
->josp
; i
++)
1843 ostack_push_u32(ctx
.frame
->ostack
, ctx
.mb
->max_stack
, ctx
.ostack
,
1846 opcode
= (jem
->jecr
>> 16) & 0xff;
1848 jep
= jem
->trap_pc
& 0xfff;
1852 done
= exception_handler_f
[jep
>> 7](&ctx
);
1853 else if (trap_handler_f
[opcode
])
1854 done
= trap_handler_f
[opcode
](&ctx
);
1857 jam_printf("Unimplemented Java Opcode 0x%02x\n", opcode
);
1864 } while (done
!= JEM_TRAP_HANDLER_FINISH
);
1870 jam_dprintf("Unknown Java Opcodes\n");
1875 void initialiseInterpreter(InitArgs
*args
) {
1876 initialiseDirect(args
);
1880 void dump_profile(void)
1885 for (i
= 0; i
< 256; i
++)
1887 jam_printf("0x%x:\t%u times,\t%lu usec\n", i
, prof
[i
].n
, prof
[i
].time
);