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