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/byteorder.h>
45 #include <asm/cachectl.h>
47 #include "arch/avr32_jem.h"
48 #include "interp_jem.h"
61 * Interpreter execution context
67 /* the interpreter execution context */
79 #define GET_THIS(ctx) do { \
80 if (!((ctx)->mb->access_flags & ACC_STATIC) && (ctx)->mb->max_locals && \
81 *(ctx)->lvars_jem) { \
82 uintptr_t *__p = (uintptr_t *)*(ctx)->lvars_jem; \
83 (ctx)->this = JAM_OBJECT(__p); \
86 jam_dprintf("[%s] %smethod with %d vars, assigning %p\n", __func__, \
87 (ctx)->mb->access_flags & ACC_STATIC ? "static " : "", \
88 (ctx)->mb->max_locals, (ctx)->this); \
91 typedef int handler_fn(struct intrp_ctx
*ctx
);
93 static void jem_opcode_rewrite(uint32_t new_opcode
, char *pc
, int argc
, ...)
98 va_start(vargs
, argc
);
100 for (i
= 1; i
<= argc
; i
++)
101 pc
[i
] = (char)va_arg(vargs
, int);
103 syscall(__NR_cacheflush
, CACHE_IFLUSH
, (int)pc
& ~31, 32);
106 #define min(x, y) ({ typeof(x) _x = (x); typeof(y) _y = (y); _x > _y ? _y : _x; })
108 //check if it is an valid object ref (see alloc.c)
109 #define OBJECT_GRAIN 8
110 #define IS_OBJECT(ptr) !(((uintptr_t)(ptr))&(OBJECT_GRAIN-1))
112 #define JEM_THROW_EXCEPTION(excep_name, message) \
114 ctx->frame->last_pc = (CodePntr)ctx->jem.jpc; \
115 signalException(excep_name, message); \
116 jem_throwException(ctx); \
119 #define JEM_NULL_POINTER_CHECK(ref) \
120 if (!ref) JEM_THROW_EXCEPTION("java/lang/NullPointerException", NULL);
122 /*********************************************
123 * JEM Trap Handlers **
124 * *******************************************/
125 static int trap_debug(struct intrp_ctx
*ctx
)
128 struct jem_state
*jem
= &ctx
->jem
;
131 static unsigned long count
;
133 jecr_u
.i
= jem
->jecr
;
135 jam_printf("[%lu] (%u): Trap 0x%08x: ostack 0x%x, opcode 0x%x @ 0x%08x, "
136 "operand 1 0x%x, operand 2 0x%x. Operands:\n",
137 count
++, pthread_self(), jem
->trap_pc
, ctx
->ostack
, jecr_u
.s
.opcode
,
138 jem
->jpc
, jecr_u
.s
.op1
, jecr_u
.s
.op2
);
140 for (i
= 0; i
< jem
->josp
; i
++) {
142 if (ostack_read_u32(ctx
->frame
->ostack
, ctx
->ostack
, i
, &v
) >= 0)
143 jam_printf("\tToS-%d: 0x%x\n", i
, v
);
150 static int jem_throwException(struct intrp_ctx
*ctx
)
152 struct jem_state
*jem
= &ctx
->jem
;
153 ExecEnv
*ee
= ctx
->ee
;
154 Object
*excep
= ee
->exception
;
155 ee
->exception
= NULL
;
157 jem
->jpc
= (unsigned long)findCatchBlock(excep
->class);
158 jam_dprintf("Found exception handler at 0x%08x\n", jem
->jpc
);
160 /* If we didn't find a handler, restore exception and
161 return to previous invocation */
164 ee
->exception
= excep
;
165 /* Original code had a "return NULL" here, which means, end of
167 return JEM_TRAP_HANDLER_FINISH
;
170 /* If we're handling a stack overflow, reduce the stack
171 back past the red zone to enable handling of further
175 ee
->overflow
= FALSE
;
176 ee
->stack_end
-= STACK_RED_ZONE_SIZE
;
179 /* Setup intepreter to run the found catch block */
181 ctx
->frame
= ee
->last_frame
;
182 ctx
->mb
= ctx
->frame
->mb
;
183 ctx
->ostack
= ctx
->frame
->ostack
;
184 ctx
->lvars_jem
= ctx
->frame
->lvars_jem
- 1;
188 ctx
->cp
= &(CLASS_CB(ctx
->mb
->class)->constant_pool
);
190 /* FIXME: don't know if this is correct, depends how we implement
192 ostack_push_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, (uint32_t)excep
);
194 /* Dispatch to the first bytecode */
198 static int opc_return(struct intrp_ctx
*ctx
)
200 ExecEnv
*ee
= ctx
->ee
;
202 /* Set interpreter state to previous frame */
203 if (ctx
->frame
->prev
->mb
== NULL
) {
204 /* The previous frame is a dummy frame - this indicates
205 * top of this Java invocation. */
206 return JEM_TRAP_HANDLER_FINISH
;
209 ctx
->frame
= ctx
->frame
->prev
;
211 jam_dprintf("[%s] return to frame %p mb %p\n", __func__
, ctx
->frame
, ctx
->frame
->mb
);
213 if (ctx
->mb
->access_flags
& ACC_SYNCHRONIZED
) {
214 Object
*sync_ob
= ctx
->mb
->access_flags
& ACC_STATIC
? (Object
*)ctx
->mb
->class : ctx
->this;
215 jam_dprintf("[%s] %smethod unlock obj %p\n", __func__
,
216 ctx
->mb
->access_flags
& ACC_STATIC
? "static " : "", sync_ob
);
217 objectUnlock(sync_ob
);
220 ctx
->ostack
= ctx
->lvars_jem
- ctx
->mb
->max_locals
+ 1 - ctx
->mb
->args_count
;
221 ctx
->mb
= ctx
->frame
->mb
;
222 ctx
->lvars_jem
= ctx
->frame
->lvars_jem
- 1;
226 ctx
->jem
.jpc
= (uint32_t)ctx
->frame
->last_pc
;
227 ctx
->cp
= &(CLASS_CB(ctx
->mb
->class)->constant_pool
);
228 jam_dprintf("[OPC_RETURN] ostack: %p, lvars_jem: %p this: %p class %p\n",
229 ctx
->ostack
, ctx
->lvars_jem
, ctx
->this,
230 ctx
->this ? ctx
->this->class : NULL
);
233 ee
->last_frame
= ctx
->frame
;
238 static int invokeMethod(struct intrp_ctx
*ctx
)
240 ExecEnv
*ee
= ctx
->ee
;
241 /* Seems like the original jamvm reused top of caller's stack for callee's
242 * local variables for passing of method arguments. Our stack and
243 * local variables grow in opposite directions now, so, this is impossible.
244 * ctx->ostack points at the beginning of the free space above ostack.
246 Frame
*new_frame
= (Frame
*)(ctx
->ostack
+ ctx
->new_mb
->max_locals
);
247 Object
*sync_ob
= NULL
;
251 jam_dprintf("[invokeMethod] with args count %d, frame %p, return to 0x%08x\n",
252 ctx
->new_mb
->args_count
, new_frame
, ctx
->jem
.jpc
);
254 ctx
->frame
->last_pc
= (CodePntr
)ctx
->jem
.jpc
;
255 ctx
->ostack
= (uintptr_t *)(new_frame
+ 1);
257 if (ostack_overflows(ctx
->ostack
, ctx
->new_mb
->max_stack
, (uintptr_t *)ee
->stack_end
)) {
258 if (ee
->overflow
++) {
259 /* Overflow when we're already throwing stack overflow.
260 Stack extension should be enough to throw exception,
261 so something's seriously gone wrong - abort the VM! */
262 jam_printf("Fatal stack overflow! Aborting VM.\n");
265 ee
->stack_end
+= STACK_RED_ZONE_SIZE
;
266 return JEM_THROW_EXCEPTION("java/lang/StackOverflowError", NULL
);
270 new_frame
->mb
= ctx
->new_mb
;
271 //TODO: it seemed lvars is in java stack, but jos[8] should be part of java stack
272 // lvars_jem requires that the highest pointer should refer to the first local variables LV0
273 // Here still not touch the java stack, allocate lvars_jem from native heap
275 new_frame
->lvars_jem
= (uintptr_t *)new_frame
;
277 for (i
= 0; i
< ctx
->new_mb
->max_locals
; i
++) {
278 if (i
< ctx
->new_mb
->args_count
) {
279 *(new_frame
->lvars_jem
- 1 - i
) = *(ctx
->arg1
+ i
);
280 jam_dprintf("arg[%d] = 0x%x@%p\n", i
, *(ctx
->arg1
+ i
), ctx
->arg1
+ i
);
284 *(new_frame
->lvars_jem
- 1 - i
) = 0xdeadbeef;
288 jam_dprintf("[invokeMethod] %s::%s() lvars_jem %p\n",
289 CLASS_CB(ctx
->new_mb
->class)->name
, ctx
->new_mb
->name
, new_frame
->lvars_jem
);
291 new_frame
->ostack
= ctx
->ostack
;
292 new_frame
->prev
= ctx
->frame
;
294 ee
->last_frame
= new_frame
;
296 if (ctx
->new_mb
->access_flags
& ACC_SYNCHRONIZED
) {
297 aobj
= (uintptr_t *)*ctx
->arg1
;
298 sync_ob
= ctx
->new_mb
->access_flags
& ACC_STATIC
?
299 (Object
*)ctx
->new_mb
->class : JAM_OBJECT(aobj
);
303 if (ctx
->new_mb
->access_flags
& ACC_NATIVE
) {
304 //FIXME: the object references in JEM are direct pointer to instance variables.
305 // While JamVM requires object references as pointers to Object type.
306 jam_dprintf("[invokeMethod] invoke native method using %p invoker\n",
307 ctx
->new_mb
->native_invoker
);
308 ctx
->ostack
= (*(uintptr_t *(*)(Class
*, MethodBlock
*, uintptr_t*))
309 ctx
->new_mb
->native_invoker
)(ctx
->new_mb
->class, ctx
->new_mb
, ctx
->arg1
);
312 objectUnlock(sync_ob
);
314 ee
->last_frame
= ctx
->frame
;
316 if (exceptionOccured0(ee
)) {
317 jam_dprintf("[invokeMethod] exception occured, goto throwException\n");
318 return jem_throwException(ctx
);
321 jam_dprintf("[invokeMethod] finish native method invoke, return to loop\n");
323 ctx
->frame
= new_frame
;
324 ctx
->mb
= ctx
->new_mb
;
325 ctx
->lvars_jem
= new_frame
->lvars_jem
- 1;
329 ctx
->jem
.jpc
= (unsigned long)ctx
->mb
->code
& ~3;
330 ctx
->cp
= &(CLASS_CB(ctx
->mb
->class)->constant_pool
);
332 jam_dprintf("[invokeMethod] invoke virtual method: mb %x "
333 "lvars %x jpc %x cp %x\n", ctx
->mb
,
334 ctx
->lvars_jem
, ctx
->jem
.jpc
, ctx
->cp
);
340 static int opc_invokesuper_quick(struct intrp_ctx
*ctx
)
342 struct jem_state
*jem
= &ctx
->jem
;
343 Operand
*operand
= &jem
->operand
;
345 jam_dprintf("[OPC_INVOKESUPER_QUICK] method table indx %d\n", operand
->i
);
346 ctx
->new_mb
= CLASS_CB(CLASS_CB(ctx
->mb
->class)->super
)->method_table
[operand
->i
];
347 jam_dprintf("[OPC_INVOKESUPER_QUICK] method args count %d\n", ctx
->new_mb
->args_count
);
349 // set up jem operand stack
350 ctx
->arg1
= ostack_address(ctx
->frame
->ostack
, ctx
->mb
->max_stack
,
351 ctx
->ostack
- ctx
->frame
->ostack
- ctx
->new_mb
->args_count
);
352 JEM_NULL_POINTER_CHECK(*ctx
->arg1
);
353 jam_dprintf("[OP_INVOKESUPER_QUICK] arg1 %x\n", *ctx
->arg1
);
354 return invokeMethod(ctx
);
357 static int opc_invokenonvirtual_quick(struct intrp_ctx
*ctx
)
359 struct jem_state
*jem
= &ctx
->jem
;
360 Operand
*operand
= &jem
->operand
;
362 ctx
->new_mb
= (MethodBlock
*)operand
->pntr
;
363 jam_dprintf("[%s] new methodblock %s (%x) with %d args\n",
364 __func__
, ctx
->new_mb
->name
, ctx
->new_mb
, ctx
->new_mb
->args_count
);
365 ctx
->arg1
= ostack_address(ctx
->frame
->ostack
, ctx
->mb
->max_stack
,
366 ctx
->ostack
- ctx
->frame
->ostack
- ctx
->new_mb
->args_count
);
368 jam_dprintf("[%s] ctx->arg1 %x\n", __func__
, *ctx
->arg1
);
369 JEM_NULL_POINTER_CHECK(*ctx
->arg1
);
370 return invokeMethod(ctx
);
373 static int opc_invokevirtual_quick(struct intrp_ctx
*ctx
)
375 struct jem_state
*jem
= &ctx
->jem
;
377 ctx
->arg1
= ostack_address(ctx
->frame
->ostack
, ctx
->mb
->max_stack
,
378 ctx
->ostack
- ctx
->frame
->ostack
- INV_QUICK_ARGS(jem
));
379 JEM_NULL_POINTER_CHECK(*ctx
->arg1
);
382 //in case of "AALOAD" loads JAM obj from reference array
383 obj
= (Object
*)*ctx
->arg1
;
384 if (!JAM_ON_STACK
|| !IS_JAM_OBJECT(obj
)) {
385 obj
= JAM_OBJECT((uintptr_t *)obj
);
386 //we should ensure ostack contains no JAM object
387 *ctx
->arg1
= (uintptr_t)INST_DATA(obj
);
390 jam_dprintf("[OPC_INVOKEVIRTUAL_QUICK] invoke on object %p from %p class %p\n",
391 obj
, ctx
->arg1
, obj
->class);
392 new_class
= obj
->class;
393 ctx
->new_mb
= CLASS_CB(new_class
)->method_table
[INV_QUICK_IDX(jem
)];
394 jam_dprintf("[OPC_INVOKEVIRTUAL_QUICK] invoke method 0x%08x\n",
396 return invokeMethod(ctx
);
399 static int opc_invokevirtual(struct intrp_ctx
*ctx
)
402 ExecEnv
*ee
= ctx
->ee
;
403 struct jem_state
*jem
= &ctx
->jem
;
405 idx
= jem
->jecr
& 0xffff;
406 ctx
->frame
->last_pc
= (CodePntr
)jem
->jpc
;
407 ctx
->new_mb
= resolveMethod(ctx
->mb
->class, idx
);
409 if (exceptionOccured0(ee
))
410 return jem_throwException(ctx
);
412 jem
->operand
.uu
.u1
= ctx
->new_mb
->args_count
;
413 jem
->operand
.uu
.u2
= ctx
->new_mb
->method_table_index
;
415 jam_dprintf("[OPC_INVOKEVIRTUAL] invoke 0x%08x with args count %d\n",
416 ctx
->new_mb
, ctx
->new_mb
->args_count
);
418 return opc_invokevirtual_quick(ctx
);
421 static int opc_invokespecial(struct intrp_ctx
*ctx
)
424 struct jem_state
*jem
= &ctx
->jem
;
425 Operand
*operand
= &jem
->operand
;
426 ExecEnv
*ee
= ctx
->ee
;
428 /* INVOKESPECIAL's operands represent an index into the Constant Pool */
429 idx
= jem
->jecr
& 0xffff;
431 jam_dprintf("[OPC_INVOKESPECIAL] constant pool index %d\n", idx
);
433 ctx
->new_mb
= resolveMethod(ctx
->mb
->class, idx
);
435 if (exceptionOccured0(ee
))
436 return jem_throwException(ctx
);
438 jam_dprintf("Resolved %s\n", ctx
->new_mb
->name
);
440 /* Check if invoking a super method... */
441 if ((CLASS_CB(ctx
->mb
->class)->access_flags
& ACC_SUPER
) &&
442 ((ctx
->new_mb
->access_flags
& ACC_PRIVATE
) == 0) && (ctx
->new_mb
->name
[0] != '<')) {
444 operand
->i
= ctx
->new_mb
->method_table_index
;
445 return opc_invokesuper_quick(ctx
);
446 #if 0 /* FIXME: verify this whole "pc" chemistry is indeed unneeded */
447 OPCODE_REWRITE(OPC_INVOKESUPER_QUICK
, cache
, operand
);
450 operand
->pntr
= ctx
->new_mb
;
451 return opc_invokenonvirtual_quick(ctx
);
457 static int opc_invokestatic_quick(struct intrp_ctx
*ctx
)
459 struct jem_state
*jem
= &ctx
->jem
;
461 ctx
->new_mb
= RESOLVED_METHOD(jem
);
462 ctx
->arg1
= ostack_address(ctx
->frame
->ostack
, ctx
->mb
->max_stack
,
463 ctx
->ostack
- ctx
->frame
->ostack
- ctx
->new_mb
->args_count
);
464 return invokeMethod(ctx
);
467 static int opc_invokestatic(struct intrp_ctx
*ctx
)
470 struct jem_state
*jem
= &ctx
->jem
;
471 Operand
*operand
= &jem
->operand
;
472 ExecEnv
*ee
= ctx
->ee
;
474 idx
= jem
->jecr
& 0xffff;
476 ctx
->frame
->last_pc
= (CodePntr
)jem
->jpc
;
477 ctx
->new_mb
= resolveMethod(ctx
->mb
->class, idx
);
479 if (exceptionOccured0(ee
))
480 return jem_throwException(ctx
);
482 operand
->pntr
= ctx
->new_mb
;
483 return opc_invokestatic_quick(ctx
);
486 static int opc_new_quick(struct intrp_ctx
*ctx
)
488 struct jem_state
*jem
= &ctx
->jem
;
489 Operand
*operand
= &jem
->operand
;
490 Class
*class = (Class
*)CP_INFO(ctx
->cp
, operand
->uui
.u1
);
493 ctx
->frame
->last_pc
= (CodePntr
)jem
->jpc
;
494 if ((obj
= allocObject(class)) == NULL
)
495 return jem_throwException(ctx
);
496 jam_dprintf("[OPC_NEW_QUICK] push obj ref %x to stack\n", obj
);
497 return ostack_push_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
,
498 (uint32_t)INST_DATA(obj
));
501 static int opc_new(struct intrp_ctx
*ctx
)
503 struct jem_state
*jem
= &ctx
->jem
;
504 Operand
*operand
= &jem
->operand
;
505 int idx
= jem
->jecr
& 0xffff;
506 int opcode
= (jem
->jecr
>> 16) & 0xff;
508 ExecEnv
*ee
= ctx
->ee
;
510 operand
->uui
.u1
= idx
;
511 operand
->uui
.u2
= opcode
;
513 jam_dprintf("[OPC_NEW] opcode: 0x%x, index: 0x%x\n", opcode
, idx
);
515 ctx
->frame
->last_pc
= (CodePntr
)jem
->jpc
;
516 class = resolveClass(ctx
->mb
->class, idx
, opcode
== OPC_NEW
);
517 if (exceptionOccured0(ee
))
518 return jem_throwException(ctx
);
520 if (opcode
== OPC_NEW
) {
521 ClassBlock
*cb
= CLASS_CB(class);
522 if (cb
->access_flags
& (ACC_INTERFACE
| ACC_ABSTRACT
)) {
523 signalException("java/lang/InstantiationError", cb
->name
);
524 return jem_throwException(ctx
);
526 /* rewrite opcode to OPC_NEW_QUICK (0xDD) */
527 jem_opcode_rewrite(0xDD, (char*)jem
->jpc
- 3, 0);
530 return opc_new_quick(ctx
);
533 static int opc_anewarray_quick(struct intrp_ctx
*ctx
)
535 struct jem_state
*jem
= &ctx
->jem
;
536 ConstantPool
*cp
= ctx
->cp
;
537 Class
*class = RESOLVED_CLASS(jem
);
538 char *name
= CLASS_CB(class)->name
;
543 ExecEnv
*ee
= ctx
->ee
;
545 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, count
);
546 ctx
->frame
->last_pc
= (CodePntr
)jem
->jpc
;
548 jam_dprintf("[OPC_ANEWARRAY_QUICK] array %s size %d\n", name
, count
);
550 signalException("java/lang/NegativeArraySizeException", NULL
);
551 return jem_throwException(ctx
);
554 ac_name
= sysMalloc(strlen(name
) + 4);
557 sprintf(ac_name
, "[%s", name
);
559 sprintf(ac_name
, "[L%s;", name
);
561 array_class
= findArrayClassFromClass(ac_name
, ctx
->mb
->class);
564 if (exceptionOccured0(ee
))
565 return jem_throwException(ctx
);
567 if ((obj
= allocArray(array_class
, count
, sizeof(Object
*))) == NULL
)
568 return jem_throwException(ctx
);
570 return ostack_push_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
,
571 (uint32_t)ARRAY_DATA(obj
));
574 static int opc_anewarray(struct intrp_ctx
*ctx
)
576 struct jem_state
*jem
= &ctx
->jem
;
577 Operand
*operand
= &jem
->operand
;
578 int idx
= jem
->jecr
& 0xffff;
579 int opcode
= (jem
->jecr
>> 16) & 0xff;
581 ExecEnv
*ee
= ctx
->ee
;
583 operand
->uui
.u1
= idx
;
584 operand
->uui
.u2
= opcode
;
586 jam_dprintf("[OPC_ANEWARRAY] index: 0x%x\n", idx
);
588 ctx
->frame
->last_pc
= (CodePntr
)jem
->jpc
;
589 //resolve the array class
590 class = resolveClass(ctx
->mb
->class, idx
, FALSE
);
592 if (exceptionOccured0(ee
))
593 return jem_throwException(ctx
);
595 return opc_anewarray_quick(ctx
);
598 static int opc_multianewarray_quick(struct intrp_ctx
*ctx
)
600 struct jem_state
*jem
= &ctx
->jem
;
601 ConstantPool
*cp
= ctx
->cp
;
602 Class
*class = RESOLVED_CLASS(jem
);
603 int i
, dim
= MULTI_ARRAY_DIM(jem
);
607 ctx
->frame
->last_pc
= (CodePntr
)jem
->jpc
;
609 jam_dprintf("[OPC_MULTIANEWARRAY_QUICK]: alloc %d dimensional array for class %s\n", dim
, CLASS_CB(class)->name
);
610 for (i
= 0; i
< dim
; i
++) {
611 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, count
);
612 jam_dprintf("[OPC_MULTIANEWARRAY_QUICK]: elements %d for dim %d\n", count
, i
);
614 signalException("java/lang/NegativeArraySizeException", NULL
);
615 return jem_throwException(ctx
);
619 /* counts are still stored in ostack even after we did pop them out */
620 if ((obj
= allocMultiArray(class, dim
, (intptr_t *)ctx
->ostack
)) == NULL
)
621 return jem_throwException(ctx
);
623 return ostack_push_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
,
624 (uint32_t)ARRAY_DATA(obj
));
627 static int opc_multianewarray(struct intrp_ctx
*ctx
)
629 struct jem_state
*jem
= &ctx
->jem
;
630 Operand
*operand
= &jem
->operand
;
631 int idx
= operand
->uui
.u1
= jem
->jecr
& 0xffff;
634 ExecEnv
*ee
= ctx
->ee
;
637 operand
->uui
.u2
= *(unsigned char*)jem
->jpc
;
638 jem
->jpc
++; /* skip dims */
640 ctx
->frame
->last_pc
= (CodePntr
)jem
->jpc
;
641 /* resolve the array class */
642 class = resolveClass(ctx
->mb
->class, idx
, FALSE
);
644 if (exceptionOccured0(ee
))
645 return jem_throwException(ctx
);
647 return opc_multianewarray_quick(ctx
);
650 static int opc_newarray(struct intrp_ctx
*ctx
)
652 struct jem_state
*jem
= &ctx
->jem
;
653 int type
= (jem
->jecr
>> 8) & 0xff;
657 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, count
);
658 ctx
->frame
->last_pc
= (CodePntr
)jem
->jpc
;
660 jam_dprintf("[OPC_NEWARRAY] alloc array type %d, count %d\n", type
, count
);
661 if ((obj
= allocTypeArray(type
, count
)) == NULL
)
662 return jem_throwException(ctx
);
664 return ostack_push_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
,
665 (uint32_t)ARRAY_DATA(obj
));
668 static int opc_putfield_quick(struct intrp_ctx
*ctx
)
672 struct jem_state
*jem
= &ctx
->jem
;
674 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, arg
);
675 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, obj
);
676 jam_dprintf("[OPC_PUTFIELD_QUICK] put field %x to obj(%d) %x\n", arg
,
677 SINGLE_INDEX(jem
), obj
);
679 JEM_NULL_POINTER_CHECK(obj
);
681 if (JAM_ON_STACK
&& IS_JAM_OBJECT(obj
))
682 obj
= (uint32_t)INST_DATA((Object
*)obj
);
684 ((uint32_t*)obj
)[SINGLE_INDEX(jem
)] = arg
;
694 static int opc_putfield2_quick(struct intrp_ctx
*ctx
)
697 struct jem_state
*jem
= &ctx
->jem
;
700 ostack_pop_u64(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, v
.i
);
701 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, obj
);
703 JEM_NULL_POINTER_CHECK((uintptr_t*)obj
);
705 if (JAM_ON_STACK
&& IS_JAM_OBJECT(obj
))
706 obj
= (uint32_t)INST_DATA((Object
*)obj
);
708 *(uint64_t *)&(((uint32_t*)obj
)[SINGLE_INDEX(jem
)]) = v
.ll
;
709 jam_dprintf("[%s] put 64 bit field 0x%llx to obj %08x\n", __func__
, v
.ll
, obj
);
714 static int opc_putfield_quick_jem0(struct intrp_ctx
*ctx
)
718 struct jem_state
*jem
= &ctx
->jem
;
720 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, arg
);
721 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, aobj
);
722 jam_dprintf("[OPC_PUTFIELD_QUICK_JEM0] field %x\n", arg
);
724 JEM_NULL_POINTER_CHECK(aobj
);
726 if (JAM_ON_STACK
&& arg
&& !IS_JAM_OBJECT(arg
))
727 arg
= (uint32_t)JAM_OBJECT((uintptr_t *)arg
);
729 if (JAM_ON_STACK
&& IS_JAM_OBJECT(aobj
))
730 aobj
= INST_DATA((Object
*)aobj
);
732 aobj
[SINGLE_INDEX(jem
)] = arg
;
733 jam_dprintf("[OPC_PUTFIELD_QUICK_JEM0] put field %x to obj(%d) %x\n", arg
,
734 SINGLE_INDEX(jem
), aobj
);
739 static int opc_putfield_quick_jem1(struct intrp_ctx
*ctx
)
741 uintptr_t *aobj
, *arg
;
742 struct jem_state
*jem
= &ctx
->jem
;
744 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, arg
);
745 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, aobj
);
746 jam_dprintf("[OPC_PUTFIELD_QUICK_JEM1] field %p\n", arg
);
748 if (JAM_ON_STACK
&& arg
&& !IS_JAM_ARRAY(arg
))
749 arg
= (uintptr_t *)JAM_ARRAY(arg
);
751 if (JAM_ON_STACK
&& IS_JAM_OBJECT(aobj
))
752 aobj
= INST_DATA((Object
*)aobj
);
754 JEM_NULL_POINTER_CHECK(aobj
);
755 aobj
[SINGLE_INDEX(jem
)] = (uintptr_t)arg
;
756 jam_dprintf("[OPC_PUTFIELD_QUICK_JEM1] put field %p to obj(%d) %p\n", arg
,
757 SINGLE_INDEX(jem
), aobj
);
762 static int opc_putfield(struct intrp_ctx
*ctx
)
764 struct jem_state
*jem
= &ctx
->jem
;
765 int idx
= jem
->jecr
& 0xffff;
767 ExecEnv
*ee
= ctx
->ee
;
769 jam_dprintf("[OPC_PUTFIELD] constant pool index %d\n", idx
);
771 ctx
->frame
->last_pc
= (CodePntr
)jem
->jpc
;
772 fb
= resolveField(ctx
->mb
->class, idx
);
773 jam_dprintf("[OPC_PUTFIELD] resolve field 0x%08x, type %c, name %s\n", fb
, *fb
->type
, fb
->name
);
775 if (exceptionOccured0(ee
))
776 return jem_throwException(ctx
);
778 jem
->operand
.i
= fb
->offset
;
782 /* rewrite opc_putfield to opc_putfield2_quick */
783 jem_opcode_rewrite(0xD1, (char*)jem
->jpc
- 3, 2, fb
->offset
>> 8, fb
->offset
);
784 return opc_putfield2_quick(ctx
);
786 jem_opcode_rewrite(0xCF, (char*)jem
->jpc
- 3, 2, fb
->offset
>> 8, fb
->offset
);
787 return opc_putfield_quick_jem0(ctx
);
789 jem_opcode_rewrite(0xCF, (char*)jem
->jpc
- 3, 2, fb
->offset
>> 8, fb
->offset
);
790 return opc_putfield_quick_jem1(ctx
);
792 jem_opcode_rewrite(0xCF, (char*)jem
->jpc
- 3, 2, fb
->offset
>> 8, fb
->offset
);
793 return opc_putfield_quick(ctx
);
797 static int opc_getfield2_quick(struct intrp_ctx
*ctx
)
800 struct jem_state
*jem
= &ctx
->jem
;
803 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, obj
);
805 JEM_NULL_POINTER_CHECK(obj
);
807 if (JAM_ON_STACK
&& IS_JAM_OBJECT(obj
))
808 obj
= (uint32_t*)INST_DATA((Object
*)obj
);
810 v
.ll
= *(uint64_t*)(&(obj
[SINGLE_INDEX(jem
)]));
811 jam_dprintf("[%s] get 64 bit field 0x%llx from obj %08x\n", __func__
, v
.ll
, obj
);
813 return ostack_push_u64(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, v
.i
);
816 static int opc_getfield_quick(struct intrp_ctx
*ctx
)
819 struct jem_state
*jem
= &ctx
->jem
;
821 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, aobj
);
822 JEM_NULL_POINTER_CHECK(aobj
);
824 if (JAM_ON_STACK
&& IS_JAM_OBJECT(aobj
))
825 aobj
= (uint32_t*)INST_DATA((Object
*)aobj
);
827 jam_dprintf("[OPC_GETFIELD_QUICK] get field %08x from obj %08x\n",
828 aobj
[SINGLE_INDEX(jem
)], aobj
);
829 return ostack_push_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
,
830 aobj
[SINGLE_INDEX(jem
)]);
833 static int opc_getfield_quick_jem0(struct intrp_ctx
*ctx
)
836 struct jem_state
*jem
= &ctx
->jem
;
838 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, aobj
);
839 JEM_NULL_POINTER_CHECK(aobj
);
841 if (JAM_ON_STACK
&& IS_JAM_OBJECT(aobj
))
842 aobj
= (uint32_t*)INST_DATA((Object
*)aobj
);
844 uint32_t value
= aobj
[SINGLE_INDEX(jem
)];
846 Object
*ref
= (Object
*)value
;
847 if (JAM_ON_STACK
&& IS_JAM_OBJECT(ref
))
849 value
= (uint32_t)INST_DATA(ref
);
850 jam_dprintf("[OPC_GETFIELD_QUICK_JEM0] obj %p ref %x, class %p : %p\n",
851 aobj
, value
, JAM_OBJECT((void *)value
)->class, ref
->class);
853 jam_dprintf("[OPC_GETFIELD_QUICK_JEM0] put obj ref %x\n", value
);
854 return ostack_push_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, value
);
857 static int opc_getfield_quick_jem1(struct intrp_ctx
*ctx
)
860 struct jem_state
*jem
= &ctx
->jem
;
862 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, aobj
);
863 JEM_NULL_POINTER_CHECK(aobj
);
865 //"aaload" would put jamvm obj ref onto the ostack
866 if (JAM_ON_STACK
&& IS_JAM_OBJECT(aobj
))
867 aobj
= (uint32_t*)INST_DATA((Object
*)aobj
);
869 uint32_t value
= aobj
[SINGLE_INDEX(jem
)];
870 jam_dprintf("[OPC_GETFIELD_QUICK_JEM1] array ref %x\n", value
);
872 Object
*ref
= (Object
*)value
;
873 if (JAM_ON_STACK
&& IS_JAM_ARRAY(ref
))
874 value
= (uint32_t)ARRAY_DATA(ref
);
876 jam_dprintf("[OPC_GETFIELD_QUICK_JEM1] put array ref %x\n", value
);
877 return ostack_push_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, value
);
880 static int opc_getfield(struct intrp_ctx
*ctx
)
882 struct jem_state
*jem
= &ctx
->jem
;
883 int idx
= jem
->jecr
& 0xffff;
885 ExecEnv
*ee
= ctx
->ee
;
887 jam_dprintf("[OPC_GETFIELD] constant pool index %d\n", idx
);
889 ctx
->frame
->last_pc
= (CodePntr
)jem
->jpc
;
890 fb
= resolveField(ctx
->mb
->class, idx
);
892 if (exceptionOccured0(ee
))
893 return jem_throwException(ctx
);
895 jem
->operand
.i
= fb
->offset
;
897 jam_dprintf("[OPC_GETFIELD] resolve field %s @ %p, type %c, offset %i, class %p\n",
898 fb
->name
, fb
, *fb
->type
, jem
->operand
.i
, fb
->class);
903 jem_opcode_rewrite(0xD0, (char*)jem
->jpc
- 3, 2, fb
->offset
>> 8, fb
->offset
);
904 return opc_getfield2_quick(ctx
);
906 * Though we assume all objrefs/arrayrefs here should be JEM compliant, but
907 * in case of some JNI code will set field natively, we still handle it
911 jem_opcode_rewrite(0xCE, (char*)jem
->jpc
- 3, 2, fb
->offset
>> 8, fb
->offset
);
912 return opc_getfield_quick_jem0(ctx
);
914 jem_opcode_rewrite(0xCE, (char*)jem
->jpc
- 3, 2, fb
->offset
>> 8, fb
->offset
);
915 return opc_getfield_quick_jem1(ctx
);
917 //jem_opcode_rewrite(0xCE, (char*)jem->jpc - 3, 2, (fb->offset>>8)&0xff, (fb->offset)&0xff);
918 return opc_getfield_quick(ctx
);
922 static int opc_ldc2_w(struct intrp_ctx
*ctx
)
926 struct jem_state
*jem
= &ctx
->jem
;
928 idx
= (jem
->jecr
& 0xffff);
929 jam_dprintf("[OPC_LDC2_W] constant pool index %d\n", idx
);
930 jem
->operand
.i
= idx
;
932 //read long long from constant pool
933 v
.ll
= (uint64_t)CP_LONG(ctx
->cp
, DOUBLE_INDEX(jem
));
934 jam_dprintf("[OPC_LDC2_W] push constant 0x%llx to stack\n", v
.ll
);
936 return ostack_push_u64(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, v
.i
);
939 static int opc_ldc_w_quick_jem(struct intrp_ctx
*ctx
)
941 struct jem_state
*jem
= &ctx
->jem
;
942 //CONSTANT_Class and CONSTANT_String are stored as object reference
943 Object
*cp_info
= (Object
*)CP_INFO(ctx
->cp
, DOUBLE_INDEX(jem
));
944 jam_dprintf("[OPC_LDC_W_QUICK_JEM] push String ref %x to stack\n", cp_info
);
945 return ostack_push_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
,
946 (uint32_t)INST_DATA(cp_info
));
949 static int opc_ldc_quick(struct intrp_ctx
*ctx
)
951 struct jem_state
*jem
= &ctx
->jem
;
952 uint32_t constant
= RESOLVED_CONSTANT(jem
);
953 jam_dprintf("[OPC_LDC_QUICK] push constant %x to stack\n", constant
);
954 return ostack_push_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, (uintptr_t)constant
);
957 static int opc_ldc_common(struct intrp_ctx
*ctx
, int idx
)
959 struct jem_state
*jem
= &ctx
->jem
;
960 ExecEnv
*ee
= ctx
->ee
;
961 ctx
->frame
->last_pc
= (CodePntr
)jem
->jpc
;
963 jem
->operand
.u
= resolveSingleConstant(ctx
->mb
->class, idx
);
965 if (exceptionOccured0(ee
))
966 return jem_throwException(ctx
);
968 switch (CP_TYPE(ctx
->cp
, idx
)) {
969 case CONSTANT_ResolvedClass
:
970 case CONSTANT_ResolvedString
:
971 jem
->operand
.i
= idx
;
972 return opc_ldc_w_quick_jem(ctx
);
974 jem_opcode_rewrite(0xCB, (char*)jem
->jpc
- 2, 0);
975 return opc_ldc_quick(ctx
);
979 static int opc_ldc(struct intrp_ctx
*ctx
)
982 struct jem_state
*jem
= &ctx
->jem
;
984 idx
= (jem
->jecr
& 0xff00) >> 8;
986 jam_dprintf("[OPC_LDC] constant pool index %d\n", idx
);
987 return opc_ldc_common(ctx
, idx
);
990 static int opc_ldc_w(struct intrp_ctx
*ctx
)
993 struct jem_state
*jem
= &ctx
->jem
;
995 idx
= (jem
->jecr
& 0xffff);
997 jam_dprintf("[OPC_LDC_W] constant pool index %d\n", idx
);
998 return opc_ldc_common(ctx
, idx
);
1001 static int opc_monitorenter(struct intrp_ctx
*ctx
)
1005 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, ptr
);
1007 obj
= JAM_OBJECT(ptr
);
1008 if (!IS_OBJECT(obj
))
1009 /* is an array ref */
1010 obj
= JAM_ARRAY(ptr
);
1011 jam_dprintf("[OPC_MONITORENTER] lock %x\n", obj
);
1012 JEM_NULL_POINTER_CHECK(obj
);
1017 static int opc_monitorexit(struct intrp_ctx
*ctx
)
1021 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, ptr
);
1023 obj
= JAM_OBJECT(ptr
);
1024 if (!IS_OBJECT(obj
))
1025 /* is an array ref */
1026 obj
= JAM_ARRAY(ptr
);
1027 jam_dprintf("[OPC_MONITOREXIT] unlock %x\n", obj
);
1028 JEM_NULL_POINTER_CHECK(obj
);
1033 static int opc_getstatic_quick(struct intrp_ctx
*ctx
)
1035 struct jem_state
*jem
= &ctx
->jem
;
1036 return ostack_push_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
,
1037 RESOLVED_FIELD(jem
)->static_value
);
1040 static int opc_getstatic2_quick(struct intrp_ctx
*ctx
)
1042 struct jem_state
*jem
= &ctx
->jem
;
1045 v
.ll
= RESOLVED_FIELD(jem
)->static_value
;
1047 return ostack_push_u64(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, v
.i
);
1050 static int opc_getstatic_quick_jem0(struct intrp_ctx
*ctx
)
1052 struct jem_state
*jem
= &ctx
->jem
;
1053 uintptr_t value
= RESOLVED_FIELD(jem
)->static_value
;
1055 jam_dprintf("[OPC_GETSTATIC_QUICK_JEM0] obj ref %x\n", value
);
1057 Object
*ref
= (Object
*)value
;
1058 if (!JAM_ON_STACK
|| IS_JAM_OBJECT(ref
))
1060 value
= (uintptr_t)INST_DATA(ref
);
1062 jam_dprintf("[OPC_GETSTATIC_QUICK_JEM0] put obj ref %x\n", value
);
1063 return ostack_push_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, value
);
1066 static int opc_getstatic_quick_jem1(struct intrp_ctx
*ctx
)
1068 struct jem_state
*jem
= &ctx
->jem
;
1069 uintptr_t value
= RESOLVED_FIELD(jem
)->static_value
;
1070 jam_dprintf("[OPC_GETSTATIC_QUICK_JEM1] array ref %x\n", value
);
1072 Object
*ref
= (Object
*)value
;
1073 if (!JAM_ON_STACK
|| IS_JAM_ARRAY(ref
))
1075 value
= (uintptr_t)ARRAY_DATA(ref
);
1077 jam_dprintf("[OPC_GETSTATIC_QUICK_JEM1] put array ref %x\n", value
);
1078 return ostack_push_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, value
);
1081 static int opc_getstatic(struct intrp_ctx
*ctx
)
1085 ExecEnv
*ee
= ctx
->ee
;
1086 struct jem_state
*jem
= &ctx
->jem
;
1088 idx
= (int)(jem
->jecr
& 0xffff);
1089 jam_dprintf("[OPC_GETSTATIC] constant pool index %d class %s\n",idx
,CLASS_CB(ctx
->mb
->class)->name
);
1091 ctx
->frame
->last_pc
= (CodePntr
)jem
->jpc
;
1092 fb
= resolveField(ctx
->mb
->class, idx
);
1094 if (exceptionOccured0(ee
))
1095 return jem_throwException(ctx
);
1097 jam_dprintf("[OPC_GETSTATIC] get static for field %08x, type %c\n", fb
, *fb
->type
);
1098 jem
->operand
.pntr
= fb
;
1099 switch (*fb
->type
) {
1102 return opc_getstatic2_quick(ctx
);
1107 return opc_getstatic_quick_jem0(ctx
);
1109 return opc_getstatic_quick_jem1(ctx
);
1111 return opc_getstatic_quick(ctx
);
1115 static int opc_putstatic2_quick(struct intrp_ctx
*ctx
)
1117 struct jem_state
*jem
= &ctx
->jem
;
1118 return ostack_pop_u64(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
,
1119 &RESOLVED_FIELD(jem
)->static_value
);
1122 static int opc_putstatic_quick(struct intrp_ctx
*ctx
)
1124 struct jem_state
*jem
= &ctx
->jem
;
1125 return ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
,
1126 RESOLVED_FIELD(jem
)->static_value
);
1129 static int opc_putstatic_quick_jem0(struct intrp_ctx
*ctx
)
1132 struct jem_state
*jem
= &ctx
->jem
;
1133 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, value
);
1135 jam_dprintf("[OPC_PUTSTATIC_QUICK_JEM0] obj %x\n", value
);
1136 if (value
&& (!JAM_ON_STACK
|| !IS_JAM_OBJECT(value
)))
1137 value
= (uintptr_t)JAM_OBJECT((uintptr_t *)value
);
1138 jam_dprintf("[OPC_PUTSTATIC_QUICK_JEM0] put obj %x\n", value
);
1139 RESOLVED_FIELD(jem
)->static_value
= value
;
1143 static int opc_putstatic_quick_jem1(struct intrp_ctx
*ctx
)
1146 struct jem_state
*jem
= &ctx
->jem
;
1147 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, value
);
1149 jam_dprintf("[OPC_PUTSTATIC_QUICK_JEM1] array %p\n", value
);
1150 if (value
&& (!JAM_ON_STACK
|| !IS_JAM_ARRAY(value
)))
1151 value
= (uintptr_t*)JAM_ARRAY(value
);
1152 jam_dprintf("[OPC_PUTSTATIC_QUICK_JEM1] put array %p\n", value
);
1153 RESOLVED_FIELD(jem
)->static_value
= (uintptr_t)value
;
1157 static int opc_putstatic(struct intrp_ctx
*ctx
)
1161 ExecEnv
*ee
= ctx
->ee
;
1162 struct jem_state
*jem
= &ctx
->jem
;
1164 idx
= (int)(jem
->jecr
& 0xffff);
1166 ctx
->frame
->last_pc
= (CodePntr
)jem
->jpc
;
1167 fb
= resolveField(ctx
->mb
->class, idx
);
1169 if (exceptionOccured0(ee
))
1170 return jem_throwException(ctx
);
1172 jam_dprintf("[OPC_PUTSTATIC] put static for field %08x, type %c\n", fb
, *fb
->type
);
1173 jem
->operand
.pntr
= fb
;
1174 switch (*fb
->type
) {
1177 //jem_opcode_rewrite(0xD5, (char*)jem->jpc - 3);
1178 return opc_putstatic2_quick(ctx
);
1180 return opc_putstatic_quick_jem0(ctx
);
1182 return opc_putstatic_quick_jem1(ctx
);
1184 return opc_putstatic_quick(ctx
);
1188 static int opc_checkcast_quick(struct intrp_ctx
*ctx
)
1190 struct jem_state
*jem
= &ctx
->jem
;
1191 ConstantPool
*cp
= ctx
->cp
;
1192 Class
*class = RESOLVED_CLASS(jem
);
1196 ostack_read_u32(ctx
->frame
->ostack
, ctx
->ostack
, 0, &ptr
);
1197 jam_dprintf("[OPC_CHECKCAST_QUICK] check cast for JEM type %x (class %s)\n", ptr
, CLASS_CB(class)->name
);
1199 #warning Does not look right!
1200 if (!JAM_ON_STACK
|| !IS_JAM_OBJECT(ptr
) || !IS_JAM_ARRAY(ptr
)) {
1201 obj
= JAM_OBJECT(ptr
);
1202 if (!IS_OBJECT(obj
)) {
1203 jam_dprintf("[OPC_CHECKCAST_QUICK] check cast for array\n");
1204 //should be array ref
1205 obj
= JAM_ARRAY(ptr
);
1207 jam_dprintf("[OPC_CHECKCAST_QUICK] check cast for object %x\n", obj
);
1211 jam_dprintf("[OPC_CHECKCAST_QUICK] check class %p (%s) for obj %p (%s)\n",
1212 class, CLASS_CB(class)->name
, obj
->class, CLASS_CB(obj
->class)->name
);
1213 if (!isInstanceOf(class, obj
->class))
1214 return JEM_THROW_EXCEPTION("java/lang/ClassCastException", CLASS_CB(obj
->class)->name
);
1220 static int opc_checkcast(struct intrp_ctx
*ctx
)
1222 struct jem_state
*jem
= &ctx
->jem
;
1223 Operand
*operand
= &jem
->operand
;
1224 int idx
= jem
->jecr
& 0xffff;
1225 int opcode
= (jem
->jecr
>> 16) & 0xff;
1227 ExecEnv
*ee
= ctx
->ee
;
1229 operand
->uui
.u1
= idx
;
1230 operand
->uui
.u2
= opcode
;
1232 jam_dprintf("[OPC_CHECKCAST] index: 0x%x\n", idx
);
1234 ctx
->frame
->last_pc
= (CodePntr
)jem
->jpc
;
1235 //resolve the cast class
1236 class = resolveClass(ctx
->mb
->class, idx
, FALSE
);
1238 if (exceptionOccured0(ee
))
1239 return jem_throwException(ctx
);
1241 return opc_checkcast_quick(ctx
);
1244 static int opc_invokeinterface_quick(struct intrp_ctx
*ctx
)
1249 int cache
= ctx
->jem
.operand
.uu
.u2
;
1251 ctx
->new_mb
= (MethodBlock
*)CP_INFO(ctx
->cp
, ctx
->jem
.operand
.uu
.u1
);
1252 ctx
->arg1
= ostack_address(ctx
->frame
->ostack
, ctx
->mb
->max_stack
,
1253 ctx
->ostack
- ctx
->frame
->ostack
- ctx
->new_mb
->args_count
);
1255 jam_dprintf("[OPC_INVOKEINTERFACE_QUICK] newmb %x (name %s) (args count %d) objref(jem) %x\n",
1256 ctx
->new_mb
, ctx
->new_mb
->name
, ctx
->new_mb
->args_count
, ctx
->arg1
);
1258 objref
= (Object
*)*ctx
->arg1
;
1259 #warning Does not look right!
1260 if (!JAM_ON_STACK
|| !IS_JAM_OBJECT(objref
) || !IS_JAM_ARRAY(objref
)) {
1261 objref
= JAM_OBJECT((uintptr_t *)objref
);
1262 if (!IS_OBJECT(objref
))
1263 objref
= JAM_ARRAY((uintptr_t *)*ctx
->arg1
);
1265 //turn type in the stack to JEM type ref
1266 *ctx
->arg1
= (uintptr_t)INST_DATA(objref
);
1268 JEM_NULL_POINTER_CHECK(objref
);
1270 cb
= CLASS_CB(objref
->class);
1272 if ((cache
>= cb
->imethod_table_size
) ||
1273 (ctx
->new_mb
->class != cb
->imethod_table
[cache
].interface
)) {
1274 for (cache
= 0; (cache
< cb
->imethod_table_size
) &&
1275 (ctx
->new_mb
->class != cb
->imethod_table
[cache
].interface
); cache
++);
1277 if (cache
== cb
->imethod_table_size
)
1278 return JEM_THROW_EXCEPTION("java/lang/IncompatibleClassChangeError",
1279 "unimplemented interface");
1282 mtbl_idx
= cb
->imethod_table
[cache
].offsets
[ctx
->new_mb
->method_table_index
];
1283 jam_dprintf("[OPC_INVOKEINTERFACE_QUICK] find method at %d\n", mtbl_idx
);
1284 ctx
->new_mb
= cb
->method_table
[mtbl_idx
];
1285 jam_dprintf("[OPC_INVOKEINTERFACE_QUICK] invoking method at %d\n", mtbl_idx
);
1286 return invokeMethod(ctx
);
1289 static int opc_invokeinterface(struct intrp_ctx
*ctx
)
1291 struct jem_state
*jem
= &ctx
->jem
;
1292 Operand
*operand
= &jem
->operand
;
1293 ExecEnv
*ee
= ctx
->ee
;
1295 int idx
= operand
->uu
.u1
= jem
->jecr
& 0xffff;
1296 /*NOTES: invokeinterface opcode is supposed to take 4 operands.
1297 * For JEM, two index bytes has been processed before trap,
1298 * so offset jpc 4 operands for next opcode
1299 *FIXME: ? not know why JEM does not handle this */
1300 ctx
->frame
->last_pc
= (CodePntr
)(jem
->jpc
+= 2);
1301 ctx
-> new_mb
= resolveInterfaceMethod(ctx
->mb
->class, idx
);
1303 jam_dprintf("[OPC_INVOKEINTERFACE] constant pool index %d\n", idx
);
1304 if (exceptionOccured0(ee
))
1305 return jem_throwException(ctx
);
1307 if (CLASS_CB(ctx
->new_mb
->class)->access_flags
& ACC_INTERFACE
) {
1309 return opc_invokeinterface_quick(ctx
);
1311 operand
->uu
.u1
= ctx
->new_mb
->args_count
;
1312 operand
->uu
.u2
= ctx
->new_mb
->method_table_index
;
1313 return opc_invokevirtual_quick(ctx
);
1317 static int opc_instanceof_quick(struct intrp_ctx
*ctx
)
1319 struct jem_state
*jem
= &ctx
->jem
;
1320 ConstantPool
*cp
= ctx
->cp
;
1321 Class
*class = RESOLVED_CLASS(jem
);
1325 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, ptr
);
1327 obj
= JAM_OBJECT(ptr
);
1328 if (!IS_OBJECT(obj
)) {
1329 jam_dprintf("[OPC_INSTANCEOF_QUICK] instanceof for array\n");
1330 //should be array ref
1331 obj
= JAM_ARRAY(ptr
);
1334 jam_dprintf("[OPC_INSTANCEOF_QUICK] check instanceof class %s for obj(%s)\n",
1335 CLASS_CB(class)->name
, CLASS_CB(obj
->class)->name
);
1337 ostack_push_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
,
1338 ptr
? (uint32_t)isInstanceOf(class, obj
->class) : 0);
1342 static int opc_instanceof(struct intrp_ctx
*ctx
)
1344 struct jem_state
*jem
= &ctx
->jem
;
1345 Operand
*operand
= &jem
->operand
;
1346 int idx
= jem
->jecr
& 0xffff;
1347 int opcode
= (jem
->jecr
>> 16) & 0xff;
1349 ExecEnv
*ee
= ctx
->ee
;
1351 operand
->uui
.u1
= idx
;
1352 operand
->uui
.u2
= opcode
;
1354 jam_dprintf("[OPC_INSTANCEOF] index: 0x%x\n", idx
);
1356 ctx
->frame
->last_pc
= (CodePntr
)jem
->jpc
;
1357 //resolve the cast class
1358 class = resolveClass(ctx
->mb
->class, idx
, FALSE
);
1360 if (exceptionOccured0(ee
))
1361 return jem_throwException(ctx
);
1363 return opc_instanceof_quick(ctx
);
1366 static int opc_aastore(struct intrp_ctx
*ctx
)
1373 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, aobj
);
1374 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, idx
);
1375 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, array
);
1377 jam_dprintf("[OPC_AASTORE] obj %p, index %d, array %p\n", aobj
, idx
, array
);
1379 /* aobj does point to an object, but we do not know if that's an array or
1380 * not, and we need to know that for the arrayStoreCheck() check below */
1381 #warning Does not look right!
1382 if (aobj
&& (!JAM_ON_STACK
|| !IS_JAM_OBJECT(aobj
) || !IS_JAM_ARRAY(aobj
))) {
1383 if (!IS_OBJECT(JAM_OBJECT(aobj
))) {
1384 //in case of storing an array to another array
1385 obj
= JAM_ARRAY(aobj
);
1387 obj
= JAM_OBJECT(aobj
);
1390 obj
= (Object
*)aobj
;
1391 array
= JAM_ARRAY((uintptr_t *)array
);
1393 jam_dprintf("[OPC_AASTORE] store obj ref %p of %p to array %p[%d/%d] of %p\n",
1394 obj
, obj
? obj
->class : obj
, array
, idx
, array
->instance
[0], array
->class);
1395 JEM_NULL_POINTER_CHECK(array
);
1397 if (idx
>= ARRAY_LEN(array
)) {
1398 char buff
[MAX_INT_DIGITS
];
1399 snprintf(buff
, MAX_INT_DIGITS
, "%d", idx
);
1400 JEM_THROW_EXCEPTION("java/lang/ArrayIndexOutOfBoundsException", buff
);
1403 if (obj
!= NULL
&& !arrayStoreCheck(array
->class, obj
->class))
1404 JEM_THROW_EXCEPTION("java/lang/ArrayStoreException", NULL
);
1406 //FIXME: If we set JEM ref here, it is very likely that some native jamvm code would directly offset
1407 // the array to get the non jamvm refs to use, which then causes segfault.
1409 ((Object
**)ARRAY_DATA(array
))[idx
] = obj
;
1411 ((uintptr_t**)ARRAY_DATA(array
))[idx
] = aobj
;
1416 static int do_javaExceptions(struct intrp_ctx
*ctx
)
1419 struct jem_state
*jem
= &ctx
->jem
;
1421 /* deliberate segfault */
1422 /* *(int *)0 = 0; */
1424 jecr_u
.i
= jem
->jecr
;
1425 /* This should not happen, because we don't use the "Java Handle" (H)
1426 * bit in the Status Register and we set JBCR to 0x80000000 - still
1427 * it does happen, but seems to be harmless so far. Just ignore. */
1428 if (jecr_u
.s
.opcode
== OPC_AASTORE
)
1429 return opc_aastore(ctx
);
1434 static int opc_afireturn(struct intrp_ctx
*ctx
)
1439 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, val
);
1441 jam_dprintf("[OPC_AFIRETURN] return 0x%08x @ %p, this %p\n",
1442 val
, ctx
->lvars_jem
, ctx
->this);
1444 ret
= opc_return(ctx
);
1446 ret
= ostack_push_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, val
);
1448 /* Function returning a value must have local variables */
1449 *ctx
->lvars_jem
= val
;
1454 static int opc_ldreturn(struct intrp_ctx
*ctx
)
1459 ostack_pop_u64(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, v
.i
);
1460 jam_dprintf("[OPC_LDRETURN] return 0x%llx\n", v
.ll
);
1462 ret
= opc_return(ctx
);
1465 ret
= ostack_push_u64(ctx
->frame
->ostack
, ctx
->mb
->max_stack
,
1468 /* Function returning a value must have local variables */
1469 *(uint64_t*)ctx
->lvars_jem
= v
.ll
;
1474 static int opc_fcmpg(struct intrp_ctx
*ctx
)
1479 ostack_pop_f32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, v2
);
1480 ostack_pop_f32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, v1
);
1489 res
= 1; /* isNaN */
1491 jam_dprintf("[OPC_FCMPG] result %d\n", res
);
1493 return ostack_push_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, res
);
1496 static int opc_fcmpl(struct intrp_ctx
*ctx
)
1501 ostack_pop_f32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, v2
);
1502 ostack_pop_f32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, v1
);
1513 jam_dprintf("[OPC_FCMPL] result %d\n", res
);
1514 return ostack_push_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, res
);
1517 static int opc_lcmp(struct intrp_ctx
*ctx
)
1519 union ull_2ui v1
, v2
;
1522 ostack_pop_u64(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, v2
.i
);
1523 ostack_pop_u64(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, v1
.i
);
1527 else if (v1
.ll
- v2
.ll
> 0LL)
1532 jam_dprintf("[%s] (0x%llx,0x%llx) result %d\n", __func__
, v1
.ll
, v2
.ll
, res
);
1533 return ostack_push_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, res
);
1536 static int opc_i2f(struct intrp_ctx
*ctx
)
1541 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, i
);
1544 jam_dprintf("[OPC_I2F] convert to %f\n", f
);
1546 return ostack_push_f32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, f
);
1549 static int opc_i2d(struct intrp_ctx
*ctx
)
1551 return JEM_TRAP_HANDLER_FINISH
;
1554 static int opc_ldiv(struct intrp_ctx
*ctx
)
1556 union ull_2ui v1
, v2
, res
;
1558 ostack_pop_u64(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, v2
.i
);
1559 ostack_pop_u64(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, v1
.i
);
1561 res
.ll
= v1
.ll
/ v2
.ll
;
1563 jam_dprintf("[%s] (0x%llx,0x%llx) result 0x%llx\n", __func__
, v1
.ll
, v2
.ll
, res
.ll
);
1565 return ostack_push_u64(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, res
.i
);
1568 static int opc_lrem(struct intrp_ctx
*ctx
)
1570 union ull_2ui v1
, v2
, res
;
1572 ostack_pop_u64(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, v2
.i
);
1573 ostack_pop_u64(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, v1
.i
);
1575 res
.ll
= v1
.ll
% v2
.ll
;
1577 jam_dprintf("[%s] (0x%llx,0x%llx) result 0x%llx\n", __func__
, v1
.ll
, v2
.ll
, res
.ll
);
1579 return ostack_push_u64(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, res
.i
);
1582 static int opc_lmul(struct intrp_ctx
*ctx
)
1584 union ull_2ui v1
, v2
, res
;
1586 ostack_pop_u64(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, v2
.i
);
1587 ostack_pop_u64(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, v1
.i
);
1589 res
.ll
= v1
.ll
* v2
.ll
;
1591 jam_dprintf("[%s] (0x%llx,0x%llx) result 0x%llx\n", __func__
, v1
.ll
, v2
.ll
, res
.ll
);
1593 return ostack_push_u64(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, res
.i
);
1596 static int opc_lushr(struct intrp_ctx
*ctx
)
1598 union ull_2ui res
, v1
;
1601 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, v2
);
1602 ostack_pop_u64(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, v1
.i
);
1604 res
.ll
= v1
.ll
>> (v2
& 0x3f);
1606 jam_dprintf("[%s] (0x%llx,%u) result 0x%llx\n", __func__
, v1
.ll
, v2
, res
.ll
);
1608 return ostack_push_u64(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, res
.i
);
1611 static int opc_lshr(struct intrp_ctx
*ctx
)
1613 union ull_2ui v1
, res
;
1616 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, v2
);
1617 ostack_pop_u64(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, v1
.i
);
1619 res
.ll
= (long long)v1
.ll
/ (1LL << (v2
& 0x3f));
1621 jam_dprintf("[%s] (0x%llx,%u) result 0x%llx\n", __func__
, v1
.ll
, v2
, res
.ll
);
1623 return ostack_push_u64(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, res
.i
);
1626 static int opc_lneg(struct intrp_ctx
*ctx
)
1628 union ull_2ui v
, res
;
1630 ostack_pop_u64(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, v
.i
);
1634 jam_dprintf("[%s] (0x%llx) result 0x%llx\n", __func__
, v
.ll
, res
.ll
);
1636 return ostack_push_u64(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, res
.i
);
1639 static int opc_fmul(struct intrp_ctx
*ctx
)
1644 ostack_pop_f32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, v2
);
1645 ostack_pop_f32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, v1
);
1649 jam_dprintf("[OPC_FMUL] result %f\n", ret
);
1651 return ostack_push_f32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, ret
);
1654 static int opc_fadd(struct intrp_ctx
*ctx
)
1659 ostack_pop_f32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, v2
);
1660 ostack_pop_f32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, v1
);
1664 jam_dprintf("[OPC_FADD] result %f\n", ret
);
1666 return ostack_push_f32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, ret
);
1669 static int opc_fsub(struct intrp_ctx
*ctx
)
1674 ostack_pop_f32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, v2
);
1675 ostack_pop_f32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, v1
);
1679 jam_dprintf("[OPC_FSUB] result %f\n", ret
);
1681 return ostack_push_f32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, ret
);
1684 static int opc_f2i(struct intrp_ctx
*ctx
)
1689 ostack_pop_f32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, value
);
1691 jam_dprintf("[OPC_F2I] float value %f\n", value
);
1692 if (value
>= (float)INT_MAX
)
1694 else if (value
<= (float)INT_MIN
)
1696 else if (value
!= value
)
1701 jam_dprintf("[OPC_F2I] int value %d\n", res
);
1703 return ostack_push_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, res
);
1706 static int opc_iinc(struct intrp_ctx
*ctx
)
1709 jecr_u
.i
= ctx
->jem
.jecr
;
1710 int index
= (int)jecr_u
.s
.op1
;
1711 int con
= (int)jecr_u
.s
.op2
;
1712 uintptr_t *ptr
= ctx
->lvars_jem
;
1714 jam_dprintf("[OPC_IINC] add %d to local var %x at %d (%d)\n",
1715 con
, ptr
[-index
], index
, ctx
->mb
->max_locals
);
1716 ptr
[-index
] = ptr
[-index
] + con
;
1718 jam_dprintf("[OPC_IINC] local var is %x now\n", ptr
[-index
]);
1722 static int opc_tableswitch(struct intrp_ctx
*ctx
)
1724 /* On entry JPC points to "default" */
1725 int32_t dflt
, high
, low
, *dflt_p
;
1730 tswitch
= (uint8_t *)(ctx
->jem
.jpc
- 3);
1731 dflt_p
= (int32_t *)(ctx
->jem
.jpc
& ~3);
1733 dflt
= __be32_to_cpu(*dflt_p
);
1734 low
= __be32_to_cpu(*(dflt_p
+ 1));
1735 high
= __be32_to_cpu(*(dflt_p
+ 2));
1737 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, idx
);
1739 if (idx
< low
|| idx
> high
)
1742 target
= __be32_to_cpu(*(dflt_p
+ 3 + idx
- low
));
1745 for (i
= 0; i
<= high
- low
; i
++) {
1746 int32_t *addr
= dflt_p
+ 3 + i
;
1749 jam_dprintf("%p:", addr
);
1750 jam_dprintf(" 0x%x", *addr
);
1751 if ((i
& 15) == 15 || i
== high
- low
)
1752 jam_dprintf("\n", addr
);
1756 jam_dprintf("[%s] trap @%p, jpc 0x%x, default 0x%x @ %p, low %d, high %d, idx %d, target 0x%x\n",
1757 __func__
, tswitch
, ctx
->jem
.jpc
, dflt
, dflt_p
, low
, high
, idx
, target
);
1759 ctx
->jem
.jpc
= (uint32_t)(tswitch
+ target
);
1764 static int opc_athrow(struct intrp_ctx
*ctx
)
1767 ostack_pop_u32(ctx
->frame
->ostack
, ctx
->mb
->max_stack
, ctx
->ostack
, obj
);
1768 ctx
->frame
->last_pc
= (CodePntr
)ctx
->jem
.jpc
;
1769 ExecEnv
*ee
= ctx
->ee
;
1771 JEM_NULL_POINTER_CHECK(obj
);
1773 if (!JAM_ON_STACK
|| !IS_JAM_OBJECT(obj
))
1774 obj
= JAM_OBJECT((uintptr_t *)obj
);
1776 jam_dprintf("[OPC_ATHROW] throw exception %s\n", CLASS_CB(obj
->class)->name
);
1777 ee
->exception
= obj
;
1778 return jem_throwException(ctx
);
1781 static int do_stackOverflow(struct intrp_ctx
*ctx
)
1783 jam_dprintf("[TRAP] STACK OVERFLOW XXXXXXXX\n");
1787 static int do_stackUnderflow(struct intrp_ctx
*ctx
)
1789 jam_dprintf("[TRAP] STACK UNDERFLOW XXXXXXXX\n");
1793 static int do_stackOverflow1(struct intrp_ctx
*ctx
)
1795 jam_dprintf("[TRAP] STACK OVERFLOW1XXXXXXXX\n");
1799 static int do_stackUnderflow1(struct intrp_ctx
*ctx
)
1801 jam_dprintf("[TRAP] STACK UNDERFLOW1XXXXXXXX\n");
1805 static handler_fn
*trap_handler_f
[256] = {
1806 [OPC_INVOKEINTERFACE
] = opc_invokeinterface
,
1807 [OPC_INVOKESPECIAL
] = opc_invokespecial
,
1808 [OPC_INVOKESUPER_QUICK
] = opc_invokesuper_quick
,
1809 [OPC_INVOKENONVIRTUAL_QUICK
] = opc_invokenonvirtual_quick
,
1810 [OPC_INVOKEVIRTUAL
] = opc_invokevirtual
,
1811 [OPC_INVOKEVIRTUAL_QUICK
] = opc_invokevirtual_quick
,
1812 [OPC_INVOKESTATIC
] = opc_invokestatic
,
1813 // [OPC_INVOKESTATIC_QUICK] = opc_invokestatic_quick,
1814 [OPC_NEW
] = opc_new
,
1815 [0xDD] = opc_new
, /* JEM: NEW_QUICK */
1816 [OPC_RETURN
] = opc_return
,
1817 [OPC_ARETURN
] = opc_afireturn
,
1818 [OPC_IRETURN
] = opc_afireturn
,
1819 [OPC_FRETURN
] = opc_afireturn
,
1820 [OPC_PUTFIELD
] = opc_putfield
,
1821 // [OPC_PUTFIELD_QUICK] = opc_putfield_quick,
1822 // [OPC_PUTFIELD2_QUICK] = opc_putfield2_quick,
1823 // [OPC_LDC_W_QUICK] = opc_ldc_w_quick,
1824 // [OPC_LDC_QUICK] = opc_ldc_quick,
1825 [OPC_LDC_W
] = opc_ldc_w
,
1826 [OPC_LDC
] = opc_ldc
,
1827 [OPC_LDC2_W
] = opc_ldc2_w
,
1828 [OPC_MONITORENTER
] = opc_monitorenter
,
1829 [OPC_MONITOREXIT
] = opc_monitorexit
,
1830 [OPC_GETSTATIC
] = opc_getstatic
,
1831 // [OPC_GETSTATIC_QUICK] = opc_getstatic_quick,
1832 // [OPC_GETSTATIC2_QUICK] = opc_getstatic2_quick,
1833 [OPC_PUTSTATIC
] = opc_putstatic
,
1834 [OPC_PUTSTATIC_QUICK
] = opc_putstatic_quick
,
1835 [OPC_PUTSTATIC2_QUICK
] = opc_putstatic2_quick
,
1836 [OPC_ANEWARRAY
] = opc_anewarray
,
1837 [OPC_ANEWARRAY_QUICK
] = opc_anewarray_quick
,
1838 [OPC_MULTIANEWARRAY
] = opc_multianewarray
,
1839 [OPC_NEWARRAY
] = opc_newarray
,
1840 [OPC_CHECKCAST
] = opc_checkcast
,
1841 [OPC_CHECKCAST_QUICK
] = opc_checkcast_quick
,
1842 [OPC_GETFIELD
] = opc_getfield
,
1843 // [OPC_GETFIELD_QUICK] = opc_getfield_quick,
1844 // [OPC_GETFIELD2_QUICK] = opc_getfield2_quick,
1845 [OPC_LSHR
] = opc_lshr
,
1846 [OPC_LUSHR
] = opc_lushr
,
1847 [OPC_LCMP
] = opc_lcmp
,
1848 [OPC_LNEG
] = opc_lneg
,
1849 [OPC_LDIV
] = opc_ldiv
,
1850 [OPC_LREM
] = opc_lrem
,
1851 [OPC_LMUL
] = opc_lmul
,
1852 [OPC_FCMPL
] = opc_fcmpl
,
1853 [OPC_FCMPG
] = opc_fcmpg
,
1854 [OPC_I2F
] = opc_i2f
,
1855 [OPC_I2D
] = opc_i2d
,
1856 [OPC_FMUL
] = opc_fmul
,
1857 [OPC_FADD
] = opc_fadd
,
1858 [OPC_FSUB
] = opc_fsub
,
1859 [OPC_F2I
] = opc_f2i
,
1860 [OPC_IINC
] = opc_iinc
,
1861 [OPC_INSTANCEOF
] = opc_instanceof
,
1862 [OPC_ATHROW
] = opc_athrow
,
1863 [OPC_LRETURN
] = opc_ldreturn
,
1864 [OPC_TABLESWITCH
] = opc_tableswitch
,
1867 static handler_fn
*exception_handler_f
[] = {
1868 [0] = do_javaExceptions
,
1869 [1] = do_stackOverflow
,
1870 [2] = do_stackUnderflow
,
1871 [3] = do_stackOverflow1
,
1872 [4] = do_stackUnderflow1
,
1875 struct jem_profile
{
1881 static struct jem_profile prof
[256];
1884 /******************************/
1885 uintptr_t *executeJava(void)
1888 * load trap entries to JEM trap table set when initializing JamVM
1894 static struct timeval tv1
, tv2
;
1896 ExecEnv
*ee
= getExecEnv();
1898 /* Initialize interpreter's static environment */
1899 struct intrp_ctx ctx
;
1900 struct jem_state
*jem
= &ctx
.jem
;
1903 ctx
.frame
= ee
->last_frame
;
1904 ctx
.mb
= ctx
.frame
->mb
;
1906 * We use ostack to save overflowing Java Operand Stack elements. On a stack
1907 * overflow we free a half of the stack (4 elements) to avoid an immediate
1908 * next overflow. When entering a trap, the Operand Stack is saved in a
1909 * temporary array in the reverse order:
1910 * ATTENTION: Looks like ToS is really in r0, not in r7, as JEM manual says
1913 * jos[7 - N] = rN (ToS - N)
1916 * UPDATE (27.06.2008)
1917 * I think, actually, the manual is right in some way... If you access
1918 * registers individually _when_ JOSP == N + 1 != 0. If they are read out
1919 * with an ldm, you get this:
1922 * jos[7 - N] = rN (ToS)
1924 * jos[7] = r0 (ToS - N)
1925 * on an overflow we push r3..r0, i.e., jos[4..7] to the frame stack, and
1926 * set saved JOSP to 4.
1928 unsigned long jos
[8];
1930 ctx
.ostack
= ctx
.frame
->ostack
;
1931 ctx
.cp
= &(CLASS_CB(ctx
.mb
->class)->constant_pool
);
1932 /* End enterpreter's static environment */
1934 //fetch the original pc before prepare direct mb
1936 /* I think, mb->code is indeed a copy of the original code[] array from the
1937 * class object. See class.c::defineClass():390 */
1939 if (ctx
.frame
->lvars_jem
) {
1940 ctx
.lvars_jem
= ctx
.frame
->lvars_jem
- 1;
1944 jam_printf("BUG: lvars_jem == NULL!!!");
1948 jam_dprintf("[executeJava] ostack %08x locals %d lvars_jem %08x\n",
1949 ctx
.ostack
, ctx
.mb
->max_locals
, ctx
.lvars_jem
);
1950 jam_dprintf("[executeJava] execute method %s on class %s\n",
1951 ctx
.mb
->name
, CLASS_CB(ctx
.mb
->class)->name
);
1954 /* Don't think we need it, at least, not in the direct.c form. There the code
1955 * is converted into an internal representation, which is useless for JEM */
1956 PREPARE_MB(ctx
.mb
);//see direct.c (prepare)
1959 jem
->jpc
= (unsigned long)ctx
.mb
->code
& ~3;
1960 jam_dprintf("[executeJava] begin on opcode %04x (%04x)\n",
1961 *(char*)jem
->jpc
, *((char*)jem
->jpc
+ 1));
1965 /* This is not thread-safe. Have to use TLS. */
1971 jam_dprintf("About to enter JEM at 0x%08x, this = %p, class = %p. Code:",
1972 jem
->jpc
, ctx
.this, ctx
.this ? ctx
.this->class : NULL
);
1973 for (i
= 0; i
< 32 && jem
->jpc
+ i
< (unsigned long)(ctx
.mb
->code
+ ctx
.mb
->code_size
); i
++) {
1975 jam_dprintf("\n0x%04x:", i
);
1976 jam_dprintf(" 0x%02x", ((char*)jem
->jpc
)[i
]);
1979 jam_dprintf("\nUp to 8 first Local Variables out of %d:\n", ctx
.mb
->max_locals
);
1980 for (i
= 0; i
< min(8, ctx
.mb
->max_locals
); i
++)
1981 jam_dprintf("LVAR_%d: 0x%08x\n", i
, *(ctx
.lvars_jem
- i
), ctx
.lvars_jem
- i
);
1984 /* On entry we need last Java Operand Stack depth, set it not deeper
1985 * than half hardware stack */
1986 jem
->josp
= min(5, ostack_depth(ctx
.frame
->ostack
, ctx
.ostack
));
1987 jam_dprintf("Pop %d words to JEM stack from %p:%p\n", jem
->josp
,
1988 ctx
.frame
->ostack
, ctx
.ostack
);
1989 /* As long as we are in asm, top jem.josp stack elements belong JEM */
1990 for (i
= 0; i
< jem
->josp
; i
++)
1991 ostack_pop_u32(ctx
.frame
->ostack
, ctx
.mb
->max_stack
, ctx
.ostack
,
1992 jos
[7 - jem
->josp
+ 1 + i
]);
1996 gettimeofday(&tv2
, NULL
);
1997 prof
[opcode
].time
+= (tv2
.tv_sec
- tv1
.tv_sec
) * 1000000 +
1998 tv2
.tv_usec
- tv1
.tv_usec
;
2003 __asm__
__volatile__(
2004 ".globl debug_jem_enter\n"
2005 "debug_jem_enter:\n"
2006 " pushm r0-r7,r10-r11\n"
2010 " mov r12, %[josp]\n" /* Cannot use %[josp] ... */
2011 " mov r11, %[ostack]\n"
2012 " pushm r11\n" /* Need ostack below */
2013 " ldm r11, r0-r7\n" /* Restore Java Operands */
2014 " cp.w r12, 0\n" /* Test josp == 0 */
2016 "5: incjosp 1\n" /* ... for loop counter, */
2017 " sub r12, 1\n" /* because it can be */
2018 " brne 5b\n" /* one of r0-r7 */
2019 "4: popjc\n" /* Restore Local Variables */
2020 " sub r10, pc, . - trap\n" /* These 3 instructions */
2021 " retj\n" /* have to stay */
2022 "trap: pushjc\n" /* together */
2023 " mfsr r11, 0x58\n" /* JOSP */
2024 " lsl r11, 28\n" /* Clear r11[31:3] using */
2025 " lsr r11, 28\n" /* one register */
2031 "2: popm r11\n" /* ostack */
2032 " stm r11, r0-r7\n" /* Save Java Operands */
2033 " popm r0-r7,r10-r11\n"
2034 " mov %[tpc], r12\n"
2035 " mov %[jpc], lr\n" /* Resume address */
2036 " mfsr %[jecr], 0x54\n" /* JECR */
2037 " mov %[josp], r8\n" /* JOSP */
2038 " .globl debug_jem_exit\n"
2040 : [jecr
] "=r" (jem
->jecr
), [tpc
] "=r" (jem
->trap_pc
),
2041 [josp
] "+r" (jem
->josp
), [jpc
] "+r" (jem
->jpc
)
2042 : [cp
] "r" (ctx
.cp
->info
), [lv0
] "r" (ctx
.lvars_jem
),
2044 : "r8", "r9", "lr", "r12", "sp", "memory", "cc"
2047 * trap_pc now holds trap pc, describing which trap has been entered,
2048 * jecr holds JECR with the trapping bytecode at bits 23..16, possibly
2049 * arguments at bits 7..0 and 15..8,
2050 * josp holds JOSP (JOSP & 0xf),
2051 * jos holds stored registers r7-r0 (note order!) - Java Operand Stack
2052 * jpc points at the trapping opcode, in case of exceptions and stack
2053 * over- and underflows, and at the next opcode, in case of a trap
2057 gettimeofday(&tv1
, NULL
);
2060 for (i
= 0; i
< jem
->josp
; i
++)
2061 ostack_push_u32(ctx
.frame
->ostack
, ctx
.mb
->max_stack
, ctx
.ostack
,
2064 opcode
= (jem
->jecr
>> 16) & 0xff;
2066 jep
= jem
->trap_pc
& 0xfff;
2070 done
= exception_handler_f
[jep
>> 7](&ctx
);
2071 else if (trap_handler_f
[opcode
])
2072 done
= trap_handler_f
[opcode
](&ctx
);
2075 jam_printf("Unimplemented Java Opcode 0x%02x\n", opcode
);
2082 } while (done
!= JEM_TRAP_HANDLER_FINISH
);
2088 jam_dprintf("Unknown Java Opcodes\n");
2093 void initialiseInterpreter(InitArgs
*args
) {
2094 initialiseDirect(args
);
2098 void dump_profile(void)
2103 for (i
= 0; i
< 256; i
++)
2105 jam_printf("0x%x:\t%u times,\t%lu usec\n", i
, prof
[i
].n
, prof
[i
].time
);