This commit is contained in:
Erik Trimble 2011-01-13 22:54:23 -08:00
commit bb7771888b
79 changed files with 1042 additions and 1089 deletions

View File

@ -4104,7 +4104,7 @@ void MacroAssembler::tlab_refill(Label& retry, Label& try_eden, Label& slow_case
ld_ptr(G2_thread, in_bytes(JavaThread::tlab_start_offset()), t1);
sub(top, t1, t1); // size of tlab's allocated portion
incr_allocated_bytes(t1, 0, t2);
incr_allocated_bytes(t1, t2, t3);
// refill the tlab with an eden allocation
bind(do_refill);
@ -4138,19 +4138,14 @@ void MacroAssembler::tlab_refill(Label& retry, Label& try_eden, Label& slow_case
delayed()->nop();
}
void MacroAssembler::incr_allocated_bytes(Register var_size_in_bytes,
int con_size_in_bytes,
Register t1) {
void MacroAssembler::incr_allocated_bytes(RegisterOrConstant size_in_bytes,
Register t1, Register t2) {
// Bump total bytes allocated by this thread
assert(t1->is_global(), "must be global reg"); // so all 64 bits are saved on a context switch
assert_different_registers(var_size_in_bytes, t1);
assert_different_registers(size_in_bytes.register_or_noreg(), t1, t2);
// v8 support has gone the way of the dodo
ldx(G2_thread, in_bytes(JavaThread::allocated_bytes_offset()), t1);
if (var_size_in_bytes->is_valid()) {
add(t1, var_size_in_bytes, t1);
} else {
add(t1, con_size_in_bytes, t1);
}
add(t1, ensure_simm13_or_reg(size_in_bytes, t2), t1);
stx(t1, G2_thread, in_bytes(JavaThread::allocated_bytes_offset()));
}

View File

@ -823,15 +823,23 @@ class Assembler : public AbstractAssembler {
};
// test if x is within signed immediate range for nbits
static bool is_simm(int x, int nbits) { return -( 1 << nbits-1 ) <= x && x < ( 1 << nbits-1 ); }
static bool is_simm(intptr_t x, int nbits) { return -( intptr_t(1) << nbits-1 ) <= x && x < ( intptr_t(1) << nbits-1 ); }
// test if -4096 <= x <= 4095
static bool is_simm13(int x) { return is_simm(x, 13); }
static bool is_simm13(intptr_t x) { return is_simm(x, 13); }
static bool is_in_wdisp_range(address a, address b, int nbits) {
intptr_t d = intptr_t(b) - intptr_t(a);
return is_simm(d, nbits + 2);
}
// test if label is in simm16 range in words (wdisp16).
bool is_in_wdisp16_range(Label& L) {
intptr_t d = intptr_t(pc()) - intptr_t(target(L));
return is_simm(d, 18);
return is_in_wdisp_range(target(L), pc(), 16);
}
// test if the distance between two addresses fits in simm30 range in words
static bool is_in_wdisp30_range(address a, address b) {
return is_in_wdisp_range(a, b, 30);
}
enum ASIs { // page 72, v9
@ -1843,6 +1851,8 @@ class MacroAssembler: public Assembler {
inline void jmp( Register s1, Register s2 );
inline void jmp( Register s1, int simm13a, RelocationHolder const& rspec = RelocationHolder() );
// Check if the call target is out of wdisp30 range (relative to the code cache)
static inline bool is_far_target(address d);
inline void call( address d, relocInfo::relocType rt = relocInfo::runtime_call_type );
inline void call( Label& L, relocInfo::relocType rt = relocInfo::runtime_call_type );
inline void callr( Register s1, Register s2 );
@ -2389,7 +2399,8 @@ public:
Label& slow_case // continuation point if fast allocation fails
);
void tlab_refill(Label& retry_tlab, Label& try_eden, Label& slow_case);
void incr_allocated_bytes(Register var_size_in_bytes, int con_size_in_bytes, Register t1);
void incr_allocated_bytes(RegisterOrConstant size_in_bytes,
Register t1, Register t2);
// interface method calling
void lookup_interface_method(Register recv_klass,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -588,10 +588,13 @@ inline void MacroAssembler::fbp( Condition c, bool a, CC cc, Predict p, Label& L
inline void MacroAssembler::jmp( Register s1, Register s2 ) { jmpl( s1, s2, G0 ); }
inline void MacroAssembler::jmp( Register s1, int simm13a, RelocationHolder const& rspec ) { jmpl( s1, simm13a, G0, rspec); }
inline bool MacroAssembler::is_far_target(address d) {
return !is_in_wdisp30_range(d, CodeCache::low_bound()) || !is_in_wdisp30_range(d, CodeCache::high_bound());
}
// Call with a check to see if we need to deal with the added
// expense of relocation and if we overflow the displacement
// of the quick call instruction./
// Check to see if we have to deal with relocations
// of the quick call instruction.
inline void MacroAssembler::call( address d, relocInfo::relocType rt ) {
#ifdef _LP64
intptr_t disp;
@ -603,14 +606,12 @@ inline void MacroAssembler::call( address d, relocInfo::relocType rt ) {
// Is this address within range of the call instruction?
// If not, use the expensive instruction sequence
disp = (intptr_t)d - (intptr_t)pc();
if ( disp != (intptr_t)(int32_t)disp ) {
if (is_far_target(d)) {
relocate(rt);
AddressLiteral dest(d);
jumpl_to(dest, O7, O7);
}
else {
Assembler::call( d, rt );
} else {
Assembler::call(d, rt);
}
#else
Assembler::call( d, rt );

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -2358,6 +2358,8 @@ void LIR_Assembler::emit_alloc_array(LIR_OpAllocArray* op) {
op->tmp3()->as_register() == G4 &&
op->tmp4()->as_register() == O1 &&
op->klass()->as_register() == G5, "must be");
LP64_ONLY( __ signx(op->len()->as_register()); )
if (UseSlowPath ||
(!UseFastNewObjectArray && (op->type() == T_OBJECT || op->type() == T_ARRAY)) ||
(!UseFastNewTypeArray && (op->type() != T_OBJECT && op->type() != T_ARRAY))) {

View File

@ -170,11 +170,13 @@ void C1_MacroAssembler::try_allocate(
Register t2, // temp register
Label& slow_case // continuation point if fast allocation fails
) {
RegisterOrConstant size_in_bytes = var_size_in_bytes->is_valid()
? RegisterOrConstant(var_size_in_bytes) : RegisterOrConstant(con_size_in_bytes);
if (UseTLAB) {
tlab_allocate(obj, var_size_in_bytes, con_size_in_bytes, t1, slow_case);
} else {
eden_allocate(obj, var_size_in_bytes, con_size_in_bytes, t1, t2, slow_case);
incr_allocated_bytes(var_size_in_bytes, con_size_in_bytes, t1);
incr_allocated_bytes(size_in_bytes, t1, t2);
}
}

View File

@ -461,7 +461,7 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
// get the instance size
__ ld(G5_klass, klassOopDesc::header_size() * HeapWordSize + Klass::layout_helper_offset_in_bytes(), G1_obj_size);
__ eden_allocate(O0_obj, G1_obj_size, 0, G3_t1, G4_t2, slow_path);
__ incr_allocated_bytes(G1_obj_size, 0, G3_t1);
__ incr_allocated_bytes(G1_obj_size, G3_t1, G4_t2);
__ initialize_object(O0_obj, G5_klass, G1_obj_size, 0, G3_t1, G4_t2);
__ verify_oop(O0_obj);
@ -577,7 +577,7 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
__ and3(G1_arr_size, ~MinObjAlignmentInBytesMask, G1_arr_size);
__ eden_allocate(O0_obj, G1_arr_size, 0, G3_t1, O1_t2, slow_path); // preserves G1_arr_size
__ incr_allocated_bytes(G1_arr_size, 0, G3_t1);
__ incr_allocated_bytes(G1_arr_size, G3_t1, O1_t2);
__ initialize_header(O0_obj, G5_klass, G4_length, G3_t1, O1_t2);
__ ldub(klass_lh, G3_t1, klass_lh_header_size_offset);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -1295,16 +1295,13 @@ void InterpreterMacroAssembler::unlock_object(Register lock_reg) {
// Get the method data pointer from the methodOop and set the
// specified register to its value.
void InterpreterMacroAssembler::set_method_data_pointer_offset(Register Roff) {
void InterpreterMacroAssembler::set_method_data_pointer() {
assert(ProfileInterpreter, "must be profiling interpreter");
Label get_continue;
ld_ptr(Lmethod, in_bytes(methodOopDesc::method_data_offset()), ImethodDataPtr);
test_method_data_pointer(get_continue);
add(ImethodDataPtr, in_bytes(methodDataOopDesc::data_offset()), ImethodDataPtr);
if (Roff != noreg)
// Roff contains a method data index ("mdi"). It defaults to zero.
add(ImethodDataPtr, Roff, ImethodDataPtr);
bind(get_continue);
}
@ -1315,10 +1312,11 @@ void InterpreterMacroAssembler::set_method_data_pointer_for_bcp() {
Label zero_continue;
// Test MDO to avoid the call if it is NULL.
ld_ptr(Lmethod, methodOopDesc::method_data_offset(), ImethodDataPtr);
ld_ptr(Lmethod, in_bytes(methodOopDesc::method_data_offset()), ImethodDataPtr);
test_method_data_pointer(zero_continue);
call_VM_leaf(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::bcp_to_di), Lmethod, Lbcp);
set_method_data_pointer_offset(O0);
add(ImethodDataPtr, in_bytes(methodDataOopDesc::data_offset()), ImethodDataPtr);
add(ImethodDataPtr, O0, ImethodDataPtr);
bind(zero_continue);
}
@ -1369,7 +1367,6 @@ void InterpreterMacroAssembler::verify_method_data_pointer() {
}
void InterpreterMacroAssembler::test_invocation_counter_for_mdp(Register invocation_count,
Register cur_bcp,
Register Rtmp,
Label &profile_continue) {
assert(ProfileInterpreter, "must be profiling interpreter");
@ -1400,8 +1397,8 @@ void InterpreterMacroAssembler::test_invocation_counter_for_mdp(Register invocat
delayed()->nop();
// Build it now.
call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method), cur_bcp);
set_method_data_pointer_offset(O0);
call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method));
set_method_data_pointer_for_bcp();
ba(false, profile_continue);
delayed()->nop();
bind(done);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -269,12 +269,11 @@ class InterpreterMacroAssembler: public MacroAssembler {
#ifndef CC_INTERP
// Interpreter profiling operations
void set_method_data_pointer() { set_method_data_pointer_offset(noreg); }
void set_method_data_pointer();
void set_method_data_pointer_for_bcp();
void set_method_data_pointer_offset(Register mdi_reg);
void test_method_data_pointer(Label& zero_continue);
void verify_method_data_pointer();
void test_invocation_counter_for_mdp(Register invocation_count, Register cur_bcp, Register Rtmp, Label &profile_continue);
void test_invocation_counter_for_mdp(Register invocation_count, Register Rtmp, Label &profile_continue);
void set_mdp_data_at(int constant, Register value);
void increment_mdp_data_at(Address counter, Register bumped_count,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -395,7 +395,7 @@ int MethodHandles::adapter_conversion_ops_supported_mask() {
//
// Generate an "entry" field for a method handle.
// This determines how the method handle will respond to calls.
void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHandles::EntryKind ek, TRAPS) {
void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHandles::EntryKind ek) {
// Here is the register state during an interpreted call,
// as set up by generate_method_handle_interpreter_entry():
// - G5: garbage temp (was MethodHandle.invoke methodOop, unused)
@ -447,8 +447,9 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
// exception. Since we use a C2I adapter to set up the
// interpreter state, arguments are expected in compiler
// argument registers.
methodHandle mh(raise_exception_method());
address c2i_entry = methodOopDesc::make_adapters(mh, CATCH);
assert(raise_exception_method(), "must be set");
address c2i_entry = raise_exception_method()->get_c2i_entry();
assert(c2i_entry, "method must be linked");
__ mov(O5_savedSP, SP); // Cut the stack back to where the caller started.

View File

@ -1,5 +1,5 @@
//
// Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
// Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
//
// This code is free software; you can redistribute it and/or modify it
@ -575,7 +575,11 @@ int MachCallDynamicJavaNode::ret_addr_offset() {
int MachCallRuntimeNode::ret_addr_offset() {
#ifdef _LP64
return NativeFarCall::instruction_size; // farcall; delay slot
if (MacroAssembler::is_far_target(entry_point())) {
return NativeFarCall::instruction_size;
} else {
return NativeCall::instruction_size;
}
#else
return NativeCall::instruction_size; // call; delay slot
#endif
@ -941,7 +945,7 @@ void emit_form3_mem_reg(CodeBuffer &cbuf, const MachNode* n, int primary, int te
#endif
}
void emit_call_reloc(CodeBuffer &cbuf, intptr_t entry_point, relocInfo::relocType rtype, bool preserve_g2 = false, bool force_far_call = false) {
void emit_call_reloc(CodeBuffer &cbuf, intptr_t entry_point, relocInfo::relocType rtype, bool preserve_g2 = false) {
// The method which records debug information at every safepoint
// expects the call to be the first instruction in the snippet as
// it creates a PcDesc structure which tracks the offset of a call
@ -963,20 +967,7 @@ void emit_call_reloc(CodeBuffer &cbuf, intptr_t entry_point, relocInfo::relocTyp
int startpos = __ offset();
#endif /* ASSERT */
#ifdef _LP64
// Calls to the runtime or native may not be reachable from compiled code,
// so we generate the far call sequence on 64 bit sparc.
// This code sequence is relocatable to any address, even on LP64.
if ( force_far_call ) {
__ relocate(rtype);
AddressLiteral dest(entry_point);
__ jumpl_to(dest, O7, O7);
}
else
#endif
{
__ call((address)entry_point, rtype);
}
__ call((address)entry_point, rtype);
if (preserve_g2) __ delayed()->mov(G2, L7);
else __ delayed()->nop();
@ -2507,7 +2498,7 @@ encode %{
// CALL directly to the runtime
// The user of this is responsible for ensuring that R_L7 is empty (killed).
emit_call_reloc(cbuf, $meth$$method, relocInfo::runtime_call_type,
/*preserve_g2=*/true, /*force far call*/true);
/*preserve_g2=*/true);
%}
enc_class preserve_SP %{

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -1364,15 +1364,8 @@ address InterpreterGenerator::generate_normal_entry(bool synchronized) {
// We have decided to profile this method in the interpreter
__ bind(profile_method);
__ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method), Lbcp, true);
#ifdef ASSERT
__ tst(O0);
__ breakpoint_trap(Assembler::notEqual);
#endif
__ set_method_data_pointer();
__ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method));
__ set_method_data_pointer_for_bcp();
__ ba(false, profile_method_continue);
__ delayed()->nop();
}

View File

@ -1689,7 +1689,7 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) {
const Register G4_invoke_ctr = G4;
__ increment_backedge_counter(G4_invoke_ctr, G1_scratch);
if (ProfileInterpreter) {
__ test_invocation_counter_for_mdp(G4_invoke_ctr, Lbcp, G3_scratch, Lforward);
__ test_invocation_counter_for_mdp(G4_invoke_ctr, G3_scratch, Lforward);
if (UseOnStackReplacement) {
__ test_backedge_count_for_osr(O2_bumped_count, O0_cur_bcp, G3_scratch);
}
@ -3447,7 +3447,8 @@ void TemplateTable::_new() {
__ delayed()->nop();
// bump total bytes allocated by this thread
__ incr_allocated_bytes(Roffset, 0, G1_scratch);
// RoldTopValue and RtopAddr are dead, so can use G1 and G3
__ incr_allocated_bytes(Roffset, G1_scratch, G3_scratch);
}
if (UseTLAB || Universe::heap()->supports_inline_contig_alloc()) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -1641,12 +1641,14 @@ void LIR_Assembler::emit_alloc_obj(LIR_OpAllocObj* op) {
}
void LIR_Assembler::emit_alloc_array(LIR_OpAllocArray* op) {
Register len = op->len()->as_register();
LP64_ONLY( __ movslq(len, len); )
if (UseSlowPath ||
(!UseFastNewObjectArray && (op->type() == T_OBJECT || op->type() == T_ARRAY)) ||
(!UseFastNewTypeArray && (op->type() != T_OBJECT && op->type() != T_ARRAY))) {
__ jmp(*op->stub()->entry());
} else {
Register len = op->len()->as_register();
Register tmp1 = op->tmp1()->as_register();
Register tmp2 = op->tmp2()->as_register();
Register tmp3 = op->tmp3()->as_register();

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -819,7 +819,7 @@ void InterpreterMacroAssembler::test_method_data_pointer(Register mdp, Label& ze
// Set the method data pointer for the current bcp.
void InterpreterMacroAssembler::set_method_data_pointer_for_bcp() {
assert(ProfileInterpreter, "must be profiling interpreter");
Label zero_continue;
Label set_mdp;
push(rax);
push(rbx);
@ -827,21 +827,17 @@ void InterpreterMacroAssembler::set_method_data_pointer_for_bcp() {
// Test MDO to avoid the call if it is NULL.
movptr(rax, Address(rbx, in_bytes(methodOopDesc::method_data_offset())));
testptr(rax, rax);
jcc(Assembler::zero, zero_continue);
jcc(Assembler::zero, set_mdp);
// rbx,: method
// rsi: bcp
call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::bcp_to_di), rbx, rsi);
// rax,: mdi
// mdo is guaranteed to be non-zero here, we checked for it before the call.
movptr(rbx, Address(rbx, in_bytes(methodOopDesc::method_data_offset())));
testptr(rbx, rbx);
jcc(Assembler::zero, zero_continue);
addptr(rbx, in_bytes(methodDataOopDesc::data_offset()));
addptr(rbx, rax);
movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), rbx);
bind(zero_continue);
addptr(rax, rbx);
bind(set_mdp);
movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), rax);
pop(rbx);
pop(rax);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -855,7 +855,7 @@ void InterpreterMacroAssembler::test_method_data_pointer(Register mdp,
// Set the method data pointer for the current bcp.
void InterpreterMacroAssembler::set_method_data_pointer_for_bcp() {
assert(ProfileInterpreter, "must be profiling interpreter");
Label zero_continue;
Label set_mdp;
push(rax);
push(rbx);
@ -863,21 +863,17 @@ void InterpreterMacroAssembler::set_method_data_pointer_for_bcp() {
// Test MDO to avoid the call if it is NULL.
movptr(rax, Address(rbx, in_bytes(methodOopDesc::method_data_offset())));
testptr(rax, rax);
jcc(Assembler::zero, zero_continue);
jcc(Assembler::zero, set_mdp);
// rbx: method
// r13: bcp
call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::bcp_to_di), rbx, r13);
// rax: mdi
// mdo is guaranteed to be non-zero here, we checked for it before the call.
movptr(rbx, Address(rbx, in_bytes(methodOopDesc::method_data_offset())));
testptr(rbx, rbx);
jcc(Assembler::zero, zero_continue);
addptr(rbx, in_bytes(methodDataOopDesc::data_offset()));
addptr(rbx, rax);
movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), rbx);
bind(zero_continue);
addptr(rax, rbx);
bind(set_mdp);
movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), rax);
pop(rbx);
pop(rax);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -390,7 +390,7 @@ int MethodHandles::adapter_conversion_ops_supported_mask() {
//
// Generate an "entry" field for a method handle.
// This determines how the method handle will respond to calls.
void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHandles::EntryKind ek, TRAPS) {
void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHandles::EntryKind ek) {
// Here is the register state during an interpreted call,
// as set up by generate_method_handle_interpreter_entry():
// - rbx: garbage temp (was MethodHandle.invoke methodOop, unused)
@ -451,8 +451,9 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
// exception. Since we use a C2I adapter to set up the
// interpreter state, arguments are expected in compiler
// argument registers.
methodHandle mh(raise_exception_method());
address c2i_entry = methodOopDesc::make_adapters(mh, CHECK);
assert(raise_exception_method(), "must be set");
address c2i_entry = raise_exception_method()->get_c2i_entry();
assert(c2i_entry, "method must be linked");
const Register rdi_pc = rax;
__ pop(rdi_pc); // caller PC

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -1367,15 +1367,8 @@ address InterpreterGenerator::generate_normal_entry(bool synchronized) {
if (ProfileInterpreter) {
// We have decided to profile this method in the interpreter
__ bind(profile_method);
__ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method), rsi, true);
__ movptr(rbx, Address(rbp, method_offset)); // restore methodOop
__ movptr(rax, Address(rbx, in_bytes(methodOopDesc::method_data_offset())));
__ movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), rax);
__ test_method_data_pointer(rax, profile_method_continue);
__ addptr(rax, in_bytes(methodDataOopDesc::data_offset()));
__ movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), rax);
__ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method));
__ set_method_data_pointer_for_bcp();
__ jmp(profile_method_continue);
}
// Handle overflow of counter and compile method

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -1383,20 +1383,8 @@ address InterpreterGenerator::generate_normal_entry(bool synchronized) {
if (ProfileInterpreter) {
// We have decided to profile this method in the interpreter
__ bind(profile_method);
__ call_VM(noreg,
CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method),
r13, true);
__ movptr(rbx, Address(rbp, method_offset)); // restore methodOop
__ movptr(rax, Address(rbx,
in_bytes(methodOopDesc::method_data_offset())));
__ movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize),
rax);
__ test_method_data_pointer(rax, profile_method_continue);
__ addptr(rax, in_bytes(methodDataOopDesc::data_offset()));
__ movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize),
rax);
__ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method));
__ set_method_data_pointer_for_bcp();
__ jmp(profile_method_continue);
}
// Handle overflow of counter and compile method

View File

@ -1665,16 +1665,9 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) {
if (ProfileInterpreter) {
// Out-of-line code to allocate method data oop.
__ bind(profile_method);
__ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method), rsi);
__ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method));
__ load_unsigned_byte(rbx, Address(rsi, 0)); // restore target bytecode
__ movptr(rcx, Address(rbp, method_offset));
__ movptr(rcx, Address(rcx, in_bytes(methodOopDesc::method_data_offset())));
__ movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), rcx);
__ test_method_data_pointer(rcx, dispatch);
// offset non-null mdp by MDO::data_offset() + IR::profile_method()
__ addptr(rcx, in_bytes(methodDataOopDesc::data_offset()));
__ addptr(rcx, rax);
__ movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), rcx);
__ set_method_data_pointer_for_bcp();
__ jmp(dispatch);
}

View File

@ -1695,21 +1695,9 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) {
if (ProfileInterpreter) {
// Out-of-line code to allocate method data oop.
__ bind(profile_method);
__ call_VM(noreg,
CAST_FROM_FN_PTR(address,
InterpreterRuntime::profile_method), r13);
__ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method));
__ load_unsigned_byte(rbx, Address(r13, 0)); // restore target bytecode
__ movptr(rcx, Address(rbp, method_offset));
__ movptr(rcx, Address(rcx,
in_bytes(methodOopDesc::method_data_offset())));
__ movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize),
rcx);
__ test_method_data_pointer(rcx, dispatch);
// offset non-null mdp by MDO::data_offset() + IR::profile_method()
__ addptr(rcx, in_bytes(methodDataOopDesc::data_offset()));
__ addptr(rcx, rax);
__ movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize),
rcx);
__ set_method_data_pointer_for_bcp();
__ jmp(dispatch);
}

View File

@ -1610,10 +1610,9 @@ int os::current_process_id() {
const char* os::dll_file_extension() { return ".so"; }
const char* os::get_temp_directory() {
const char *prop = Arguments::get_property("java.io.tmpdir");
return prop == NULL ? "/tmp" : prop;
}
// This must be hard coded because it's the system's temporary
// directory not the java application's temp directory, ala java.io.tmpdir.
const char* os::get_temp_directory() { return "/tmp"; }
static bool file_exists(const char* filename) {
struct stat statbuf;

View File

@ -1884,10 +1884,9 @@ void os::set_error_file(const char *logfile) {}
const char* os::dll_file_extension() { return ".so"; }
const char* os::get_temp_directory() {
const char *prop = Arguments::get_property("java.io.tmpdir");
return prop == NULL ? "/tmp" : prop;
}
// This must be hard coded because it's the system's temporary
// directory not the java application's temp directory, ala java.io.tmpdir.
const char* os::get_temp_directory() { return "/tmp"; }
static bool file_exists(const char* filename) {
struct stat statbuf;

View File

@ -1044,9 +1044,9 @@ os::closedir(DIR *dirp)
return 0;
}
// This must be hard coded because it's the system's temporary
// directory not the java application's temp directory, ala java.io.tmpdir.
const char* os::get_temp_directory() {
const char *prop = Arguments::get_property("java.io.tmpdir");
if (prop != 0) return prop;
static char path_buf[MAX_PATH];
if (GetTempPath(MAX_PATH, path_buf)>0)
return path_buf;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -54,6 +54,8 @@ inline void Atomic::dec (volatile jint* dest) { (void)add (-1, dest);
inline void Atomic::dec_ptr(volatile intptr_t* dest) { (void)add_ptr(-1, dest); }
inline void Atomic::dec_ptr(volatile void* dest) { (void)add_ptr(-1, dest); }
inline jlong Atomic::load(volatile jlong* src) { return *src; }
inline jint Atomic::add (jint add_value, volatile jint* dest) {
intptr_t rv;
__asm__ volatile(

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -100,11 +100,6 @@ inline jint Atomic::cmpxchg (jint exchange_value, volatile jint*
return exchange_value;
}
extern "C" {
// defined in linux_x86.s
jlong _Atomic_cmpxchg_long(jlong, volatile jlong*, jlong, bool);
}
#ifdef AMD64
inline void Atomic::store (jlong store_value, jlong* dest) { *dest = store_value; }
inline void Atomic::store (jlong store_value, volatile jlong* dest) { *dest = store_value; }
@ -164,9 +159,9 @@ inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void*
return (void*)cmpxchg((jlong)exchange_value, (volatile jlong*)dest, (jlong)compare_value);
}
#else
//inline void Atomic::store (jlong store_value, jlong* dest) { *dest = store_value; }
//inline void Atomic::store (jlong store_value, volatile jlong* dest) { *dest = store_value; }
inline jlong Atomic::load(volatile jlong* src) { return *src; }
#else // !AMD64
inline intptr_t Atomic::add_ptr(intptr_t add_value, volatile intptr_t* dest) {
return (intptr_t)Atomic::add((jint)add_value, (volatile jint*)dest);
@ -189,6 +184,12 @@ inline intptr_t Atomic::xchg_ptr(intptr_t exchange_value, volatile intptr_t* des
return (intptr_t)xchg((jint)exchange_value, (volatile jint*)dest);
}
extern "C" {
// defined in linux_x86.s
jlong _Atomic_cmpxchg_long(jlong, volatile jlong*, jlong, bool);
void _Atomic_move_long(volatile jlong* src, volatile jlong* dst);
}
inline jlong Atomic::cmpxchg (jlong exchange_value, volatile jlong* dest, jlong compare_value) {
return _Atomic_cmpxchg_long(exchange_value, dest, compare_value, os::is_MP());
}
@ -200,6 +201,21 @@ inline intptr_t Atomic::cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t*
inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void* dest, void* compare_value) {
return (void*)cmpxchg((jint)exchange_value, (volatile jint*)dest, (jint)compare_value);
}
inline jlong Atomic::load(volatile jlong* src) {
volatile jlong dest;
_Atomic_move_long(src, &dest);
return dest;
}
inline void Atomic::store(jlong store_value, jlong* dest) {
_Atomic_move_long((volatile jlong*)&store_value, (volatile jlong*)dest);
}
inline void Atomic::store(jlong store_value, volatile jlong* dest) {
_Atomic_move_long((volatile jlong*)&store_value, dest);
}
#endif // AMD64
#endif // OS_CPU_LINUX_X86_VM_ATOMIC_LINUX_X86_INLINE_HPP

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@ -38,6 +38,7 @@
.globl _mmx_Copy_arrayof_conjoint_jshorts
.globl _Atomic_cmpxchg_long
.globl _Atomic_move_long
.text
@ -653,3 +654,15 @@ _Atomic_cmpxchg_long:
popl %ebx
ret
# Support for jlong Atomic::load and Atomic::store.
# void _Atomic_move_long(volatile jlong* src, volatile jlong* dst)
.p2align 4,,15
.type _Atomic_move_long,@function
_Atomic_move_long:
movl 4(%esp), %eax # src
fildll (%eax)
movl 8(%esp), %eax # dest
fistpll (%eax)
ret

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,6 +25,7 @@
#ifndef OS_CPU_LINUX_X86_VM_ORDERACCESS_LINUX_X86_INLINE_HPP
#define OS_CPU_LINUX_X86_VM_ORDERACCESS_LINUX_X86_INLINE_HPP
#include "runtime/atomic.hpp"
#include "runtime/orderAccess.hpp"
#include "vm_version_x86.hpp"
@ -64,11 +65,11 @@ inline void OrderAccess::fence() {
inline jbyte OrderAccess::load_acquire(volatile jbyte* p) { return *p; }
inline jshort OrderAccess::load_acquire(volatile jshort* p) { return *p; }
inline jint OrderAccess::load_acquire(volatile jint* p) { return *p; }
inline jlong OrderAccess::load_acquire(volatile jlong* p) { return *p; }
inline jlong OrderAccess::load_acquire(volatile jlong* p) { return Atomic::load(p); }
inline jubyte OrderAccess::load_acquire(volatile jubyte* p) { return *p; }
inline jushort OrderAccess::load_acquire(volatile jushort* p) { return *p; }
inline juint OrderAccess::load_acquire(volatile juint* p) { return *p; }
inline julong OrderAccess::load_acquire(volatile julong* p) { return *p; }
inline julong OrderAccess::load_acquire(volatile julong* p) { return Atomic::load((volatile jlong*)p); }
inline jfloat OrderAccess::load_acquire(volatile jfloat* p) { return *p; }
inline jdouble OrderAccess::load_acquire(volatile jdouble* p) { return *p; }
@ -79,11 +80,11 @@ inline void* OrderAccess::load_ptr_acquire(const volatile void* p) { return *
inline void OrderAccess::release_store(volatile jbyte* p, jbyte v) { *p = v; }
inline void OrderAccess::release_store(volatile jshort* p, jshort v) { *p = v; }
inline void OrderAccess::release_store(volatile jint* p, jint v) { *p = v; }
inline void OrderAccess::release_store(volatile jlong* p, jlong v) { *p = v; }
inline void OrderAccess::release_store(volatile jlong* p, jlong v) { Atomic::store(v, p); }
inline void OrderAccess::release_store(volatile jubyte* p, jubyte v) { *p = v; }
inline void OrderAccess::release_store(volatile jushort* p, jushort v) { *p = v; }
inline void OrderAccess::release_store(volatile juint* p, juint v) { *p = v; }
inline void OrderAccess::release_store(volatile julong* p, julong v) { *p = v; }
inline void OrderAccess::release_store(volatile julong* p, julong v) { Atomic::store((jlong)v, (volatile jlong*)p); }
inline void OrderAccess::release_store(volatile jfloat* p, jfloat v) { *p = v; }
inline void OrderAccess::release_store(volatile jdouble* p, jdouble v) { *p = v; }
@ -178,7 +179,7 @@ inline void OrderAccess::release_store_fence(volatile jlong* p, jlong v)
: "0" (v), "r" (p)
: "memory");
#else
*p = v; fence();
release_store(p, v); fence();
#endif // AMD64
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -151,14 +151,22 @@ inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void*
return (void*)cmpxchg((jint)exchange_value, (volatile jint*)dest, (jint)compare_value);
}
extern "C" void _Atomic_load_long(volatile jlong* src, volatile jlong* dst);
extern "C" void _Atomic_move_long(volatile jlong* src, volatile jlong* dst);
inline jlong Atomic::load(volatile jlong* src) {
volatile jlong dest;
_Atomic_load_long(src, &dest);
_Atomic_move_long(src, &dest);
return dest;
}
inline void Atomic::store(jlong store_value, jlong* dest) {
_Atomic_move_long((volatile jlong*)&store_value, (volatile jlong*)dest);
}
inline void Atomic::store(jlong store_value, volatile jlong* dest) {
_Atomic_move_long((volatile jlong*)&store_value, dest);
}
#endif // AMD64
#ifdef _GNU_SOURCE

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,6 +25,7 @@
#ifndef OS_CPU_SOLARIS_X86_VM_ORDERACCESS_SOLARIS_X86_INLINE_HPP
#define OS_CPU_SOLARIS_X86_VM_ORDERACCESS_SOLARIS_X86_INLINE_HPP
#include "runtime/atomic.hpp"
#include "runtime/orderAccess.hpp"
#include "vm_version_x86.hpp"
@ -80,11 +81,11 @@ extern "C" {
inline jbyte OrderAccess::load_acquire(volatile jbyte* p) { return *p; }
inline jshort OrderAccess::load_acquire(volatile jshort* p) { return *p; }
inline jint OrderAccess::load_acquire(volatile jint* p) { return *p; }
inline jlong OrderAccess::load_acquire(volatile jlong* p) { return *p; }
inline jlong OrderAccess::load_acquire(volatile jlong* p) { return Atomic::load(p); }
inline jubyte OrderAccess::load_acquire(volatile jubyte* p) { return *p; }
inline jushort OrderAccess::load_acquire(volatile jushort* p) { return *p; }
inline juint OrderAccess::load_acquire(volatile juint* p) { return *p; }
inline julong OrderAccess::load_acquire(volatile julong* p) { return *p; }
inline julong OrderAccess::load_acquire(volatile julong* p) { return Atomic::load((volatile jlong*)p); }
inline jfloat OrderAccess::load_acquire(volatile jfloat* p) { return *p; }
inline jdouble OrderAccess::load_acquire(volatile jdouble* p) { return *p; }
@ -95,11 +96,11 @@ inline void* OrderAccess::load_ptr_acquire(const volatile void* p) { return *
inline void OrderAccess::release_store(volatile jbyte* p, jbyte v) { *p = v; }
inline void OrderAccess::release_store(volatile jshort* p, jshort v) { *p = v; }
inline void OrderAccess::release_store(volatile jint* p, jint v) { *p = v; }
inline void OrderAccess::release_store(volatile jlong* p, jlong v) { *p = v; }
inline void OrderAccess::release_store(volatile jlong* p, jlong v) { Atomic::store(v, p); }
inline void OrderAccess::release_store(volatile jubyte* p, jubyte v) { *p = v; }
inline void OrderAccess::release_store(volatile jushort* p, jushort v) { *p = v; }
inline void OrderAccess::release_store(volatile juint* p, juint v) { *p = v; }
inline void OrderAccess::release_store(volatile julong* p, julong v) { *p = v; }
inline void OrderAccess::release_store(volatile julong* p, julong v) { Atomic::store((jlong)v, (volatile jlong*)p); }
inline void OrderAccess::release_store(volatile jfloat* p, jfloat v) { *p = v; }
inline void OrderAccess::release_store(volatile jdouble* p, jdouble v) { *p = v; }
@ -123,11 +124,11 @@ inline void OrderAccess::store_ptr_fence(void** p, void* v) { *p = v;
inline void OrderAccess::release_store_fence(volatile jbyte* p, jbyte v) { *p = v; fence(); }
inline void OrderAccess::release_store_fence(volatile jshort* p, jshort v) { *p = v; fence(); }
inline void OrderAccess::release_store_fence(volatile jint* p, jint v) { *p = v; fence(); }
inline void OrderAccess::release_store_fence(volatile jlong* p, jlong v) { *p = v; fence(); }
inline void OrderAccess::release_store_fence(volatile jlong* p, jlong v) { release_store(p, v); fence(); }
inline void OrderAccess::release_store_fence(volatile jubyte* p, jubyte v) { *p = v; fence(); }
inline void OrderAccess::release_store_fence(volatile jushort* p, jushort v) { *p = v; fence(); }
inline void OrderAccess::release_store_fence(volatile juint* p, juint v) { *p = v; fence(); }
inline void OrderAccess::release_store_fence(volatile julong* p, julong v) { *p = v; fence(); }
inline void OrderAccess::release_store_fence(volatile julong* p, julong v) { release_store(p, v); fence(); }
inline void OrderAccess::release_store_fence(volatile jfloat* p, jfloat v) { *p = v; fence(); }
inline void OrderAccess::release_store_fence(volatile jdouble* p, jdouble v) { *p = v; fence(); }

View File

@ -1,5 +1,5 @@
//
// Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
// Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
//
// This code is free software; you can redistribute it and/or modify it
@ -104,8 +104,9 @@
popl %ebx
.end
// Support for void Atomic::load(volatile jlong* src, volatile jlong* dest).
.inline _Atomic_load_long,2
// Support for jlong Atomic::load and Atomic::store.
// void _Atomic_move_long(volatile jlong* src, volatile jlong* dst)
.inline _Atomic_move_long,2
movl 0(%esp), %eax // src
fildll (%eax)
movl 4(%esp), %eax // dest

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -137,10 +137,10 @@ inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void*
return (void*)cmpxchg((jlong)exchange_value, (volatile jlong*)dest, (jlong)compare_value);
}
inline jlong Atomic::load(volatile jlong* src) { return *src; }
#else // !AMD64
//inline void Atomic::store (jlong store_value, jlong* dest) { *dest = store_value; }
//inline void Atomic::store (jlong store_value, volatile jlong* dest) { *dest = store_value; }
inline jint Atomic::add (jint add_value, volatile jint* dest) {
int mp = os::is_MP();
__asm {
@ -254,6 +254,33 @@ inline intptr_t Atomic::cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t*
inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void* dest, void* compare_value) {
return (void*)cmpxchg((jint)exchange_value, (volatile jint*)dest, (jint)compare_value);
}
inline jlong Atomic::load(volatile jlong* src) {
volatile jlong dest;
volatile jlong* pdest = &dest;
__asm {
mov eax, src
fild qword ptr [eax]
mov eax, pdest
fistp qword ptr [eax]
}
return dest;
}
inline void Atomic::store(jlong store_value, volatile jlong* dest) {
volatile jlong* src = &store_value;
__asm {
mov eax, src
fild qword ptr [eax]
mov eax, dest
fistp qword ptr [eax]
}
}
inline void Atomic::store(jlong store_value, jlong* dest) {
Atomic::store(store_value, (volatile jlong*)dest);
}
#endif // AMD64
#pragma warning(default: 4035) // Enables warnings reporting missing return statement

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,6 +25,7 @@
#ifndef OS_CPU_WINDOWS_X86_VM_ORDERACCESS_WINDOWS_X86_INLINE_HPP
#define OS_CPU_WINDOWS_X86_VM_ORDERACCESS_WINDOWS_X86_INLINE_HPP
#include "runtime/atomic.hpp"
#include "runtime/orderAccess.hpp"
#include "vm_version_x86.hpp"
@ -65,11 +66,11 @@ inline void OrderAccess::fence() {
inline jbyte OrderAccess::load_acquire(volatile jbyte* p) { return *p; }
inline jshort OrderAccess::load_acquire(volatile jshort* p) { return *p; }
inline jint OrderAccess::load_acquire(volatile jint* p) { return *p; }
inline jlong OrderAccess::load_acquire(volatile jlong* p) { return *p; }
inline jlong OrderAccess::load_acquire(volatile jlong* p) { return Atomic::load(p); }
inline jubyte OrderAccess::load_acquire(volatile jubyte* p) { return *p; }
inline jushort OrderAccess::load_acquire(volatile jushort* p) { return *p; }
inline juint OrderAccess::load_acquire(volatile juint* p) { return *p; }
inline julong OrderAccess::load_acquire(volatile julong* p) { return *p; }
inline julong OrderAccess::load_acquire(volatile julong* p) { return Atomic::load((volatile jlong*)p); }
inline jfloat OrderAccess::load_acquire(volatile jfloat* p) { return *p; }
inline jdouble OrderAccess::load_acquire(volatile jdouble* p) { return *p; }
@ -80,11 +81,11 @@ inline void* OrderAccess::load_ptr_acquire(const volatile void* p) { return *
inline void OrderAccess::release_store(volatile jbyte* p, jbyte v) { *p = v; }
inline void OrderAccess::release_store(volatile jshort* p, jshort v) { *p = v; }
inline void OrderAccess::release_store(volatile jint* p, jint v) { *p = v; }
inline void OrderAccess::release_store(volatile jlong* p, jlong v) { *p = v; }
inline void OrderAccess::release_store(volatile jlong* p, jlong v) { Atomic::store(v, p); }
inline void OrderAccess::release_store(volatile jubyte* p, jubyte v) { *p = v; }
inline void OrderAccess::release_store(volatile jushort* p, jushort v) { *p = v; }
inline void OrderAccess::release_store(volatile juint* p, juint v) { *p = v; }
inline void OrderAccess::release_store(volatile julong* p, julong v) { *p = v; }
inline void OrderAccess::release_store(volatile julong* p, julong v) { Atomic::store((jlong)v, (volatile jlong*)p); }
inline void OrderAccess::release_store(volatile jfloat* p, jfloat v) { *p = v; }
inline void OrderAccess::release_store(volatile jdouble* p, jdouble v) { *p = v; }
@ -188,7 +189,7 @@ inline void OrderAccess::release_store_fence(volatile jint* p, jint v) {
#endif // AMD64
}
inline void OrderAccess::release_store_fence(volatile jlong* p, jlong v) { *p = v; fence(); }
inline void OrderAccess::release_store_fence(volatile jlong* p, jlong v) { release_store(p, v); fence(); }
inline void OrderAccess::release_store_fence(volatile jubyte* p, jubyte v) { release_store_fence((volatile jbyte*)p, (jbyte)v); }
inline void OrderAccess::release_store_fence(volatile jushort* p, jushort v) { release_store_fence((volatile jshort*)p, (jshort)v); }

View File

@ -1990,9 +1990,8 @@ void LIRGenerator::do_UnsafeGetObject(UnsafeGetObject* x) {
LIR_Opr reg = reg = rlock_result(x, x->basic_type());
if (x->is_volatile() && os::is_MP()) __ membar_acquire();
get_Object_unsafe(reg, src.result(), off.result(), type, x->is_volatile());
if (x->is_volatile() && os::is_MP()) __ membar();
if (x->is_volatile() && os::is_MP()) __ membar_acquire();
}
@ -2014,6 +2013,7 @@ void LIRGenerator::do_UnsafePutObject(UnsafePutObject* x) {
if (x->is_volatile() && os::is_MP()) __ membar_release();
put_Object_unsafe(src.result(), off.result(), data.result(), type, x->is_volatile());
if (x->is_volatile() && os::is_MP()) __ membar();
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -38,11 +38,12 @@
// Return an adapter for this MethodHandle.
ciMethod* ciMethodHandle::get_adapter(bool is_invokedynamic) const {
VM_ENTRY_MARK;
Handle h(get_oop());
methodHandle callee(_callee->get_methodOop());
MethodHandleCompiler mhc(h, callee, is_invokedynamic, THREAD);
methodHandle m = mhc.compile(CHECK_NULL);
// We catch all exceptions here that could happen in the method
// handle compiler and stop the VM.
MethodHandleCompiler mhc(h, callee, is_invokedynamic, CATCH);
methodHandle m = mhc.compile(CATCH);
return CURRENT_ENV->get_object(m())->as_method();
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -172,6 +172,8 @@ class SymbolPropertyTable;
\
template(sun_jkernel_DownloadManager_klass, sun_jkernel_DownloadManager, Opt_Kernel) \
\
template(sun_misc_PostVMInitHook_klass, sun_misc_PostVMInitHook, Opt) \
\
/* Preload boxing klasses */ \
template(Boolean_klass, java_lang_Boolean, Pre) \
template(Character_klass, java_lang_Character, Pre) \

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -111,6 +111,7 @@
template(sun_jkernel_DownloadManager, "sun/jkernel/DownloadManager") \
template(getBootClassPathEntryForClass_name, "getBootClassPathEntryForClass") \
template(setBootClassLoaderHook_name, "setBootClassLoaderHook") \
template(sun_misc_PostVMInitHook, "sun/misc/PostVMInitHook") \
\
/* class file format tags */ \
template(tag_source_file, "SourceFile") \

View File

@ -3478,6 +3478,7 @@ void CMSCollector::checkpointRootsInitial(bool asynch) {
assert(_collectorState == InitialMarking, "Wrong collector state");
check_correct_thread_executing();
TraceCMSMemoryManagerStats tms(_collectorState);
ReferenceProcessor* rp = ref_processor();
SpecializationStats::clear();
assert(_restart_addr == NULL, "Control point invariant");
@ -5940,11 +5941,6 @@ void CMSCollector::refProcessingWork(bool asynch, bool clear_all_soft_refs) {
}
rp->verify_no_references_recorded();
assert(!rp->discovery_enabled(), "should have been disabled");
// JVMTI object tagging is based on JNI weak refs. If any of these
// refs were cleared then JVMTI needs to update its maps and
// maybe post ObjectFrees to agents.
JvmtiExport::cms_ref_processing_epilogue();
}
#ifndef PRODUCT
@ -6305,6 +6301,7 @@ void CMSCollector::do_CMS_operation(CMS_op_type op) {
switch (op) {
case CMS_op_checkpointRootsInitial: {
SvcGCMarker sgcm(SvcGCMarker::OTHER);
checkpointRootsInitial(true); // asynch
if (PrintGC) {
_cmsGen->printOccupancy("initial-mark");
@ -6312,6 +6309,7 @@ void CMSCollector::do_CMS_operation(CMS_op_type op) {
break;
}
case CMS_op_checkpointRootsFinal: {
SvcGCMarker sgcm(SvcGCMarker::OTHER);
checkpointRootsFinal(true, // asynch
false, // !clear_all_soft_refs
false); // !init_mark_was_synchronous
@ -7881,25 +7879,23 @@ SweepClosure::SweepClosure(CMSCollector* collector,
}
// We need this destructor to reclaim any space at the end
// of the space, which do_blk below may not have added back to
// the free lists. [basically dealing with the "fringe effect"]
// of the space, which do_blk below may not yet have added back to
// the free lists.
SweepClosure::~SweepClosure() {
assert_lock_strong(_freelistLock);
// this should be treated as the end of a free run if any
// The current free range should be returned to the free lists
// as one coalesced chunk.
assert(_limit >= _sp->bottom() && _limit <= _sp->end(),
"sweep _limit out of bounds");
// Flush any remaining coterminal free run as a single
// coalesced chunk to the appropriate free list.
if (inFreeRange()) {
flushCurFreeChunk(freeFinger(),
pointer_delta(_limit, freeFinger()));
assert(freeFinger() < _limit, "the finger pointeth off base");
assert(freeFinger() < _limit, "freeFinger points too high");
flush_cur_free_chunk(freeFinger(), pointer_delta(_limit, freeFinger()));
if (CMSTraceSweeper) {
gclog_or_tty->print("destructor:");
gclog_or_tty->print("Sweep:put_free_blk 0x%x ("SIZE_FORMAT") "
"[coalesced:"SIZE_FORMAT"]\n",
freeFinger(), pointer_delta(_limit, freeFinger()),
lastFreeRangeCoalesced());
gclog_or_tty->print("Sweep: last chunk: ");
gclog_or_tty->print("put_free_blk 0x%x ("SIZE_FORMAT") [coalesced:"SIZE_FORMAT"]\n",
freeFinger(), pointer_delta(_limit, freeFinger()), lastFreeRangeCoalesced());
}
}
} // else nothing to flush
NOT_PRODUCT(
if (Verbose && PrintGC) {
gclog_or_tty->print("Collected "SIZE_FORMAT" objects, "
@ -7936,9 +7932,8 @@ SweepClosure::~SweepClosure() {
void SweepClosure::initialize_free_range(HeapWord* freeFinger,
bool freeRangeInFreeLists) {
if (CMSTraceSweeper) {
gclog_or_tty->print("---- Start free range 0x%x with free block [%d] (%d)\n",
freeFinger, _sp->block_size(freeFinger),
freeRangeInFreeLists);
gclog_or_tty->print("---- Start free range at 0x%x with free block (%d)\n",
freeFinger, freeRangeInFreeLists);
}
assert(!inFreeRange(), "Trampling existing free range");
set_inFreeRange(true);
@ -7993,21 +7988,36 @@ size_t SweepClosure::do_blk_careful(HeapWord* addr) {
// may have caused us to coalesce the block ending at the address _limit
// with a newly expanded chunk (this happens when _limit was set to the
// previous _end of the space), so we may have stepped past _limit; see CR 6977970.
if (addr >= _limit) { // we have swept up to or past the limit, do nothing more
if (addr >= _limit) { // we have swept up to or past the limit: finish up
assert(_limit >= _sp->bottom() && _limit <= _sp->end(),
"sweep _limit out of bounds");
assert(addr < _sp->end(), "addr out of bounds");
// help the closure application finish
// Flush any remaining coterminal free run as a single
// coalesced chunk to the appropriate free list.
if (inFreeRange()) {
assert(freeFinger() < _limit, "finger points too high");
flush_cur_free_chunk(freeFinger(),
pointer_delta(addr, freeFinger()));
if (CMSTraceSweeper) {
gclog_or_tty->print("Sweep: last chunk: ");
gclog_or_tty->print("put_free_blk 0x%x ("SIZE_FORMAT") "
"[coalesced:"SIZE_FORMAT"]\n",
freeFinger(), pointer_delta(addr, freeFinger()),
lastFreeRangeCoalesced());
}
}
// help the iterator loop finish
return pointer_delta(_sp->end(), addr);
}
assert(addr < _limit, "sweep invariant");
assert(addr < _limit, "sweep invariant");
// check if we should yield
do_yield_check(addr);
if (fc->isFree()) {
// Chunk that is already free
res = fc->size();
doAlreadyFreeChunk(fc);
do_already_free_chunk(fc);
debug_only(_sp->verifyFreeLists());
assert(res == fc->size(), "Don't expect the size to change");
NOT_PRODUCT(
@ -8017,7 +8027,7 @@ size_t SweepClosure::do_blk_careful(HeapWord* addr) {
NOT_PRODUCT(_last_fc = fc;)
} else if (!_bitMap->isMarked(addr)) {
// Chunk is fresh garbage
res = doGarbageChunk(fc);
res = do_garbage_chunk(fc);
debug_only(_sp->verifyFreeLists());
NOT_PRODUCT(
_numObjectsFreed++;
@ -8025,7 +8035,7 @@ size_t SweepClosure::do_blk_careful(HeapWord* addr) {
)
} else {
// Chunk that is alive.
res = doLiveChunk(fc);
res = do_live_chunk(fc);
debug_only(_sp->verifyFreeLists());
NOT_PRODUCT(
_numObjectsLive++;
@ -8078,7 +8088,7 @@ size_t SweepClosure::do_blk_careful(HeapWord* addr) {
// to a free list which may be overpopulated.
//
void SweepClosure::doAlreadyFreeChunk(FreeChunk* fc) {
void SweepClosure::do_already_free_chunk(FreeChunk* fc) {
size_t size = fc->size();
// Chunks that cannot be coalesced are not in the
// free lists.
@ -8094,23 +8104,23 @@ void SweepClosure::doAlreadyFreeChunk(FreeChunk* fc) {
// addr and purported end of this block.
_bitMap->verifyNoOneBitsInRange(addr + 1, addr + size);
// Some chunks cannot be coalesced in under any circumstances.
// Some chunks cannot be coalesced under any circumstances.
// See the definition of cantCoalesce().
if (!fc->cantCoalesce()) {
// This chunk can potentially be coalesced.
if (_sp->adaptive_freelists()) {
// All the work is done in
doPostIsFreeOrGarbageChunk(fc, size);
do_post_free_or_garbage_chunk(fc, size);
} else { // Not adaptive free lists
// this is a free chunk that can potentially be coalesced by the sweeper;
if (!inFreeRange()) {
// if the next chunk is a free block that can't be coalesced
// it doesn't make sense to remove this chunk from the free lists
FreeChunk* nextChunk = (FreeChunk*)(addr + size);
assert((HeapWord*)nextChunk <= _limit, "sweep invariant");
if ((HeapWord*)nextChunk < _limit && // there's a next chunk...
nextChunk->isFree() && // which is free...
nextChunk->cantCoalesce()) { // ... but cant be coalesced
assert((HeapWord*)nextChunk <= _sp->end(), "Chunk size out of bounds?");
if ((HeapWord*)nextChunk < _sp->end() && // There is another free chunk to the right ...
nextChunk->isFree() && // ... which is free...
nextChunk->cantCoalesce()) { // ... but can't be coalesced
// nothing to do
} else {
// Potentially the start of a new free range:
@ -8156,14 +8166,14 @@ void SweepClosure::doAlreadyFreeChunk(FreeChunk* fc) {
// as the end of a free run if any
if (inFreeRange()) {
// we kicked some butt; time to pick up the garbage
assert(freeFinger() < addr, "the finger pointeth off base");
flushCurFreeChunk(freeFinger(), pointer_delta(addr, freeFinger()));
assert(freeFinger() < addr, "freeFinger points too high");
flush_cur_free_chunk(freeFinger(), pointer_delta(addr, freeFinger()));
}
// else, nothing to do, just continue
}
}
size_t SweepClosure::doGarbageChunk(FreeChunk* fc) {
size_t SweepClosure::do_garbage_chunk(FreeChunk* fc) {
// This is a chunk of garbage. It is not in any free list.
// Add it to a free list or let it possibly be coalesced into
// a larger chunk.
@ -8175,7 +8185,7 @@ size_t SweepClosure::doGarbageChunk(FreeChunk* fc) {
// addr and purported end of just dead object.
_bitMap->verifyNoOneBitsInRange(addr + 1, addr + size);
doPostIsFreeOrGarbageChunk(fc, size);
do_post_free_or_garbage_chunk(fc, size);
} else {
if (!inFreeRange()) {
// start of a new free range
@ -8214,35 +8224,16 @@ size_t SweepClosure::doGarbageChunk(FreeChunk* fc) {
return size;
}
size_t SweepClosure::doLiveChunk(FreeChunk* fc) {
size_t SweepClosure::do_live_chunk(FreeChunk* fc) {
HeapWord* addr = (HeapWord*) fc;
// The sweeper has just found a live object. Return any accumulated
// left hand chunk to the free lists.
if (inFreeRange()) {
if (_sp->adaptive_freelists()) {
flushCurFreeChunk(freeFinger(),
pointer_delta(addr, freeFinger()));
} else { // not adaptive freelists
set_inFreeRange(false);
// Add the free range back to the free list if it is not already
// there.
if (!freeRangeInFreeLists()) {
assert(freeFinger() < addr, "the finger pointeth off base");
if (CMSTraceSweeper) {
gclog_or_tty->print("Sweep:put_free_blk 0x%x (%d) "
"[coalesced:%d]\n",
freeFinger(), pointer_delta(addr, freeFinger()),
lastFreeRangeCoalesced());
}
_sp->addChunkAndRepairOffsetTable(freeFinger(),
pointer_delta(addr, freeFinger()), lastFreeRangeCoalesced());
}
}
assert(freeFinger() < addr, "freeFinger points too high");
flush_cur_free_chunk(freeFinger(), pointer_delta(addr, freeFinger()));
}
// Common code path for original and adaptive free lists.
// this object is live: we'd normally expect this to be
// This object is live: we'd normally expect this to be
// an oop, and like to assert the following:
// assert(oop(addr)->is_oop(), "live block should be an oop");
// However, as we commented above, this may be an object whose
@ -8257,7 +8248,7 @@ size_t SweepClosure::doLiveChunk(FreeChunk* fc) {
assert(size == CompactibleFreeListSpace::adjustObjectSize(size),
"alignment problem");
#ifdef DEBUG
#ifdef DEBUG
if (oop(addr)->klass_or_null() != NULL &&
( !_collector->should_unload_classes()
|| (oop(addr)->is_parsable()) &&
@ -8271,7 +8262,7 @@ size_t SweepClosure::doLiveChunk(FreeChunk* fc) {
CompactibleFreeListSpace::adjustObjectSize(oop(addr)->size()),
"P-mark and computed size do not agree");
}
#endif
#endif
} else {
// This should be an initialized object that's alive.
@ -8298,19 +8289,17 @@ size_t SweepClosure::doLiveChunk(FreeChunk* fc) {
return size;
}
void SweepClosure::doPostIsFreeOrGarbageChunk(FreeChunk* fc,
size_t chunkSize) {
// doPostIsFreeOrGarbageChunk() should only be called in the smart allocation
// scheme.
void SweepClosure::do_post_free_or_garbage_chunk(FreeChunk* fc,
size_t chunkSize) {
// do_post_free_or_garbage_chunk() should only be called in the case
// of the adaptive free list allocator.
bool fcInFreeLists = fc->isFree();
assert(_sp->adaptive_freelists(), "Should only be used in this case.");
assert((HeapWord*)fc <= _limit, "sweep invariant");
if (CMSTestInFreeList && fcInFreeLists) {
assert(_sp->verifyChunkInFreeLists(fc),
"free chunk is not in free lists");
assert(_sp->verifyChunkInFreeLists(fc), "free chunk is not in free lists");
}
if (CMSTraceSweeper) {
gclog_or_tty->print_cr(" -- pick up another chunk at 0x%x (%d)", fc, chunkSize);
}
@ -8382,20 +8371,21 @@ void SweepClosure::doPostIsFreeOrGarbageChunk(FreeChunk* fc,
if (inFreeRange()) {
// In a free range but cannot coalesce with the right hand chunk.
// Put the current free range into the free lists.
flushCurFreeChunk(freeFinger(),
pointer_delta(addr, freeFinger()));
flush_cur_free_chunk(freeFinger(),
pointer_delta(addr, freeFinger()));
}
// Set up for new free range. Pass along whether the right hand
// chunk is in the free lists.
initialize_free_range((HeapWord*)fc, fcInFreeLists);
}
}
void SweepClosure::flushCurFreeChunk(HeapWord* chunk, size_t size) {
void SweepClosure::flush_cur_free_chunk(HeapWord* chunk, size_t size) {
assert(inFreeRange(), "Should only be called if currently in a free range.");
assert(size > 0,
"A zero sized chunk cannot be added to the free lists.");
if (!freeRangeInFreeLists()) {
if(CMSTestInFreeList) {
if (CMSTestInFreeList) {
FreeChunk* fc = (FreeChunk*) chunk;
fc->setSize(size);
assert(!_sp->verifyChunkInFreeLists(fc),
@ -8430,7 +8420,7 @@ void SweepClosure::do_yield_work(HeapWord* addr) {
// chunk just flushed, they will need to wait for the next
// sweep to be coalesced.
if (inFreeRange()) {
flushCurFreeChunk(freeFinger(), pointer_delta(addr, freeFinger()));
flush_cur_free_chunk(freeFinger(), pointer_delta(addr, freeFinger()));
}
// First give up the locks, then yield, then re-lock.

View File

@ -1701,7 +1701,9 @@ class SweepClosure: public BlkClosureCareful {
CMSCollector* _collector; // collector doing the work
ConcurrentMarkSweepGeneration* _g; // Generation being swept
CompactibleFreeListSpace* _sp; // Space being swept
HeapWord* _limit;
HeapWord* _limit;// the address at which the sweep should stop because
// we do not expect blocks eligible for sweeping past
// that address.
Mutex* _freelistLock; // Free list lock (in space)
CMSBitMap* _bitMap; // Marking bit map (in
// generation)
@ -1745,14 +1747,13 @@ class SweepClosure: public BlkClosureCareful {
private:
// Code that is common to a free chunk or garbage when
// encountered during sweeping.
void doPostIsFreeOrGarbageChunk(FreeChunk *fc,
size_t chunkSize);
void do_post_free_or_garbage_chunk(FreeChunk *fc, size_t chunkSize);
// Process a free chunk during sweeping.
void doAlreadyFreeChunk(FreeChunk *fc);
void do_already_free_chunk(FreeChunk *fc);
// Process a garbage chunk during sweeping.
size_t doGarbageChunk(FreeChunk *fc);
size_t do_garbage_chunk(FreeChunk *fc);
// Process a live chunk during sweeping.
size_t doLiveChunk(FreeChunk* fc);
size_t do_live_chunk(FreeChunk* fc);
// Accessors.
HeapWord* freeFinger() const { return _freeFinger; }
@ -1769,7 +1770,7 @@ class SweepClosure: public BlkClosureCareful {
// Initialize a free range.
void initialize_free_range(HeapWord* freeFinger, bool freeRangeInFreeLists);
// Return this chunk to the free lists.
void flushCurFreeChunk(HeapWord* chunk, size_t size);
void flush_cur_free_chunk(HeapWord* chunk, size_t size);
// Check if we should yield and do so when necessary.
inline void do_yield_check(HeapWord* addr);

View File

@ -31,6 +31,7 @@
#include "gc_implementation/g1/g1RemSet.hpp"
#include "gc_implementation/g1/heapRegionRemSet.hpp"
#include "gc_implementation/g1/heapRegionSeq.inline.hpp"
#include "gc_implementation/shared/vmGCOperations.hpp"
#include "memory/genOopClosures.inline.hpp"
#include "memory/referencePolicy.hpp"
#include "memory/resourceArea.hpp"
@ -1142,6 +1143,8 @@ void ConcurrentMark::checkpointRootsFinal(bool clear_all_soft_refs) {
return;
}
SvcGCMarker sgcm(SvcGCMarker::OTHER);
if (VerifyDuringGC) {
HandleMark hm; // handle scope
gclog_or_tty->print(" VerifyDuringGC:(before)");

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -222,7 +222,7 @@ void G1BlockOffsetArray::split_block(HeapWord* blk, size_t blk_size,
// Action_mark - update the BOT for the block [blk_start, blk_end).
// Current typical use is for splitting a block.
// Action_single - udpate the BOT for an allocation.
// Action_single - update the BOT for an allocation.
// Action_verify - BOT verification.
void G1BlockOffsetArray::do_block_internal(HeapWord* blk_start,
HeapWord* blk_end,
@ -331,47 +331,6 @@ G1BlockOffsetArray::mark_block(HeapWord* blk_start, HeapWord* blk_end) {
do_block_internal(blk_start, blk_end, Action_mark);
}
void G1BlockOffsetArray::join_blocks(HeapWord* blk1, HeapWord* blk2) {
HeapWord* blk1_start = Universe::heap()->block_start(blk1);
HeapWord* blk2_start = Universe::heap()->block_start(blk2);
assert(blk1 == blk1_start && blk2 == blk2_start,
"Must be block starts.");
assert(blk1 + _sp->block_size(blk1) == blk2, "Must be contiguous.");
size_t blk1_start_index = _array->index_for(blk1);
size_t blk2_start_index = _array->index_for(blk2);
assert(blk1_start_index <= blk2_start_index, "sanity");
HeapWord* blk2_card_start = _array->address_for_index(blk2_start_index);
if (blk2 == blk2_card_start) {
// blk2 starts a card. Does blk1 start on the prevous card, or futher
// back?
assert(blk1_start_index < blk2_start_index, "must be lower card.");
if (blk1_start_index + 1 == blk2_start_index) {
// previous card; new value for blk2 card is size of blk1.
_array->set_offset_array(blk2_start_index, (u_char) _sp->block_size(blk1));
} else {
// Earlier card; go back a card.
_array->set_offset_array(blk2_start_index, N_words);
}
} else {
// blk2 does not start a card. Does it cross a card? If not, nothing
// to do.
size_t blk2_end_index =
_array->index_for(blk2 + _sp->block_size(blk2) - 1);
assert(blk2_end_index >= blk2_start_index, "sanity");
if (blk2_end_index > blk2_start_index) {
// Yes, it crosses a card. The value for the next card must change.
if (blk1_start_index + 1 == blk2_start_index) {
// previous card; new value for second blk2 card is size of blk1.
_array->set_offset_array(blk2_start_index + 1,
(u_char) _sp->block_size(blk1));
} else {
// Earlier card; go back a card.
_array->set_offset_array(blk2_start_index + 1, N_words);
}
}
}
}
HeapWord* G1BlockOffsetArray::block_start_unsafe(const void* addr) {
assert(_bottom <= addr && addr < _end,
"addr must be covered by this Array");
@ -580,16 +539,51 @@ void G1BlockOffsetArray::alloc_block_work2(HeapWord** threshold_, size_t* index_
#endif
}
void
G1BlockOffsetArray::set_for_starts_humongous(HeapWord* new_end) {
assert(_end == new_end, "_end should have already been updated");
// The first BOT entry should have offset 0.
_array->set_offset_array(_array->index_for(_bottom), 0);
// The rest should point to the first one.
set_remainder_to_point_to_start(_bottom + N_words, new_end);
bool
G1BlockOffsetArray::verify_for_object(HeapWord* obj_start,
size_t word_size) const {
size_t first_card = _array->index_for(obj_start);
size_t last_card = _array->index_for(obj_start + word_size - 1);
if (!_array->is_card_boundary(obj_start)) {
// If the object is not on a card boundary the BOT entry of the
// first card should point to another object so we should not
// check that one.
first_card += 1;
}
for (size_t card = first_card; card <= last_card; card += 1) {
HeapWord* card_addr = _array->address_for_index(card);
HeapWord* block_start = block_start_const(card_addr);
if (block_start != obj_start) {
gclog_or_tty->print_cr("block start: "PTR_FORMAT" is incorrect - "
"card index: "SIZE_FORMAT" "
"card addr: "PTR_FORMAT" BOT entry: %u "
"obj: "PTR_FORMAT" word size: "SIZE_FORMAT" "
"cards: ["SIZE_FORMAT","SIZE_FORMAT"]",
block_start, card, card_addr,
_array->offset_array(card),
obj_start, word_size, first_card, last_card);
return false;
}
}
return true;
}
#ifndef PRODUCT
void
G1BlockOffsetArray::print_on(outputStream* out) {
size_t from_index = _array->index_for(_bottom);
size_t to_index = _array->index_for(_end);
out->print_cr(">> BOT for area ["PTR_FORMAT","PTR_FORMAT") "
"cards ["SIZE_FORMAT","SIZE_FORMAT")",
_bottom, _end, from_index, to_index);
for (size_t i = from_index; i < to_index; ++i) {
out->print_cr(" entry "SIZE_FORMAT_W(8)" | "PTR_FORMAT" : %3u",
i, _array->address_for_index(i),
(uint) _array->offset_array(i));
}
}
#endif // !PRODUCT
//////////////////////////////////////////////////////////////////////
// G1BlockOffsetArrayContigSpace
//////////////////////////////////////////////////////////////////////
@ -641,10 +635,20 @@ void G1BlockOffsetArrayContigSpace::zero_bottom_entry() {
}
void
G1BlockOffsetArrayContigSpace::set_for_starts_humongous(HeapWord* new_end) {
G1BlockOffsetArray::set_for_starts_humongous(new_end);
G1BlockOffsetArrayContigSpace::set_for_starts_humongous(HeapWord* new_top) {
assert(new_top <= _end, "_end should have already been updated");
// Make sure _next_offset_threshold and _next_offset_index point to new_end.
_next_offset_threshold = new_end;
_next_offset_index = _array->index_for(new_end);
// The first BOT entry should have offset 0.
zero_bottom_entry();
initialize_threshold();
alloc_block(_bottom, new_top);
}
#ifndef PRODUCT
void
G1BlockOffsetArrayContigSpace::print_on(outputStream* out) {
G1BlockOffsetArray::print_on(out);
out->print_cr(" next offset threshold: "PTR_FORMAT, _next_offset_threshold);
out->print_cr(" next offset index: "SIZE_FORMAT, _next_offset_index);
}
#endif // !PRODUCT

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -352,11 +352,6 @@ public:
// The following methods are useful and optimized for a
// general, non-contiguous space.
// The given arguments are required to be the starts of adjacent ("blk1"
// before "blk2") well-formed blocks covered by "this". After this call,
// they should be considered to form one block.
virtual void join_blocks(HeapWord* blk1, HeapWord* blk2);
// Given a block [blk_start, blk_start + full_blk_size), and
// a left_blk_size < full_blk_size, adjust the BOT to show two
// blocks [blk_start, blk_start + left_blk_size) and
@ -429,6 +424,12 @@ public:
verify_single_block(blk, blk + size);
}
// Used by region verification. Checks that the contents of the
// BOT reflect that there's a single object that spans the address
// range [obj_start, obj_start + word_size); returns true if this is
// the case, returns false if it's not.
bool verify_for_object(HeapWord* obj_start, size_t word_size) const;
// Verify that the given block is before _unallocated_block
inline void verify_not_unallocated(HeapWord* blk_start,
HeapWord* blk_end) const {
@ -444,7 +445,7 @@ public:
void check_all_cards(size_t left_card, size_t right_card) const;
virtual void set_for_starts_humongous(HeapWord* new_end);
virtual void print_on(outputStream* out) PRODUCT_RETURN;
};
// A subtype of BlockOffsetArray that takes advantage of the fact
@ -494,7 +495,9 @@ class G1BlockOffsetArrayContigSpace: public G1BlockOffsetArray {
HeapWord* block_start_unsafe(const void* addr);
HeapWord* block_start_unsafe_const(const void* addr) const;
virtual void set_for_starts_humongous(HeapWord* new_end);
void set_for_starts_humongous(HeapWord* new_top);
virtual void print_on(outputStream* out) PRODUCT_RETURN;
};
#endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1BLOCKOFFSETTABLE_HPP

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -610,6 +610,39 @@ G1CollectedHeap::retire_cur_alloc_region(HeapRegion* cur_alloc_region) {
// of the free region list is revamped as part of CR 6977804.
wait_for_cleanup_complete();
// Other threads might still be trying to allocate using CASes out
// of the region we are retiring, as they can do so without holding
// the Heap_lock. So we first have to make sure that noone else can
// allocate in it by doing a maximal allocation. Even if our CAS
// attempt fails a few times, we'll succeed sooner or later given
// that a failed CAS attempt mean that the region is getting closed
// to being full (someone else succeeded in allocating into it).
size_t free_word_size = cur_alloc_region->free() / HeapWordSize;
// This is the minimum free chunk we can turn into a dummy
// object. If the free space falls below this, then noone can
// allocate in this region anyway (all allocation requests will be
// of a size larger than this) so we won't have to perform the dummy
// allocation.
size_t min_word_size_to_fill = CollectedHeap::min_fill_size();
while (free_word_size >= min_word_size_to_fill) {
HeapWord* dummy =
cur_alloc_region->par_allocate_no_bot_updates(free_word_size);
if (dummy != NULL) {
// If the allocation was successful we should fill in the space.
CollectedHeap::fill_with_object(dummy, free_word_size);
break;
}
free_word_size = cur_alloc_region->free() / HeapWordSize;
// It's also possible that someone else beats us to the
// allocation and they fill up the region. In that case, we can
// just get out of the loop
}
assert(cur_alloc_region->free() / HeapWordSize < min_word_size_to_fill,
"sanity");
retire_cur_alloc_region_common(cur_alloc_region);
assert(_cur_alloc_region == NULL, "post-condition");
}
@ -661,27 +694,29 @@ G1CollectedHeap::replace_cur_alloc_region_and_allocate(size_t word_size,
// young type.
OrderAccess::storestore();
// Now allocate out of the new current alloc region. We could
// have re-used allocate_from_cur_alloc_region() but its
// operation is slightly different to what we need here. First,
// allocate_from_cur_alloc_region() is only called outside a
// safepoint and will always unlock the Heap_lock if it returns
// a non-NULL result. Second, it assumes that the current alloc
// region is what's already assigned in _cur_alloc_region. What
// we want here is to actually do the allocation first before we
// assign the new region to _cur_alloc_region. This ordering is
// not currently important, but it will be essential when we
// change the code to support CAS allocation in the future (see
// CR 6994297).
//
// This allocate method does BOT updates and we don't need them in
// the young generation. This will be fixed in the near future by
// CR 6994297.
HeapWord* result = new_cur_alloc_region->allocate(word_size);
// Now, perform the allocation out of the region we just
// allocated. Note that noone else can access that region at
// this point (as _cur_alloc_region has not been updated yet),
// so we can just go ahead and do the allocation without any
// atomics (and we expect this allocation attempt to
// suceeded). Given that other threads can attempt an allocation
// with a CAS and without needing the Heap_lock, if we assigned
// the new region to _cur_alloc_region before first allocating
// into it other threads might have filled up the new region
// before we got a chance to do the allocation ourselves. In
// that case, we would have needed to retire the region, grab a
// new one, and go through all this again. Allocating out of the
// new region before assigning it to _cur_alloc_region avoids
// all this.
HeapWord* result =
new_cur_alloc_region->allocate_no_bot_updates(word_size);
assert(result != NULL, "we just allocate out of an empty region "
"so allocation should have been successful");
assert(is_in(result), "result should be in the heap");
// Now make sure that the store to _cur_alloc_region does not
// float above the store to top.
OrderAccess::storestore();
_cur_alloc_region = new_cur_alloc_region;
if (!at_safepoint) {
@ -718,6 +753,9 @@ G1CollectedHeap::attempt_allocation_slow(size_t word_size) {
for (int try_count = 1; /* we'll return or break */; try_count += 1) {
bool succeeded = true;
// Every time we go round the loop we should be holding the Heap_lock.
assert_heap_locked();
{
// We may have concurrent cleanup working at the time. Wait for
// it to complete. In the future we would probably want to make
@ -734,7 +772,8 @@ G1CollectedHeap::attempt_allocation_slow(size_t word_size) {
// attempt as it's redundant (we only reach here after an
// allocation attempt has been unsuccessful).
wait_for_cleanup_complete();
HeapWord* result = attempt_allocation(word_size);
HeapWord* result = attempt_allocation_locked(word_size);
if (result != NULL) {
assert_heap_not_locked();
return result;
@ -748,7 +787,6 @@ G1CollectedHeap::attempt_allocation_slow(size_t word_size) {
if (g1_policy()->can_expand_young_list()) {
// Yes, we are allowed to expand the young gen. Let's try to
// allocate a new current alloc region.
HeapWord* result =
replace_cur_alloc_region_and_allocate(word_size,
false, /* at_safepoint */
@ -771,20 +809,23 @@ G1CollectedHeap::attempt_allocation_slow(size_t word_size) {
// rather than causing more, now probably unnecessary, GC attempts.
JavaThread* jthr = JavaThread::current();
assert(jthr != NULL, "sanity");
if (!jthr->in_critical()) {
MutexUnlocker mul(Heap_lock);
GC_locker::stall_until_clear();
// We'll then fall off the end of the ("if GC locker active")
// if-statement and retry the allocation further down in the
// loop.
} else {
if (jthr->in_critical()) {
if (CheckJNICalls) {
fatal("Possible deadlock due to allocating while"
" in jni critical section");
}
// We are returning NULL so the protocol is that we're still
// holding the Heap_lock.
assert_heap_locked();
return NULL;
}
Heap_lock->unlock();
GC_locker::stall_until_clear();
// No need to relock the Heap_lock. We'll fall off to the code
// below the else-statement which assumes that we are not
// holding the Heap_lock.
} else {
// We are not locked out. So, let's try to do a GC. The VM op
// will retry the allocation before it completes.
@ -805,11 +846,10 @@ G1CollectedHeap::attempt_allocation_slow(size_t word_size) {
dirty_young_block(result, word_size);
return result;
}
Heap_lock->lock();
}
assert_heap_locked();
// Both paths that get us here from above unlock the Heap_lock.
assert_heap_not_locked();
// We can reach here when we were unsuccessful in doing a GC,
// because another thread beat us to it, or because we were locked
@ -948,10 +988,8 @@ HeapWord* G1CollectedHeap::attempt_allocation_at_safepoint(size_t word_size,
if (!expect_null_cur_alloc_region) {
HeapRegion* cur_alloc_region = _cur_alloc_region;
if (cur_alloc_region != NULL) {
// This allocate method does BOT updates and we don't need them in
// the young generation. This will be fixed in the near future by
// CR 6994297.
HeapWord* result = cur_alloc_region->allocate(word_size);
// We are at a safepoint so no reason to use the MT-safe version.
HeapWord* result = cur_alloc_region->allocate_no_bot_updates(word_size);
if (result != NULL) {
assert(is_in(result), "result should be in the heap");
@ -983,20 +1021,17 @@ HeapWord* G1CollectedHeap::allocate_new_tlab(size_t word_size) {
assert_heap_not_locked_and_not_at_safepoint();
assert(!isHumongous(word_size), "we do not allow TLABs of humongous size");
Heap_lock->lock();
// First attempt: try allocating out of the current alloc region or
// after replacing the current alloc region.
// First attempt: Try allocating out of the current alloc region
// using a CAS. If that fails, take the Heap_lock and retry the
// allocation, potentially replacing the current alloc region.
HeapWord* result = attempt_allocation(word_size);
if (result != NULL) {
assert_heap_not_locked();
return result;
}
assert_heap_locked();
// Second attempt: go into the even slower path where we might
// try to schedule a collection.
// Second attempt: Go to the slower path where we might try to
// schedule a collection.
result = attempt_allocation_slow(word_size);
if (result != NULL) {
assert_heap_not_locked();
@ -1004,6 +1039,7 @@ HeapWord* G1CollectedHeap::allocate_new_tlab(size_t word_size) {
}
assert_heap_locked();
// Need to unlock the Heap_lock before returning.
Heap_lock->unlock();
return NULL;
}
@ -1022,11 +1058,10 @@ G1CollectedHeap::mem_allocate(size_t word_size,
for (int try_count = 1; /* we'll return */; try_count += 1) {
unsigned int gc_count_before;
{
Heap_lock->lock();
if (!isHumongous(word_size)) {
// First attempt: try allocating out of the current alloc
// region or after replacing the current alloc region.
// First attempt: Try allocating out of the current alloc region
// using a CAS. If that fails, take the Heap_lock and retry the
// allocation, potentially replacing the current alloc region.
HeapWord* result = attempt_allocation(word_size);
if (result != NULL) {
assert_heap_not_locked();
@ -1035,14 +1070,17 @@ G1CollectedHeap::mem_allocate(size_t word_size,
assert_heap_locked();
// Second attempt: go into the even slower path where we might
// try to schedule a collection.
// Second attempt: Go to the slower path where we might try to
// schedule a collection.
result = attempt_allocation_slow(word_size);
if (result != NULL) {
assert_heap_not_locked();
return result;
}
} else {
// attempt_allocation_humongous() requires the Heap_lock to be held.
Heap_lock->lock();
HeapWord* result = attempt_allocation_humongous(word_size,
false /* at_safepoint */);
if (result != NULL) {
@ -1054,7 +1092,8 @@ G1CollectedHeap::mem_allocate(size_t word_size,
assert_heap_locked();
// Read the gc count while the heap lock is held.
gc_count_before = SharedHeap::heap()->total_collections();
// We cannot be at a safepoint, so it is safe to unlock the Heap_lock
// Release the Heap_lock before attempting the collection.
Heap_lock->unlock();
}
@ -1192,7 +1231,7 @@ bool G1CollectedHeap::do_collection(bool explicit_gc,
return false;
}
DTraceGCProbeMarker gc_probe_marker(true /* full */);
SvcGCMarker sgcm(SvcGCMarker::FULL);
ResourceMark rm;
if (PrintHeapAtGC) {
@ -1868,7 +1907,7 @@ jint G1CollectedHeap::initialize() {
ReservedSpace heap_rs(max_byte_size + pgs->max_size(),
HeapRegion::GrainBytes,
false /*ism*/, addr);
UseLargePages, addr);
if (UseCompressedOops) {
if (addr != NULL && !heap_rs.is_reserved()) {
@ -1877,13 +1916,13 @@ jint G1CollectedHeap::initialize() {
// Try again to reserver heap higher.
addr = Universe::preferred_heap_base(total_reserved, Universe::ZeroBasedNarrowOop);
ReservedSpace heap_rs0(total_reserved, HeapRegion::GrainBytes,
false /*ism*/, addr);
UseLargePages, addr);
if (addr != NULL && !heap_rs0.is_reserved()) {
// Failed to reserve at specified address again - give up.
addr = Universe::preferred_heap_base(total_reserved, Universe::HeapBasedNarrowOop);
assert(addr == NULL, "");
ReservedSpace heap_rs1(total_reserved, HeapRegion::GrainBytes,
false /*ism*/, addr);
UseLargePages, addr);
heap_rs = heap_rs1;
} else {
heap_rs = heap_rs0;
@ -3214,7 +3253,7 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
return false;
}
DTraceGCProbeMarker gc_probe_marker(false /* full */);
SvcGCMarker sgcm(SvcGCMarker::MINOR);
ResourceMark rm;
if (PrintHeapAtGC) {
@ -3856,13 +3895,15 @@ private:
size_t _next_marked_bytes;
OopsInHeapRegionClosure *_cl;
public:
RemoveSelfPointerClosure(G1CollectedHeap* g1, OopsInHeapRegionClosure* cl) :
_g1(g1), _cm(_g1->concurrent_mark()), _prev_marked_bytes(0),
RemoveSelfPointerClosure(G1CollectedHeap* g1, HeapRegion* hr,
OopsInHeapRegionClosure* cl) :
_g1(g1), _hr(hr), _cm(_g1->concurrent_mark()), _prev_marked_bytes(0),
_next_marked_bytes(0), _cl(cl) {}
size_t prev_marked_bytes() { return _prev_marked_bytes; }
size_t next_marked_bytes() { return _next_marked_bytes; }
// <original comment>
// The original idea here was to coalesce evacuated and dead objects.
// However that caused complications with the block offset table (BOT).
// In particular if there were two TLABs, one of them partially refined.
@ -3871,15 +3912,24 @@ public:
// of TLAB_2. If the last object of the TLAB_1 and the first object
// of TLAB_2 are coalesced, then the cards of the unrefined part
// would point into middle of the filler object.
//
// The current approach is to not coalesce and leave the BOT contents intact.
// </original comment>
//
// We now reset the BOT when we start the object iteration over the
// region and refine its entries for every object we come across. So
// the above comment is not really relevant and we should be able
// to coalesce dead objects if we want to.
void do_object(oop obj) {
HeapWord* obj_addr = (HeapWord*) obj;
assert(_hr->is_in(obj_addr), "sanity");
size_t obj_size = obj->size();
_hr->update_bot_for_object(obj_addr, obj_size);
if (obj->is_forwarded() && obj->forwardee() == obj) {
// The object failed to move.
assert(!_g1->is_obj_dead(obj), "We should not be preserving dead objs.");
_cm->markPrev(obj);
assert(_cm->isPrevMarked(obj), "Should be marked!");
_prev_marked_bytes += (obj->size() * HeapWordSize);
_prev_marked_bytes += (obj_size * HeapWordSize);
if (_g1->mark_in_progress() && !_g1->is_obj_ill(obj)) {
_cm->markAndGrayObjectIfNecessary(obj);
}
@ -3901,7 +3951,7 @@ public:
} else {
// The object has been either evacuated or is dead. Fill it with a
// dummy object.
MemRegion mr((HeapWord*)obj, obj->size());
MemRegion mr((HeapWord*)obj, obj_size);
CollectedHeap::fill_with_object(mr);
_cm->clearRangeBothMaps(mr);
}
@ -3921,10 +3971,13 @@ void G1CollectedHeap::remove_self_forwarding_pointers() {
HeapRegion* cur = g1_policy()->collection_set();
while (cur != NULL) {
assert(g1_policy()->assertMarkedBytesDataOK(), "Should be!");
assert(!cur->isHumongous(), "sanity");
RemoveSelfPointerClosure rspc(_g1h, cl);
if (cur->evacuation_failed()) {
assert(cur->in_collection_set(), "bad CS");
RemoveSelfPointerClosure rspc(_g1h, cur, cl);
cur->reset_bot();
cl->set_region(cur);
cur->object_iterate(&rspc);
@ -3989,15 +4042,6 @@ void G1CollectedHeap::drain_evac_failure_scan_stack() {
}
}
void G1CollectedHeap::handle_evacuation_failure(oop old) {
markOop m = old->mark();
// forward to self
assert(!old->is_forwarded(), "precondition");
old->forward_to(old);
handle_evacuation_failure_common(old, m);
}
oop
G1CollectedHeap::handle_evacuation_failure_par(OopsInHeapRegionClosure* cl,
oop old) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -430,7 +430,8 @@ protected:
bool* gc_overhead_limit_was_exceeded);
// The following methods, allocate_from_cur_allocation_region(),
// attempt_allocation(), replace_cur_alloc_region_and_allocate(),
// attempt_allocation(), attempt_allocation_locked(),
// replace_cur_alloc_region_and_allocate(),
// attempt_allocation_slow(), and attempt_allocation_humongous()
// have very awkward pre- and post-conditions with respect to
// locking:
@ -481,20 +482,30 @@ protected:
// successfully manage to allocate it, or NULL.
// It tries to satisfy an allocation request out of the current
// allocating region, which is passed as a parameter. It assumes
// that the caller has checked that the current allocating region is
// not NULL. Given that the caller has to check the current
// allocating region for at least NULL, it might as well pass it as
// the first parameter so that the method doesn't have to read it
// from the _cur_alloc_region field again.
// alloc region, which is passed as a parameter. It assumes that the
// caller has checked that the current alloc region is not NULL.
// Given that the caller has to check the current alloc region for
// at least NULL, it might as well pass it as the first parameter so
// that the method doesn't have to read it from the
// _cur_alloc_region field again. It is called from both
// attempt_allocation() and attempt_allocation_locked() and the
// with_heap_lock parameter indicates whether the caller was holding
// the heap lock when it called it or not.
inline HeapWord* allocate_from_cur_alloc_region(HeapRegion* cur_alloc_region,
size_t word_size);
size_t word_size,
bool with_heap_lock);
// It attempts to allocate out of the current alloc region. If that
// fails, it retires the current alloc region (if there is one),
// tries to get a new one and retries the allocation.
// First-level of allocation slow path: it attempts to allocate out
// of the current alloc region in a lock-free manner using a CAS. If
// that fails it takes the Heap_lock and calls
// attempt_allocation_locked() for the second-level slow path.
inline HeapWord* attempt_allocation(size_t word_size);
// Second-level of allocation slow path: while holding the Heap_lock
// it tries to allocate out of the current alloc region and, if that
// fails, tries to allocate out of a new current alloc region.
inline HeapWord* attempt_allocation_locked(size_t word_size);
// It assumes that the current alloc region has been retired and
// tries to allocate a new one. If it's successful, it performs the
// allocation out of the new current alloc region and updates
@ -506,11 +517,11 @@ protected:
bool do_dirtying,
bool can_expand);
// The slow path when we are unable to allocate a new current alloc
// region to satisfy an allocation request (i.e., when
// attempt_allocation() fails). It will try to do an evacuation
// pause, which might stall due to the GC locker, and retry the
// allocation attempt when appropriate.
// Third-level of allocation slow path: when we are unable to
// allocate a new current alloc region to satisfy an allocation
// request (i.e., when attempt_allocation_locked() fails). It will
// try to do an evacuation pause, which might stall due to the GC
// locker, and retry the allocation attempt when appropriate.
HeapWord* attempt_allocation_slow(size_t word_size);
// The method that tries to satisfy a humongous allocation
@ -826,7 +837,6 @@ protected:
void finalize_for_evac_failure();
// An attempt to evacuate "obj" has failed; take necessary steps.
void handle_evacuation_failure(oop obj);
oop handle_evacuation_failure_par(OopsInHeapRegionClosure* cl, oop obj);
void handle_evacuation_failure_common(oop obj, markOop m);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -63,10 +63,12 @@ inline bool G1CollectedHeap::obj_in_cs(oop obj) {
// assumptions of this method (and other related ones).
inline HeapWord*
G1CollectedHeap::allocate_from_cur_alloc_region(HeapRegion* cur_alloc_region,
size_t word_size) {
assert_heap_locked_and_not_at_safepoint();
size_t word_size,
bool with_heap_lock) {
assert_not_at_safepoint();
assert(with_heap_lock == Heap_lock->owned_by_self(),
"with_heap_lock and Heap_lock->owned_by_self() should be a tautology");
assert(cur_alloc_region != NULL, "pre-condition of the method");
assert(cur_alloc_region == _cur_alloc_region, "pre-condition of the method");
assert(cur_alloc_region->is_young(),
"we only support young current alloc regions");
assert(!isHumongous(word_size), "allocate_from_cur_alloc_region() "
@ -76,20 +78,24 @@ G1CollectedHeap::allocate_from_cur_alloc_region(HeapRegion* cur_alloc_region,
assert(!cur_alloc_region->is_empty(),
err_msg("region ["PTR_FORMAT","PTR_FORMAT"] should not be empty",
cur_alloc_region->bottom(), cur_alloc_region->end()));
// This allocate method does BOT updates and we don't need them in
// the young generation. This will be fixed in the near future by
// CR 6994297.
HeapWord* result = cur_alloc_region->allocate(word_size);
HeapWord* result = cur_alloc_region->par_allocate_no_bot_updates(word_size);
if (result != NULL) {
assert(is_in(result), "result should be in the heap");
Heap_lock->unlock();
if (with_heap_lock) {
Heap_lock->unlock();
}
assert_heap_not_locked();
// Do the dirtying after we release the Heap_lock.
dirty_young_block(result, word_size);
return result;
}
assert_heap_locked();
if (with_heap_lock) {
assert_heap_locked();
} else {
assert_heap_not_locked();
}
return NULL;
}
@ -97,31 +103,27 @@ G1CollectedHeap::allocate_from_cur_alloc_region(HeapRegion* cur_alloc_region,
// assumptions of this method (and other related ones).
inline HeapWord*
G1CollectedHeap::attempt_allocation(size_t word_size) {
assert_heap_locked_and_not_at_safepoint();
assert_heap_not_locked_and_not_at_safepoint();
assert(!isHumongous(word_size), "attempt_allocation() should not be called "
"for humongous allocation requests");
HeapRegion* cur_alloc_region = _cur_alloc_region;
if (cur_alloc_region != NULL) {
HeapWord* result = allocate_from_cur_alloc_region(cur_alloc_region,
word_size);
word_size,
false /* with_heap_lock */);
assert_heap_not_locked();
if (result != NULL) {
assert_heap_not_locked();
return result;
}
assert_heap_locked();
// Since we couldn't successfully allocate into it, retire the
// current alloc region.
retire_cur_alloc_region(cur_alloc_region);
}
// Try to get a new region and allocate out of it
HeapWord* result = replace_cur_alloc_region_and_allocate(word_size,
false, /* at_safepoint */
true, /* do_dirtying */
false /* can_expand */);
// Our attempt to allocate lock-free failed as the current
// allocation region is either NULL or full. So, we'll now take the
// Heap_lock and retry.
Heap_lock->lock();
HeapWord* result = attempt_allocation_locked(word_size);
if (result != NULL) {
assert_heap_not_locked();
return result;
@ -145,6 +147,45 @@ G1CollectedHeap::retire_cur_alloc_region_common(HeapRegion* cur_alloc_region) {
_cur_alloc_region = NULL;
}
inline HeapWord*
G1CollectedHeap::attempt_allocation_locked(size_t word_size) {
assert_heap_locked_and_not_at_safepoint();
assert(!isHumongous(word_size), "attempt_allocation_locked() "
"should not be called for humongous allocation requests");
// First, reread the current alloc region and retry the allocation
// in case somebody replaced it while we were waiting to get the
// Heap_lock.
HeapRegion* cur_alloc_region = _cur_alloc_region;
if (cur_alloc_region != NULL) {
HeapWord* result = allocate_from_cur_alloc_region(
cur_alloc_region, word_size,
true /* with_heap_lock */);
if (result != NULL) {
assert_heap_not_locked();
return result;
}
// We failed to allocate out of the current alloc region, so let's
// retire it before getting a new one.
retire_cur_alloc_region(cur_alloc_region);
}
assert_heap_locked();
// Try to get a new region and allocate out of it
HeapWord* result = replace_cur_alloc_region_and_allocate(word_size,
false, /* at_safepoint */
true, /* do_dirtying */
false /* can_expand */);
if (result != NULL) {
assert_heap_not_locked();
return result;
}
assert_heap_locked();
return NULL;
}
// It dirties the cards that cover the block so that so that the post
// write barrier never queues anything when updating objects on this
// block. It is assumed (and in fact we assert) that the block

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -386,26 +386,27 @@ void HeapRegion::calc_gc_efficiency() {
}
// </PREDICTION>
void HeapRegion::set_startsHumongous(HeapWord* new_end) {
void HeapRegion::set_startsHumongous(HeapWord* new_top, HeapWord* new_end) {
assert(end() == _orig_end,
"Should be normal before the humongous object allocation");
assert(top() == bottom(), "should be empty");
assert(bottom() <= new_top && new_top <= new_end, "pre-condition");
_humongous_type = StartsHumongous;
_humongous_start_region = this;
set_end(new_end);
_offsets.set_for_starts_humongous(new_end);
_offsets.set_for_starts_humongous(new_top);
}
void HeapRegion::set_continuesHumongous(HeapRegion* start) {
void HeapRegion::set_continuesHumongous(HeapRegion* first_hr) {
assert(end() == _orig_end,
"Should be normal before the humongous object allocation");
assert(top() == bottom(), "should be empty");
assert(start->startsHumongous(), "pre-condition");
assert(first_hr->startsHumongous(), "pre-condition");
_humongous_type = ContinuesHumongous;
_humongous_start_region = start;
_humongous_start_region = first_hr;
}
bool HeapRegion::claimHeapRegion(jint claimValue) {
@ -782,9 +783,6 @@ void HeapRegion::verify(bool allow_dirty) const {
verify(allow_dirty, /* use_prev_marking */ true, /* failures */ &dummy);
}
#define OBJ_SAMPLE_INTERVAL 0
#define BLOCK_SAMPLE_INTERVAL 100
// This really ought to be commoned up into OffsetTableContigSpace somehow.
// We would need a mechanism to make that code skip dead objects.
@ -795,83 +793,125 @@ void HeapRegion::verify(bool allow_dirty,
*failures = false;
HeapWord* p = bottom();
HeapWord* prev_p = NULL;
int objs = 0;
int blocks = 0;
VerifyLiveClosure vl_cl(g1, use_prev_marking);
bool is_humongous = isHumongous();
bool do_bot_verify = !is_young();
size_t object_num = 0;
while (p < top()) {
size_t size = oop(p)->size();
if (is_humongous != g1->isHumongous(size)) {
oop obj = oop(p);
size_t obj_size = obj->size();
object_num += 1;
if (is_humongous != g1->isHumongous(obj_size)) {
gclog_or_tty->print_cr("obj "PTR_FORMAT" is of %shumongous size ("
SIZE_FORMAT" words) in a %shumongous region",
p, g1->isHumongous(size) ? "" : "non-",
size, is_humongous ? "" : "non-");
p, g1->isHumongous(obj_size) ? "" : "non-",
obj_size, is_humongous ? "" : "non-");
*failures = true;
return;
}
object_num += 1;
if (blocks == BLOCK_SAMPLE_INTERVAL) {
HeapWord* res = block_start_const(p + (size/2));
if (p != res) {
gclog_or_tty->print_cr("offset computation 1 for "PTR_FORMAT" and "
SIZE_FORMAT" returned "PTR_FORMAT,
p, size, res);
*failures = true;
return;
}
blocks = 0;
} else {
blocks++;
// If it returns false, verify_for_object() will output the
// appropriate messasge.
if (do_bot_verify && !_offsets.verify_for_object(p, obj_size)) {
*failures = true;
return;
}
if (objs == OBJ_SAMPLE_INTERVAL) {
oop obj = oop(p);
if (!g1->is_obj_dead_cond(obj, this, use_prev_marking)) {
if (obj->is_oop()) {
klassOop klass = obj->klass();
if (!klass->is_perm()) {
gclog_or_tty->print_cr("klass "PTR_FORMAT" of object "PTR_FORMAT" "
"not in perm", klass, obj);
*failures = true;
return;
} else if (!klass->is_klass()) {
gclog_or_tty->print_cr("klass "PTR_FORMAT" of object "PTR_FORMAT" "
"not a klass", klass, obj);
*failures = true;
return;
} else {
vl_cl.set_containing_obj(obj);
obj->oop_iterate(&vl_cl);
if (vl_cl.failures()) {
*failures = true;
}
if (G1MaxVerifyFailures >= 0 &&
vl_cl.n_failures() >= G1MaxVerifyFailures) {
return;
}
}
} else {
gclog_or_tty->print_cr(PTR_FORMAT" no an oop", obj);
if (!g1->is_obj_dead_cond(obj, this, use_prev_marking)) {
if (obj->is_oop()) {
klassOop klass = obj->klass();
if (!klass->is_perm()) {
gclog_or_tty->print_cr("klass "PTR_FORMAT" of object "PTR_FORMAT" "
"not in perm", klass, obj);
*failures = true;
return;
} else if (!klass->is_klass()) {
gclog_or_tty->print_cr("klass "PTR_FORMAT" of object "PTR_FORMAT" "
"not a klass", klass, obj);
*failures = true;
return;
} else {
vl_cl.set_containing_obj(obj);
obj->oop_iterate(&vl_cl);
if (vl_cl.failures()) {
*failures = true;
}
if (G1MaxVerifyFailures >= 0 &&
vl_cl.n_failures() >= G1MaxVerifyFailures) {
return;
}
}
}
objs = 0;
} else {
objs++;
}
prev_p = p;
p += size;
}
HeapWord* rend = end();
HeapWord* rtop = top();
if (rtop < rend) {
HeapWord* res = block_start_const(rtop + (rend - rtop) / 2);
if (res != rtop) {
gclog_or_tty->print_cr("offset computation 2 for "PTR_FORMAT" and "
PTR_FORMAT" returned "PTR_FORMAT,
rtop, rend, res);
} else {
gclog_or_tty->print_cr(PTR_FORMAT" no an oop", obj);
*failures = true;
return;
}
}
prev_p = p;
p += obj_size;
}
if (p != top()) {
gclog_or_tty->print_cr("end of last object "PTR_FORMAT" "
"does not match top "PTR_FORMAT, p, top());
*failures = true;
return;
}
HeapWord* the_end = end();
assert(p == top(), "it should still hold");
// Do some extra BOT consistency checking for addresses in the
// range [top, end). BOT look-ups in this range should yield
// top. No point in doing that if top == end (there's nothing there).
if (p < the_end) {
// Look up top
HeapWord* addr_1 = p;
HeapWord* b_start_1 = _offsets.block_start_const(addr_1);
if (b_start_1 != p) {
gclog_or_tty->print_cr("BOT look up for top: "PTR_FORMAT" "
" yielded "PTR_FORMAT", expecting "PTR_FORMAT,
addr_1, b_start_1, p);
*failures = true;
return;
}
// Look up top + 1
HeapWord* addr_2 = p + 1;
if (addr_2 < the_end) {
HeapWord* b_start_2 = _offsets.block_start_const(addr_2);
if (b_start_2 != p) {
gclog_or_tty->print_cr("BOT look up for top + 1: "PTR_FORMAT" "
" yielded "PTR_FORMAT", expecting "PTR_FORMAT,
addr_2, b_start_2, p);
*failures = true;
return;
}
}
// Look up an address between top and end
size_t diff = pointer_delta(the_end, p) / 2;
HeapWord* addr_3 = p + diff;
if (addr_3 < the_end) {
HeapWord* b_start_3 = _offsets.block_start_const(addr_3);
if (b_start_3 != p) {
gclog_or_tty->print_cr("BOT look up for top + diff: "PTR_FORMAT" "
" yielded "PTR_FORMAT", expecting "PTR_FORMAT,
addr_3, b_start_3, p);
*failures = true;
return;
}
}
// Loook up end - 1
HeapWord* addr_4 = the_end - 1;
HeapWord* b_start_4 = _offsets.block_start_const(addr_4);
if (b_start_4 != p) {
gclog_or_tty->print_cr("BOT look up for end - 1: "PTR_FORMAT" "
" yielded "PTR_FORMAT", expecting "PTR_FORMAT,
addr_4, b_start_4, p);
*failures = true;
return;
}
}
@ -880,12 +920,6 @@ void HeapRegion::verify(bool allow_dirty,
"but has "SIZE_FORMAT", objects",
bottom(), end(), object_num);
*failures = true;
}
if (p != top()) {
gclog_or_tty->print_cr("end of last object "PTR_FORMAT" "
"does not match top "PTR_FORMAT, p, top());
*failures = true;
return;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -173,6 +173,19 @@ class G1OffsetTableContigSpace: public ContiguousSpace {
virtual HeapWord* cross_threshold(HeapWord* start, HeapWord* end);
virtual void print() const;
void reset_bot() {
_offsets.zero_bottom_entry();
_offsets.initialize_threshold();
}
void update_bot_for_object(HeapWord* start, size_t word_size) {
_offsets.alloc_block(start, word_size);
}
void print_bot_on(outputStream* out) {
_offsets.print_on(out);
}
};
class HeapRegion: public G1OffsetTableContigSpace {
@ -359,6 +372,15 @@ class HeapRegion: public G1OffsetTableContigSpace {
Allocated
};
inline HeapWord* par_allocate_no_bot_updates(size_t word_size) {
assert(is_young(), "we can only skip BOT updates on young regions");
return ContiguousSpace::par_allocate(word_size);
}
inline HeapWord* allocate_no_bot_updates(size_t word_size) {
assert(is_young(), "we can only skip BOT updates on young regions");
return ContiguousSpace::allocate(word_size);
}
// If this region is a member of a HeapRegionSeq, the index in that
// sequence, otherwise -1.
int hrs_index() const { return _hrs_index; }
@ -404,13 +426,35 @@ class HeapRegion: public G1OffsetTableContigSpace {
return _humongous_start_region;
}
// Causes the current region to represent a humongous object spanning "n"
// regions.
void set_startsHumongous(HeapWord* new_end);
// Makes the current region be a "starts humongous" region, i.e.,
// the first region in a series of one or more contiguous regions
// that will contain a single "humongous" object. The two parameters
// are as follows:
//
// new_top : The new value of the top field of this region which
// points to the end of the humongous object that's being
// allocated. If there is more than one region in the series, top
// will lie beyond this region's original end field and on the last
// region in the series.
//
// new_end : The new value of the end field of this region which
// points to the end of the last region in the series. If there is
// one region in the series (namely: this one) end will be the same
// as the original end of this region.
//
// Updating top and end as described above makes this region look as
// if it spans the entire space taken up by all the regions in the
// series and an single allocation moved its top to new_top. This
// ensures that the space (capacity / allocated) taken up by all
// humongous regions can be calculated by just looking at the
// "starts humongous" regions and by ignoring the "continues
// humongous" regions.
void set_startsHumongous(HeapWord* new_top, HeapWord* new_end);
// The regions that continue a humongous sequence should be added using
// this method, in increasing address order.
void set_continuesHumongous(HeapRegion* start);
// Makes the current region be a "continues humongous'
// region. first_hr is the "start humongous" region of the series
// which this region will be part of.
void set_continuesHumongous(HeapRegion* first_hr);
// If the region has a remembered set, return a pointer to it.
HeapRegionRemSet* rem_set() const {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -144,7 +144,7 @@ HeapRegionSeq::alloc_obj_from_region_index(int ind, size_t word_size) {
// will also update the BOT covering all the regions to reflect
// that there is a single object that starts at the bottom of the
// first region.
first_hr->set_startsHumongous(new_end);
first_hr->set_startsHumongous(new_top, new_end);
// Then, if there are any, we will set up the "continues
// humongous" regions.

View File

@ -38,7 +38,6 @@ VM_G1CollectForAllocation::VM_G1CollectForAllocation(
}
void VM_G1CollectForAllocation::doit() {
JvmtiGCForAllocationMarker jgcm;
G1CollectedHeap* g1h = G1CollectedHeap::heap();
_result = g1h->satisfy_failed_allocation(_word_size, &_pause_succeeded);
assert(_result == NULL || _pause_succeeded,
@ -46,7 +45,6 @@ void VM_G1CollectForAllocation::doit() {
}
void VM_G1CollectFull::doit() {
JvmtiGCFullMarker jgcm;
G1CollectedHeap* g1h = G1CollectedHeap::heap();
GCCauseSetter x(g1h, _gc_cause);
g1h->do_full_collection(false /* clear_all_soft_refs */);
@ -72,7 +70,6 @@ VM_G1IncCollectionPause::VM_G1IncCollectionPause(
}
void VM_G1IncCollectionPause::doit() {
JvmtiGCForAllocationMarker jgcm;
G1CollectedHeap* g1h = G1CollectedHeap::heap();
assert(!_should_initiate_conc_mark ||
((_gc_cause == GCCause::_gc_locker && GCLockerInvokesConcurrent) ||

View File

@ -42,8 +42,7 @@ VM_ParallelGCFailedAllocation::VM_ParallelGCFailedAllocation(size_t size,
}
void VM_ParallelGCFailedAllocation::doit() {
JvmtiGCForAllocationMarker jgcm;
notify_gc_begin(false);
SvcGCMarker sgcm(SvcGCMarker::MINOR);
ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "must be a ParallelScavengeHeap");
@ -54,8 +53,6 @@ void VM_ParallelGCFailedAllocation::doit() {
if (_result == NULL && GC_locker::is_active_and_needs_gc()) {
set_gc_locked();
}
notify_gc_end();
}
VM_ParallelGCFailedPermanentAllocation::VM_ParallelGCFailedPermanentAllocation(size_t size,
@ -67,8 +64,7 @@ VM_ParallelGCFailedPermanentAllocation::VM_ParallelGCFailedPermanentAllocation(s
}
void VM_ParallelGCFailedPermanentAllocation::doit() {
JvmtiGCFullMarker jgcm;
notify_gc_begin(true);
SvcGCMarker sgcm(SvcGCMarker::FULL);
ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "must be a ParallelScavengeHeap");
@ -78,7 +74,6 @@ void VM_ParallelGCFailedPermanentAllocation::doit() {
if (_result == NULL && GC_locker::is_active_and_needs_gc()) {
set_gc_locked();
}
notify_gc_end();
}
// Only used for System.gc() calls
@ -91,8 +86,7 @@ VM_ParallelGCSystemGC::VM_ParallelGCSystemGC(unsigned int gc_count,
}
void VM_ParallelGCSystemGC::doit() {
JvmtiGCFullMarker jgcm;
notify_gc_begin(true);
SvcGCMarker sgcm(SvcGCMarker::FULL);
ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
assert(heap->kind() == CollectedHeap::ParallelScavengeHeap,
@ -106,5 +100,4 @@ void VM_ParallelGCSystemGC::doit() {
} else {
heap->invoke_full_gc(false);
}
notify_gc_end();
}

View File

@ -31,7 +31,6 @@
#include "memory/oopFactory.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/instanceRefKlass.hpp"
#include "prims/jvmtiExport.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/init.hpp"
#include "runtime/interfaceSupport.hpp"
@ -40,6 +39,7 @@
#ifndef SERIALGC
#include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
#endif
HS_DTRACE_PROBE_DECL1(hotspot, gc__begin, bool);
HS_DTRACE_PROBE_DECL(hotspot, gc__end);
@ -158,8 +158,7 @@ void VM_GC_HeapInspection::doit() {
void VM_GenCollectForAllocation::doit() {
JvmtiGCForAllocationMarker jgcm;
notify_gc_begin(false);
SvcGCMarker sgcm(SvcGCMarker::MINOR);
GenCollectedHeap* gch = GenCollectedHeap::heap();
GCCauseSetter gccs(gch, _gc_cause);
@ -169,22 +168,19 @@ void VM_GenCollectForAllocation::doit() {
if (_res == NULL && GC_locker::is_active_and_needs_gc()) {
set_gc_locked();
}
notify_gc_end();
}
void VM_GenCollectFull::doit() {
JvmtiGCFullMarker jgcm;
notify_gc_begin(true);
SvcGCMarker sgcm(SvcGCMarker::FULL);
GenCollectedHeap* gch = GenCollectedHeap::heap();
GCCauseSetter gccs(gch, _gc_cause);
gch->do_full_collection(gch->must_clear_all_soft_refs(), _max_level);
notify_gc_end();
}
void VM_GenCollectForPermanentAllocation::doit() {
JvmtiGCForAllocationMarker jgcm;
notify_gc_begin(true);
SvcGCMarker sgcm(SvcGCMarker::FULL);
SharedHeap* heap = (SharedHeap*)Universe::heap();
GCCauseSetter gccs(heap, _gc_cause);
switch (heap->kind()) {
@ -209,5 +205,4 @@ void VM_GenCollectForPermanentAllocation::doit() {
if (_res == NULL && GC_locker::is_active_and_needs_gc()) {
set_gc_locked();
}
notify_gc_end();
}

View File

@ -30,6 +30,7 @@
#include "runtime/jniHandles.hpp"
#include "runtime/synchronizer.hpp"
#include "runtime/vm_operations.hpp"
#include "prims/jvmtiExport.hpp"
// The following class hierarchy represents
// a set of operations (VM_Operation) related to GC.
@ -209,13 +210,17 @@ class VM_GenCollectForPermanentAllocation: public VM_GC_Operation {
HeapWord* result() const { return _res; }
};
class DTraceGCProbeMarker : public StackObj {
public:
DTraceGCProbeMarker(bool full) {
VM_GC_Operation::notify_gc_begin(full);
class SvcGCMarker : public StackObj {
private:
JvmtiGCMarker _jgcm;
public:
typedef enum { MINOR, FULL, OTHER } reason_type;
SvcGCMarker(reason_type reason ) {
VM_GC_Operation::notify_gc_begin(reason == FULL);
}
~DTraceGCProbeMarker() {
~SvcGCMarker() {
VM_GC_Operation::notify_gc_end();
}
};

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -884,7 +884,7 @@ IRT_LEAF(jint, InterpreterRuntime::bcp_to_di(methodOopDesc* method, address cur_
return mdo->bci_to_di(bci);
IRT_END
IRT_ENTRY(jint, InterpreterRuntime::profile_method(JavaThread* thread, address cur_bcp))
IRT_ENTRY(void, InterpreterRuntime::profile_method(JavaThread* thread))
// use UnlockFlagSaver to clear and restore the _do_not_unlock_if_synchronized
// flag, in case this method triggers classloading which will call into Java.
UnlockFlagSaver fs(thread);
@ -893,16 +893,12 @@ IRT_ENTRY(jint, InterpreterRuntime::profile_method(JavaThread* thread, address c
frame fr = thread->last_frame();
assert(fr.is_interpreted_frame(), "must come from interpreter");
methodHandle method(thread, fr.interpreter_frame_method());
int bci = method->bci_from(cur_bcp);
methodOopDesc::build_interpreter_method_data(method, THREAD);
if (HAS_PENDING_EXCEPTION) {
assert((PENDING_EXCEPTION->is_a(SystemDictionary::OutOfMemoryError_klass())), "we expect only an OOM error here");
CLEAR_PENDING_EXCEPTION;
// and fall through...
}
methodDataOop mdo = method->method_data();
if (mdo == NULL) return 0;
return mdo->bci_to_di(bci);
IRT_END

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -164,7 +164,7 @@ class InterpreterRuntime: AllStatic {
// Interpreter profiling support
static jint bcp_to_di(methodOopDesc* method, address cur_bcp);
static jint profile_method(JavaThread* thread, address cur_bcp);
static void profile_method(JavaThread* thread);
static void update_mdp_for_ret(JavaThread* thread, int bci);
#ifdef ASSERT
static void verify_mdp(methodOopDesc* method, address bcp, address mdp);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -36,8 +36,8 @@ class arrayKlass: public Klass {
friend class VMStructs;
private:
int _dimension; // This is n'th-dimensional array.
klassOop _higher_dimension; // Refers the (n+1)'th-dimensional array (if present).
klassOop _lower_dimension; // Refers the (n-1)'th-dimensional array (if present).
volatile klassOop _higher_dimension; // Refers the (n+1)'th-dimensional array (if present).
volatile klassOop _lower_dimension; // Refers the (n-1)'th-dimensional array (if present).
int _vtable_len; // size of vtable for this klass
juint _alloc_size; // allocation profiling support
oop _component_mirror; // component type, as a java/lang/Class

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -235,8 +235,9 @@ klassOop objArrayKlass::array_klass_impl(objArrayKlassHandle this_oop, bool or_n
objArrayKlassKlass::cast(Universe::objArrayKlassKlassObj())->
allocate_objArray_klass(dimension + 1, this_oop, CHECK_NULL);
ak = objArrayKlassHandle(THREAD, new_klass);
this_oop->set_higher_dimension(ak());
ak->set_lower_dimension(this_oop());
OrderAccess::storestore();
this_oop->set_higher_dimension(ak());
assert(ak->oop_is_objArray(), "incorrect initialization of objArrayKlass");
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -179,6 +179,7 @@ klassOop typeArrayKlass::array_klass_impl(typeArrayKlassHandle h_this, bool or_n
dimension + 1, h_this, CHECK_NULL);
h_ak = objArrayKlassHandle(THREAD, oak);
h_ak->set_lower_dimension(h_this());
OrderAccess::storestore();
h_this->set_higher_dimension(h_ak());
assert(h_ak->oop_is_objArray(), "incorrect initialization of objArrayKlass");
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -2187,8 +2187,11 @@ const TypePtr *TypeRawPtr::add_offset( intptr_t offset ) const {
case TypePtr::NotNull:
return this;
case TypePtr::Null:
case TypePtr::Constant:
return make( _bits+offset );
case TypePtr::Constant: {
address bits = _bits+offset;
if ( bits == 0 ) return TypePtr::NULL_PTR;
return make( bits );
}
default: ShouldNotReachHere();
}
return NULL; // Lint noise

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -1649,7 +1649,8 @@ typedef struct {
* the new bit is also added in the main/baseline.
*/
unsigned int thread_park_blocker : 1;
unsigned int : 31;
unsigned int post_vm_init_hook_enabled : 1;
unsigned int : 30;
unsigned int : 32;
unsigned int : 32;
} jdk_version_info;

View File

@ -13048,8 +13048,8 @@ myInit() {
<event label="Garbage Collection Start"
id="GarbageCollectionStart" const="JVMTI_EVENT_GARBAGE_COLLECTION_START" num="81">
<description>
A Garbage Collection Start event is sent when a full cycle
garbage collection begins.
A Garbage Collection Start event is sent when a
garbage collection pause begins.
Only stop-the-world collections are reported--that is, collections during
which all threads cease to modify the state of the Java virtual machine.
This means that some collectors will never generate these events.
@ -13075,8 +13075,8 @@ myInit() {
<event label="Garbage Collection Finish"
id="GarbageCollectionFinish" const="JVMTI_EVENT_GARBAGE_COLLECTION_FINISH" num="82">
<description>
A Garbage Collection Finish event is sent when a full
garbage collection cycle ends.
A Garbage Collection Finish event is sent when a
garbage collection pause ends.
This event is sent while the VM is still stopped, thus
the event handler must not use JNI functions and
must not use <jvmti/> functions except those which

View File

@ -667,14 +667,13 @@ void
JvmtiEventControllerPrivate::thread_ended(JavaThread *thread) {
// Removes the JvmtiThreadState associated with the specified thread.
// May be called after all environments have been disposed.
assert(JvmtiThreadState_lock->is_locked(), "sanity check");
EC_TRACE(("JVMTI [%s] # thread ended", JvmtiTrace::safe_get_thread_name(thread)));
JvmtiThreadState *state = thread->jvmti_thread_state();
if (state != NULL) {
MutexLocker mu(JvmtiThreadState_lock);
delete state;
}
assert(state != NULL, "else why are we here?");
delete state;
}
void JvmtiEventControllerPrivate::set_event_callbacks(JvmtiEnvBase *env,

View File

@ -2253,12 +2253,14 @@ void JvmtiExport::post_vm_object_alloc(JavaThread *thread, oop object) {
void JvmtiExport::cleanup_thread(JavaThread* thread) {
assert(JavaThread::current() == thread, "thread is not current");
MutexLocker mu(JvmtiThreadState_lock);
// This has to happen after the thread state is removed, which is
// why it is not in post_thread_end_event like its complement
// Maybe both these functions should be rolled into the posts?
JvmtiEventController::thread_ended(thread);
if (thread->jvmti_thread_state() != NULL) {
// This has to happen after the thread state is removed, which is
// why it is not in post_thread_end_event like its complement
// Maybe both these functions should be rolled into the posts?
JvmtiEventController::thread_ended(thread);
}
}
void JvmtiExport::oops_do(OopClosure* f) {
@ -2358,15 +2360,6 @@ jint JvmtiExport::load_agent_library(AttachOperation* op, outputStream* st) {
}
#endif // SERVICES_KERNEL
// CMS has completed referencing processing so may need to update
// tag maps.
void JvmtiExport::cms_ref_processing_epilogue() {
if (JvmtiEnv::environments_might_exist()) {
JvmtiTagMap::cms_ref_processing_epilogue();
}
}
////////////////////////////////////////////////////////////////////////////////////////////////
// Setup current current thread for event collection.
@ -2536,36 +2529,20 @@ NoJvmtiVMObjectAllocMark::~NoJvmtiVMObjectAllocMark() {
}
};
JvmtiGCMarker::JvmtiGCMarker(bool full) : _full(full), _invocation_count(0) {
assert(Thread::current()->is_VM_thread(), "wrong thread");
JvmtiGCMarker::JvmtiGCMarker() {
// if there aren't any JVMTI environments then nothing to do
if (!JvmtiEnv::environments_might_exist()) {
return;
}
if (ForceFullGCJVMTIEpilogues) {
// force 'Full GC' was done semantics for JVMTI GC epilogues
_full = true;
}
// GarbageCollectionStart event posted from VM thread - okay because
// JVMTI is clear that the "world is stopped" and callback shouldn't
// try to call into the VM.
if (JvmtiExport::should_post_garbage_collection_start()) {
JvmtiExport::post_garbage_collection_start();
}
// if "full" is false it probably means this is a scavenge of the young
// generation. However it could turn out that a "full" GC is required
// so we record the number of collections so that it can be checked in
// the destructor.
if (!_full) {
_invocation_count = Universe::heap()->total_full_collections();
if (SafepointSynchronize::is_at_safepoint()) {
// Do clean up tasks that need to be done at a safepoint
JvmtiEnvBase::check_for_periodic_clean_up();
}
// Do clean up tasks that need to be done at a safepoint
JvmtiEnvBase::check_for_periodic_clean_up();
}
JvmtiGCMarker::~JvmtiGCMarker() {
@ -2578,21 +2555,5 @@ JvmtiGCMarker::~JvmtiGCMarker() {
if (JvmtiExport::should_post_garbage_collection_finish()) {
JvmtiExport::post_garbage_collection_finish();
}
// we might have initially started out doing a scavenge of the young
// generation but could have ended up doing a "full" GC - check the
// GC count to see.
if (!_full) {
_full = (_invocation_count != Universe::heap()->total_full_collections());
}
// Full collection probably means the perm generation has been GC'ed
// so we clear the breakpoint cache.
if (_full) {
JvmtiCurrentBreakpoints::gc_epilogue();
}
// Notify heap/object tagging support
JvmtiTagMap::gc_epilogue(_full);
}
#endif // JVMTI_KERNEL

View File

@ -356,9 +356,6 @@ class JvmtiExport : public AllStatic {
// SetNativeMethodPrefix support
static char** get_all_native_method_prefixes(int* count_ptr);
// call after CMS has completed referencing processing
static void cms_ref_processing_epilogue() KERNEL_RETURN;
};
// Support class used by JvmtiDynamicCodeEventCollector and others. It
@ -492,55 +489,11 @@ class NoJvmtiVMObjectAllocMark : public StackObj {
// Base class for reporting GC events to JVMTI.
class JvmtiGCMarker : public StackObj {
private:
bool _full; // marks a "full" GC
unsigned int _invocation_count; // GC invocation count
protected:
JvmtiGCMarker(bool full) KERNEL_RETURN; // protected
~JvmtiGCMarker() KERNEL_RETURN; // protected
};
// Support class used to report GC events to JVMTI. The class is stack
// allocated and should be placed in the doit() implementation of all
// vm operations that do a stop-the-world GC for failed allocation.
//
// Usage :-
//
// void VM_GenCollectForAllocation::doit() {
// JvmtiGCForAllocationMarker jgcm;
// :
// }
//
// If jvmti is not enabled the constructor and destructor is essentially
// a no-op (no overhead).
//
class JvmtiGCForAllocationMarker : public JvmtiGCMarker {
public:
JvmtiGCForAllocationMarker() : JvmtiGCMarker(false) {
}
JvmtiGCMarker() KERNEL_RETURN;
~JvmtiGCMarker() KERNEL_RETURN;
};
// Support class used to report GC events to JVMTI. The class is stack
// allocated and should be placed in the doit() implementation of all
// vm operations that do a "full" stop-the-world GC. This class differs
// from JvmtiGCForAllocationMarker in that this class assumes that a
// "full" GC will happen.
//
// Usage :-
//
// void VM_GenCollectFull::doit() {
// JvmtiGCFullMarker jgcm;
// :
// }
//
class JvmtiGCFullMarker : public JvmtiGCMarker {
public:
JvmtiGCFullMarker() : JvmtiGCMarker(true) {
}
};
// JvmtiHideSingleStepping is a helper class for hiding
// internal single step events.
class JvmtiHideSingleStepping : public StackObj {

View File

@ -212,14 +212,7 @@ void GrowableCache::oops_do(OopClosure* f) {
for (int i=0; i<len; i++) {
GrowableElement *e = _elements->at(i);
e->oops_do(f);
}
}
void GrowableCache::gc_epilogue() {
int len = _elements->length();
// recompute the new cache value after GC
for (int i=0; i<len; i++) {
_cache[i] = _elements->at(i)->getCacheValue();
_cache[i] = e->getCacheValue();
}
}
@ -401,10 +394,6 @@ void JvmtiBreakpoints::oops_do(OopClosure* f) {
_bps.oops_do(f);
}
void JvmtiBreakpoints::gc_epilogue() {
_bps.gc_epilogue();
}
void JvmtiBreakpoints::print() {
#ifndef PRODUCT
ResourceMark rm;
@ -534,13 +523,6 @@ void JvmtiCurrentBreakpoints::oops_do(OopClosure* f) {
}
}
void JvmtiCurrentBreakpoints::gc_epilogue() {
if (_jvmti_breakpoints != NULL) {
_jvmti_breakpoints->gc_epilogue();
}
}
///////////////////////////////////////////////////////////////
//
// class VM_GetOrSetLocal

View File

@ -117,7 +117,6 @@ public:
void clear();
// apply f to every element and update the cache
void oops_do(OopClosure* f);
void gc_epilogue();
};
@ -149,7 +148,6 @@ public:
void remove (int index) { _cache.remove(index); }
void clear() { _cache.clear(); }
void oops_do(OopClosure* f) { _cache.oops_do(f); }
void gc_epilogue() { _cache.gc_epilogue(); }
};
@ -278,7 +276,6 @@ public:
int length();
void oops_do(OopClosure* f);
void gc_epilogue();
void print();
int set(JvmtiBreakpoint& bp);
@ -328,7 +325,6 @@ public:
static inline bool is_breakpoint(address bcp);
static void oops_do(OopClosure* f);
static void gc_epilogue();
};
// quickly test whether the bcp matches a cached breakpoint in the list

View File

@ -50,7 +50,7 @@
// JvmtiTagHashmapEntry
//
// Each entry encapsulates a JNI weak reference to the tagged object
// Each entry encapsulates a reference to the tagged object
// and the tag value. In addition an entry includes a next pointer which
// is used to chain entries together.
@ -58,24 +58,25 @@ class JvmtiTagHashmapEntry : public CHeapObj {
private:
friend class JvmtiTagMap;
jweak _object; // JNI weak ref to tagged object
oop _object; // tagged object
jlong _tag; // the tag
JvmtiTagHashmapEntry* _next; // next on the list
inline void init(jweak object, jlong tag) {
inline void init(oop object, jlong tag) {
_object = object;
_tag = tag;
_next = NULL;
}
// constructor
JvmtiTagHashmapEntry(jweak object, jlong tag) { init(object, tag); }
JvmtiTagHashmapEntry(oop object, jlong tag) { init(object, tag); }
public:
// accessor methods
inline jweak object() const { return _object; }
inline jlong tag() const { return _tag; }
inline oop object() const { return _object; }
inline oop* object_addr() { return &_object; }
inline jlong tag() const { return _tag; }
inline void set_tag(jlong tag) {
assert(tag != 0, "can't be zero");
@ -92,9 +93,7 @@ class JvmtiTagHashmapEntry : public CHeapObj {
// A hashmap is essentially a table of pointers to entries. Entries
// are hashed to a location, or position in the table, and then
// chained from that location. The "key" for hashing is address of
// the object, or oop. The "value" is the JNI weak reference to the
// object and the tag value. Keys are not stored with the entry.
// Instead the weak reference is resolved to obtain the key.
// the object, or oop. The "value" is the tag value.
//
// A hashmap maintains a count of the number entries in the hashmap
// and resizes if the number of entries exceeds a given threshold.
@ -206,7 +205,7 @@ class JvmtiTagHashmap : public CHeapObj {
JvmtiTagHashmapEntry* entry = _table[i];
while (entry != NULL) {
JvmtiTagHashmapEntry* next = entry->next();
oop key = JNIHandles::resolve(entry->object());
oop key = entry->object();
assert(key != NULL, "jni weak reference cleared!!");
unsigned int h = hash(key, new_size);
JvmtiTagHashmapEntry* anchor = new_table[h];
@ -299,14 +298,12 @@ class JvmtiTagHashmap : public CHeapObj {
unsigned int h = hash(key);
JvmtiTagHashmapEntry* entry = _table[h];
while (entry != NULL) {
oop orig_key = JNIHandles::resolve(entry->object());
assert(orig_key != NULL, "jni weak reference cleared!!");
if (key == orig_key) {
break;
if (entry->object() == key) {
return entry;
}
entry = entry->next();
}
return entry;
return NULL;
}
@ -343,9 +340,7 @@ class JvmtiTagHashmap : public CHeapObj {
JvmtiTagHashmapEntry* entry = _table[h];
JvmtiTagHashmapEntry* prev = NULL;
while (entry != NULL) {
oop orig_key = JNIHandles::resolve(entry->object());
assert(orig_key != NULL, "jni weak reference cleared!!");
if (key == orig_key) {
if (key == entry->object()) {
break;
}
prev = entry;
@ -418,54 +413,6 @@ void JvmtiTagHashmap::compute_next_trace_threshold() {
}
}
// memory region for young generation
MemRegion JvmtiTagMap::_young_gen;
// get the memory region used for the young generation
void JvmtiTagMap::get_young_generation() {
CollectedHeap* ch = Universe::heap();
switch (ch->kind()) {
case (CollectedHeap::GenCollectedHeap): {
_young_gen = ((GenCollectedHeap*)ch)->get_gen(0)->reserved();
break;
}
#ifndef SERIALGC
case (CollectedHeap::ParallelScavengeHeap): {
_young_gen = ((ParallelScavengeHeap*)ch)->young_gen()->reserved();
break;
}
case (CollectedHeap::G1CollectedHeap): {
// Until a more satisfactory solution is implemented, all
// oops in the tag map will require rehash at each gc.
// This is a correct, if extremely inefficient solution.
// See RFE 6621729 for related commentary.
_young_gen = ch->reserved_region();
break;
}
#endif // !SERIALGC
default:
ShouldNotReachHere();
}
}
// returns true if oop is in the young generation
inline bool JvmtiTagMap::is_in_young(oop o) {
assert(_young_gen.start() != NULL, "checking");
void* p = (void*)o;
bool in_young = _young_gen.contains(p);
return in_young;
}
// returns the appropriate hashmap for a given object
inline JvmtiTagHashmap* JvmtiTagMap::hashmap_for(oop o) {
if (is_in_young(o)) {
return _hashmap[0];
} else {
return _hashmap[1];
}
}
// create a JvmtiTagMap
JvmtiTagMap::JvmtiTagMap(JvmtiEnv* env) :
_env(env),
@ -476,13 +423,7 @@ JvmtiTagMap::JvmtiTagMap(JvmtiEnv* env) :
assert(JvmtiThreadState_lock->is_locked(), "sanity check");
assert(((JvmtiEnvBase *)env)->tag_map() == NULL, "tag map already exists for environment");
// create the hashmaps
for (int i=0; i<n_hashmaps; i++) {
_hashmap[i] = new JvmtiTagHashmap();
}
// get the memory region used by the young generation
get_young_generation();
_hashmap = new JvmtiTagHashmap();
// finally add us to the environment
((JvmtiEnvBase *)env)->set_tag_map(this);
@ -496,25 +437,20 @@ JvmtiTagMap::~JvmtiTagMap() {
// also being destroryed.
((JvmtiEnvBase *)_env)->set_tag_map(NULL);
// iterate over the hashmaps and destroy each of the entries
for (int i=0; i<n_hashmaps; i++) {
JvmtiTagHashmap* hashmap = _hashmap[i];
JvmtiTagHashmapEntry** table = hashmap->table();
for (int j=0; j<hashmap->size(); j++) {
JvmtiTagHashmapEntry *entry = table[j];
while (entry != NULL) {
JvmtiTagHashmapEntry* next = entry->next();
jweak ref = entry->object();
JNIHandles::destroy_weak_global(ref);
delete entry;
entry = next;
}
JvmtiTagHashmapEntry** table = _hashmap->table();
for (int j = 0; j < _hashmap->size(); j++) {
JvmtiTagHashmapEntry* entry = table[j];
while (entry != NULL) {
JvmtiTagHashmapEntry* next = entry->next();
delete entry;
entry = next;
}
// finally destroy the hashmap
delete hashmap;
}
// finally destroy the hashmap
delete _hashmap;
_hashmap = NULL;
// remove any entries on the free list
JvmtiTagHashmapEntry* entry = _free_entries;
while (entry != NULL) {
@ -522,12 +458,13 @@ JvmtiTagMap::~JvmtiTagMap() {
delete entry;
entry = next;
}
_free_entries = NULL;
}
// create a hashmap entry
// - if there's an entry on the (per-environment) free list then this
// is returned. Otherwise an new entry is allocated.
JvmtiTagHashmapEntry* JvmtiTagMap::create_entry(jweak ref, jlong tag) {
JvmtiTagHashmapEntry* JvmtiTagMap::create_entry(oop ref, jlong tag) {
assert(Thread::current()->is_VM_thread() || is_locked(), "checking");
JvmtiTagHashmapEntry* entry;
if (_free_entries == NULL) {
@ -558,10 +495,10 @@ void JvmtiTagMap::destroy_entry(JvmtiTagHashmapEntry* entry) {
// returns the tag map for the given environments. If the tag map
// doesn't exist then it is created.
JvmtiTagMap* JvmtiTagMap::tag_map_for(JvmtiEnv* env) {
JvmtiTagMap* tag_map = ((JvmtiEnvBase *)env)->tag_map();
JvmtiTagMap* tag_map = ((JvmtiEnvBase*)env)->tag_map();
if (tag_map == NULL) {
MutexLocker mu(JvmtiThreadState_lock);
tag_map = ((JvmtiEnvBase *)env)->tag_map();
tag_map = ((JvmtiEnvBase*)env)->tag_map();
if (tag_map == NULL) {
tag_map = new JvmtiTagMap(env);
}
@ -573,17 +510,13 @@ JvmtiTagMap* JvmtiTagMap::tag_map_for(JvmtiEnv* env) {
// iterate over all entries in the tag map.
void JvmtiTagMap::entry_iterate(JvmtiTagHashmapEntryClosure* closure) {
for (int i=0; i<n_hashmaps; i++) {
JvmtiTagHashmap* hashmap = _hashmap[i];
hashmap->entry_iterate(closure);
}
hashmap()->entry_iterate(closure);
}
// returns true if the hashmaps are empty
bool JvmtiTagMap::is_empty() {
assert(SafepointSynchronize::is_at_safepoint() || is_locked(), "checking");
assert(n_hashmaps == 2, "not implemented");
return ((_hashmap[0]->entry_count() == 0) && (_hashmap[1]->entry_count() == 0));
return hashmap()->entry_count() == 0;
}
@ -591,7 +524,7 @@ bool JvmtiTagMap::is_empty() {
// not tagged
//
static inline jlong tag_for(JvmtiTagMap* tag_map, oop o) {
JvmtiTagHashmapEntry* entry = tag_map->hashmap_for(o)->find(o);
JvmtiTagHashmapEntry* entry = tag_map->hashmap()->find(o);
if (entry == NULL) {
return 0;
} else {
@ -655,7 +588,7 @@ class CallbackWrapper : public StackObj {
// record the context
_tag_map = tag_map;
_hashmap = tag_map->hashmap_for(_o);
_hashmap = tag_map->hashmap();
_entry = _hashmap->find(_o);
// get object tag
@ -694,23 +627,18 @@ void inline CallbackWrapper::post_callback_tag_update(oop o,
if (obj_tag != 0) {
// callback has tagged the object
assert(Thread::current()->is_VM_thread(), "must be VMThread");
HandleMark hm;
Handle h(o);
jweak ref = JNIHandles::make_weak_global(h);
entry = tag_map()->create_entry(ref, obj_tag);
entry = tag_map()->create_entry(o, obj_tag);
hashmap->add(o, entry);
}
} else {
// object was previously tagged - the callback may have untagged
// the object or changed the tag value
if (obj_tag == 0) {
jweak ref = entry->object();
JvmtiTagHashmapEntry* entry_removed = hashmap->remove(o);
assert(entry_removed == entry, "checking");
tag_map()->destroy_entry(entry);
JNIHandles::destroy_weak_global(ref);
} else {
if (obj_tag != entry->tag()) {
entry->set_tag(obj_tag);
@ -760,7 +688,7 @@ class TwoOopCallbackWrapper : public CallbackWrapper {
// for Classes the klassOop is tagged
_referrer = klassOop_if_java_lang_Class(referrer);
// record the context
_referrer_hashmap = tag_map->hashmap_for(_referrer);
_referrer_hashmap = tag_map->hashmap();
_referrer_entry = _referrer_hashmap->find(_referrer);
// get object tag
@ -796,8 +724,7 @@ class TwoOopCallbackWrapper : public CallbackWrapper {
//
// This function is performance critical. If many threads attempt to tag objects
// around the same time then it's possible that the Mutex associated with the
// tag map will be a hot lock. Eliminating this lock will not eliminate the issue
// because creating a JNI weak reference requires acquiring a global lock also.
// tag map will be a hot lock.
void JvmtiTagMap::set_tag(jobject object, jlong tag) {
MutexLocker ml(lock());
@ -808,22 +735,14 @@ void JvmtiTagMap::set_tag(jobject object, jlong tag) {
o = klassOop_if_java_lang_Class(o);
// see if the object is already tagged
JvmtiTagHashmap* hashmap = hashmap_for(o);
JvmtiTagHashmap* hashmap = _hashmap;
JvmtiTagHashmapEntry* entry = hashmap->find(o);
// if the object is not already tagged then we tag it
if (entry == NULL) {
if (tag != 0) {
HandleMark hm;
Handle h(o);
jweak ref = JNIHandles::make_weak_global(h);
// the object may have moved because make_weak_global may
// have blocked - thus it is necessary resolve the handle
// and re-hash the object.
o = h();
entry = create_entry(ref, tag);
hashmap_for(o)->add(o, entry);
entry = create_entry(o, tag);
hashmap->add(o, entry);
} else {
// no-op
}
@ -831,13 +750,9 @@ void JvmtiTagMap::set_tag(jobject object, jlong tag) {
// if the object is already tagged then we either update
// the tag (if a new tag value has been provided)
// or remove the object if the new tag value is 0.
// Removing the object requires that we also delete the JNI
// weak ref to the object.
if (tag == 0) {
jweak ref = entry->object();
hashmap->remove(o);
destroy_entry(entry);
JNIHandles::destroy_weak_global(ref);
} else {
entry->set_tag(tag);
}
@ -1626,8 +1541,8 @@ class TagObjectCollector : public JvmtiTagHashmapEntryClosure {
void do_entry(JvmtiTagHashmapEntry* entry) {
for (int i=0; i<_tag_count; i++) {
if (_tags[i] == entry->tag()) {
oop o = JNIHandles::resolve(entry->object());
assert(o != NULL && o != JNIHandles::deleted_handle(), "sanity check");
oop o = entry->object();
assert(o != NULL, "sanity check");
// the mirror is tagged
if (o->is_klass()) {
@ -3374,62 +3289,21 @@ void JvmtiTagMap::follow_references(jint heap_filter,
}
// called post-GC
// - for each JVMTI environment with an object tag map, call its rehash
// function to re-sync with the new object locations.
void JvmtiTagMap::gc_epilogue(bool full) {
assert(SafepointSynchronize::is_at_safepoint(), "must be executed at a safepoint");
void JvmtiTagMap::weak_oops_do(BoolObjectClosure* is_alive, OopClosure* f) {
assert(SafepointSynchronize::is_at_safepoint(),
"must be executed at a safepoint");
if (JvmtiEnv::environments_might_exist()) {
// re-obtain the memory region for the young generation (might
// changed due to adaptive resizing policy)
get_young_generation();
JvmtiEnvIterator it;
for (JvmtiEnvBase* env = it.first(); env != NULL; env = it.next(env)) {
JvmtiTagMap* tag_map = env->tag_map();
if (tag_map != NULL && !tag_map->is_empty()) {
TraceTime t(full ? "JVMTI Full Rehash " : "JVMTI Rehash ", TraceJVMTIObjectTagging);
if (full) {
tag_map->rehash(0, n_hashmaps);
} else {
tag_map->rehash(0, 0); // tag map for young gen only
}
tag_map->do_weak_oops(is_alive, f);
}
}
}
}
// CMS has completed referencing processing so we may have JNI weak refs
// to objects in the CMS generation that have been GC'ed.
void JvmtiTagMap::cms_ref_processing_epilogue() {
assert(SafepointSynchronize::is_at_safepoint(), "must be executed at a safepoint");
assert(UseConcMarkSweepGC, "should only be used with CMS");
if (JvmtiEnv::environments_might_exist()) {
JvmtiEnvIterator it;
for (JvmtiEnvBase* env = it.first(); env != NULL; env = it.next(env)) {
JvmtiTagMap* tag_map = ((JvmtiEnvBase *)env)->tag_map();
if (tag_map != NULL && !tag_map->is_empty()) {
TraceTime t("JVMTI Rehash (CMS) ", TraceJVMTIObjectTagging);
tag_map->rehash(1, n_hashmaps); // assume CMS not used in young gen
}
}
}
}
// For each entry in the hashmaps 'start' to 'end' :
//
// 1. resolve the JNI weak reference
//
// 2. If it resolves to NULL it means the object has been freed so the entry
// is removed, the weak reference destroyed, and the object free event is
// posted (if enabled).
//
// 3. If the weak reference resolves to an object then we re-hash the object
// to see if it has moved or has been promoted (from the young to the old
// generation for example).
//
void JvmtiTagMap::rehash(int start, int end) {
void JvmtiTagMap::do_weak_oops(BoolObjectClosure* is_alive, OopClosure* f) {
// does this environment have the OBJECT_FREE event enabled
bool post_object_free = env()->is_enabled(JVMTI_EVENT_OBJECT_FREE);
@ -3437,143 +3311,98 @@ void JvmtiTagMap::rehash(int start, int end) {
// counters used for trace message
int freed = 0;
int moved = 0;
int promoted = 0;
// we assume there are two hashmaps - one for the young generation
// and the other for all other spaces.
assert(n_hashmaps == 2, "not implemented");
JvmtiTagHashmap* young_hashmap = _hashmap[0];
JvmtiTagHashmap* other_hashmap = _hashmap[1];
JvmtiTagHashmap* hashmap = this->hashmap();
// reenable sizing (if disabled)
young_hashmap->set_resizing_enabled(true);
other_hashmap->set_resizing_enabled(true);
hashmap->set_resizing_enabled(true);
// when re-hashing the hashmap corresponding to the young generation we
// collect the entries corresponding to objects that have been promoted.
JvmtiTagHashmapEntry* promoted_entries = NULL;
if (end >= n_hashmaps) {
end = n_hashmaps - 1;
// if the hashmap is empty then we can skip it
if (hashmap->_entry_count == 0) {
return;
}
for (int i=start; i <= end; i++) {
JvmtiTagHashmap* hashmap = _hashmap[i];
// now iterate through each entry in the table
// if the hashmap is empty then we can skip it
if (hashmap->_entry_count == 0) {
continue;
}
JvmtiTagHashmapEntry** table = hashmap->table();
int size = hashmap->size();
// now iterate through each entry in the table
JvmtiTagHashmapEntry* delayed_add = NULL;
JvmtiTagHashmapEntry** table = hashmap->table();
int size = hashmap->size();
for (int pos = 0; pos < size; ++pos) {
JvmtiTagHashmapEntry* entry = table[pos];
JvmtiTagHashmapEntry* prev = NULL;
for (int pos=0; pos<size; pos++) {
JvmtiTagHashmapEntry* entry = table[pos];
JvmtiTagHashmapEntry* prev = NULL;
while (entry != NULL) {
JvmtiTagHashmapEntry* next = entry->next();
while (entry != NULL) {
JvmtiTagHashmapEntry* next = entry->next();
oop* obj = entry->object_addr();
jweak ref = entry->object();
oop oop = JNIHandles::resolve(ref);
// has object been GC'ed
if (!is_alive->do_object_b(entry->object())) {
// grab the tag
jlong tag = entry->tag();
guarantee(tag != 0, "checking");
// has object been GC'ed
if (oop == NULL) {
// grab the tag
jlong tag = entry->tag();
guarantee(tag != 0, "checking");
// remove GC'ed entry from hashmap and return the
// entry to the free list
hashmap->remove(prev, pos, entry);
destroy_entry(entry);
// remove GC'ed entry from hashmap and return the
// entry to the free list
hashmap->remove(prev, pos, entry);
destroy_entry(entry);
// post the event to the profiler
if (post_object_free) {
JvmtiExport::post_object_free(env(), tag);
}
// destroy the weak ref
JNIHandles::destroy_weak_global(ref);
++freed;
} else {
f->do_oop(entry->object_addr());
oop new_oop = entry->object();
// post the event to the profiler
if (post_object_free) {
JvmtiExport::post_object_free(env(), tag);
// if the object has moved then re-hash it and move its
// entry to its new location.
unsigned int new_pos = JvmtiTagHashmap::hash(new_oop, size);
if (new_pos != (unsigned int)pos) {
if (prev == NULL) {
table[pos] = next;
} else {
prev->set_next(next);
}
freed++;
entry = next;
continue;
}
// if this is the young hashmap then the object is either promoted
// or moved.
// if this is the other hashmap then the object is moved.
bool same_gen;
if (i == 0) {
assert(hashmap == young_hashmap, "checking");
same_gen = is_in_young(oop);
} else {
same_gen = true;
}
if (same_gen) {
// if the object has moved then re-hash it and move its
// entry to its new location.
unsigned int new_pos = JvmtiTagHashmap::hash(oop, size);
if (new_pos != (unsigned int)pos) {
if (prev == NULL) {
table[pos] = next;
} else {
prev->set_next(next);
}
if (new_pos < (unsigned int)pos) {
entry->set_next(table[new_pos]);
table[new_pos] = entry;
moved++;
} else {
// object didn't move
prev = entry;
// Delay adding this entry to it's new position as we'd end up
// hitting it again during this iteration.
entry->set_next(delayed_add);
delayed_add = entry;
}
moved++;
} else {
// object has been promoted so remove the entry from the
// young hashmap
assert(hashmap == young_hashmap, "checking");
hashmap->remove(prev, pos, entry);
// move the entry to the promoted list
entry->set_next(promoted_entries);
promoted_entries = entry;
// object didn't move
prev = entry;
}
entry = next;
}
entry = next;
}
}
// add the entries, corresponding to the promoted objects, to the
// other hashmap.
JvmtiTagHashmapEntry* entry = promoted_entries;
while (entry != NULL) {
oop o = JNIHandles::resolve(entry->object());
assert(hashmap_for(o) == other_hashmap, "checking");
JvmtiTagHashmapEntry* next = entry->next();
other_hashmap->add(o, entry);
entry = next;
promoted++;
// Re-add all the entries which were kept aside
while (delayed_add != NULL) {
JvmtiTagHashmapEntry* next = delayed_add->next();
unsigned int pos = JvmtiTagHashmap::hash(delayed_add->object(), size);
delayed_add->set_next(table[pos]);
table[pos] = delayed_add;
delayed_add = next;
}
// stats
if (TraceJVMTIObjectTagging) {
int total_moves = promoted + moved;
int post_total = 0;
for (int i=0; i<n_hashmaps; i++) {
post_total += _hashmap[i]->_entry_count;
}
int post_total = hashmap->_entry_count;
int pre_total = post_total + freed;
tty->print("(%d->%d, %d freed, %d promoted, %d total moves)",
pre_total, post_total, freed, promoted, total_moves);
tty->print_cr("(%d->%d, %d freed, %d total moves)",
pre_total, post_total, freed, moved);
}
}

View File

@ -45,17 +45,12 @@ class JvmtiTagMap : public CHeapObj {
private:
enum{
n_hashmaps = 2, // encapsulates 2 hashmaps
max_free_entries = 4096 // maximum number of free entries per env
max_free_entries = 4096 // maximum number of free entries per env
};
// memory region for young generation
static MemRegion _young_gen;
static void get_young_generation();
JvmtiEnv* _env; // the jvmti environment
Mutex _lock; // lock for this tag map
JvmtiTagHashmap* _hashmap[n_hashmaps]; // the hashmaps
JvmtiTagHashmap* _hashmap; // the hashmap
JvmtiTagHashmapEntry* _free_entries; // free list for this environment
int _free_entries_count; // number of entries on the free list
@ -67,11 +62,7 @@ class JvmtiTagMap : public CHeapObj {
inline Mutex* lock() { return &_lock; }
inline JvmtiEnv* env() const { return _env; }
// rehash tags maps for generation start to end
void rehash(int start, int end);
// indicates if the object is in the young generation
static bool is_in_young(oop o);
void do_weak_oops(BoolObjectClosure* is_alive, OopClosure* f);
// iterate over all entries in this tag map
void entry_iterate(JvmtiTagHashmapEntryClosure* closure);
@ -81,11 +72,10 @@ class JvmtiTagMap : public CHeapObj {
// indicates if this tag map is locked
bool is_locked() { return lock()->is_locked(); }
// return the appropriate hashmap for a given object
JvmtiTagHashmap* hashmap_for(oop o);
JvmtiTagHashmap* hashmap() { return _hashmap; }
// create/destroy entries
JvmtiTagHashmapEntry* create_entry(jweak ref, jlong tag);
JvmtiTagHashmapEntry* create_entry(oop ref, jlong tag);
void destroy_entry(JvmtiTagHashmapEntry* entry);
// returns true if the hashmaps are empty
@ -134,11 +124,8 @@ class JvmtiTagMap : public CHeapObj {
jint* count_ptr, jobject** object_result_ptr,
jlong** tag_result_ptr);
// call post-GC to rehash the tag maps.
static void gc_epilogue(bool full);
// call after referencing processing has completed (CMS)
static void cms_ref_processing_epilogue();
static void weak_oops_do(
BoolObjectClosure* is_alive, OopClosure* f) KERNEL_RETURN;
};
#endif // SHARE_VM_PRIMS_JVMTITAGMAP_HPP

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -137,7 +137,6 @@ BasicType MethodHandleChain::compute_bound_arg_type(oop target, methodOop m, int
void MethodHandleChain::lose(const char* msg, TRAPS) {
assert(false, "lose");
_lose_message = msg;
if (!THREAD->is_Java_thread() || ((JavaThread*)THREAD)->thread_state() != _thread_in_vm) {
// throw a preallocated exception

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -111,7 +111,7 @@ bool MethodHandles::spot_check_entry_names() {
//------------------------------------------------------------------------------
// MethodHandles::generate_adapters
//
void MethodHandles::generate_adapters(TRAPS) {
void MethodHandles::generate_adapters() {
if (!EnableMethodHandles || SystemDictionary::MethodHandle_klass() == NULL) return;
assert(_adapter_code == NULL, "generate only once");
@ -123,20 +123,20 @@ void MethodHandles::generate_adapters(TRAPS) {
vm_exit_out_of_memory(_adapter_code_size, "CodeCache: no room for MethodHandles adapters");
CodeBuffer code(_adapter_code);
MethodHandlesAdapterGenerator g(&code);
g.generate(CHECK);
g.generate();
}
//------------------------------------------------------------------------------
// MethodHandlesAdapterGenerator::generate
//
void MethodHandlesAdapterGenerator::generate(TRAPS) {
void MethodHandlesAdapterGenerator::generate() {
// Generate generic method handle adapters.
for (MethodHandles::EntryKind ek = MethodHandles::_EK_FIRST;
ek < MethodHandles::_EK_LIMIT;
ek = MethodHandles::EntryKind(1 + (int)ek)) {
StubCodeMark mark(this, "MethodHandle", MethodHandles::entry_name(ek));
MethodHandles::generate_method_handle_stub(_masm, ek, CHECK);
MethodHandles::generate_method_handle_stub(_masm, ek);
}
}
@ -2621,10 +2621,20 @@ JVM_ENTRY(void, JVM_RegisterMethodHandleMethods(JNIEnv *env, jclass MHN_class))
warning("JSR 292 method handle code is mismatched to this JVM. Disabling support.");
enable_MH = false;
}
} else {
enable_MH = false;
}
}
if (enable_MH) {
// We need to link the MethodHandleImpl klass before we generate
// the method handle adapters as the _raise_exception adapter uses
// one of its methods (and its c2i-adapter).
KlassHandle k = SystemDictionaryHandles::MethodHandleImpl_klass();
instanceKlass* ik = instanceKlass::cast(k());
ik->link_class(CHECK);
MethodHandles::generate_adapters();
MethodHandles::set_enabled(true);
}
@ -2645,10 +2655,5 @@ JVM_ENTRY(void, JVM_RegisterMethodHandleMethods(JNIEnv *env, jclass MHN_class))
MethodHandles::set_enabled(true);
}
}
// Generate method handles adapters if enabled.
if (MethodHandles::enabled()) {
MethodHandles::generate_adapters(CHECK);
}
}
JVM_END

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -294,11 +294,11 @@ class MethodHandles: AllStatic {
enum { _suppress_defc = 1, _suppress_name = 2, _suppress_type = 4 };
// Generate MethodHandles adapters.
static void generate_adapters(TRAPS);
static void generate_adapters();
// Called from InterpreterGenerator and MethodHandlesAdapterGenerator.
static address generate_method_handle_interpreter_entry(MacroAssembler* _masm);
static void generate_method_handle_stub(MacroAssembler* _masm, EntryKind ek, TRAPS);
static void generate_method_handle_stub(MacroAssembler* _masm, EntryKind ek);
// argument list parsing
static int argument_slot(oop method_type, int arg);
@ -530,7 +530,7 @@ class MethodHandlesAdapterGenerator : public StubCodeGenerator {
public:
MethodHandlesAdapterGenerator(CodeBuffer* code) : StubCodeGenerator(code) {}
void generate(TRAPS);
void generate();
};
#endif // SHARE_VM_PRIMS_METHODHANDLES_HPP

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -154,12 +154,11 @@ jint Unsafe_invocation_key_to_method_slot(jint key) {
#define GET_FIELD_VOLATILE(obj, offset, type_name, v) \
oop p = JNIHandles::resolve(obj); \
volatile type_name v = *(volatile type_name*)index_oop_from_field_offset_long(p, offset)
volatile type_name v = OrderAccess::load_acquire((volatile type_name*)index_oop_from_field_offset_long(p, offset));
#define SET_FIELD_VOLATILE(obj, offset, type_name, x) \
oop p = JNIHandles::resolve(obj); \
*(volatile type_name*)index_oop_from_field_offset_long(p, offset) = x; \
OrderAccess::fence();
OrderAccess::release_store_fence((volatile type_name*)index_oop_from_field_offset_long(p, offset), x);
// Macros for oops that check UseCompressedOops
@ -181,7 +180,8 @@ jint Unsafe_invocation_key_to_method_slot(jint key) {
v = oopDesc::decode_heap_oop(n); \
} else { \
v = *(volatile oop*)index_oop_from_field_offset_long(p, offset); \
}
} \
OrderAccess::acquire();
// Get/SetObject must be special-cased, since it works with handles.
@ -248,14 +248,22 @@ UNSAFE_ENTRY(void, Unsafe_SetObjectVolatile(JNIEnv *env, jobject unsafe, jobject
UnsafeWrapper("Unsafe_SetObjectVolatile");
oop x = JNIHandles::resolve(x_h);
oop p = JNIHandles::resolve(obj);
void* addr = index_oop_from_field_offset_long(p, offset);
OrderAccess::release();
if (UseCompressedOops) {
oop_store((narrowOop*)index_oop_from_field_offset_long(p, offset), x);
oop_store((narrowOop*)addr, x);
} else {
oop_store((oop*)index_oop_from_field_offset_long(p, offset), x);
oop_store((oop*)addr, x);
}
OrderAccess::fence();
UNSAFE_END
#if defined(SPARC) || defined(X86)
// Sparc and X86 have atomic jlong (8 bytes) instructions
#else
// Keep old code for platforms which may not have atomic jlong (8 bytes) instructions
// Volatile long versions must use locks if !VM_Version::supports_cx8().
// support_cx8 is a surrogate for 'supports atomic long memory ops'.
@ -291,6 +299,7 @@ UNSAFE_ENTRY(void, Unsafe_SetLongVolatile(JNIEnv *env, jobject unsafe, jobject o
}
UNSAFE_END
#endif // not SPARC and not X86
#define DEFINE_GETSETOOP(jboolean, Boolean) \
\
@ -320,6 +329,16 @@ UNSAFE_END \
\
// END DEFINE_GETSETOOP.
DEFINE_GETSETOOP(jboolean, Boolean)
DEFINE_GETSETOOP(jbyte, Byte)
DEFINE_GETSETOOP(jshort, Short);
DEFINE_GETSETOOP(jchar, Char);
DEFINE_GETSETOOP(jint, Int);
DEFINE_GETSETOOP(jlong, Long);
DEFINE_GETSETOOP(jfloat, Float);
DEFINE_GETSETOOP(jdouble, Double);
#undef DEFINE_GETSETOOP
#define DEFINE_GETSETOOP_VOLATILE(jboolean, Boolean) \
\
@ -336,47 +355,49 @@ UNSAFE_END \
\
// END DEFINE_GETSETOOP_VOLATILE.
DEFINE_GETSETOOP(jboolean, Boolean)
DEFINE_GETSETOOP(jbyte, Byte)
DEFINE_GETSETOOP(jshort, Short);
DEFINE_GETSETOOP(jchar, Char);
DEFINE_GETSETOOP(jint, Int);
DEFINE_GETSETOOP(jlong, Long);
DEFINE_GETSETOOP(jfloat, Float);
DEFINE_GETSETOOP(jdouble, Double);
DEFINE_GETSETOOP_VOLATILE(jboolean, Boolean)
DEFINE_GETSETOOP_VOLATILE(jbyte, Byte)
DEFINE_GETSETOOP_VOLATILE(jshort, Short);
DEFINE_GETSETOOP_VOLATILE(jchar, Char);
DEFINE_GETSETOOP_VOLATILE(jint, Int);
// no long -- handled specially
DEFINE_GETSETOOP_VOLATILE(jfloat, Float);
DEFINE_GETSETOOP_VOLATILE(jdouble, Double);
#undef DEFINE_GETSETOOP
#if defined(SPARC) || defined(X86)
// Sparc and X86 have atomic jlong (8 bytes) instructions
DEFINE_GETSETOOP_VOLATILE(jlong, Long);
#endif
#undef DEFINE_GETSETOOP_VOLATILE
// The non-intrinsified versions of setOrdered just use setVolatile
UNSAFE_ENTRY(void, Unsafe_SetOrderedInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint x)) \
UnsafeWrapper("Unsafe_SetOrderedInt"); \
SET_FIELD_VOLATILE(obj, offset, jint, x); \
UNSAFE_ENTRY(void, Unsafe_SetOrderedInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint x))
UnsafeWrapper("Unsafe_SetOrderedInt");
SET_FIELD_VOLATILE(obj, offset, jint, x);
UNSAFE_END
UNSAFE_ENTRY(void, Unsafe_SetOrderedObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h))
UnsafeWrapper("Unsafe_SetOrderedObject");
oop x = JNIHandles::resolve(x_h);
oop p = JNIHandles::resolve(obj);
void* addr = index_oop_from_field_offset_long(p, offset);
OrderAccess::release();
if (UseCompressedOops) {
oop_store((narrowOop*)index_oop_from_field_offset_long(p, offset), x);
oop_store((narrowOop*)addr, x);
} else {
oop_store((oop*)index_oop_from_field_offset_long(p, offset), x);
oop_store((oop*)addr, x);
}
OrderAccess::fence();
UNSAFE_END
UNSAFE_ENTRY(void, Unsafe_SetOrderedLong(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong x))
UnsafeWrapper("Unsafe_SetOrderedLong");
#if defined(SPARC) || defined(X86)
// Sparc and X86 have atomic jlong (8 bytes) instructions
SET_FIELD_VOLATILE(obj, offset, jlong, x);
#else
// Keep old code for platforms which may not have atomic long (8 bytes) instructions
{
if (VM_Version::supports_cx8()) {
SET_FIELD_VOLATILE(obj, offset, jlong, x);
@ -388,6 +409,7 @@ UNSAFE_ENTRY(void, Unsafe_SetOrderedLong(JNIEnv *env, jobject unsafe, jobject ob
*addr = x;
}
}
#endif
UNSAFE_END
////// Data in the C heap.

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -918,9 +918,7 @@ bool Arguments::add_property(const char* prop) {
} else if (strcmp(key, "sun.java.command") == 0) {
_java_command = value;
// don't add this property to the properties exposed to the java application
FreeHeap(key);
return true;
// Record value in Arguments, but let it get passed to Java.
} else if (strcmp(key, "sun.java.launcher.pid") == 0) {
// launcher.pid property is private and is processed
// in process_sun_java_launcher_properties();

View File

@ -1198,9 +1198,6 @@ class CommandLineFlags {
product(ccstr, TraceJVMTI, NULL, \
"Trace flags for JVMTI functions and events") \
\
product(bool, ForceFullGCJVMTIEpilogues, false, \
"Force 'Full GC' was done semantics for JVMTI GC epilogues") \
\
/* This option can change an EMCP method into an obsolete method. */ \
/* This can affect tests that except specific methods to be EMCP. */ \
/* This option should be used with caution. */ \

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -663,7 +663,8 @@ void JDK_Version::initialize() {
}
_current = JDK_Version(major, minor, micro, info.update_version,
info.special_update_version, build,
info.thread_park_blocker == 1);
info.thread_park_blocker == 1,
info.post_vm_init_hook_enabled == 1);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -92,6 +92,7 @@ class JDK_Version VALUE_OBJ_CLASS_SPEC {
bool _partially_initialized;
bool _thread_park_blocker;
bool _post_vm_init_hook_enabled;
bool is_valid() const {
return (_major != 0 || _partially_initialized);
@ -113,14 +114,15 @@ class JDK_Version VALUE_OBJ_CLASS_SPEC {
JDK_Version() : _major(0), _minor(0), _micro(0), _update(0),
_special(0), _build(0), _partially_initialized(false),
_thread_park_blocker(false) {}
_thread_park_blocker(false), _post_vm_init_hook_enabled(false) {}
JDK_Version(uint8_t major, uint8_t minor = 0, uint8_t micro = 0,
uint8_t update = 0, uint8_t special = 0, uint8_t build = 0,
bool thread_park_blocker = false) :
bool thread_park_blocker = false, bool post_vm_init_hook_enabled = false) :
_major(major), _minor(minor), _micro(micro), _update(update),
_special(special), _build(build), _partially_initialized(false),
_thread_park_blocker(thread_park_blocker) {}
_thread_park_blocker(thread_park_blocker),
_post_vm_init_hook_enabled(post_vm_init_hook_enabled) {}
// Returns the current running JDK version
static JDK_Version current() { return _current; }
@ -144,6 +146,9 @@ class JDK_Version VALUE_OBJ_CLASS_SPEC {
bool supports_thread_park_blocker() const {
return _thread_park_blocker;
}
bool post_vm_init_hook_enabled() const {
return _post_vm_init_hook_enabled;
}
// Performs a full ordering comparison using all fields (update, build, etc.)
int compare(const JDK_Version& other) const;

View File

@ -25,6 +25,7 @@
#include "precompiled.hpp"
#include "classfile/systemDictionary.hpp"
#include "oops/oop.inline.hpp"
#include "prims/jvmtiTagMap.hpp"
#include "runtime/jniHandles.hpp"
#include "runtime/mutexLocker.hpp"
#ifdef TARGET_OS_FAMILY_linux
@ -428,6 +429,12 @@ void JNIHandleBlock::weak_oops_do(BoolObjectClosure* is_alive,
break;
}
}
/*
* JvmtiTagMap may also contain weak oops. The iteration of it is placed
* here so that we don't need to add it to each of the collectors.
*/
JvmtiTagMap::weak_oops_do(is_alive, f);
}

View File

@ -31,6 +31,7 @@
#include "compiler/compileBroker.hpp"
#include "interpreter/interpreter.hpp"
#include "interpreter/linkResolver.hpp"
#include "jvmtifiles/jvmtiEnv.hpp"
#include "memory/oopFactory.hpp"
#include "memory/universe.inline.hpp"
#include "oops/instanceKlass.hpp"
@ -977,6 +978,19 @@ static void set_jkernel_boot_classloader_hook(TRAPS) {
}
#endif // KERNEL
// General purpose hook into Java code, run once when the VM is initialized.
// The Java library method itself may be changed independently from the VM.
static void call_postVMInitHook(TRAPS) {
klassOop k = SystemDictionary::sun_misc_PostVMInitHook_klass();
instanceKlassHandle klass (THREAD, k);
if (klass.not_null()) {
JavaValue result(T_VOID);
JavaCalls::call_static(&result, klass, vmSymbolHandles::run_method_name(),
vmSymbolHandles::void_method_signature(),
CHECK);
}
}
static void reset_vm_info_property(TRAPS) {
// the vm info string
ResourceMark rm(THREAD);
@ -1699,7 +1713,7 @@ void JavaThread::exit(bool destroy_vm, ExitType exit_type) {
tlab().make_parsable(true); // retire TLAB
}
if (jvmti_thread_state() != NULL) {
if (JvmtiEnv::environments_might_exist()) {
JvmtiExport::cleanup_thread(this);
}
@ -3345,6 +3359,14 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) {
BiasedLocking::init();
if (JDK_Version::current().post_vm_init_hook_enabled()) {
call_postVMInitHook(THREAD);
// The Java side of PostVMInitHook.run must deal with all
// exceptions and provide means of diagnosis.
if (HAS_PENDING_EXCEPTION) {
CLEAR_PENDING_EXCEPTION;
}
}
// Start up the WatcherThread if there are any periodic tasks
// NOTE: All PeriodicTasks should be registered by now. If they

View File

@ -809,7 +809,7 @@ class JavaThread: public Thread {
//
// _vm_exited is a special value to cover the case of a JavaThread
// executing native code after the VM itself is terminated.
TerminatedTypes _terminated;
volatile TerminatedTypes _terminated;
// suspend/resume support
volatile bool _suspend_equivalent; // Suspend equivalent condition
jint _in_deopt_handler; // count of deoptimization

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -219,8 +219,8 @@ static inline uint64_t cast_uint64_t(size_t x)
volatile_nonstatic_field(oopDesc, _metadata._compressed_klass, narrowOop) \
static_field(oopDesc, _bs, BarrierSet*) \
nonstatic_field(arrayKlass, _dimension, int) \
nonstatic_field(arrayKlass, _higher_dimension, klassOop) \
nonstatic_field(arrayKlass, _lower_dimension, klassOop) \
volatile_nonstatic_field(arrayKlass, _higher_dimension, klassOop) \
volatile_nonstatic_field(arrayKlass, _lower_dimension, klassOop) \
nonstatic_field(arrayKlass, _vtable_len, int) \
nonstatic_field(arrayKlass, _alloc_size, juint) \
nonstatic_field(arrayKlass, _component_mirror, oop) \

View File

@ -874,11 +874,13 @@ void VMError::report_and_die() {
}
if (fd == -1) {
// try temp directory
const char * tmpdir = os::get_temp_directory();
jio_snprintf(buffer, sizeof(buffer), "%s%shs_err_pid%u.log",
tmpdir, os::file_separator(), os::current_process_id());
fd = open(buffer, O_WRONLY | O_CREAT | O_TRUNC, 0666);
// try temp directory if it exists.
if (tmpdir != NULL && tmpdir[0] != '\0') {
jio_snprintf(buffer, sizeof(buffer), "%s%shs_err_pid%u.log",
tmpdir, os::file_separator(), os::current_process_id());
fd = open(buffer, O_WRONLY | O_CREAT | O_TRUNC, 0666);
}
}
if (fd != -1) {