src/cpu/x86/vm/templateTable_x86_32.cpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File hotspot-dvm Cdiff src/cpu/x86/vm/templateTable_x86_32.cpp

src/cpu/x86/vm/templateTable_x86_32.cpp

Print this page
rev 423 : imported patch indy.patch

*** 204,219 **** __ get_method(scratch); // Let breakpoint table handling rewrite to quicker bytecode __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::set_original_bytecode_at), scratch, rsi, bc); #ifndef ASSERT __ jmpb(patch_done); - __ bind(fast_patch); - } #else __ jmp(patch_done); __ bind(fast_patch); } Label okay; __ load_unsigned_byte(scratch, at_bcp(0)); __ cmpl(scratch, (int)Bytecodes::java_code(bytecode)); __ jccb(Assembler::equal, okay); __ cmpl(scratch, bc); --- 204,219 ---- __ get_method(scratch); // Let breakpoint table handling rewrite to quicker bytecode __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::set_original_bytecode_at), scratch, rsi, bc); #ifndef ASSERT __ jmpb(patch_done); #else __ jmp(patch_done); + #endif __ bind(fast_patch); } + #ifdef ASSERT Label okay; __ load_unsigned_byte(scratch, at_bcp(0)); __ cmpl(scratch, (int)Bytecodes::java_code(bytecode)); __ jccb(Assembler::equal, okay); __ cmpl(scratch, bc);
*** 2103,2126 **** __ membar(order_constraint); } void TemplateTable::resolve_cache_and_index(int byte_no, Register Rcache, Register index) { assert(byte_no == 1 || byte_no == 2, "byte_no out of range"); Register temp = rbx; assert_different_registers(Rcache, index, temp); const int shift_count = (1 + byte_no)*BitsPerByte; Label resolved; ! __ get_cache_and_index_at_bcp(Rcache, index, 1); __ movl(temp, Address(Rcache, index, Address::times_4, constantPoolCacheOopDesc::base_offset() + ConstantPoolCacheEntry::indices_offset())); __ shrl(temp, shift_count); // have we resolved this bytecode? __ andl(temp, 0xFF); __ cmpl(temp, (int)bytecode()); __ jcc(Assembler::equal, resolved); // resolve first time through address entry; switch (bytecode()) { case Bytecodes::_getstatic : // fall through --- 2103,2133 ---- __ membar(order_constraint); } void TemplateTable::resolve_cache_and_index(int byte_no, Register Rcache, Register index) { assert(byte_no == 1 || byte_no == 2, "byte_no out of range"); + bool is_invokedynamic = (bytecode() == Bytecodes::_invokedynamic); Register temp = rbx; assert_different_registers(Rcache, index, temp); const int shift_count = (1 + byte_no)*BitsPerByte; Label resolved; ! __ get_cache_and_index_at_bcp(Rcache, index, 1, is_invokedynamic); ! if (is_invokedynamic) { ! // we are resolved if the f1 field contains a non-null CallSite object ! __ cmpptr(Address(Rcache, index, Address::times_ptr, constantPoolCacheOopDesc::base_offset() + ConstantPoolCacheEntry::f1_offset()), (int32_t) NULL_WORD); ! __ jcc(Assembler::notEqual, resolved); ! } else { __ movl(temp, Address(Rcache, index, Address::times_4, constantPoolCacheOopDesc::base_offset() + ConstantPoolCacheEntry::indices_offset())); __ shrl(temp, shift_count); // have we resolved this bytecode? __ andl(temp, 0xFF); __ cmpl(temp, (int)bytecode()); __ jcc(Assembler::equal, resolved); + } // resolve first time through address entry; switch (bytecode()) { case Bytecodes::_getstatic : // fall through
*** 2129,2144 **** case Bytecodes::_putfield : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_get_put); break; case Bytecodes::_invokevirtual : // fall through case Bytecodes::_invokespecial : // fall through case Bytecodes::_invokestatic : // fall through case Bytecodes::_invokeinterface: entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invoke); break; default : ShouldNotReachHere(); break; } __ movl(temp, (int)bytecode()); __ call_VM(noreg, entry, temp); // Update registers with resolved info ! __ get_cache_and_index_at_bcp(Rcache, index, 1); __ bind(resolved); } // The cache and index registers must be set before call --- 2136,2152 ---- case Bytecodes::_putfield : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_get_put); break; case Bytecodes::_invokevirtual : // fall through case Bytecodes::_invokespecial : // fall through case Bytecodes::_invokestatic : // fall through case Bytecodes::_invokeinterface: entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invoke); break; + case Bytecodes::_invokedynamic : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokedynamic); break; default : ShouldNotReachHere(); break; } __ movl(temp, (int)bytecode()); __ call_VM(noreg, entry, temp); // Update registers with resolved info ! __ get_cache_and_index_at_bcp(Rcache, index, 1, is_invokedynamic); __ bind(resolved); } // The cache and index registers must be set before call
*** 2879,2914 **** // implemented elsewhere ShouldNotReachHere(); } ! void TemplateTable::prepare_invoke(Register method, Register index, int byte_no, Bytecodes::Code code) { // determine flags const bool is_invokeinterface = code == Bytecodes::_invokeinterface; const bool is_invokevirtual = code == Bytecodes::_invokevirtual; const bool is_invokespecial = code == Bytecodes::_invokespecial; const bool load_receiver = code != Bytecodes::_invokestatic; const bool receiver_null_check = is_invokespecial; const bool save_flags = is_invokeinterface || is_invokevirtual; // setup registers & access constant pool cache const Register recv = rcx; const Register flags = rdx; assert_different_registers(method, index, recv, flags); // save 'interpreter return address' __ save_bcp(); load_invoke_cp_cache_entry(byte_no, method, index, flags, is_invokevirtual); // load receiver if needed (note: no return address pushed yet) if (load_receiver) { __ movl(recv, flags); __ andl(recv, 0xFF); // recv count is 0 based? ! __ movl(recv, Address(rsp, recv, Interpreter::stackElementScale(), -Interpreter::expr_offset_in_bytes(1))); __ verify_oop(recv); } // do null check if needed if (receiver_null_check) { __ null_check(recv); } --- 2887,2935 ---- // implemented elsewhere ShouldNotReachHere(); } ! void TemplateTable::prepare_invoke(Register method, Register index, int byte_no) { ! bool neg_byte_no = (byte_no < 0); ! if (neg_byte_no) byte_no = -byte_no; ! // determine flags + Bytecodes::Code code = bytecode(); const bool is_invokeinterface = code == Bytecodes::_invokeinterface; + const bool is_invokedynamic = code == Bytecodes::_invokedynamic; const bool is_invokevirtual = code == Bytecodes::_invokevirtual; const bool is_invokespecial = code == Bytecodes::_invokespecial; const bool load_receiver = code != Bytecodes::_invokestatic; const bool receiver_null_check = is_invokespecial; const bool save_flags = is_invokeinterface || is_invokevirtual; // setup registers & access constant pool cache const Register recv = rcx; const Register flags = rdx; assert_different_registers(method, index, recv, flags); + assert(!neg_byte_no || is_invokedynamic, "byte_no<0 hack only for invdyn"); + const bool is_invdyn_bootstrap = neg_byte_no; + // save 'interpreter return address' __ save_bcp(); load_invoke_cp_cache_entry(byte_no, method, index, flags, is_invokevirtual); // load receiver if needed (note: no return address pushed yet) if (load_receiver) { __ movl(recv, flags); __ andl(recv, 0xFF); // recv count is 0 based? ! Address recv_addr(rsp, recv, Interpreter::stackElementScale(), -Interpreter::expr_offset_in_bytes(1)); ! if (is_invokedynamic) { ! __ lea(recv, recv_addr); ! } else { ! __ movptr(recv, recv_addr); __ verify_oop(recv); } + } // do null check if needed if (receiver_null_check) { __ null_check(recv); }
*** 2920,2934 **** // compute return type __ shrl(flags, ConstantPoolCacheEntry::tosBits); // Make sure we don't need to mask flags for tosBits after the above shift ConstantPoolCacheEntry::verify_tosBits(); // load return address ! { const int table = ! is_invokeinterface ! ? (int)Interpreter::return_5_addrs_by_index_table() ! : (int)Interpreter::return_3_addrs_by_index_table(); ! __ movl(flags, Address(noreg, flags, Address::times_4, table)); } // push return address __ push(flags); --- 2941,2959 ---- // compute return type __ shrl(flags, ConstantPoolCacheEntry::tosBits); // Make sure we don't need to mask flags for tosBits after the above shift ConstantPoolCacheEntry::verify_tosBits(); // load return address ! { ! address table_addr = ! (is_invdyn_bootstrap) ! ? (address)Interpreter::return_5_unbox_addrs_by_index_table() ! : (is_invokeinterface || is_invokedynamic) ! ? (address)Interpreter::return_5_addrs_by_index_table() ! : (address)Interpreter::return_3_addrs_by_index_table(); ! ExternalAddress table(table_addr); ! __ movptr(flags, ArrayAddress(table, Address(noreg, flags, Address::times_ptr))); } // push return address __ push(flags);
*** 2986,2996 **** } void TemplateTable::invokevirtual(int byte_no) { transition(vtos, vtos); ! prepare_invoke(rbx, noreg, byte_no, bytecode()); // rbx,: index // rcx: receiver // rdx: flags --- 3011,3021 ---- } void TemplateTable::invokevirtual(int byte_no) { transition(vtos, vtos); ! prepare_invoke(rbx, noreg, byte_no); // rbx,: index // rcx: receiver // rdx: flags
*** 2998,3018 **** } void TemplateTable::invokespecial(int byte_no) { transition(vtos, vtos); ! prepare_invoke(rbx, noreg, byte_no, bytecode()); // do the call __ verify_oop(rbx); __ profile_call(rax); __ jump_from_interpreted(rbx, rax); } void TemplateTable::invokestatic(int byte_no) { transition(vtos, vtos); ! prepare_invoke(rbx, noreg, byte_no, bytecode()); // do the call __ verify_oop(rbx); __ profile_call(rax); __ jump_from_interpreted(rbx, rax); } --- 3023,3043 ---- } void TemplateTable::invokespecial(int byte_no) { transition(vtos, vtos); ! prepare_invoke(rbx, noreg, byte_no); // do the call __ verify_oop(rbx); __ profile_call(rax); __ jump_from_interpreted(rbx, rax); } void TemplateTable::invokestatic(int byte_no) { transition(vtos, vtos); ! prepare_invoke(rbx, noreg, byte_no); // do the call __ verify_oop(rbx); __ profile_call(rax); __ jump_from_interpreted(rbx, rax); }
*** 3024,3034 **** } void TemplateTable::invokeinterface(int byte_no) { transition(vtos, vtos); ! prepare_invoke(rax, rbx, byte_no, bytecode()); // rax,: Interface // rbx,: index // rcx: receiver // rdx: flags --- 3049,3059 ---- } void TemplateTable::invokeinterface(int byte_no) { transition(vtos, vtos); ! prepare_invoke(rax, rbx, byte_no); // rax,: Interface // rbx,: index // rcx: receiver // rdx: flags
*** 3176,3185 **** --- 3201,3283 ---- // rcx: receiver // rbx,: methodOop __ jump_from_interpreted(rbx, rdx); } + void TemplateTable::invokedynamic(int byte_no) { + transition(vtos, vtos); + + if (!InvokeDynamic) { + // We do not encounter this bytecode if !InvokeDynamic. + // See Rewriter::rewrite_invokedynamic. + __ stop("invokedynamic not enabled"); + return; + } + + prepare_invoke(rax, rbx, byte_no); + + // rax: CallSite object (f1) + // rbx: unused (f2) + // rcx: receiver address + // rdx: flags (unused) + + if (ProfileInterpreter) { + Label L; + __ movl(rdx, Address(rcx, 0)); + __ testl(rdx, rdx); + __ jcc(Assembler::zero, L); + + // Get receiver klass into rdx + __ movl(rdx, Address(rdx, oopDesc::klass_offset_in_bytes())); + __ verify_oop(rdx); + __ bind(L); + + // profile this call + __ profile_virtual_call(rdx, rsi, rdi, true); + } + + Label handle_unlinked_site; + __ movptr(rcx, Address(rax, __ delayed_value(java_dyn_impl_DynCallSite::target_offset_in_bytes, rcx))); + __ testptr(rcx, rcx); + __ jcc(Assembler::zero, handle_unlinked_site); + + __ prepare_to_jump_from_interpreted(); + __ jump_to_method_handle_entry(rcx, rdx); + + // Initial calls come here... + __ bind(handle_unlinked_site); + __ pop(rcx); // remove return address pushed by prepare_invoke + + address entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::bootstrap_invokedynamic); + // squish stacked arguments together on stack, preceded by call site + // return bootstrap method as a handle in rcx + __ restore_bcp(); // rsi must be correct for call_VM + __ call_VM(rax, entry, rax); + __ movl(rdi, rax); // protect MH from prepare_invoke + + // recompute return address + __ restore_bcp(); // rsi must be correct for prepare_invoke + prepare_invoke(rax, rbx, -byte_no); + // rax: CallSite object (f1) + // rbx: unused (f2) + // rcx: receiver address (now holds arglist) + // rdx: flags + + // save SP now, before we add the bootstrap call to the stack + __ prepare_to_jump_from_interpreted(); + + // let's play adapter + __ pop(rbx); // return value + __ push(rdi); // boot MH + __ push(rax); // call site + __ movptr(rcx, Address(rcx, 0)); + __ push(rcx); // arglist + __ push(rbx); // return value + __ mov(rcx, rdi); + __ jump_to_method_handle_entry(rcx, rdx); + } + //---------------------------------------------------------------------------------------------------- // Allocation void TemplateTable::_new() { transition(vtos, atos);
src/cpu/x86/vm/templateTable_x86_32.cpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File