2932 __ load_receiver(temp, recv); // __ argument_address uses Gargs but we need Lesp
2933 __ verify_oop(recv);
2934 }
2935
2936 // compute return type
2937 __ srl(flags, ConstantPoolCacheEntry::tos_state_shift, ra);
2938 // Make sure we don't need to mask flags after the above shift
2939 ConstantPoolCacheEntry::verify_tos_state_shift();
2940 // load return address
2941 {
2942 const address table_addr = (address) Interpreter::invoke_return_entry_table_for(code);
2943 AddressLiteral table(table_addr);
2944 __ set(table, temp);
2945 __ sll(ra, LogBytesPerWord, ra);
2946 __ ld_ptr(Address(temp, ra), ra);
2947 }
2948 }
2949
2950
2951 void TemplateTable::generate_vtable_call(Register Rrecv, Register Rindex, Register Rret) {
2952 Register Rcall = Rindex;
2953 assert_different_registers(Rcall, G5_method, Gargs, Rret);
2954
2955 // get target Method* & entry point
2956 __ lookup_virtual_method(Rrecv, Rindex, G5_method);
2957 __ profile_arguments_type(G5_method, Rcall, Gargs, true);
2958 __ call_from_interpreter(Rcall, Gargs, Rret);
2959 }
2960
2961 void TemplateTable::invokevirtual(int byte_no) {
2962 transition(vtos, vtos);
2963 assert(byte_no == f2_byte, "use this argument");
2964
2965 Register Rscratch = G3_scratch;
2966 Register Rtemp = G4_scratch;
2967 Register Rret = Lscratch;
2968 Register O0_recv = O0;
2969 Label notFinal;
2970
2971 load_invoke_cp_cache_entry(byte_no, G5_method, noreg, Rret, true, false, false);
2972 __ mov(SP, O5_savedSP); // record SP that we wanted the callee to restore
2973
2974 // Check for vfinal
2975 __ set((1 << ConstantPoolCacheEntry::is_vfinal_shift), G4_scratch);
2976 __ btst(Rret, G4_scratch);
2977 __ br(Assembler::zero, false, Assembler::pt, notFinal);
3194 __ ld(Rscratch, itableOffsetEntry::offset_offset_in_bytes(), Rscratch);
3195
3196 assert(itableMethodEntry::method_offset_in_bytes() == 0, "adjust instruction below");
3197 __ sll(Rindex, exact_log2(itableMethodEntry::size() * wordSize), Rindex); // Rindex *= 8;
3198 __ add(Rscratch, Rindex, Rscratch);
3199 __ ld_ptr(O2_Klass, Rscratch, G5_method);
3200
3201 // Check for abstract method error.
3202 {
3203 Label ok;
3204 __ br_notnull_short(G5_method, Assembler::pt, ok);
3205 call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError));
3206 __ should_not_reach_here();
3207 __ bind(ok);
3208 }
3209
3210 Register Rcall = Rinterface;
3211 assert_different_registers(Rcall, G5_method, Gargs, Rret);
3212
3213 __ profile_arguments_type(G5_method, Rcall, Gargs, true);
3214 __ call_from_interpreter(Rcall, Gargs, Rret);
3215 }
3216
3217 void TemplateTable::invokehandle(int byte_no) {
3218 transition(vtos, vtos);
3219 assert(byte_no == f1_byte, "use this argument");
3220
3221 const Register Rret = Lscratch;
3222 const Register G4_mtype = G4_scratch;
3223 const Register O0_recv = O0;
3224 const Register Rscratch = G3_scratch;
3225
3226 prepare_invoke(byte_no, G5_method, Rret, G4_mtype, O0_recv);
3227 __ null_check(O0_recv);
3228
3229 // G4: MethodType object (from cpool->resolved_references[f1], if necessary)
3230 // G5: MH.invokeExact_MT method (from f2)
3231
3232 // Note: G4_mtype is already pushed (if necessary) by prepare_invoke
3233
3469
3470 void TemplateTable::arraylength() {
3471 transition(atos, itos);
3472 Label ok;
3473 __ verify_oop(Otos_i);
3474 __ tst(Otos_i);
3475 __ throw_if_not_1_x( Assembler::notZero, ok );
3476 __ delayed()->ld(Otos_i, arrayOopDesc::length_offset_in_bytes(), Otos_i);
3477 __ throw_if_not_2( Interpreter::_throw_NullPointerException_entry, G3_scratch, ok);
3478 }
3479
3480
3481 void TemplateTable::checkcast() {
3482 transition(atos, atos);
3483 Label done, is_null, quicked, cast_ok, resolved;
3484 Register Roffset = G1_scratch;
3485 Register RobjKlass = O5;
3486 Register RspecifiedKlass = O4;
3487
3488 // Check for casting a NULL
3489 __ br_null_short(Otos_i, Assembler::pn, is_null);
3490
3491 // Get value klass in RobjKlass
3492 __ load_klass(Otos_i, RobjKlass); // get value klass
3493
3494 // Get constant pool tag
3495 __ get_2_byte_integer_at_bcp(1, Lscratch, Roffset, InterpreterMacroAssembler::Unsigned);
3496
3497 // See if the checkcast has been quickened
3498 __ get_cpool_and_tags(Lscratch, G3_scratch);
3499 __ add(G3_scratch, Array<u1>::base_offset_in_bytes(), G3_scratch);
3500 __ ldub(G3_scratch, Roffset, G3_scratch);
3501 __ cmp(G3_scratch, JVM_CONSTANT_Class);
3502 __ br(Assembler::equal, true, Assembler::pt, quicked);
3503 __ delayed()->sll(Roffset, LogBytesPerWord, Roffset);
3504
3505 __ push_ptr(); // save receiver for result, and for GC
3506 call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::quicken_io_cc) );
3507 __ get_vm_result_2(RspecifiedKlass);
3508 __ pop_ptr(Otos_i, G3_scratch); // restore receiver
3509
3525
3526 __ bind(cast_ok);
3527
3528 if (ProfileInterpreter) {
3529 __ ba_short(done);
3530 }
3531 __ bind(is_null);
3532 __ profile_null_seen(G3_scratch);
3533 __ bind(done);
3534 }
3535
3536
3537 void TemplateTable::instanceof() {
3538 Label done, is_null, quicked, resolved;
3539 transition(atos, itos);
3540 Register Roffset = G1_scratch;
3541 Register RobjKlass = O5;
3542 Register RspecifiedKlass = O4;
3543
3544 // Check for casting a NULL
3545 __ br_null_short(Otos_i, Assembler::pt, is_null);
3546
3547 // Get value klass in RobjKlass
3548 __ load_klass(Otos_i, RobjKlass); // get value klass
3549
3550 // Get constant pool tag
3551 __ get_2_byte_integer_at_bcp(1, Lscratch, Roffset, InterpreterMacroAssembler::Unsigned);
3552
3553 // See if the checkcast has been quickened
3554 __ get_cpool_and_tags(Lscratch, G3_scratch);
3555 __ add(G3_scratch, Array<u1>::base_offset_in_bytes(), G3_scratch);
3556 __ ldub(G3_scratch, Roffset, G3_scratch);
3557 __ cmp(G3_scratch, JVM_CONSTANT_Class);
3558 __ br(Assembler::equal, true, Assembler::pt, quicked);
3559 __ delayed()->sll(Roffset, LogBytesPerWord, Roffset);
3560
3561 __ push_ptr(); // save receiver for result, and for GC
3562 call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::quicken_io_cc) );
3563 __ get_vm_result_2(RspecifiedKlass);
3564 __ pop_ptr(Otos_i, G3_scratch); // restore receiver
3565
|
2932 __ load_receiver(temp, recv); // __ argument_address uses Gargs but we need Lesp
2933 __ verify_oop(recv);
2934 }
2935
2936 // compute return type
2937 __ srl(flags, ConstantPoolCacheEntry::tos_state_shift, ra);
2938 // Make sure we don't need to mask flags after the above shift
2939 ConstantPoolCacheEntry::verify_tos_state_shift();
2940 // load return address
2941 {
2942 const address table_addr = (address) Interpreter::invoke_return_entry_table_for(code);
2943 AddressLiteral table(table_addr);
2944 __ set(table, temp);
2945 __ sll(ra, LogBytesPerWord, ra);
2946 __ ld_ptr(Address(temp, ra), ra);
2947 }
2948 }
2949
2950
2951 void TemplateTable::generate_vtable_call(Register Rrecv, Register Rindex, Register Rret) {
2952 Register Rtemp = G4_scratch;
2953 Register Rcall = Rindex;
2954 assert_different_registers(Rcall, G5_method, Gargs, Rret);
2955
2956 // get target Method* & entry point
2957 __ lookup_virtual_method(Rrecv, Rindex, G5_method);
2958 __ profile_arguments_type(G5_method, Rcall, Gargs, true);
2959 __ profile_called_method(G5_method, Rtemp);
2960 __ call_from_interpreter(Rcall, Gargs, Rret);
2961 }
2962
2963 void TemplateTable::invokevirtual(int byte_no) {
2964 transition(vtos, vtos);
2965 assert(byte_no == f2_byte, "use this argument");
2966
2967 Register Rscratch = G3_scratch;
2968 Register Rtemp = G4_scratch;
2969 Register Rret = Lscratch;
2970 Register O0_recv = O0;
2971 Label notFinal;
2972
2973 load_invoke_cp_cache_entry(byte_no, G5_method, noreg, Rret, true, false, false);
2974 __ mov(SP, O5_savedSP); // record SP that we wanted the callee to restore
2975
2976 // Check for vfinal
2977 __ set((1 << ConstantPoolCacheEntry::is_vfinal_shift), G4_scratch);
2978 __ btst(Rret, G4_scratch);
2979 __ br(Assembler::zero, false, Assembler::pt, notFinal);
3196 __ ld(Rscratch, itableOffsetEntry::offset_offset_in_bytes(), Rscratch);
3197
3198 assert(itableMethodEntry::method_offset_in_bytes() == 0, "adjust instruction below");
3199 __ sll(Rindex, exact_log2(itableMethodEntry::size() * wordSize), Rindex); // Rindex *= 8;
3200 __ add(Rscratch, Rindex, Rscratch);
3201 __ ld_ptr(O2_Klass, Rscratch, G5_method);
3202
3203 // Check for abstract method error.
3204 {
3205 Label ok;
3206 __ br_notnull_short(G5_method, Assembler::pt, ok);
3207 call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError));
3208 __ should_not_reach_here();
3209 __ bind(ok);
3210 }
3211
3212 Register Rcall = Rinterface;
3213 assert_different_registers(Rcall, G5_method, Gargs, Rret);
3214
3215 __ profile_arguments_type(G5_method, Rcall, Gargs, true);
3216 __ profile_called_method(G5_method, Rscratch);
3217 __ call_from_interpreter(Rcall, Gargs, Rret);
3218 }
3219
3220 void TemplateTable::invokehandle(int byte_no) {
3221 transition(vtos, vtos);
3222 assert(byte_no == f1_byte, "use this argument");
3223
3224 const Register Rret = Lscratch;
3225 const Register G4_mtype = G4_scratch;
3226 const Register O0_recv = O0;
3227 const Register Rscratch = G3_scratch;
3228
3229 prepare_invoke(byte_no, G5_method, Rret, G4_mtype, O0_recv);
3230 __ null_check(O0_recv);
3231
3232 // G4: MethodType object (from cpool->resolved_references[f1], if necessary)
3233 // G5: MH.invokeExact_MT method (from f2)
3234
3235 // Note: G4_mtype is already pushed (if necessary) by prepare_invoke
3236
3472
3473 void TemplateTable::arraylength() {
3474 transition(atos, itos);
3475 Label ok;
3476 __ verify_oop(Otos_i);
3477 __ tst(Otos_i);
3478 __ throw_if_not_1_x( Assembler::notZero, ok );
3479 __ delayed()->ld(Otos_i, arrayOopDesc::length_offset_in_bytes(), Otos_i);
3480 __ throw_if_not_2( Interpreter::_throw_NullPointerException_entry, G3_scratch, ok);
3481 }
3482
3483
3484 void TemplateTable::checkcast() {
3485 transition(atos, atos);
3486 Label done, is_null, quicked, cast_ok, resolved;
3487 Register Roffset = G1_scratch;
3488 Register RobjKlass = O5;
3489 Register RspecifiedKlass = O4;
3490
3491 // Check for casting a NULL
3492 __ br_null(Otos_i, false, Assembler::pn, is_null);
3493 __ delayed()->nop();
3494
3495 // Get value klass in RobjKlass
3496 __ load_klass(Otos_i, RobjKlass); // get value klass
3497
3498 // Get constant pool tag
3499 __ get_2_byte_integer_at_bcp(1, Lscratch, Roffset, InterpreterMacroAssembler::Unsigned);
3500
3501 // See if the checkcast has been quickened
3502 __ get_cpool_and_tags(Lscratch, G3_scratch);
3503 __ add(G3_scratch, Array<u1>::base_offset_in_bytes(), G3_scratch);
3504 __ ldub(G3_scratch, Roffset, G3_scratch);
3505 __ cmp(G3_scratch, JVM_CONSTANT_Class);
3506 __ br(Assembler::equal, true, Assembler::pt, quicked);
3507 __ delayed()->sll(Roffset, LogBytesPerWord, Roffset);
3508
3509 __ push_ptr(); // save receiver for result, and for GC
3510 call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::quicken_io_cc) );
3511 __ get_vm_result_2(RspecifiedKlass);
3512 __ pop_ptr(Otos_i, G3_scratch); // restore receiver
3513
3529
3530 __ bind(cast_ok);
3531
3532 if (ProfileInterpreter) {
3533 __ ba_short(done);
3534 }
3535 __ bind(is_null);
3536 __ profile_null_seen(G3_scratch);
3537 __ bind(done);
3538 }
3539
3540
3541 void TemplateTable::instanceof() {
3542 Label done, is_null, quicked, resolved;
3543 transition(atos, itos);
3544 Register Roffset = G1_scratch;
3545 Register RobjKlass = O5;
3546 Register RspecifiedKlass = O4;
3547
3548 // Check for casting a NULL
3549 __ br_null(Otos_i, false, Assembler::pt, is_null);
3550 __ delayed()->nop();
3551
3552 // Get value klass in RobjKlass
3553 __ load_klass(Otos_i, RobjKlass); // get value klass
3554
3555 // Get constant pool tag
3556 __ get_2_byte_integer_at_bcp(1, Lscratch, Roffset, InterpreterMacroAssembler::Unsigned);
3557
3558 // See if the checkcast has been quickened
3559 __ get_cpool_and_tags(Lscratch, G3_scratch);
3560 __ add(G3_scratch, Array<u1>::base_offset_in_bytes(), G3_scratch);
3561 __ ldub(G3_scratch, Roffset, G3_scratch);
3562 __ cmp(G3_scratch, JVM_CONSTANT_Class);
3563 __ br(Assembler::equal, true, Assembler::pt, quicked);
3564 __ delayed()->sll(Roffset, LogBytesPerWord, Roffset);
3565
3566 __ push_ptr(); // save receiver for result, and for GC
3567 call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::quicken_io_cc) );
3568 __ get_vm_result_2(RspecifiedKlass);
3569 __ pop_ptr(Otos_i, G3_scratch); // restore receiver
3570
|