src/cpu/x86/vm/templateTable_x86_64.cpp
Index
Unified diffs
Context diffs
Sdiffs
Wdiffs
Patch
New
Old
Previous File
Next File
6829192 Cdiff src/cpu/x86/vm/templateTable_x86_64.cpp
src/cpu/x86/vm/templateTable_x86_64.cpp
Print this page
rev 1022 : 6829192: JSR 292 needs to support 64-bit x86
Summary: changes for method handles and invokedynamic
Reviewed-by: ?, ?
*** 201,222 ****
__ movzbl(scratch, at_bcp(0));
__ cmpl(scratch, Bytecodes::_breakpoint);
__ jcc(Assembler::notEqual, fast_patch);
__ 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, r13, 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));
__ jcc(Assembler::equal, okay);
__ cmpl(scratch, bc);
--- 201,219 ----
__ movzbl(scratch, at_bcp(0));
__ cmpl(scratch, Bytecodes::_breakpoint);
__ jcc(Assembler::notEqual, fast_patch);
__ 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, r13, 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));
__ jcc(Assembler::equal, okay);
__ cmpl(scratch, bc);
*** 2052,2081 ****
if (os::is_MP()) { // Not needed on single CPU
__ 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");
const 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_8,
! 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:
--- 2049,2080 ----
if (os::is_MP()) { // Not needed on single CPU
__ 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);
const 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_ptr, 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:
*** 2088,2106 ****
case Bytecodes::_invokespecial:
case Bytecodes::_invokestatic:
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 Rcache and index registers must be set before call
void TemplateTable::load_field_cp_cache_entry(Register obj,
--- 2087,2108 ----
case Bytecodes::_invokespecial:
case Bytecodes::_invokestatic:
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 Rcache and index registers must be set before call
void TemplateTable::load_field_cp_cache_entry(Register obj,
*** 2830,2848 ****
void TemplateTable::count_calls(Register method, Register temp) {
// 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;
--- 2832,2849 ----
void TemplateTable::count_calls(Register method, Register temp) {
// implemented elsewhere
ShouldNotReachHere();
}
! void TemplateTable::prepare_invoke(Register method, Register index, int 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 && code != Bytecodes::_invokedynamic);
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;
*** 2856,2869 ****
// load receiver if needed (note: no return address pushed yet)
if (load_receiver) {
__ movl(recv, flags);
__ andl(recv, 0xFF);
if (TaggedStackInterpreter) __ shll(recv, 1); // index*2
! __ movptr(recv, Address(rsp, recv, Address::times_8,
! -Interpreter::expr_offset_in_bytes(1)));
__ verify_oop(recv);
}
// do null check if needed
if (receiver_null_check) {
__ null_check(recv);
}
--- 2857,2874 ----
// load receiver if needed (note: no return address pushed yet)
if (load_receiver) {
__ movl(recv, flags);
__ andl(recv, 0xFF);
if (TaggedStackInterpreter) __ shll(recv, 1); // index*2
! Address recv_addr(rsp, recv, Address::times_8, -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);
}
*** 2876,2889 ****
__ 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
{
! ExternalAddress return_5((address)Interpreter::return_5_addrs_by_index_table());
! ExternalAddress return_3((address)Interpreter::return_3_addrs_by_index_table());
! __ lea(rscratch1, (is_invokeinterface ? return_5 : return_3));
! __ movptr(flags, Address(rscratch1, flags, Address::times_8));
}
// push return address
__ push(flags);
--- 2881,2898 ----
__ 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;
! if (is_invokeinterface || is_invokedynamic)
! table_addr = (address)Interpreter::return_5_addrs_by_index_table();
! else
! table_addr = (address)Interpreter::return_3_addrs_by_index_table();
! ExternalAddress table(table_addr);
! __ lea(rscratch1, table);
! __ movptr(flags, Address(rscratch1, flags, Address::times_ptr));
}
// push return address
__ push(flags);
*** 2945,2955 ****
}
void TemplateTable::invokevirtual(int byte_no) {
transition(vtos, vtos);
! prepare_invoke(rbx, noreg, byte_no, bytecode());
// rbx: index
// rcx: receiver
// rdx: flags
--- 2954,2964 ----
}
void TemplateTable::invokevirtual(int byte_no) {
transition(vtos, vtos);
! prepare_invoke(rbx, noreg, byte_no);
// rbx: index
// rcx: receiver
// rdx: flags
*** 2957,2977 ****
}
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);
}
--- 2966,2986 ----
}
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);
}
*** 2981,2991 ****
__ stop("fast_invokevfinal not used on amd64");
}
void TemplateTable::invokeinterface(int byte_no) {
transition(vtos, vtos);
! prepare_invoke(rax, rbx, byte_no, bytecode());
// rax: Interface
// rbx: index
// rcx: receiver
// rdx: flags
--- 2990,3000 ----
__ stop("fast_invokevfinal not used on amd64");
}
void TemplateTable::invokeinterface(int byte_no) {
transition(vtos, vtos);
! prepare_invoke(rax, rbx, byte_no);
// rax: Interface
// rbx: index
// rcx: receiver
// rdx: flags
*** 3070,3080 ****
// the call_VM checks for exception, so we should never return here.
__ should_not_reach_here();
return;
}
! __ stop("invokedynamic NYI");//6815692//
}
//-----------------------------------------------------------------------------
// Allocation
--- 3079,3106 ----
// the call_VM checks for exception, so we should never return here.
__ should_not_reach_here();
return;
}
! prepare_invoke(rax, rbx, byte_no);
!
! // rax: CallSite object (f1)
! // rbx: unused (f2)
! // rcx: receiver address
! // rdx: flags (unused)
!
! if (ProfileInterpreter) {
! Label L;
! // %%% should make a type profile for any invokedynamic that takes a ref argument
! // profile this call
! __ profile_call(r13);
! }
!
! __ movptr(rcx, Address(rax, __ delayed_value(java_dyn_CallSite::target_offset_in_bytes, rcx)));
! __ null_check(rcx);
! __ prepare_to_jump_from_interpreted();
! __ jump_to_method_handle_entry(rcx, rdx);
}
//-----------------------------------------------------------------------------
// Allocation
src/cpu/x86/vm/templateTable_x86_64.cpp
Index
Unified diffs
Context diffs
Sdiffs
Wdiffs
Patch
New
Old
Previous File
Next File