Changeset 1391 for branches/GNU/src/gcc/libjava/interpret.cc
- Timestamp:
- Apr 27, 2004, 8:39:34 PM (21 years ago)
- Location:
- branches/GNU/src/gcc
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/GNU/src/gcc
- Property svn:ignore
-
old new 26 26 configure.vr 27 27 configure.vrs 28 dir.info 28 29 Makefile 29 dir.info30 30 lost+found 31 31 update.out
-
- Property svn:ignore
-
branches/GNU/src/gcc/libjava/interpret.cc
-
Property cvs2svn:cvs-rev
changed from
1.1
to1.1.1.2
r1390 r1391 1 1 // interpret.cc - Code for the interpreter 2 2 3 /* Copyright (C) 1999, 2000, 2001 3 /* Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation 4 4 5 5 This file is part of libgcj. … … 13 13 #include <config.h> 14 14 15 // Define this to get the direct-threaded interpreter. If undefined, 16 // we revert to a basic bytecode interpreter. The former is faster 17 // but uses more memory. 18 #define DIRECT_THREADED 19 15 20 #pragma implementation "java-interp.h" 16 21 … … 18 23 #include <java-cpool.h> 19 24 #include <java-interp.h> 20 // #include <java/lang/fdlibm.h>21 25 #include <java/lang/System.h> 22 26 #include <java/lang/String.h> … … 32 36 #include <java/lang/ArithmeticException.h> 33 37 #include <java/lang/IncompatibleClassChangeError.h> 38 #include <java/lang/Thread.h> 34 39 #include <java-insns.h> 35 40 #include <java-signal.h> … … 51 56 52 57 extern "C" double __ieee754_fmod (double,double); 58 59 // This represents a single slot in the "compiled" form of the 60 // bytecode. 61 union insn_slot 62 { 63 // Address of code. 64 void *insn; 65 // An integer value used by an instruction. 66 jint int_val; 67 // A pointer value used by an instruction. 68 void *datum; 69 }; 70 71 // The type of the PC depends on whether we're doing direct threading 72 // or a more ordinary bytecode interpreter. 73 #ifdef DIRECT_THREADED 74 typedef insn_slot *pc_t; 75 #else 76 typedef unsigned char *pc_t; 77 #endif 53 78 54 79 static inline void dupx (_Jv_word *sp, int n, int x) … … 200 225 #ifdef HANDLE_SEGV 201 226 #define NULLCHECK(X) 202 #define NULLARRAYCHECK(X) do { SAVE_PC; } while (0)227 #define NULLARRAYCHECK(X) 203 228 #else 204 229 #define NULLCHECK(X) \ 205 230 do { if ((X)==NULL) throw_null_pointer_exception (); } while (0) 206 231 #define NULLARRAYCHECK(X) \ 207 do { if ((X)==NULL) { SAVE_PC;throw_null_pointer_exception (); } } while (0)232 do { if ((X)==NULL) { throw_null_pointer_exception (); } } while (0) 208 233 #endif 209 234 … … 216 241 while (0) 217 242 218 // this method starts the actual running of the method. It is inlined 219 // in three different variants in the static methods run_normal, 220 // run_sync_object and run_sync_class (see below). Those static methods 221 // are installed directly in the stub for this method (by 222 // _Jv_InterpMethod::ncode, in resolve.cc). 223 224 inline jobject 225 _Jv_InterpMethod::run (ffi_cif* cif, 226 void *retp, 227 ffi_raw *args, 228 _Jv_InterpMethodInvocation *inv) 243 void _Jv_InterpMethod::run_normal (ffi_cif *, 244 void* ret, 245 ffi_raw * args, 246 void* __this) 229 247 { 230 inv->running = this; 231 inv->pc = bytecode (); 232 inv->sp = inv->stack_base (); 233 _Jv_word *locals = inv->local_base (); 248 _Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this; 249 _this->run (ret, args); 250 } 251 252 void _Jv_InterpMethod::run_synch_object (ffi_cif *, 253 void* ret, 254 ffi_raw * args, 255 void* __this) 256 { 257 _Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this; 258 259 jobject rcv = (jobject) args[0].ptr; 260 JvSynchronize mutex (rcv); 261 262 _this->run (ret, args); 263 } 264 265 void _Jv_InterpMethod::run_synch_class (ffi_cif *, 266 void* ret, 267 ffi_raw * args, 268 void* __this) 269 { 270 _Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this; 271 272 jclass sync = _this->defining_class; 273 JvSynchronize mutex (sync); 274 275 _this->run (ret, args); 276 } 277 278 #ifdef DIRECT_THREADED 279 // "Compile" a method by turning it from bytecode to direct-threaded 280 // code. 281 void 282 _Jv_InterpMethod::compile (const void * const *insn_targets) 283 { 284 insn_slot *insns = NULL; 285 int next = 0; 286 unsigned char *codestart = bytecode (); 287 unsigned char *end = codestart + code_length; 288 _Jv_word *pool_data = defining_class->constants.data; 289 290 #define SET_ONE(Field, Value) \ 291 do \ 292 { \ 293 if (first_pass) \ 294 ++next; \ 295 else \ 296 insns[next++].Field = Value; \ 297 } \ 298 while (0) 299 300 #define SET_INSN(Value) SET_ONE (insn, (void *) Value) 301 #define SET_INT(Value) SET_ONE (int_val, Value) 302 #define SET_DATUM(Value) SET_ONE (datum, Value) 303 304 // Map from bytecode PC to slot in INSNS. 305 int *pc_mapping = (int *) __builtin_alloca (sizeof (int) * code_length); 306 for (int i = 0; i < code_length; ++i) 307 pc_mapping[i] = -1; 308 309 for (int i = 0; i < 2; ++i) 310 { 311 jboolean first_pass = i == 0; 312 313 if (! first_pass) 314 { 315 insns = (insn_slot *) _Jv_AllocBytes (sizeof (insn_slot) * next); 316 next = 0; 317 } 318 319 unsigned char *pc = codestart; 320 while (pc < end) 321 { 322 int base_pc_val = pc - codestart; 323 if (first_pass) 324 pc_mapping[base_pc_val] = next; 325 326 java_opcode opcode = (java_opcode) *pc++; 327 // Just elide NOPs. 328 if (opcode == op_nop) 329 continue; 330 SET_INSN (insn_targets[opcode]); 331 332 switch (opcode) 333 { 334 case op_nop: 335 case op_aconst_null: 336 case op_iconst_m1: 337 case op_iconst_0: 338 case op_iconst_1: 339 case op_iconst_2: 340 case op_iconst_3: 341 case op_iconst_4: 342 case op_iconst_5: 343 case op_lconst_0: 344 case op_lconst_1: 345 case op_fconst_0: 346 case op_fconst_1: 347 case op_fconst_2: 348 case op_dconst_0: 349 case op_dconst_1: 350 case op_iload_0: 351 case op_iload_1: 352 case op_iload_2: 353 case op_iload_3: 354 case op_lload_0: 355 case op_lload_1: 356 case op_lload_2: 357 case op_lload_3: 358 case op_fload_0: 359 case op_fload_1: 360 case op_fload_2: 361 case op_fload_3: 362 case op_dload_0: 363 case op_dload_1: 364 case op_dload_2: 365 case op_dload_3: 366 case op_aload_0: 367 case op_aload_1: 368 case op_aload_2: 369 case op_aload_3: 370 case op_iaload: 371 case op_laload: 372 case op_faload: 373 case op_daload: 374 case op_aaload: 375 case op_baload: 376 case op_caload: 377 case op_saload: 378 case op_istore_0: 379 case op_istore_1: 380 case op_istore_2: 381 case op_istore_3: 382 case op_lstore_0: 383 case op_lstore_1: 384 case op_lstore_2: 385 case op_lstore_3: 386 case op_fstore_0: 387 case op_fstore_1: 388 case op_fstore_2: 389 case op_fstore_3: 390 case op_dstore_0: 391 case op_dstore_1: 392 case op_dstore_2: 393 case op_dstore_3: 394 case op_astore_0: 395 case op_astore_1: 396 case op_astore_2: 397 case op_astore_3: 398 case op_iastore: 399 case op_lastore: 400 case op_fastore: 401 case op_dastore: 402 case op_aastore: 403 case op_bastore: 404 case op_castore: 405 case op_sastore: 406 case op_pop: 407 case op_pop2: 408 case op_dup: 409 case op_dup_x1: 410 case op_dup_x2: 411 case op_dup2: 412 case op_dup2_x1: 413 case op_dup2_x2: 414 case op_swap: 415 case op_iadd: 416 case op_isub: 417 case op_imul: 418 case op_idiv: 419 case op_irem: 420 case op_ishl: 421 case op_ishr: 422 case op_iushr: 423 case op_iand: 424 case op_ior: 425 case op_ixor: 426 case op_ladd: 427 case op_lsub: 428 case op_lmul: 429 case op_ldiv: 430 case op_lrem: 431 case op_lshl: 432 case op_lshr: 433 case op_lushr: 434 case op_land: 435 case op_lor: 436 case op_lxor: 437 case op_fadd: 438 case op_fsub: 439 case op_fmul: 440 case op_fdiv: 441 case op_frem: 442 case op_dadd: 443 case op_dsub: 444 case op_dmul: 445 case op_ddiv: 446 case op_drem: 447 case op_ineg: 448 case op_i2b: 449 case op_i2c: 450 case op_i2s: 451 case op_lneg: 452 case op_fneg: 453 case op_dneg: 454 case op_i2l: 455 case op_i2f: 456 case op_i2d: 457 case op_l2i: 458 case op_l2f: 459 case op_l2d: 460 case op_f2i: 461 case op_f2l: 462 case op_f2d: 463 case op_d2i: 464 case op_d2l: 465 case op_d2f: 466 case op_lcmp: 467 case op_fcmpl: 468 case op_fcmpg: 469 case op_dcmpl: 470 case op_dcmpg: 471 case op_monitorenter: 472 case op_monitorexit: 473 case op_ireturn: 474 case op_lreturn: 475 case op_freturn: 476 case op_dreturn: 477 case op_areturn: 478 case op_return: 479 case op_athrow: 480 case op_arraylength: 481 // No argument, nothing else to do. 482 break; 483 484 case op_bipush: 485 SET_INT (get1s (pc)); 486 ++pc; 487 break; 488 489 case op_ldc: 490 { 491 int index = get1u (pc); 492 ++pc; 493 SET_DATUM (pool_data[index].o); 494 } 495 break; 496 497 case op_ret: 498 case op_iload: 499 case op_lload: 500 case op_fload: 501 case op_dload: 502 case op_aload: 503 case op_istore: 504 case op_lstore: 505 case op_fstore: 506 case op_dstore: 507 case op_astore: 508 case op_newarray: 509 SET_INT (get1u (pc)); 510 ++pc; 511 break; 512 513 case op_iinc: 514 SET_INT (get1u (pc)); 515 SET_INT (get1s (pc + 1)); 516 pc += 2; 517 break; 518 519 case op_ldc_w: 520 { 521 int index = get2u (pc); 522 pc += 2; 523 SET_DATUM (pool_data[index].o); 524 } 525 break; 526 527 case op_ldc2_w: 528 { 529 int index = get2u (pc); 530 pc += 2; 531 SET_DATUM (&pool_data[index]); 532 } 533 break; 534 535 case op_sipush: 536 SET_INT (get2s (pc)); 537 pc += 2; 538 break; 539 540 case op_new: 541 case op_getstatic: 542 case op_getfield: 543 case op_putfield: 544 case op_putstatic: 545 case op_anewarray: 546 case op_instanceof: 547 case op_checkcast: 548 case op_invokespecial: 549 case op_invokestatic: 550 case op_invokevirtual: 551 SET_INT (get2u (pc)); 552 pc += 2; 553 break; 554 555 case op_multianewarray: 556 SET_INT (get2u (pc)); 557 SET_INT (get1u (pc + 2)); 558 pc += 3; 559 break; 560 561 case op_jsr: 562 case op_ifeq: 563 case op_ifne: 564 case op_iflt: 565 case op_ifge: 566 case op_ifgt: 567 case op_ifle: 568 case op_if_icmpeq: 569 case op_if_icmpne: 570 case op_if_icmplt: 571 case op_if_icmpge: 572 case op_if_icmpgt: 573 case op_if_icmple: 574 case op_if_acmpeq: 575 case op_if_acmpne: 576 case op_ifnull: 577 case op_ifnonnull: 578 case op_goto: 579 { 580 int offset = get2s (pc); 581 pc += 2; 582 583 int new_pc = base_pc_val + offset; 584 585 bool orig_was_goto = opcode == op_goto; 586 587 // Thread jumps. We limit the loop count; this lets 588 // us avoid infinite loops if the bytecode contains 589 // such. `10' is arbitrary. 590 int count = 10; 591 while (codestart[new_pc] == op_goto && count-- > 0) 592 new_pc += get2s (&codestart[new_pc + 1]); 593 594 // If the jump takes us to a `return' instruction and 595 // the original branch was an unconditional goto, then 596 // we hoist the return. 597 opcode = (java_opcode) codestart[new_pc]; 598 if (orig_was_goto 599 && (opcode == op_ireturn || opcode == op_lreturn 600 || opcode == op_freturn || opcode == op_dreturn 601 || opcode == op_areturn || opcode == op_return)) 602 { 603 --next; 604 SET_INSN (insn_targets[opcode]); 605 } 606 else 607 SET_DATUM (&insns[pc_mapping[new_pc]]); 608 } 609 break; 610 611 case op_tableswitch: 612 { 613 while ((pc - codestart) % 4 != 0) 614 ++pc; 615 616 jint def = get4 (pc); 617 SET_DATUM (&insns[pc_mapping[base_pc_val + def]]); 618 pc += 4; 619 620 int low = get4 (pc); 621 SET_INT (low); 622 pc += 4; 623 int high = get4 (pc); 624 SET_INT (high); 625 pc += 4; 626 627 for (int i = low; i <= high; ++i) 628 { 629 SET_DATUM (&insns[pc_mapping[base_pc_val + get4 (pc)]]); 630 pc += 4; 631 } 632 } 633 break; 634 635 case op_lookupswitch: 636 { 637 while ((pc - codestart) % 4 != 0) 638 ++pc; 639 640 jint def = get4 (pc); 641 SET_DATUM (&insns[pc_mapping[base_pc_val + def]]); 642 pc += 4; 643 644 jint npairs = get4 (pc); 645 pc += 4; 646 SET_INT (npairs); 647 648 while (npairs-- > 0) 649 { 650 jint match = get4 (pc); 651 jint offset = get4 (pc + 4); 652 SET_INT (match); 653 SET_DATUM (&insns[pc_mapping[base_pc_val + offset]]); 654 pc += 8; 655 } 656 } 657 break; 658 659 case op_invokeinterface: 660 { 661 jint index = get2u (pc); 662 pc += 2; 663 // We ignore the next two bytes. 664 pc += 2; 665 SET_INT (index); 666 } 667 break; 668 669 case op_wide: 670 { 671 opcode = (java_opcode) get1u (pc); 672 pc += 1; 673 jint val = get2u (pc); 674 pc += 2; 675 676 // We implement narrow and wide instructions using the 677 // same code in the interpreter. So we rewrite the 678 // instruction slot here. 679 if (! first_pass) 680 insns[next - 1].insn = (void *) insn_targets[opcode]; 681 SET_INT (val); 682 683 if (opcode == op_iinc) 684 { 685 SET_INT (get2s (pc)); 686 pc += 2; 687 } 688 } 689 break; 690 691 case op_jsr_w: 692 case op_goto_w: 693 { 694 jint offset = get4 (pc); 695 pc += 4; 696 SET_DATUM (&insns[pc_mapping[base_pc_val + offset]]); 697 } 698 break; 699 700 // Some "can't happen" cases that we include for 701 // error-checking purposes. 702 case op_putfield_1: 703 case op_putfield_2: 704 case op_putfield_4: 705 case op_putfield_8: 706 case op_putfield_a: 707 case op_putstatic_1: 708 case op_putstatic_2: 709 case op_putstatic_4: 710 case op_putstatic_8: 711 case op_putstatic_a: 712 case op_getfield_1: 713 case op_getfield_2s: 714 case op_getfield_2u: 715 case op_getfield_4: 716 case op_getfield_8: 717 case op_getfield_a: 718 case op_getstatic_1: 719 case op_getstatic_2s: 720 case op_getstatic_2u: 721 case op_getstatic_4: 722 case op_getstatic_8: 723 case op_getstatic_a: 724 default: 725 // Fail somehow. 726 break; 727 } 728 } 729 } 730 731 // Now update exceptions. 732 _Jv_InterpException *exc = exceptions (); 733 for (int i = 0; i < exc_count; ++i) 734 { 735 exc[i].start_pc.p = &insns[pc_mapping[exc[i].start_pc.i]]; 736 exc[i].end_pc.p = &insns[pc_mapping[exc[i].end_pc.i]]; 737 exc[i].handler_pc.p = &insns[pc_mapping[exc[i].handler_pc.i]]; 738 jclass handler = (_Jv_ResolvePoolEntry (defining_class, 739 exc[i].handler_type.i)).clazz; 740 exc[i].handler_type.p = handler; 741 } 742 743 prepared = insns; 744 } 745 #endif /* DIRECT_THREADED */ 746 747 // This function exists so that the stack-tracing code can find the 748 // boundaries of the interpreter. 749 void 750 _Jv_StartOfInterpreter (void) 751 { 752 } 753 754 void 755 _Jv_InterpMethod::run (void *retp, ffi_raw *args) 756 { 757 using namespace java::lang::reflect; 758 759 // FRAME_DESC registers this particular invocation as the top-most 760 // interpreter frame. This lets the stack tracing code (for 761 // Throwable) print information about the method being interpreted 762 // rather than about the interpreter itself. FRAME_DESC has a 763 // destructor so it cleans up automatically when the interpreter 764 // returns. 765 java::lang::Thread *thread = java::lang::Thread::currentThread(); 766 _Jv_MethodChain frame_desc (this, 767 (_Jv_MethodChain **) &thread->interp_frame); 768 769 _Jv_word stack[max_stack]; 770 _Jv_word *sp = stack; 771 772 _Jv_word locals[max_locals]; 234 773 235 774 /* Go straight at it! the ffi raw format matches the internal … … 238 777 memcpy ((void*) locals, (void*) args, args_raw_size); 239 778 240 next_segment: 241 242 jobject ex = NULL; 243 244 try 245 { 246 continue1 (inv); 247 } 248 catch (java::lang::Throwable *ex2) 249 { 250 ex = ex2; 251 } 252 253 if (ex == 0) // no exception... 254 { 255 /* define sp locally, so the POP? macros will pick it up */ 256 _Jv_word *sp = inv->sp; 257 int rtype = cif->rtype->type; 258 259 if (rtype == FFI_TYPE_POINTER) 260 { 261 jobject r = POPA(); 262 *(jobject*) retp = r; 263 return 0; 264 } 265 else if (rtype == FFI_TYPE_SINT32) 266 { 267 jint r = POPI(); 268 *(jint*)retp = r; 269 return 0; 270 } 271 else if (rtype == FFI_TYPE_VOID) 272 { 273 return 0; 274 } 275 else switch (rtype) 276 { 277 case FFI_TYPE_FLOAT: 278 { 279 jfloat r = POPF(); 280 *(jfloat*)retp = r; 281 return 0; 282 } 283 284 case FFI_TYPE_DOUBLE: 285 { 286 jdouble r = POPD(); 287 *(jdouble*)retp = r; 288 return 0; 289 } 290 291 case FFI_TYPE_UINT8: 292 case FFI_TYPE_UINT16: 293 case FFI_TYPE_UINT32: 294 case FFI_TYPE_SINT8: 295 case FFI_TYPE_SINT16: 296 { 297 jint r = POPI(); 298 *(jint*)retp = r; 299 return 0; 300 } 301 302 case FFI_TYPE_SINT64: 303 { 304 jlong r = POPL(); 305 *(jlong*)retp = r; 306 return 0; 307 } 308 309 default: 310 throw_internal_error ("unknown return type"); 311 } 312 } 313 314 /** handle an exception */ 315 if ( find_exception (ex, inv) ) 316 goto next_segment; 317 318 return ex; 319 } 320 321 #define SAVE_PC inv->pc = pc 322 323 bool _Jv_InterpMethod::find_exception (jobject ex, 324 _Jv_InterpMethodInvocation *inv) 325 { 326 // We subtract one because the PC was incremented before it was 327 // saved. 328 int logical_pc = inv->pc - 1 - bytecode (); 329 _Jv_InterpException *exc = exceptions (); 330 jclass exc_class = ex->getClass (); 331 332 for (int i = 0; i < exc_count; i++) 333 { 334 if (exc[i].start_pc <= logical_pc && logical_pc < exc[i].end_pc) 335 { 336 jclass handler; 337 338 if (exc[i].handler_type != 0) 339 handler = (_Jv_ResolvePoolEntry (defining_class, 340 exc[i].handler_type)).clazz; 341 else 342 handler = NULL; 343 344 if (handler==NULL || handler->isAssignableFrom (exc_class)) 345 { 346 inv->pc = bytecode () + exc[i].handler_pc; 347 inv->sp = inv->stack_base (); // reset stack 348 (inv->sp++)->o = ex; // push exception 349 return true; 350 } 351 } 352 } 353 return false; 354 } 355 356 void _Jv_InterpMethod::run_normal (ffi_cif* cif, 357 void* ret, 358 ffi_raw * args, 359 void* __this) 360 { 361 _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this; 362 363 // we do the alloca of the method invocation here, to allow the method 364 // "run" ro be inlined. Otherwise gcc will ignore the inline directive. 365 int storage_size = _this->max_stack+_this->max_locals; 366 _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*) 367 __builtin_alloca (sizeof (_Jv_InterpMethodInvocation) 368 + storage_size * sizeof (_Jv_word)); 369 370 jobject ex = _this->run (cif, ret, args, inv); 371 if (ex != 0) throw static_cast<jthrowable>(ex); 372 } 373 374 void _Jv_InterpMethod::run_synch_object (ffi_cif* cif, 375 void* ret, 376 ffi_raw * args, 377 void* __this) 378 { 379 _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this; 380 jobject rcv = (jobject)args[0].ptr; 381 382 int storage_size = _this->max_stack+_this->max_locals; 383 _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*) 384 __builtin_alloca (sizeof (_Jv_InterpMethodInvocation) 385 + storage_size * sizeof (_Jv_word)); 386 387 _Jv_MonitorEnter (rcv); 388 jobject ex = _this->run (cif, ret, args, inv); 389 _Jv_MonitorExit (rcv); 390 391 if (ex != 0) throw static_cast<jthrowable>(ex); 392 } 393 394 void _Jv_InterpMethod::run_synch_class (ffi_cif* cif, 395 void* ret, 396 ffi_raw * args, 397 void* __this) 398 { 399 _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this; 400 jclass sync = _this->defining_class; 401 402 int storage_size = _this->max_stack+_this->max_locals; 403 _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*) 404 __builtin_alloca (sizeof (_Jv_InterpMethodInvocation) 405 + storage_size * sizeof (_Jv_word)); 406 407 _Jv_MonitorEnter (sync); 408 jobject ex = _this->run (cif, ret, args, inv); 409 _Jv_MonitorExit (sync); 410 411 if (ex != 0) throw static_cast<jthrowable>(ex); 412 } 413 414 /* 415 This proceeds execution, as designated in "inv". If an exception 416 happens, then it is simply thrown, and handled in Java. Thus, the pc 417 needs to be stored in the inv->pc at all times, so we can figure 418 out which handler (if any) to invoke. 419 420 One design issue, which I have not completely considered, is if it 421 should be possible to have interpreted classes linked in! Seldom used 422 (or non-critical) classes could reasonably be interpreted. 423 */ 424 425 426 void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv) 427 { 428 using namespace java::lang::reflect; 429 430 _Jv_word *sp = inv->sp; 431 unsigned char *pc = inv->pc; 432 _Jv_word *locals = inv->local_base (); 433 434 _Jv_word *pool_data = defining_class->constants.data; 435 436 /* these two are used in the invokeXXX instructions */ 779 _Jv_word *pool_data = defining_class->constants.data; 780 781 /* These three are temporaries for common code used by several 782 instructions. */ 437 783 void (*fun)(); 438 784 _Jv_ResolvedMethod* rmeth; 785 int tmpval; 439 786 440 787 #define INSN_LABEL(op) &&insn_##op 441 #define GOTO_INSN(op) goto *(insn_target[op])442 788 443 789 static const void *const insn_target[] = … … 629 975 INSN_LABEL(invokestatic), 630 976 INSN_LABEL(invokeinterface), 631 0, /* op_xxxunusedxxx1,*/977 0, /* Unused. */ 632 978 INSN_LABEL(new), 633 979 INSN_LABEL(newarray), … … 639 985 INSN_LABEL(monitorenter), 640 986 INSN_LABEL(monitorexit), 987 #ifdef DIRECT_THREADED 988 0, // wide 989 #else 641 990 INSN_LABEL(wide), 991 #endif 642 992 INSN_LABEL(multianewarray), 643 993 INSN_LABEL(ifnull), … … 645 995 INSN_LABEL(goto_w), 646 996 INSN_LABEL(jsr_w), 997 0 647 998 }; 648 999 649 /* If the macro INLINE_SWITCH is not defined, then the main loop 650 operates as one big (normal) switch statement. If it is defined, 651 then the case selection is performed `inline' in the end of the 652 code for each case. The latter saves a native branch instruction 653 for each java-instruction, but expands the code size somewhat. 654 655 NOTE: On i386 defining INLINE_SWITCH improves over all 656 performance approximately seven percent, but it may be different 657 for other machines. At some point, this may be made into a proper 658 configuration parameter. */ 659 660 #define INLINE_SWITCH 661 662 #ifdef INLINE_SWITCH 663 664 #define NEXT_INSN do { GOTO_INSN(*pc++); } while (0) 665 666 667 NEXT_INSN; 1000 pc_t pc; 1001 1002 #ifdef DIRECT_THREADED 1003 1004 #define NEXT_INSN goto *((pc++)->insn) 1005 #define INTVAL() ((pc++)->int_val) 1006 #define AVAL() ((pc++)->datum) 1007 1008 #define GET1S() INTVAL () 1009 #define GET2S() INTVAL () 1010 #define GET1U() INTVAL () 1011 #define GET2U() INTVAL () 1012 #define AVAL1U() AVAL () 1013 #define AVAL2U() AVAL () 1014 #define AVAL2UP() AVAL () 1015 #define SKIP_GOTO ++pc 1016 #define GOTO_VAL() (insn_slot *) pc->datum 1017 #define PCVAL(unionval) unionval.p 1018 #define AMPAMP(label) &&label 1019 1020 // Compile if we must. 1021 if (prepared == NULL) 1022 compile (insn_target); 1023 pc = (insn_slot *) prepared; 1024 668 1025 #else 669 1026 670 #define NEXT_INSN goto next_insn 671 672 next_insn: 673 GOTO_INSN (*pc++); 674 675 #endif 676 677 /* The first few instructions here are ordered according to their 678 frequency, in the hope that this will improve code locality a 679 little. */ 680 681 insn_aload_0: // 0x2a 682 LOADA(0); 683 NEXT_INSN; 684 685 insn_iload: // 0x15 686 LOADI (get1u (pc++)); 687 NEXT_INSN; 688 689 insn_iload_1: // 0x1b 1027 #define NEXT_INSN goto *(insn_target[*pc++]) 1028 1029 #define GET1S() get1s (pc++) 1030 #define GET2S() (pc += 2, get2s (pc- 2)) 1031 #define GET1U() get1u (pc++) 1032 #define GET2U() (pc += 2, get2u (pc - 2)) 1033 #define AVAL1U() ({ int index = get1u (pc++); pool_data[index].o; }) 1034 #define AVAL2U() ({ int index = get2u (pc); pc += 2; pool_data[index].o; }) 1035 #define AVAL2UP() ({ int index = get2u (pc); pc += 2; &pool_data[index]; }) 1036 #define SKIP_GOTO pc += 2 1037 #define GOTO_VAL() pc - 1 + get2s (pc) 1038 #define PCVAL(unionval) unionval.i 1039 #define AMPAMP(label) NULL 1040 1041 pc = bytecode (); 1042 1043 #endif /* DIRECT_THREADED */ 1044 1045 #define TAKE_GOTO pc = GOTO_VAL () 1046 1047 try 1048 { 1049 // We keep nop around. It is used if we're interpreting the 1050 // bytecodes and not doing direct threading. 1051 insn_nop: 1052 NEXT_INSN; 1053 1054 /* The first few instructions here are ordered according to their 1055 frequency, in the hope that this will improve code locality a 1056 little. */ 1057 1058 insn_aload_0: // 0x2a 1059 LOADA (0); 1060 NEXT_INSN; 1061 1062 insn_iload: // 0x15 1063 LOADI (GET1U ()); 1064 NEXT_INSN; 1065 1066 insn_iload_1: // 0x1b 690 1067 LOADI (1); 691 1068 NEXT_INSN; 692 1069 693 insn_invokevirtual: // 0xb6 694 SAVE_PC; 695 { 696 int index = get2u (pc); pc += 2; 1070 insn_invokevirtual: // 0xb6 1071 { 1072 int index = GET2U (); 697 1073 698 1074 /* _Jv_ResolvePoolEntry returns immediately if the value already … … 720 1096 { 721 1097 jobject rcv = sp[0].o; 722 _Jv_VTable *table = *(_Jv_VTable**) rcv;723 fun = (void (*)()) table->get_method (rmeth->vtable_index);1098 _Jv_VTable *table = *(_Jv_VTable**) rcv; 1099 fun = (void (*)()) table->get_method (rmeth->vtable_index); 724 1100 } 1101 1102 #ifdef DIRECT_THREADED 1103 // Rewrite instruction so that we use a faster pre-resolved 1104 // method. 1105 pc[-2].insn = &&invokevirtual_resolved; 1106 pc[-1].datum = rmeth; 1107 #endif /* DIRECT_THREADED */ 725 1108 } 726 1109 goto perform_invoke; 727 1110 728 perform_invoke: 1111 #ifdef DIRECT_THREADED 1112 invokevirtual_resolved: 1113 { 1114 rmeth = (_Jv_ResolvedMethod *) AVAL (); 1115 sp -= rmeth->stack_item_count; 1116 // We don't use NULLCHECK here because we can't rely on that 1117 // working if the method is final. So instead we do an 1118 // explicit test. 1119 if (! sp[0].o) 1120 throw new java::lang::NullPointerException; 1121 1122 if (rmeth->vtable_index == -1) 1123 { 1124 // final methods do not appear in the vtable, 1125 // if it does not appear in the superclass. 1126 fun = (void (*)()) rmeth->method->ncode; 1127 } 1128 else 1129 { 1130 jobject rcv = sp[0].o; 1131 _Jv_VTable *table = *(_Jv_VTable**) rcv; 1132 fun = (void (*)()) table->get_method (rmeth->vtable_index); 1133 } 1134 } 1135 goto perform_invoke; 1136 #endif /* DIRECT_THREADED */ 1137 1138 perform_invoke: 729 1139 { 730 1140 /* here goes the magic again... */ … … 758 1168 /* skip */ 759 1169 } 760 else switch (rtype)1170 else 761 1171 { 762 case FFI_TYPE_SINT8: 763 { 764 jbyte value = (*(jint*)&rvalue) & 0xff; 765 PUSHI (value); 766 } 767 break; 768 769 case FFI_TYPE_SINT16: 770 { 771 jshort value = (*(jint*)&rvalue) & 0xffff; 772 PUSHI (value); 773 } 774 break; 775 776 case FFI_TYPE_UINT16: 777 { 778 jint value = (*(jint*)&rvalue) & 0xffff; 779 PUSHI (value); 780 } 781 break; 782 783 case FFI_TYPE_FLOAT: 784 PUSHF (*(jfloat*)&rvalue); 785 break; 786 787 case FFI_TYPE_DOUBLE: 788 PUSHD (rvalue); 789 break; 790 791 case FFI_TYPE_SINT64: 792 PUSHL (*(jlong*)&rvalue); 793 break; 794 795 default: 796 throw_internal_error ("unknown return type in invokeXXX"); 1172 switch (rtype) 1173 { 1174 case FFI_TYPE_SINT8: 1175 { 1176 jbyte value = (*(jint*)&rvalue) & 0xff; 1177 PUSHI (value); 1178 } 1179 break; 1180 1181 case FFI_TYPE_SINT16: 1182 { 1183 jshort value = (*(jint*)&rvalue) & 0xffff; 1184 PUSHI (value); 1185 } 1186 break; 1187 1188 case FFI_TYPE_UINT16: 1189 { 1190 jint value = (*(jint*)&rvalue) & 0xffff; 1191 PUSHI (value); 1192 } 1193 break; 1194 1195 case FFI_TYPE_FLOAT: 1196 PUSHF (*(jfloat*)&rvalue); 1197 break; 1198 1199 case FFI_TYPE_DOUBLE: 1200 PUSHD (rvalue); 1201 break; 1202 1203 case FFI_TYPE_SINT64: 1204 PUSHL (*(jlong*)&rvalue); 1205 break; 1206 1207 default: 1208 throw_internal_error ("unknown return type in invokeXXX"); 1209 } 797 1210 } 798 799 } 800 NEXT_INSN; 801 802 803 insn_nop: 804 NEXT_INSN; 805 806 insn_aconst_null: 1211 } 1212 NEXT_INSN; 1213 1214 insn_aconst_null: 807 1215 PUSHA (NULL); 808 1216 NEXT_INSN; 809 1217 810 1218 insn_iconst_m1: 811 1219 PUSHI (-1); 812 1220 NEXT_INSN; 813 1221 814 1222 insn_iconst_0: 815 1223 PUSHI (0); 816 1224 NEXT_INSN; 817 1225 818 1226 insn_iconst_1: 819 1227 PUSHI (1); 820 1228 NEXT_INSN; 821 1229 822 1230 insn_iconst_2: 823 1231 PUSHI (2); 824 1232 NEXT_INSN; 825 1233 826 1234 insn_iconst_3: 827 1235 PUSHI (3); 828 1236 NEXT_INSN; 829 1237 830 1238 insn_iconst_4: 831 1239 PUSHI (4); 832 1240 NEXT_INSN; 833 1241 834 1242 insn_iconst_5: 835 1243 PUSHI (5); 836 1244 NEXT_INSN; 837 1245 838 1246 insn_lconst_0: 839 1247 PUSHL (0); 840 1248 NEXT_INSN; 841 1249 842 1250 insn_lconst_1: 843 1251 PUSHL (1); 844 1252 NEXT_INSN; 845 1253 846 1254 insn_fconst_0: 847 1255 PUSHF (0); 848 1256 NEXT_INSN; 849 1257 850 1258 insn_fconst_1: 851 1259 PUSHF (1); 852 1260 NEXT_INSN; 853 1261 854 1262 insn_fconst_2: 855 1263 PUSHF (2); 856 1264 NEXT_INSN; 857 1265 858 1266 insn_dconst_0: 859 1267 PUSHD (0); 860 1268 NEXT_INSN; 861 1269 862 1270 insn_dconst_1: 863 1271 PUSHD (1); 864 1272 NEXT_INSN; 865 1273 866 insn_bipush: 867 PUSHI (get1s(pc++)); 868 NEXT_INSN; 869 870 insn_sipush: 871 PUSHI (get2s(pc)); pc += 2; 872 NEXT_INSN; 873 874 insn_ldc: 875 { 876 int index = get1u (pc++); 877 PUSHA(pool_data[index].o); 878 } 879 NEXT_INSN; 880 881 insn_ldc_w: 882 { 883 int index = get2u (pc); pc += 2; 884 PUSHA(pool_data[index].o); 885 } 886 NEXT_INSN; 887 888 insn_ldc2_w: 889 { 890 int index = get2u (pc); pc += 2; 891 memcpy (sp, &pool_data[index], 2*sizeof (_Jv_word)); 1274 insn_bipush: 1275 // For direct threaded, bipush and sipush are the same. 1276 #ifndef DIRECT_THREADED 1277 PUSHI (GET1S ()); 1278 NEXT_INSN; 1279 #endif /* DIRECT_THREADED */ 1280 insn_sipush: 1281 PUSHI (GET2S ()); 1282 NEXT_INSN; 1283 1284 insn_ldc: 1285 // For direct threaded, ldc and ldc_w are the same. 1286 #ifndef DIRECT_THREADED 1287 PUSHA ((jobject) AVAL1U ()); 1288 NEXT_INSN; 1289 #endif /* DIRECT_THREADED */ 1290 insn_ldc_w: 1291 PUSHA ((jobject) AVAL2U ()); 1292 NEXT_INSN; 1293 1294 insn_ldc2_w: 1295 { 1296 void *where = AVAL2UP (); 1297 memcpy (sp, where, 2*sizeof (_Jv_word)); 892 1298 sp += 2; 893 1299 } 894 1300 NEXT_INSN; 895 1301 896 897 LOADL ( get1u (pc++));898 NEXT_INSN; 899 900 901 LOADF ( get1u (pc++));902 NEXT_INSN; 903 904 905 LOADD ( get1u (pc++));906 NEXT_INSN; 907 908 909 LOADA ( get1u (pc++));910 NEXT_INSN; 911 912 1302 insn_lload: 1303 LOADL (GET1U ()); 1304 NEXT_INSN; 1305 1306 insn_fload: 1307 LOADF (GET1U ()); 1308 NEXT_INSN; 1309 1310 insn_dload: 1311 LOADD (GET1U ()); 1312 NEXT_INSN; 1313 1314 insn_aload: 1315 LOADA (GET1U ()); 1316 NEXT_INSN; 1317 1318 insn_iload_0: 913 1319 LOADI (0); 914 1320 NEXT_INSN; 915 1321 916 1322 insn_iload_2: 917 1323 LOADI (2); 918 1324 NEXT_INSN; 919 1325 920 1326 insn_iload_3: 921 1327 LOADI (3); 922 1328 NEXT_INSN; 923 1329 924 1330 insn_lload_0: 925 1331 LOADL (0); 926 1332 NEXT_INSN; 927 1333 928 1334 insn_lload_1: 929 1335 LOADL (1); 930 1336 NEXT_INSN; 931 1337 932 1338 insn_lload_2: 933 1339 LOADL (2); 934 1340 NEXT_INSN; 935 1341 936 1342 insn_lload_3: 937 1343 LOADL (3); 938 1344 NEXT_INSN; 939 1345 940 1346 insn_fload_0: 941 1347 LOADF (0); 942 1348 NEXT_INSN; 943 1349 944 1350 insn_fload_1: 945 1351 LOADF (1); 946 1352 NEXT_INSN; 947 1353 948 1354 insn_fload_2: 949 1355 LOADF (2); 950 1356 NEXT_INSN; 951 1357 952 1358 insn_fload_3: 953 1359 LOADF (3); 954 1360 NEXT_INSN; 955 1361 956 1362 insn_dload_0: 957 1363 LOADD (0); 958 1364 NEXT_INSN; 959 1365 960 1366 insn_dload_1: 961 1367 LOADD (1); 962 1368 NEXT_INSN; 963 1369 964 1370 insn_dload_2: 965 1371 LOADD (2); 966 1372 NEXT_INSN; 967 1373 968 1374 insn_dload_3: 969 1375 LOADD (3); 970 1376 NEXT_INSN; 971 1377 972 1378 insn_aload_1: 973 1379 LOADA(1); 974 1380 NEXT_INSN; 975 1381 976 1382 insn_aload_2: 977 1383 LOADA(2); 978 1384 NEXT_INSN; 979 1385 980 1386 insn_aload_3: 981 1387 LOADA(3); 982 1388 NEXT_INSN; 983 1389 984 1390 insn_iaload: 985 1391 { 986 1392 jint index = POPI(); … … 992 1398 NEXT_INSN; 993 1399 994 1400 insn_laload: 995 1401 { 996 1402 jint index = POPI(); … … 1002 1408 NEXT_INSN; 1003 1409 1004 1410 insn_faload: 1005 1411 { 1006 1412 jint index = POPI(); … … 1012 1418 NEXT_INSN; 1013 1419 1014 1420 insn_daload: 1015 1421 { 1016 1422 jint index = POPI(); … … 1022 1428 NEXT_INSN; 1023 1429 1024 1430 insn_aaload: 1025 1431 { 1026 1432 jint index = POPI(); … … 1032 1438 NEXT_INSN; 1033 1439 1034 1440 insn_baload: 1035 1441 { 1036 1442 jint index = POPI(); … … 1042 1448 NEXT_INSN; 1043 1449 1044 1450 insn_caload: 1045 1451 { 1046 1452 jint index = POPI(); … … 1052 1458 NEXT_INSN; 1053 1459 1054 1460 insn_saload: 1055 1461 { 1056 1462 jint index = POPI(); … … 1062 1468 NEXT_INSN; 1063 1469 1064 1065 STOREI ( get1u (pc++));1066 NEXT_INSN; 1067 1068 1069 STOREL ( get1u (pc++));1070 NEXT_INSN; 1071 1072 1073 STOREF ( get1u (pc++));1074 NEXT_INSN; 1075 1076 1077 STORED ( get1u (pc++));1078 NEXT_INSN; 1079 1080 1081 STOREA ( get1u (pc++));1082 NEXT_INSN; 1083 1084 1470 insn_istore: 1471 STOREI (GET1U ()); 1472 NEXT_INSN; 1473 1474 insn_lstore: 1475 STOREL (GET1U ()); 1476 NEXT_INSN; 1477 1478 insn_fstore: 1479 STOREF (GET1U ()); 1480 NEXT_INSN; 1481 1482 insn_dstore: 1483 STORED (GET1U ()); 1484 NEXT_INSN; 1485 1486 insn_astore: 1487 STOREA (GET1U ()); 1488 NEXT_INSN; 1489 1490 insn_istore_0: 1085 1491 STOREI (0); 1086 1492 NEXT_INSN; 1087 1493 1088 1494 insn_istore_1: 1089 1495 STOREI (1); 1090 1496 NEXT_INSN; 1091 1497 1092 1498 insn_istore_2: 1093 1499 STOREI (2); 1094 1500 NEXT_INSN; 1095 1501 1096 1502 insn_istore_3: 1097 1503 STOREI (3); 1098 1504 NEXT_INSN; 1099 1505 1100 1506 insn_lstore_0: 1101 1507 STOREL (0); 1102 1508 NEXT_INSN; 1103 1509 1104 1510 insn_lstore_1: 1105 1511 STOREL (1); 1106 1512 NEXT_INSN; 1107 1513 1108 1514 insn_lstore_2: 1109 1515 STOREL (2); 1110 1516 NEXT_INSN; 1111 1517 1112 1518 insn_lstore_3: 1113 1519 STOREL (3); 1114 1520 NEXT_INSN; 1115 1521 1116 1522 insn_fstore_0: 1117 1523 STOREF (0); 1118 1524 NEXT_INSN; 1119 1525 1120 1526 insn_fstore_1: 1121 1527 STOREF (1); 1122 1528 NEXT_INSN; 1123 1529 1124 1530 insn_fstore_2: 1125 1531 STOREF (2); 1126 1532 NEXT_INSN; 1127 1533 1128 1534 insn_fstore_3: 1129 1535 STOREF (3); 1130 1536 NEXT_INSN; 1131 1537 1132 1538 insn_dstore_0: 1133 1539 STORED (0); 1134 1540 NEXT_INSN; 1135 1541 1136 1542 insn_dstore_1: 1137 1543 STORED (1); 1138 1544 NEXT_INSN; 1139 1545 1140 1546 insn_dstore_2: 1141 1547 STORED (2); 1142 1548 NEXT_INSN; 1143 1549 1144 1550 insn_dstore_3: 1145 1551 STORED (3); 1146 1552 NEXT_INSN; 1147 1553 1148 1554 insn_astore_0: 1149 1555 STOREA(0); 1150 1556 NEXT_INSN; 1151 1557 1152 1558 insn_astore_1: 1153 1559 STOREA(1); 1154 1560 NEXT_INSN; 1155 1561 1156 1562 insn_astore_2: 1157 1563 STOREA(2); 1158 1564 NEXT_INSN; 1159 1565 1160 1566 insn_astore_3: 1161 1567 STOREA(3); 1162 1568 NEXT_INSN; 1163 1569 1164 1570 insn_iastore: 1165 1571 { 1166 1572 jint value = POPI(); … … 1173 1579 NEXT_INSN; 1174 1580 1175 1581 insn_lastore: 1176 1582 { 1177 1583 jlong value = POPL(); … … 1184 1590 NEXT_INSN; 1185 1591 1186 1592 insn_fastore: 1187 1593 { 1188 1594 jfloat value = POPF(); … … 1195 1601 NEXT_INSN; 1196 1602 1197 1603 insn_dastore: 1198 1604 { 1199 1605 jdouble value = POPD(); … … 1206 1612 NEXT_INSN; 1207 1613 1208 1614 insn_aastore: 1209 1615 { 1210 1616 jobject value = POPA(); … … 1218 1624 NEXT_INSN; 1219 1625 1220 1626 insn_bastore: 1221 1627 { 1222 1628 jbyte value = (jbyte) POPI(); … … 1229 1635 NEXT_INSN; 1230 1636 1231 1637 insn_castore: 1232 1638 { 1233 1639 jchar value = (jchar) POPI(); … … 1240 1646 NEXT_INSN; 1241 1647 1242 1648 insn_sastore: 1243 1649 { 1244 1650 jshort value = (jshort) POPI(); … … 1251 1657 NEXT_INSN; 1252 1658 1253 1659 insn_pop: 1254 1660 sp -= 1; 1255 1661 NEXT_INSN; 1256 1662 1257 1663 insn_pop2: 1258 1664 sp -= 2; 1259 1665 NEXT_INSN; 1260 1666 1261 1667 insn_dup: 1262 1668 sp[0] = sp[-1]; 1263 1669 sp += 1; 1264 1670 NEXT_INSN; 1265 1671 1266 1672 insn_dup_x1: 1267 1673 dupx (sp, 1, 1); sp+=1; 1268 1674 NEXT_INSN; 1269 1675 1270 1676 insn_dup_x2: 1271 1677 dupx (sp, 1, 2); sp+=1; 1272 1678 NEXT_INSN; 1273 1679 1274 1680 insn_dup2: 1275 1681 sp[0] = sp[-2]; 1276 1682 sp[1] = sp[-1]; … … 1278 1684 NEXT_INSN; 1279 1685 1280 1686 insn_dup2_x1: 1281 1687 dupx (sp, 2, 1); sp+=2; 1282 1688 NEXT_INSN; 1283 1689 1284 1690 insn_dup2_x2: 1285 1691 dupx (sp, 2, 2); sp+=2; 1286 1692 NEXT_INSN; 1287 1693 1288 1694 insn_swap: 1289 1695 { 1290 1696 jobject tmp1 = POPA(); … … 1295 1701 NEXT_INSN; 1296 1702 1297 1703 insn_iadd: 1298 1704 BINOPI(+); 1299 1705 NEXT_INSN; 1300 1706 1301 1707 insn_ladd: 1302 1708 BINOPL(+); 1303 1709 NEXT_INSN; 1304 1710 1305 1711 insn_fadd: 1306 1712 BINOPF(+); 1307 1713 NEXT_INSN; 1308 1714 1309 1715 insn_dadd: 1310 1716 BINOPD(+); 1311 1717 NEXT_INSN; 1312 1718 1313 1719 insn_isub: 1314 1720 BINOPI(-); 1315 1721 NEXT_INSN; 1316 1722 1317 1723 insn_lsub: 1318 1724 BINOPL(-); 1319 1725 NEXT_INSN; 1320 1726 1321 1727 insn_fsub: 1322 1728 BINOPF(-); 1323 1729 NEXT_INSN; 1324 1730 1325 1731 insn_dsub: 1326 1732 BINOPD(-); 1327 1733 NEXT_INSN; 1328 1734 1329 1735 insn_imul: 1330 1736 BINOPI(*); 1331 1737 NEXT_INSN; 1332 1738 1333 1739 insn_lmul: 1334 1740 BINOPL(*); 1335 1741 NEXT_INSN; 1336 1742 1337 1743 insn_fmul: 1338 1744 BINOPF(*); 1339 1745 NEXT_INSN; 1340 1746 1341 1747 insn_dmul: 1342 1748 BINOPD(*); 1343 1749 NEXT_INSN; 1344 1750 1345 insn_idiv: 1346 SAVE_PC; 1751 insn_idiv: 1347 1752 { 1348 1753 jint value2 = POPI(); … … 1353 1758 NEXT_INSN; 1354 1759 1355 insn_ldiv: 1356 SAVE_PC; 1760 insn_ldiv: 1357 1761 { 1358 1762 jlong value2 = POPL(); … … 1363 1767 NEXT_INSN; 1364 1768 1365 1769 insn_fdiv: 1366 1770 { 1367 1771 jfloat value2 = POPF(); … … 1372 1776 NEXT_INSN; 1373 1777 1374 1778 insn_ddiv: 1375 1779 { 1376 1780 jdouble value2 = POPD(); … … 1381 1785 NEXT_INSN; 1382 1786 1383 insn_irem: 1384 SAVE_PC; 1787 insn_irem: 1385 1788 { 1386 1789 jint value2 = POPI(); … … 1391 1794 NEXT_INSN; 1392 1795 1393 insn_lrem: 1394 SAVE_PC; 1796 insn_lrem: 1395 1797 { 1396 1798 jlong value2 = POPL(); … … 1401 1803 NEXT_INSN; 1402 1804 1403 1805 insn_frem: 1404 1806 { 1405 1807 jfloat value2 = POPF(); … … 1410 1812 NEXT_INSN; 1411 1813 1412 1814 insn_drem: 1413 1815 { 1414 1816 jdouble value2 = POPD(); … … 1419 1821 NEXT_INSN; 1420 1822 1421 1823 insn_ineg: 1422 1824 { 1423 1825 jint value = POPI(); … … 1426 1828 NEXT_INSN; 1427 1829 1428 1830 insn_lneg: 1429 1831 { 1430 1832 jlong value = POPL(); … … 1433 1835 NEXT_INSN; 1434 1836 1435 1837 insn_fneg: 1436 1838 { 1437 1839 jfloat value = POPF(); … … 1440 1842 NEXT_INSN; 1441 1843 1442 1844 insn_dneg: 1443 1845 { 1444 1846 jdouble value = POPD(); … … 1447 1849 NEXT_INSN; 1448 1850 1449 1851 insn_ishl: 1450 1852 { 1451 1853 jint shift = (POPI() & 0x1f); … … 1455 1857 NEXT_INSN; 1456 1858 1457 1859 insn_lshl: 1458 1860 { 1459 1861 jint shift = (POPI() & 0x3f); … … 1463 1865 NEXT_INSN; 1464 1866 1465 1867 insn_ishr: 1466 1868 { 1467 1869 jint shift = (POPI() & 0x1f); … … 1471 1873 NEXT_INSN; 1472 1874 1473 1875 insn_lshr: 1474 1876 { 1475 1877 jint shift = (POPI() & 0x3f); … … 1479 1881 NEXT_INSN; 1480 1882 1481 1883 insn_iushr: 1482 1884 { 1483 1885 jint shift = (POPI() & 0x1f); 1484 unsigned long value =POPI();1886 UINT32 value = (UINT32) POPI(); 1485 1887 PUSHI ((jint) (value >> shift)); 1486 1888 } 1487 1889 NEXT_INSN; 1488 1890 1489 1891 insn_lushr: 1490 1892 { 1491 1893 jint shift = (POPI() & 0x3f); … … 1495 1897 NEXT_INSN; 1496 1898 1497 1899 insn_iand: 1498 1900 BINOPI (&); 1499 1901 NEXT_INSN; 1500 1902 1501 1903 insn_land: 1502 1904 BINOPL (&); 1503 1905 NEXT_INSN; 1504 1906 1505 1907 insn_ior: 1506 1908 BINOPI (|); 1507 1909 NEXT_INSN; 1508 1910 1509 1911 insn_lor: 1510 1912 BINOPL (|); 1511 1913 NEXT_INSN; 1512 1914 1513 1915 insn_ixor: 1514 1916 BINOPI (^); 1515 1917 NEXT_INSN; 1516 1918 1517 1919 insn_lxor: 1518 1920 BINOPL (^); 1519 1921 NEXT_INSN; 1520 1922 1521 1522 { 1523 jint index = get1u (pc++);1524 jint amount = get1s (pc++);1923 insn_iinc: 1924 { 1925 jint index = GET1U (); 1926 jint amount = GET1S (); 1525 1927 locals[index].i += amount; 1526 1928 } 1527 1929 NEXT_INSN; 1528 1930 1529 1931 insn_i2l: 1530 1932 {jlong value = POPI(); PUSHL (value);} 1531 1933 NEXT_INSN; 1532 1934 1533 1935 insn_i2f: 1534 1936 {jfloat value = POPI(); PUSHF (value);} 1535 1937 NEXT_INSN; 1536 1938 1537 1939 insn_i2d: 1538 1940 {jdouble value = POPI(); PUSHD (value);} 1539 1941 NEXT_INSN; 1540 1942 1541 1943 insn_l2i: 1542 1944 {jint value = POPL(); PUSHI (value);} 1543 1945 NEXT_INSN; 1544 1946 1545 1947 insn_l2f: 1546 1948 {jfloat value = POPL(); PUSHF (value);} 1547 1949 NEXT_INSN; 1548 1950 1549 1951 insn_l2d: 1550 1952 {jdouble value = POPL(); PUSHD (value);} 1551 1953 NEXT_INSN; 1552 1954 1553 1955 insn_f2i: 1554 1956 { 1555 1957 using namespace java::lang; … … 1559 1961 NEXT_INSN; 1560 1962 1561 1963 insn_f2l: 1562 1964 { 1563 1965 using namespace java::lang; … … 1567 1969 NEXT_INSN; 1568 1970 1569 1971 insn_f2d: 1570 1972 { jdouble value = POPF (); PUSHD(value); } 1571 1973 NEXT_INSN; 1572 1974 1573 1975 insn_d2i: 1574 1976 { 1575 1977 using namespace java::lang; … … 1579 1981 NEXT_INSN; 1580 1982 1581 1983 insn_d2l: 1582 1984 { 1583 1985 using namespace java::lang; … … 1587 1989 NEXT_INSN; 1588 1990 1589 1991 insn_d2f: 1590 1992 { jfloat value = POPD (); PUSHF(value); } 1591 1993 NEXT_INSN; 1592 1994 1593 1995 insn_i2b: 1594 1996 { jbyte value = POPI (); PUSHI(value); } 1595 1997 NEXT_INSN; 1596 1998 1597 1999 insn_i2c: 1598 2000 { jchar value = POPI (); PUSHI(value); } 1599 2001 NEXT_INSN; 1600 2002 1601 2003 insn_i2s: 1602 2004 { jshort value = POPI (); PUSHI(value); } 1603 2005 NEXT_INSN; 1604 2006 1605 2007 insn_lcmp: 1606 2008 { 1607 2009 jlong value2 = POPL (); … … 1616 2018 NEXT_INSN; 1617 2019 1618 insn_fcmpl: 1619 insn_fcmpg: 2020 insn_fcmpl: 2021 tmpval = -1; 2022 goto fcmp; 2023 2024 insn_fcmpg: 2025 tmpval = 1; 2026 2027 fcmp: 1620 2028 { 1621 2029 jfloat value2 = POPF (); … … 1627 2035 else if (value1 < value2) 1628 2036 PUSHI (-1); 1629 else if ((*(pc-1)) == op_fcmpg)1630 PUSHI (1);1631 2037 else 1632 PUSHI (-1); 1633 } 1634 NEXT_INSN; 1635 1636 insn_dcmpl: 1637 insn_dcmpg: 2038 PUSHI (tmpval); 2039 } 2040 NEXT_INSN; 2041 2042 insn_dcmpl: 2043 tmpval = 1; 2044 goto dcmp; 2045 2046 insn_dcmpg: 2047 tmpval = -1; 2048 2049 dcmp: 1638 2050 { 1639 2051 jdouble value2 = POPD (); … … 1645 2057 else if (value1 < value2) 1646 2058 PUSHI (-1); 1647 else if ((*(pc-1)) == op_dcmpg)1648 PUSHI (1);1649 2059 else 1650 PUSHI (-1); 1651 } 1652 NEXT_INSN; 1653 1654 insn_ifeq: 1655 { 1656 jint offset = get2s (pc); 2060 PUSHI (tmpval); 2061 } 2062 NEXT_INSN; 2063 2064 insn_ifeq: 2065 { 1657 2066 if (POPI() == 0) 1658 pc = pc-1+offset;2067 TAKE_GOTO; 1659 2068 else 1660 pc = pc+2; 1661 } 1662 NEXT_INSN; 1663 1664 insn_ifne: 1665 { 1666 jint offset = get2s (pc); 2069 SKIP_GOTO; 2070 } 2071 NEXT_INSN; 2072 2073 insn_ifne: 2074 { 1667 2075 if (POPI() != 0) 1668 pc = pc-1+offset;2076 TAKE_GOTO; 1669 2077 else 1670 pc = pc+2; 1671 } 1672 NEXT_INSN; 1673 1674 insn_iflt: 1675 { 1676 jint offset = get2s (pc); 2078 SKIP_GOTO; 2079 } 2080 NEXT_INSN; 2081 2082 insn_iflt: 2083 { 1677 2084 if (POPI() < 0) 1678 pc = pc-1+offset;2085 TAKE_GOTO; 1679 2086 else 1680 pc = pc+2; 1681 } 1682 NEXT_INSN; 1683 1684 insn_ifge: 1685 { 1686 jint offset = get2s (pc); 2087 SKIP_GOTO; 2088 } 2089 NEXT_INSN; 2090 2091 insn_ifge: 2092 { 1687 2093 if (POPI() >= 0) 1688 pc = pc-1+offset;2094 TAKE_GOTO; 1689 2095 else 1690 pc = pc+2; 1691 } 1692 NEXT_INSN; 1693 1694 insn_ifgt: 1695 { 1696 jint offset = get2s (pc); 2096 SKIP_GOTO; 2097 } 2098 NEXT_INSN; 2099 2100 insn_ifgt: 2101 { 1697 2102 if (POPI() > 0) 1698 pc = pc-1+offset;2103 TAKE_GOTO; 1699 2104 else 1700 pc = pc+2; 1701 } 1702 NEXT_INSN; 1703 1704 insn_ifle: 1705 { 1706 jint offset = get2s (pc); 2105 SKIP_GOTO; 2106 } 2107 NEXT_INSN; 2108 2109 insn_ifle: 2110 { 1707 2111 if (POPI() <= 0) 1708 pc = pc-1+offset;2112 TAKE_GOTO; 1709 2113 else 1710 pc = pc+2; 1711 } 1712 NEXT_INSN; 1713 1714 insn_if_icmpeq: 1715 { 1716 jint offset = get2s (pc); 2114 SKIP_GOTO; 2115 } 2116 NEXT_INSN; 2117 2118 insn_if_icmpeq: 2119 { 1717 2120 jint value2 = POPI(); 1718 2121 jint value1 = POPI(); 1719 2122 if (value1 == value2) 1720 pc = pc-1+offset;2123 TAKE_GOTO; 1721 2124 else 1722 pc = pc+2; 1723 } 1724 NEXT_INSN; 1725 1726 insn_if_icmpne: 1727 { 1728 jint offset = get2s (pc); 2125 SKIP_GOTO; 2126 } 2127 NEXT_INSN; 2128 2129 insn_if_icmpne: 2130 { 1729 2131 jint value2 = POPI(); 1730 2132 jint value1 = POPI(); 1731 2133 if (value1 != value2) 1732 pc = pc-1+offset;2134 TAKE_GOTO; 1733 2135 else 1734 pc = pc+2; 1735 } 1736 NEXT_INSN; 1737 1738 insn_if_icmplt: 1739 { 1740 jint offset = get2s (pc); 2136 SKIP_GOTO; 2137 } 2138 NEXT_INSN; 2139 2140 insn_if_icmplt: 2141 { 1741 2142 jint value2 = POPI(); 1742 2143 jint value1 = POPI(); 1743 2144 if (value1 < value2) 1744 pc = pc-1+offset;2145 TAKE_GOTO; 1745 2146 else 1746 pc = pc+2; 1747 } 1748 NEXT_INSN; 1749 1750 insn_if_icmpge: 1751 { 1752 jint offset = get2s (pc); 2147 SKIP_GOTO; 2148 } 2149 NEXT_INSN; 2150 2151 insn_if_icmpge: 2152 { 1753 2153 jint value2 = POPI(); 1754 2154 jint value1 = POPI(); 1755 2155 if (value1 >= value2) 1756 pc = pc-1+offset;2156 TAKE_GOTO; 1757 2157 else 1758 pc = pc+2; 1759 } 1760 NEXT_INSN; 1761 1762 insn_if_icmpgt: 1763 { 1764 jint offset = get2s (pc); 2158 SKIP_GOTO; 2159 } 2160 NEXT_INSN; 2161 2162 insn_if_icmpgt: 2163 { 1765 2164 jint value2 = POPI(); 1766 2165 jint value1 = POPI(); 1767 2166 if (value1 > value2) 1768 pc = pc-1+offset;2167 TAKE_GOTO; 1769 2168 else 1770 pc = pc+2; 1771 } 1772 NEXT_INSN; 1773 1774 insn_if_icmple: 1775 { 1776 jint offset = get2s (pc); 2169 SKIP_GOTO; 2170 } 2171 NEXT_INSN; 2172 2173 insn_if_icmple: 2174 { 1777 2175 jint value2 = POPI(); 1778 2176 jint value1 = POPI(); 1779 2177 if (value1 <= value2) 1780 pc = pc-1+offset;2178 TAKE_GOTO; 1781 2179 else 1782 pc = pc+2; 1783 } 1784 NEXT_INSN; 1785 1786 insn_if_acmpeq: 1787 { 1788 jint offset = get2s (pc); 2180 SKIP_GOTO; 2181 } 2182 NEXT_INSN; 2183 2184 insn_if_acmpeq: 2185 { 1789 2186 jobject value2 = POPA(); 1790 2187 jobject value1 = POPA(); 1791 2188 if (value1 == value2) 1792 pc = pc-1+offset;2189 TAKE_GOTO; 1793 2190 else 1794 pc = pc+2; 1795 } 1796 NEXT_INSN; 1797 1798 insn_if_acmpne: 1799 { 1800 jint offset = get2s (pc); 2191 SKIP_GOTO; 2192 } 2193 NEXT_INSN; 2194 2195 insn_if_acmpne: 2196 { 1801 2197 jobject value2 = POPA(); 1802 2198 jobject value1 = POPA(); 1803 2199 if (value1 != value2) 1804 pc = pc-1+offset;2200 TAKE_GOTO; 1805 2201 else 1806 pc = pc+2; 1807 } 1808 NEXT_INSN; 1809 1810 insn_goto: 1811 { 1812 jint offset = get2s (pc); 1813 pc = pc-1+offset; 1814 } 1815 NEXT_INSN; 1816 1817 insn_jsr: 1818 { 1819 unsigned char *base_pc = pc-1; 1820 jint offset = get2s (pc); pc += 2; 1821 PUSHA ((jobject)pc); 1822 pc = base_pc+offset; 1823 } 1824 NEXT_INSN; 1825 1826 insn_ret: 1827 { 1828 jint index = get1u (pc); 1829 pc = (unsigned char*) PEEKA (index); 1830 } 1831 NEXT_INSN; 1832 1833 insn_tableswitch: 1834 { 2202 SKIP_GOTO; 2203 } 2204 NEXT_INSN; 2205 2206 insn_goto_w: 2207 #ifndef DIRECT_THREADED 2208 // For direct threaded, goto and goto_w are the same. 2209 pc = pc - 1 + get4 (pc); 2210 NEXT_INSN; 2211 #endif /* DIRECT_THREADED */ 2212 insn_goto: 2213 TAKE_GOTO; 2214 NEXT_INSN; 2215 2216 insn_jsr_w: 2217 #ifndef DIRECT_THREADED 2218 // For direct threaded, jsr and jsr_w are the same. 2219 { 2220 pc_t next = pc - 1 + get4 (pc); 2221 pc += 4; 2222 PUSHA ((jobject) pc); 2223 pc = next; 2224 } 2225 NEXT_INSN; 2226 #endif /* DIRECT_THREADED */ 2227 insn_jsr: 2228 { 2229 pc_t next = GOTO_VAL(); 2230 SKIP_GOTO; 2231 PUSHA ((jobject) pc); 2232 pc = next; 2233 } 2234 NEXT_INSN; 2235 2236 insn_ret: 2237 { 2238 jint index = GET1U (); 2239 pc = (pc_t) PEEKA (index); 2240 } 2241 NEXT_INSN; 2242 2243 insn_tableswitch: 2244 { 2245 #ifdef DIRECT_THREADED 2246 void *def = (pc++)->datum; 2247 2248 int index = POPI(); 2249 2250 jint low = INTVAL (); 2251 jint high = INTVAL (); 2252 2253 if (index < low || index > high) 2254 pc = (insn_slot *) def; 2255 else 2256 pc = (insn_slot *) ((pc + index - low)->datum); 2257 #else 2258 pc_t base_pc = pc - 1; 2259 int index = POPI (); 2260 2261 pc_t base = (pc_t) bytecode (); 2262 while ((pc - base) % 4 != 0) 2263 ++pc; 2264 2265 jint def = get4 (pc); 2266 jint low = get4 (pc + 4); 2267 jint high = get4 (pc + 8); 2268 if (index < low || index > high) 2269 pc = base_pc + def; 2270 else 2271 pc = base_pc + get4 (pc + 4 * (index - low + 3)); 2272 #endif /* DIRECT_THREADED */ 2273 } 2274 NEXT_INSN; 2275 2276 insn_lookupswitch: 2277 { 2278 #ifdef DIRECT_THREADED 2279 void *def = (pc++)->insn; 2280 2281 int index = POPI(); 2282 2283 jint npairs = INTVAL (); 2284 2285 int max = npairs - 1; 2286 int min = 0; 2287 2288 // Simple binary search... 2289 while (min < max) 2290 { 2291 int half = (min + max) / 2; 2292 int match = pc[2 * half].int_val; 2293 2294 if (index == match) 2295 { 2296 // Found it. 2297 pc = (insn_slot *) pc[2 * half + 1].datum; 2298 NEXT_INSN; 2299 } 2300 else if (index < match) 2301 // We can use HALF - 1 here because we check again on 2302 // loop exit. 2303 max = half - 1; 2304 else 2305 // We can use HALF + 1 here because we check again on 2306 // loop exit. 2307 min = half + 1; 2308 } 2309 if (index == pc[2 * min].int_val) 2310 pc = (insn_slot *) pc[2 * min + 1].datum; 2311 else 2312 pc = (insn_slot *) def; 2313 #else 1835 2314 unsigned char *base_pc = pc-1; 1836 2315 int index = POPI(); … … 1838 2317 unsigned char* base = bytecode (); 1839 2318 while ((pc-base) % 4 != 0) 1840 pc++; 1841 1842 jint def = get4 (pc); 1843 jint low = get4 (pc+4); 1844 jint high = get4 (pc+8); 1845 1846 if (index < low || index > high) 1847 pc = base_pc + def; 1848 else 1849 pc = base_pc + get4 (pc+4*(index-low+3)); 1850 } 1851 NEXT_INSN; 1852 1853 insn_lookupswitch: 1854 { 1855 unsigned char *base_pc = pc-1; 1856 int index = POPI(); 1857 1858 unsigned char* base = bytecode (); 1859 while ((pc-base) % 4 != 0) 1860 pc++; 2319 ++pc; 1861 2320 1862 2321 jint def = get4 (pc); … … 1866 2325 int min = 0; 1867 2326 1868 // simple binary search...2327 // Simple binary search... 1869 2328 while (min < max) 1870 2329 { … … 1874 2333 if (index == match) 1875 2334 min = max = half; 1876 1877 2335 else if (index < match) 1878 max = half-1; 1879 2336 // We can use HALF - 1 here because we check again on 2337 // loop exit. 2338 max = half - 1; 1880 2339 else 1881 min = half+1; 2340 // We can use HALF + 1 here because we check again on 2341 // loop exit. 2342 min = half + 1; 1882 2343 } 1883 2344 … … 1886 2347 else 1887 2348 pc = base_pc + def; 1888 } 1889 NEXT_INSN; 1890 1891 /* on return, just save the sp and return to caller */ 1892 insn_ireturn: 1893 insn_lreturn: 1894 insn_freturn: 1895 insn_dreturn: 1896 insn_areturn: 1897 insn_return: 1898 inv->sp = sp; 2349 #endif /* DIRECT_THREADED */ 2350 } 2351 NEXT_INSN; 2352 2353 insn_areturn: 2354 *(jobject *) retp = POPA (); 1899 2355 return; 1900 2356 1901 insn_getstatic: 1902 SAVE_PC; 1903 { 1904 jint fieldref_index = get2u (pc); pc += 2; 2357 insn_lreturn: 2358 *(jlong *) retp = POPL (); 2359 return; 2360 2361 insn_freturn: 2362 *(jfloat *) retp = POPF (); 2363 return; 2364 2365 insn_dreturn: 2366 *(jdouble *) retp = POPD (); 2367 return; 2368 2369 insn_ireturn: 2370 *(jint *) retp = POPI (); 2371 return; 2372 2373 insn_return: 2374 return; 2375 2376 insn_getstatic: 2377 { 2378 jint fieldref_index = GET2U (); 1905 2379 _Jv_ResolvePoolEntry (defining_class, fieldref_index); 1906 2380 _Jv_Field *field = pool_data[fieldref_index].field; … … 1912 2386 jclass type = field->type; 1913 2387 2388 // We rewrite the instruction once we discover what it refers 2389 // to. 2390 void *newinsn = NULL; 1914 2391 if (type->isPrimitive ()) 1915 2392 { … … 1918 2395 case 1: 1919 2396 PUSHI (*(jbyte*) (field->u.addr)); 2397 newinsn = AMPAMP (getstatic_resolved_1); 1920 2398 break; 1921 2399 1922 2400 case 2: 1923 2401 if (type == JvPrimClass (char)) 1924 PUSHI(*(jchar*) (field->u.addr)); 2402 { 2403 PUSHI(*(jchar*) (field->u.addr)); 2404 newinsn = AMPAMP (getstatic_resolved_char); 2405 } 1925 2406 else 1926 PUSHI(*(jshort*) (field->u.addr)); 2407 { 2408 PUSHI(*(jshort*) (field->u.addr)); 2409 newinsn = AMPAMP (getstatic_resolved_short); 2410 } 1927 2411 break; 1928 2412 1929 2413 case 4: 1930 2414 PUSHI(*(jint*) (field->u.addr)); 2415 newinsn = AMPAMP (getstatic_resolved_4); 1931 2416 break; 1932 2417 1933 2418 case 8: 1934 2419 PUSHL(*(jlong*) (field->u.addr)); 2420 newinsn = AMPAMP (getstatic_resolved_8); 1935 2421 break; 1936 2422 } … … 1939 2425 { 1940 2426 PUSHA(*(jobject*) (field->u.addr)); 2427 newinsn = AMPAMP (getstatic_resolved_obj); 1941 2428 } 1942 } 1943 NEXT_INSN; 1944 1945 insn_getfield: 1946 SAVE_PC; 1947 { 1948 jint fieldref_index = get2u (pc); pc += 2; 2429 2430 #ifdef DIRECT_THREADED 2431 pc[-2].insn = newinsn; 2432 pc[-1].datum = field->u.addr; 2433 #endif /* DIRECT_THREADED */ 2434 } 2435 NEXT_INSN; 2436 2437 #ifdef DIRECT_THREADED 2438 getstatic_resolved_1: 2439 PUSHI (*(jbyte *) AVAL ()); 2440 NEXT_INSN; 2441 2442 getstatic_resolved_char: 2443 PUSHI (*(jchar *) AVAL ()); 2444 NEXT_INSN; 2445 2446 getstatic_resolved_short: 2447 PUSHI (*(jshort *) AVAL ()); 2448 NEXT_INSN; 2449 2450 getstatic_resolved_4: 2451 PUSHI (*(jint *) AVAL ()); 2452 NEXT_INSN; 2453 2454 getstatic_resolved_8: 2455 PUSHL (*(jlong *) AVAL ()); 2456 NEXT_INSN; 2457 2458 getstatic_resolved_obj: 2459 PUSHA (*(jobject *) AVAL ()); 2460 NEXT_INSN; 2461 #endif /* DIRECT_THREADED */ 2462 2463 insn_getfield: 2464 { 2465 jint fieldref_index = GET2U (); 1949 2466 _Jv_ResolvePoolEntry (defining_class, fieldref_index); 1950 2467 _Jv_Field *field = pool_data[fieldref_index].field; … … 1962 2479 NULLCHECK(obj); 1963 2480 2481 void *newinsn = NULL; 1964 2482 if (type->isPrimitive ()) 1965 2483 { … … 1968 2486 case 1: 1969 2487 PUSHI (*(jbyte*) ((char*)obj + field_offset)); 2488 newinsn = AMPAMP (getfield_resolved_1); 1970 2489 break; 1971 2490 1972 2491 case 2: 1973 2492 if (type == JvPrimClass (char)) 1974 PUSHI (*(jchar*) ((char*)obj + field_offset)); 2493 { 2494 PUSHI (*(jchar*) ((char*)obj + field_offset)); 2495 newinsn = AMPAMP (getfield_resolved_char); 2496 } 1975 2497 else 1976 PUSHI (*(jshort*) ((char*)obj + field_offset)); 2498 { 2499 PUSHI (*(jshort*) ((char*)obj + field_offset)); 2500 newinsn = AMPAMP (getfield_resolved_short); 2501 } 1977 2502 break; 1978 2503 1979 2504 case 4: 1980 2505 PUSHI (*(jint*) ((char*)obj + field_offset)); 2506 newinsn = AMPAMP (getfield_resolved_4); 1981 2507 break; 1982 2508 1983 2509 case 8: 1984 2510 PUSHL(*(jlong*) ((char*)obj + field_offset)); 2511 newinsn = AMPAMP (getfield_resolved_8); 1985 2512 break; 1986 2513 } … … 1989 2516 { 1990 2517 PUSHA(*(jobject*) ((char*)obj + field_offset)); 2518 newinsn = AMPAMP (getfield_resolved_obj); 1991 2519 } 1992 } 1993 NEXT_INSN; 1994 1995 insn_putstatic: 1996 SAVE_PC; 1997 { 1998 jint fieldref_index = get2u (pc); pc += 2; 2520 2521 #ifdef DIRECT_THREADED 2522 pc[-2].insn = newinsn; 2523 pc[-1].int_val = field_offset; 2524 #endif /* DIRECT_THREADED */ 2525 } 2526 NEXT_INSN; 2527 2528 #ifdef DIRECT_THREADED 2529 getfield_resolved_1: 2530 { 2531 char *obj = (char *) POPA (); 2532 NULLCHECK (obj); 2533 PUSHI (*(jbyte *) (obj + INTVAL ())); 2534 } 2535 NEXT_INSN; 2536 2537 getfield_resolved_char: 2538 { 2539 char *obj = (char *) POPA (); 2540 NULLCHECK (obj); 2541 PUSHI (*(jchar *) (obj + INTVAL ())); 2542 } 2543 NEXT_INSN; 2544 2545 getfield_resolved_short: 2546 { 2547 char *obj = (char *) POPA (); 2548 NULLCHECK (obj); 2549 PUSHI (*(jshort *) (obj + INTVAL ())); 2550 } 2551 NEXT_INSN; 2552 2553 getfield_resolved_4: 2554 { 2555 char *obj = (char *) POPA (); 2556 NULLCHECK (obj); 2557 PUSHI (*(jint *) (obj + INTVAL ())); 2558 } 2559 NEXT_INSN; 2560 2561 getfield_resolved_8: 2562 { 2563 char *obj = (char *) POPA (); 2564 NULLCHECK (obj); 2565 PUSHL (*(jlong *) (obj + INTVAL ())); 2566 } 2567 NEXT_INSN; 2568 2569 getfield_resolved_obj: 2570 { 2571 char *obj = (char *) POPA (); 2572 NULLCHECK (obj); 2573 PUSHA (*(jobject *) (obj + INTVAL ())); 2574 } 2575 NEXT_INSN; 2576 #endif /* DIRECT_THREADED */ 2577 2578 insn_putstatic: 2579 { 2580 jint fieldref_index = GET2U (); 1999 2581 _Jv_ResolvePoolEntry (defining_class, fieldref_index); 2000 2582 _Jv_Field *field = pool_data[fieldref_index].field; … … 2007 2589 (JvNewStringLatin1 ("field no longer static")); 2008 2590 2591 void *newinsn = NULL; 2009 2592 if (type->isPrimitive ()) 2010 2593 { … … 2015 2598 jint value = POPI(); 2016 2599 *(jbyte*) (field->u.addr) = value; 2600 newinsn = AMPAMP (putstatic_resolved_1); 2017 2601 break; 2018 2602 } … … 2022 2606 jint value = POPI(); 2023 2607 *(jchar*) (field->u.addr) = value; 2608 newinsn = AMPAMP (putstatic_resolved_2); 2024 2609 break; 2025 2610 } … … 2029 2614 jint value = POPI(); 2030 2615 *(jint*) (field->u.addr) = value; 2616 newinsn = AMPAMP (putstatic_resolved_4); 2031 2617 break; 2032 2618 } … … 2036 2622 jlong value = POPL(); 2037 2623 *(jlong*) (field->u.addr) = value; 2624 newinsn = AMPAMP (putstatic_resolved_8); 2038 2625 break; 2039 2626 } … … 2044 2631 jobject value = POPA(); 2045 2632 *(jobject*) (field->u.addr) = value; 2633 newinsn = AMPAMP (putstatic_resolved_obj); 2046 2634 } 2047 } 2048 NEXT_INSN; 2049 2050 2051 insn_putfield: 2052 SAVE_PC; 2053 { 2054 jint fieldref_index = get2u (pc); pc += 2; 2635 2636 #ifdef DIRECT_THREADED 2637 pc[-2].insn = newinsn; 2638 pc[-1].datum = field->u.addr; 2639 #endif /* DIRECT_THREADED */ 2640 } 2641 NEXT_INSN; 2642 2643 #ifdef DIRECT_THREADED 2644 putstatic_resolved_1: 2645 *(jbyte *) AVAL () = POPI (); 2646 NEXT_INSN; 2647 2648 putstatic_resolved_2: 2649 *(jchar *) AVAL () = POPI (); 2650 NEXT_INSN; 2651 2652 putstatic_resolved_4: 2653 *(jint *) AVAL () = POPI (); 2654 NEXT_INSN; 2655 2656 putstatic_resolved_8: 2657 *(jlong *) AVAL () = POPL (); 2658 NEXT_INSN; 2659 2660 putstatic_resolved_obj: 2661 *(jobject *) AVAL () = POPA (); 2662 NEXT_INSN; 2663 #endif /* DIRECT_THREADED */ 2664 2665 insn_putfield: 2666 { 2667 jint fieldref_index = GET2U (); 2055 2668 _Jv_ResolvePoolEntry (defining_class, fieldref_index); 2056 2669 _Jv_Field *field = pool_data[fieldref_index].field; … … 2066 2679 throw new java::lang::VirtualMachineError; 2067 2680 2681 void *newinsn = NULL; 2068 2682 if (type->isPrimitive ()) 2069 2683 { … … 2076 2690 NULLCHECK(obj); 2077 2691 *(jbyte*) ((char*)obj + field_offset) = value; 2692 newinsn = AMPAMP (putfield_resolved_1); 2078 2693 break; 2079 2694 } … … 2085 2700 NULLCHECK(obj); 2086 2701 *(jchar*) ((char*)obj + field_offset) = value; 2702 newinsn = AMPAMP (putfield_resolved_2); 2087 2703 break; 2088 2704 } … … 2094 2710 NULLCHECK(obj); 2095 2711 *(jint*) ((char*)obj + field_offset) = value; 2712 newinsn = AMPAMP (putfield_resolved_4); 2096 2713 break; 2097 2714 } … … 2103 2720 NULLCHECK(obj); 2104 2721 *(jlong*) ((char*)obj + field_offset) = value; 2722 newinsn = AMPAMP (putfield_resolved_8); 2105 2723 break; 2106 2724 } … … 2113 2731 NULLCHECK(obj); 2114 2732 *(jobject*) ((char*)obj + field_offset) = value; 2733 newinsn = AMPAMP (putfield_resolved_obj); 2115 2734 } 2116 } 2117 NEXT_INSN; 2118 2119 insn_invokespecial: 2120 SAVE_PC; 2121 { 2122 int index = get2u (pc); pc += 2; 2735 2736 #ifdef DIRECT_THREADED 2737 pc[-2].insn = newinsn; 2738 pc[-1].int_val = field_offset; 2739 #endif /* DIRECT_THREADED */ 2740 } 2741 NEXT_INSN; 2742 2743 #ifdef DIRECT_THREADED 2744 putfield_resolved_1: 2745 { 2746 jint val = POPI (); 2747 char *obj = (char *) POPA (); 2748 NULLCHECK (obj); 2749 *(jbyte *) (obj + INTVAL ()) = val; 2750 } 2751 NEXT_INSN; 2752 2753 putfield_resolved_2: 2754 { 2755 jint val = POPI (); 2756 char *obj = (char *) POPA (); 2757 NULLCHECK (obj); 2758 *(jchar *) (obj + INTVAL ()) = val; 2759 } 2760 NEXT_INSN; 2761 2762 putfield_resolved_4: 2763 { 2764 jint val = POPI (); 2765 char *obj = (char *) POPA (); 2766 NULLCHECK (obj); 2767 *(jint *) (obj + INTVAL ()) = val; 2768 } 2769 NEXT_INSN; 2770 2771 putfield_resolved_8: 2772 { 2773 jlong val = POPL (); 2774 char *obj = (char *) POPA (); 2775 NULLCHECK (obj); 2776 *(jlong *) (obj + INTVAL ()) = val; 2777 } 2778 NEXT_INSN; 2779 2780 putfield_resolved_obj: 2781 { 2782 jobject val = POPA (); 2783 char *obj = (char *) POPA (); 2784 NULLCHECK (obj); 2785 *(jobject *) (obj + INTVAL ()) = val; 2786 } 2787 NEXT_INSN; 2788 #endif /* DIRECT_THREADED */ 2789 2790 insn_invokespecial: 2791 { 2792 int index = GET2U (); 2123 2793 2124 2794 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod; … … 2126 2796 sp -= rmeth->stack_item_count; 2127 2797 2128 NULLCHECK (sp[0].o); 2798 // We don't use NULLCHECK here because we can't rely on that 2799 // working for <init>. So instead we do an explicit test. 2800 if (! sp[0].o) 2801 throw new java::lang::NullPointerException; 2129 2802 2130 2803 fun = (void (*)()) rmeth->method->ncode; 2804 2805 #ifdef DIRECT_THREADED 2806 // Rewrite instruction so that we use a faster pre-resolved 2807 // method. 2808 pc[-2].insn = &&invokespecial_resolved; 2809 pc[-1].datum = rmeth; 2810 #endif /* DIRECT_THREADED */ 2131 2811 } 2132 2812 goto perform_invoke; 2133 2813 2134 insn_invokestatic: 2135 SAVE_PC; 2136 { 2137 int index = get2u (pc); pc += 2; 2814 #ifdef DIRECT_THREADED 2815 invokespecial_resolved: 2816 { 2817 rmeth = (_Jv_ResolvedMethod *) AVAL (); 2818 sp -= rmeth->stack_item_count; 2819 // We don't use NULLCHECK here because we can't rely on that 2820 // working for <init>. So instead we do an explicit test. 2821 if (! sp[0].o) 2822 throw new java::lang::NullPointerException; 2823 fun = (void (*)()) rmeth->method->ncode; 2824 } 2825 goto perform_invoke; 2826 #endif /* DIRECT_THREADED */ 2827 2828 insn_invokestatic: 2829 { 2830 int index = GET2U (); 2138 2831 2139 2832 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod; … … 2143 2836 _Jv_InitClass (rmeth->klass); 2144 2837 fun = (void (*)()) rmeth->method->ncode; 2838 2839 #ifdef DIRECT_THREADED 2840 // Rewrite instruction so that we use a faster pre-resolved 2841 // method. 2842 pc[-2].insn = &&invokestatic_resolved; 2843 pc[-1].datum = rmeth; 2844 #endif /* DIRECT_THREADED */ 2145 2845 } 2146 2846 goto perform_invoke; 2147 2847 2148 insn_invokeinterface: 2149 SAVE_PC; 2150 { 2151 int index = get2u (pc); pc += 2; 2152 2153 // invokeinterface has two unused bytes... 2154 pc += 2; 2848 #ifdef DIRECT_THREADED 2849 invokestatic_resolved: 2850 { 2851 rmeth = (_Jv_ResolvedMethod *) AVAL (); 2852 sp -= rmeth->stack_item_count; 2853 fun = (void (*)()) rmeth->method->ncode; 2854 } 2855 goto perform_invoke; 2856 #endif /* DIRECT_THREADED */ 2857 2858 insn_invokeinterface: 2859 { 2860 int index = GET2U (); 2155 2861 2156 2862 rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod; … … 2166 2872 rmeth->method->name, 2167 2873 rmeth->method->signature); 2874 2875 #ifdef DIRECT_THREADED 2876 // Rewrite instruction so that we use a faster pre-resolved 2877 // method. 2878 pc[-2].insn = &&invokeinterface_resolved; 2879 pc[-1].datum = rmeth; 2880 #else 2881 // Skip dummy bytes. 2882 pc += 2; 2883 #endif /* DIRECT_THREADED */ 2168 2884 } 2169 2885 goto perform_invoke; 2170 2886 2171 2172 insn_new: 2173 SAVE_PC; 2174 { 2175 int index = get2u (pc); pc += 2; 2887 #ifdef DIRECT_THREADED 2888 invokeinterface_resolved: 2889 { 2890 rmeth = (_Jv_ResolvedMethod *) AVAL (); 2891 sp -= rmeth->stack_item_count; 2892 jobject rcv = sp[0].o; 2893 NULLCHECK (rcv); 2894 fun = (void (*)()) 2895 _Jv_LookupInterfaceMethod (rcv->getClass (), 2896 rmeth->method->name, 2897 rmeth->method->signature); 2898 } 2899 goto perform_invoke; 2900 #endif /* DIRECT_THREADED */ 2901 2902 insn_new: 2903 { 2904 int index = GET2U (); 2176 2905 jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz; 2177 2906 _Jv_InitClass (klass); 2178 2907 jobject res = _Jv_AllocObject (klass, klass->size_in_bytes); 2179 2908 PUSHA (res); 2180 } 2181 NEXT_INSN; 2182 2183 insn_newarray: 2184 SAVE_PC; 2185 { 2186 int atype = get1u (pc++); 2909 2910 #ifdef DIRECT_THREADED 2911 pc[-2].insn = &&new_resolved; 2912 pc[-1].datum = klass; 2913 #endif /* DIRECT_THREADED */ 2914 } 2915 NEXT_INSN; 2916 2917 #ifdef DIRECT_THREADED 2918 new_resolved: 2919 { 2920 jclass klass = (jclass) AVAL (); 2921 jobject res = _Jv_AllocObject (klass, klass->size_in_bytes); 2922 PUSHA (res); 2923 } 2924 NEXT_INSN; 2925 #endif /* DIRECT_THREADED */ 2926 2927 insn_newarray: 2928 { 2929 int atype = GET1U (); 2187 2930 int size = POPI(); 2188 2931 jobject result = _Jv_NewArray (atype, size); … … 2191 2934 NEXT_INSN; 2192 2935 2193 insn_anewarray: 2194 SAVE_PC; 2195 { 2196 int index = get2u (pc); pc += 2; 2936 insn_anewarray: 2937 { 2938 int index = GET2U (); 2197 2939 jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz; 2198 2940 int size = POPI(); … … 2200 2942 jobject result = _Jv_NewObjectArray (size, klass, 0); 2201 2943 PUSHA (result); 2202 } 2203 NEXT_INSN; 2204 2205 insn_arraylength: 2944 2945 #ifdef DIRECT_THREADED 2946 pc[-2].insn = &&anewarray_resolved; 2947 pc[-1].datum = klass; 2948 #endif /* DIRECT_THREADED */ 2949 } 2950 NEXT_INSN; 2951 2952 #ifdef DIRECT_THREADED 2953 anewarray_resolved: 2954 { 2955 jclass klass = (jclass) AVAL (); 2956 int size = POPI (); 2957 jobject result = _Jv_NewObjectArray (size, klass, 0); 2958 PUSHA (result); 2959 } 2960 NEXT_INSN; 2961 #endif /* DIRECT_THREADED */ 2962 2963 insn_arraylength: 2206 2964 { 2207 2965 __JArray *arr = (__JArray*)POPA(); … … 2211 2969 NEXT_INSN; 2212 2970 2213 insn_athrow: 2214 SAVE_PC; 2971 insn_athrow: 2215 2972 { 2216 2973 jobject value = POPA(); … … 2219 2976 NEXT_INSN; 2220 2977 2221 insn_checkcast: 2222 SAVE_PC; 2978 insn_checkcast: 2223 2979 { 2224 2980 jobject value = POPA(); 2225 jint index = get2u (pc); pc += 2;2981 jint index = GET2U (); 2226 2982 jclass to = (_Jv_ResolvePoolEntry (defining_class, index)).clazz; 2227 2983 2228 2984 if (value != NULL && ! to->isInstance (value)) 2229 { 2230 throw new java::lang::ClassCastException (to->getName()); 2231 } 2985 throw new java::lang::ClassCastException (to->getName()); 2232 2986 2233 2987 PUSHA (value); 2234 } 2235 NEXT_INSN; 2236 2237 insn_instanceof: 2238 SAVE_PC; 2988 2989 #ifdef DIRECT_THREADED 2990 pc[-2].insn = &&checkcast_resolved; 2991 pc[-1].datum = to; 2992 #endif /* DIRECT_THREADED */ 2993 } 2994 NEXT_INSN; 2995 2996 #ifdef DIRECT_THREADED 2997 checkcast_resolved: 2998 { 2999 jobject value = POPA (); 3000 jclass to = (jclass) AVAL (); 3001 if (value != NULL && ! to->isInstance (value)) 3002 throw new java::lang::ClassCastException (to->getName()); 3003 PUSHA (value); 3004 } 3005 NEXT_INSN; 3006 #endif /* DIRECT_THREADED */ 3007 3008 insn_instanceof: 2239 3009 { 2240 3010 jobject value = POPA(); 2241 jint index = get2u (pc); pc += 2;3011 jint index = GET2U (); 2242 3012 jclass to = (_Jv_ResolvePoolEntry (defining_class, index)).clazz; 2243 3013 PUSHI (to->isInstance (value)); 2244 } 2245 NEXT_INSN; 2246 2247 insn_monitorenter: 2248 SAVE_PC; 3014 3015 #ifdef DIRECT_THREADED 3016 pc[-2].insn = &&instanceof_resolved; 3017 pc[-1].datum = to; 3018 #endif /* DIRECT_THREADED */ 3019 } 3020 NEXT_INSN; 3021 3022 #ifdef DIRECT_THREADED 3023 instanceof_resolved: 3024 { 3025 jobject value = POPA (); 3026 jclass to = (jclass) AVAL (); 3027 PUSHI (to->isInstance (value)); 3028 } 3029 NEXT_INSN; 3030 #endif /* DIRECT_THREADED */ 3031 3032 insn_monitorenter: 2249 3033 { 2250 3034 jobject value = POPA(); … … 2254 3038 NEXT_INSN; 2255 3039 2256 insn_monitorexit: 2257 SAVE_PC; 3040 insn_monitorexit: 2258 3041 { 2259 3042 jobject value = POPA(); … … 2263 3046 NEXT_INSN; 2264 3047 2265 insn_ifnull: 2266 { 2267 unsigned char* base_pc = pc-1; 2268 jint offset = get2s (pc); pc += 2; 3048 insn_ifnull: 3049 { 2269 3050 jobject val = POPA(); 2270 3051 if (val == NULL) 2271 pc = base_pc+offset;2272 } 2273 NEXT_INSN;2274 2275 insn_ifnonnull:2276 { 2277 unsigned char* base_pc = pc-1; 2278 jint offset = get2s (pc); pc += 2; 3052 TAKE_GOTO; 3053 else 3054 SKIP_GOTO; 3055 } 3056 NEXT_INSN; 3057 3058 insn_ifnonnull: 3059 { 2279 3060 jobject val = POPA(); 2280 3061 if (val != NULL) 2281 pc = base_pc+offset; 2282 } 2283 NEXT_INSN; 2284 2285 insn_wide: 2286 SAVE_PC; 3062 TAKE_GOTO; 3063 else 3064 SKIP_GOTO; 3065 } 3066 NEXT_INSN; 3067 3068 insn_multianewarray: 3069 { 3070 int kind_index = GET2U (); 3071 int dim = GET1U (); 3072 3073 jclass type 3074 = (_Jv_ResolvePoolEntry (defining_class, kind_index)).clazz; 3075 _Jv_InitClass (type); 3076 jint *sizes = (jint*) __builtin_alloca (sizeof (jint)*dim); 3077 3078 for (int i = dim - 1; i >= 0; i--) 3079 { 3080 sizes[i] = POPI (); 3081 } 3082 3083 jobject res = _Jv_NewMultiArray (type,dim, sizes); 3084 3085 PUSHA (res); 3086 } 3087 NEXT_INSN; 3088 3089 #ifndef DIRECT_THREADED 3090 insn_wide: 2287 3091 { 2288 3092 jint the_mod_op = get1u (pc++); … … 2344 3148 2345 3149 } 2346 2347 insn_multianewarray: 2348 SAVE_PC; 2349 { 2350 int kind_index = get2u (pc); pc += 2; 2351 int dim = get1u (pc); pc += 1; 2352 2353 jclass type 2354 = (_Jv_ResolvePoolEntry (defining_class, kind_index)).clazz; 2355 _Jv_InitClass (type); 2356 jint *sizes = (jint*) __builtin_alloca (sizeof (jint)*dim); 2357 2358 for (int i = dim - 1; i >= 0; i--) 2359 { 2360 sizes[i] = POPI (); 2361 } 2362 2363 jobject res = _Jv_NewMultiArray (type,dim, sizes); 2364 2365 PUSHA (res); 2366 } 2367 NEXT_INSN; 2368 2369 insn_goto_w: 2370 { 2371 unsigned char* base_pc = pc-1; 2372 int offset = get4 (pc); pc += 4; 2373 pc = base_pc+offset; 2374 } 2375 NEXT_INSN; 2376 2377 insn_jsr_w: 2378 { 2379 unsigned char* base_pc = pc-1; 2380 int offset = get4 (pc); pc += 4; 2381 PUSHA((jobject)pc); 2382 pc = base_pc+offset; 2383 } 2384 NEXT_INSN; 3150 #endif /* DIRECT_THREADED */ 3151 } 3152 catch (java::lang::Throwable *ex) 3153 { 3154 #ifdef DIRECT_THREADED 3155 void *logical_pc = (void *) ((insn_slot *) pc - 1); 3156 #else 3157 int logical_pc = pc - 1 - bytecode (); 3158 #endif 3159 _Jv_InterpException *exc = exceptions (); 3160 jclass exc_class = ex->getClass (); 3161 3162 for (int i = 0; i < exc_count; i++) 3163 { 3164 if (PCVAL (exc[i].start_pc) <= logical_pc 3165 && logical_pc < PCVAL (exc[i].end_pc)) 3166 { 3167 #ifdef DIRECT_THREADED 3168 jclass handler = (jclass) exc[i].handler_type.p; 3169 #else 3170 jclass handler = NULL; 3171 if (exc[i].handler_type.i != 0) 3172 handler = (_Jv_ResolvePoolEntry (defining_class, 3173 exc[i].handler_type.i)).clazz; 3174 #endif /* DIRECT_THREADED */ 3175 3176 if (handler == NULL || handler->isAssignableFrom (exc_class)) 3177 { 3178 #ifdef DIRECT_THREADED 3179 pc = (insn_slot *) exc[i].handler_pc.p; 3180 #else 3181 pc = bytecode () + exc[i].handler_pc.i; 3182 #endif /* DIRECT_THREADED */ 3183 sp = stack; 3184 sp++->o = ex; // Push exception. 3185 NEXT_INSN; 3186 } 3187 } 3188 } 3189 3190 // No handler, so re-throw. 3191 throw ex; 3192 } 2385 3193 } 2386 3194 3195 // This function exists so that the stack-tracing code can find the 3196 // boundaries of the interpreter. 3197 void 3198 _Jv_EndOfInterpreter (void) 3199 { 3200 } 2387 3201 2388 3202 static void -
Property cvs2svn:cvs-rev
changed from
Note:
See TracChangeset
for help on using the changeset viewer.