This commit is contained in:
Alejandro Murillo 2014-03-28 09:15:41 -07:00
commit 958938e6a4
144 changed files with 5064 additions and 622 deletions

View File

@ -95,7 +95,9 @@ static task_t getTask(JNIEnv *env, jobject this_obj) {
#define CHECK_EXCEPTION_CLEAR_(value) if ((*env)->ExceptionOccurred(env)) { (*env)->ExceptionClear(env); return value; }
static void throw_new_debugger_exception(JNIEnv* env, const char* errMsg) {
(*env)->ThrowNew(env, (*env)->FindClass(env, "sun/jvm/hotspot/debugger/DebuggerException"), errMsg);
jclass exceptionClass = (*env)->FindClass(env, "sun/jvm/hotspot/debugger/DebuggerException");
CHECK_EXCEPTION;
(*env)->ThrowNew(env, exceptionClass, errMsg);
}
static struct ps_prochandle* get_proc_handle(JNIEnv* env, jobject this_obj) {
@ -129,6 +131,7 @@ static struct ps_prochandle* get_proc_handle(JNIEnv* env, jobject this_obj) {
JNIEXPORT void JNICALL
Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_init0(JNIEnv *env, jclass cls) {
symbolicatorID = (*env)->GetFieldID(env, cls, "symbolicator", "J");
CHECK_EXCEPTION;
taskID = (*env)->GetFieldID(env, cls, "task", "J");
CHECK_EXCEPTION;
@ -236,13 +239,16 @@ JNIEXPORT jobject JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_loo
(JNIEnv *env, jobject this_obj, jlong addr) {
uintptr_t offset;
const char* sym = NULL;
jstring sym_string;
struct ps_prochandle* ph = get_proc_handle(env, this_obj);
if (ph != NULL && ph->core != NULL) {
sym = symbol_for_pc(ph, (uintptr_t) addr, &offset);
if (sym == NULL) return 0;
sym_string = (*env)->NewStringUTF(env, sym);
CHECK_EXCEPTION_(0);
return (*env)->CallObjectMethod(env, this_obj, createClosestSymbol_ID,
(*env)->NewStringUTF(env, sym), (jlong)offset);
sym_string, (jlong)offset);
}
return 0;
}
@ -749,11 +755,14 @@ static void fillLoadObjects(JNIEnv* env, jobject this_obj, struct ps_prochandle*
const char* name;
jobject loadObject;
jobject loadObjectList;
jstring nameString;
base = get_lib_base(ph, i);
name = get_lib_name(ph, i);
nameString = (*env)->NewStringUTF(env, name);
CHECK_EXCEPTION;
loadObject = (*env)->CallObjectMethod(env, this_obj, createLoadObject_ID,
(*env)->NewStringUTF(env, name), (jlong)0, (jlong)base);
nameString, (jlong)0, (jlong)base);
CHECK_EXCEPTION;
loadObjectList = (*env)->GetObjectField(env, this_obj, loadObjectList_ID);
CHECK_EXCEPTION;

View File

@ -287,8 +287,43 @@ else
@$(ECHO) "Error: trying to build a minimal target but JVM_VARIANT_MINIMAL1 is not true."
endif
remove_old_debuginfo:
ifeq ($(JVM_VARIANT_CLIENT), true)
ifeq ($(ZIP_DEBUGINFO_FILES),1)
ifeq ($(OSNAME), windows)
$(RM) -f $(EXPORT_CLIENT_DIR)/jvm.map $(EXPORT_CLIENT_DIR)/jvm.pdb
else
$(RM) -f $(EXPORT_CLIENT_DIR)/libjvm.debuginfo
endif
else
$(RM) -f $(EXPORT_CLIENT_DIR)/libjvm.diz
endif
endif
ifeq ($(findstring true, $(JVM_VARIANT_SERVER) $(JVM_VARIANT_ZERO) $(JVM_VARIANT_ZEROSHARK)), true)
ifeq ($(ZIP_DEBUGINFO_FILES),1)
ifeq ($(OSNAME), windows)
$(RM) -f $(EXPORT_SERVER_DIR)/jvm.map $(EXPORT_SERVER_DIR)/jvm.pdb
else
ifeq ($(OS_VENDOR), Darwin)
$(RM) -rf $(EXPORT_SERVER_DIR)/libjvm.dylib.dSYM
else
$(RM) -f $(EXPORT_SERVER_DIR)/libjvm.debuginfo
endif
endif
else
$(RM) -f $(EXPORT_SERVER_DIR)/libjvm.diz
endif
endif
ifeq ($(JVM_VARIANT_MINIMAL1),true)
ifeq ($(ZIP_DEBUGINFO_FILES),1)
$(RM) -f $(EXPORT_MINIMAL_DIR)/libjvm.debuginfo
else
$(RM) -f $(EXPORT_MINIMAL_DIR)/libjvm.diz
endif
endif
# Export file rule
generic_export: $(EXPORT_LIST)
generic_export: $(EXPORT_LIST) remove_old_debuginfo
export_product:
$(MAKE) BUILD_FLAVOR=$(@:export_%=%) generic_export
@ -841,4 +876,4 @@ include $(GAMMADIR)/make/jprt.gmk
export_jdk_product export_jdk_fastdebug export_jdk_debug \
create_jdk copy_jdk update_jdk test_jdk \
copy_product_jdk copy_fastdebug_jdk copy_debug_jdk \
$(HS_ALT_MAKE)/Makefile.make
$(HS_ALT_MAKE)/Makefile.make remove_old_debuginfo

View File

@ -101,7 +101,7 @@ CXXFLAGS = \
# This is VERY important! The version define must only be supplied to vm_version.o
# If not, ccache will not re-use the cache at all, since the version string might contain
# a time and date.
vm_version.o: CXXFLAGS += ${JRE_VERSION}
CXXFLAGS/vm_version.o += ${JRE_VERSION}
CXXFLAGS/BYFILE = $(CXXFLAGS/$@)

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright 2012, 2013 SAP AG. All rights reserved.
* Copyright 2012, 2014 SAP AG. 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
@ -24,7 +24,6 @@
*/
#include "precompiled.hpp"
#include "asm/assembler.hpp"
#include "asm/assembler.inline.hpp"
#include "gc_interface/collectedHeap.inline.hpp"
#include "interpreter/interpreter.hpp"
@ -37,6 +36,7 @@
#include "runtime/os.hpp"
#include "runtime/sharedRuntime.hpp"
#include "runtime/stubRoutines.hpp"
#include "utilities/macros.hpp"
#if INCLUDE_ALL_GCS
#include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
#include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"
@ -384,10 +384,10 @@ int Assembler::load_const_optimized(Register d, long x, Register tmp, bool retur
bool load_xa = (xa != 0) || (xb < 0);
bool return_xd = false;
if (load_xa) lis(tmp, xa);
if (xc) lis(d, xc);
if (load_xa) { lis(tmp, xa); }
if (xc) { lis(d, xc); }
if (load_xa) {
if (xb) ori(tmp, tmp, xb); // No addi, we support tmp == R0.
if (xb) { ori(tmp, tmp, (unsigned short)xb); } // No addi, we support tmp == R0.
} else {
li(tmp, xb); // non-negative
}
@ -409,18 +409,18 @@ int Assembler::load_const_optimized(Register d, long x, Register tmp, bool retur
// opt 4: avoid adding 0
if (xa) { // Highest 16-bit needed?
lis(d, xa);
if (xb) addi(d, d, xb);
if (xb) { addi(d, d, xb); }
} else {
li(d, xb);
}
sldi(d, d, 32);
if (xc) addis(d, d, xc);
if (xc) { addis(d, d, xc); }
}
// opt 5: Return offset to be inserted into following instruction.
if (return_simm16_rest) return xd;
if (xd) addi(d, d, xd);
if (xd) { addi(d, d, xd); }
return 0;
}
@ -696,4 +696,5 @@ void Assembler::test_asm() {
tty->print_cr("\ntest_asm disassembly (0x%lx 0x%lx):", code()->insts_begin(), code()->insts_end());
code()->decode();
}
#endif // !PRODUCT

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright 2012, 2013 SAP AG. All rights reserved.
* Copyright 2012, 2014 SAP AG. 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
@ -139,7 +139,8 @@ inline void Assembler::cmpldi(ConditionRegister crx, Register a, int ui16) { A
inline void Assembler::cmplw( ConditionRegister crx, Register a, Register b) { Assembler::cmpl( crx, 0, a, b); }
inline void Assembler::cmpld( ConditionRegister crx, Register a, Register b) { Assembler::cmpl( crx, 1, a, b); }
inline void Assembler::isel(Register d, Register a, Register b, int c) { emit_int32(ISEL_OPCODE | rt(d) | ra(a) | rb(b) | bc(c)); }
inline void Assembler::isel(Register d, Register a, Register b, int c) { guarantee(VM_Version::has_isel(), "opcode not supported on this hardware");
emit_int32(ISEL_OPCODE | rt(d) | ra(a) | rb(b) | bc(c)); }
// PPC 1, section 3.3.11, Fixed-Point Logical Instructions
inline void Assembler::andi_( Register a, Register s, int ui16) { emit_int32(ANDI_OPCODE | rta(a) | rs(s) | uimm(ui16, 16)); }
@ -531,9 +532,12 @@ inline void Assembler::fmr_(FloatRegister d, FloatRegister b) { emit_int32( FMR_
//inline void Assembler::mffgpr( FloatRegister d, Register b) { emit_int32( MFFGPR_OPCODE | frt(d) | rb(b) | rc(0)); }
//inline void Assembler::mftgpr( Register d, FloatRegister b) { emit_int32( MFTGPR_OPCODE | rt(d) | frb(b) | rc(0)); }
// add cmpb and popcntb to detect ppc power version.
inline void Assembler::cmpb( Register a, Register s, Register b) { emit_int32( CMPB_OPCODE | rta(a) | rs(s) | rb(b) | rc(0)); }
inline void Assembler::popcntb(Register a, Register s) { emit_int32( POPCNTB_OPCODE | rta(a) | rs(s)); };
inline void Assembler::popcntw(Register a, Register s) { emit_int32( POPCNTW_OPCODE | rta(a) | rs(s)); };
inline void Assembler::cmpb( Register a, Register s, Register b) { guarantee(VM_Version::has_cmpb(), "opcode not supported on this hardware");
emit_int32( CMPB_OPCODE | rta(a) | rs(s) | rb(b) | rc(0)); }
inline void Assembler::popcntb(Register a, Register s) { guarantee(VM_Version::has_popcntb(), "opcode not supported on this hardware");
emit_int32( POPCNTB_OPCODE | rta(a) | rs(s)); };
inline void Assembler::popcntw(Register a, Register s) { guarantee(VM_Version::has_popcntw(), "opcode not supported on this hardware");
emit_int32( POPCNTW_OPCODE | rta(a) | rs(s)); };
inline void Assembler::popcntd(Register a, Register s) { emit_int32( POPCNTD_OPCODE | rta(a) | rs(s)); };
inline void Assembler::fneg( FloatRegister d, FloatRegister b) { emit_int32( FNEG_OPCODE | frt(d) | frb(b) | rc(0)); }
@ -568,14 +572,17 @@ inline void Assembler::fctidz(FloatRegister d, FloatRegister b) { emit_int32( FC
inline void Assembler::fctiw( FloatRegister d, FloatRegister b) { emit_int32( FCTIW_OPCODE | frt(d) | frb(b) | rc(0)); }
inline void Assembler::fctiwz(FloatRegister d, FloatRegister b) { emit_int32( FCTIWZ_OPCODE | frt(d) | frb(b) | rc(0)); }
inline void Assembler::fcfid( FloatRegister d, FloatRegister b) { emit_int32( FCFID_OPCODE | frt(d) | frb(b) | rc(0)); }
inline void Assembler::fcfids(FloatRegister d, FloatRegister b) { emit_int32( FCFIDS_OPCODE | frt(d) | frb(b) | rc(0)); }
inline void Assembler::fcfids(FloatRegister d, FloatRegister b) { guarantee(VM_Version::has_fcfids(), "opcode not supported on this hardware");
emit_int32( FCFIDS_OPCODE | frt(d) | frb(b) | rc(0)); }
// PPC 1, section 4.6.7 Floating-Point Compare Instructions
inline void Assembler::fcmpu( ConditionRegister crx, FloatRegister a, FloatRegister b) { emit_int32( FCMPU_OPCODE | bf(crx) | fra(a) | frb(b)); }
// PPC 1, section 5.2.1 Floating-Point Arithmetic Instructions
inline void Assembler::fsqrt( FloatRegister d, FloatRegister b) { emit_int32( FSQRT_OPCODE | frt(d) | frb(b) | rc(0)); }
inline void Assembler::fsqrts(FloatRegister d, FloatRegister b) { emit_int32( FSQRTS_OPCODE | frt(d) | frb(b) | rc(0)); }
inline void Assembler::fsqrt( FloatRegister d, FloatRegister b) { guarantee(VM_Version::has_fsqrt(), "opcode not supported on this hardware");
emit_int32( FSQRT_OPCODE | frt(d) | frb(b) | rc(0)); }
inline void Assembler::fsqrts(FloatRegister d, FloatRegister b) { guarantee(VM_Version::has_fsqrts(), "opcode not supported on this hardware");
emit_int32( FSQRTS_OPCODE | frt(d) | frb(b) | rc(0)); }
// Vector instructions for >= Power6.
inline void Assembler::lvebx( VectorRegister d, Register s1, Register s2) { emit_int32( LVEBX_OPCODE | vrt(d) | ra0mem(s1) | rb(s2)); }
@ -703,7 +710,8 @@ inline void Assembler::vcmpgtsw_(VectorRegister d,VectorRegister a, VectorRegist
inline void Assembler::vcmpgtub_(VectorRegister d,VectorRegister a, VectorRegister b) { emit_int32( VCMPGTUB_OPCODE | vrt(d) | vra(a) | vrb(b) | vcmp_rc(1)); }
inline void Assembler::vcmpgtuh_(VectorRegister d,VectorRegister a, VectorRegister b) { emit_int32( VCMPGTUH_OPCODE | vrt(d) | vra(a) | vrb(b) | vcmp_rc(1)); }
inline void Assembler::vcmpgtuw_(VectorRegister d,VectorRegister a, VectorRegister b) { emit_int32( VCMPGTUW_OPCODE | vrt(d) | vra(a) | vrb(b) | vcmp_rc(1)); }
inline void Assembler::vand( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VAND_OPCODE | vrt(d) | vra(a) | vrb(b)); }
inline void Assembler::vand( VectorRegister d, VectorRegister a, VectorRegister b) { guarantee(VM_Version::has_vand(), "opcode not supported on this hardware");
emit_int32( VAND_OPCODE | vrt(d) | vra(a) | vrb(b)); }
inline void Assembler::vandc( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VANDC_OPCODE | vrt(d) | vra(a) | vrb(b)); }
inline void Assembler::vnor( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VNOR_OPCODE | vrt(d) | vra(a) | vrb(b)); }
inline void Assembler::vor( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VOR_OPCODE | vrt(d) | vra(a) | vrb(b)); }

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright 2012, 2013 SAP AG. All rights reserved.
* Copyright 2012, 2014 SAP AG. 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
@ -87,7 +87,7 @@ define_pd_global(uint64_t,MaxRAM, 4ULL*G);
define_pd_global(uintx, CodeCacheMinBlockLength, 4);
define_pd_global(uintx, CodeCacheMinimumUseSpace, 400*K);
define_pd_global(bool, TrapBasedRangeChecks, false);
define_pd_global(bool, TrapBasedRangeChecks, true);
// Heap related flags
define_pd_global(uintx,MetaspaceSize, ScaleForWordSize(16*M));

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright 2012, 2013 SAP AG. All rights reserved.
* Copyright 2012, 2014 SAP AG. 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
@ -24,8 +24,6 @@
*/
#include "precompiled.hpp"
#include "asm/assembler.hpp"
#include "asm/assembler.inline.hpp"
#include "asm/macroAssembler.inline.hpp"
#include "compiler/disassembler.hpp"
#include "gc_interface/collectedHeap.inline.hpp"
@ -1120,7 +1118,7 @@ address MacroAssembler::call_c_using_toc(const FunctionDescriptor* fd,
}
return _last_calls_return_pc;
}
#endif
#endif // ABI_ELFv2
void MacroAssembler::call_VM_base(Register oop_result,
Register last_java_sp,
@ -1794,7 +1792,7 @@ void MacroAssembler::biased_locking_enter(ConditionRegister cr_reg, Register obj
cmpwi(cr_reg, temp_reg, markOopDesc::biased_lock_pattern);
bne(cr_reg, cas_label);
load_klass_with_trap_null_check(temp_reg, obj_reg);
load_klass(temp_reg, obj_reg);
load_const_optimized(temp2_reg, ~((int) markOopDesc::age_mask_in_place));
ld(temp_reg, in_bytes(Klass::prototype_header_offset()), temp_reg);
@ -1891,7 +1889,7 @@ void MacroAssembler::biased_locking_enter(ConditionRegister cr_reg, Register obj
// the bias from one thread to another directly in this situation.
andi(temp_reg, mark_reg, markOopDesc::age_mask_in_place);
orr(temp_reg, R16_thread, temp_reg);
load_klass_with_trap_null_check(temp2_reg, obj_reg);
load_klass(temp2_reg, obj_reg);
ld(temp2_reg, in_bytes(Klass::prototype_header_offset()), temp2_reg);
orr(temp_reg, temp_reg, temp2_reg);
@ -1927,7 +1925,7 @@ void MacroAssembler::biased_locking_enter(ConditionRegister cr_reg, Register obj
// that another thread raced us for the privilege of revoking the
// bias of this particular object, so it's okay to continue in the
// normal locking code.
load_klass_with_trap_null_check(temp_reg, obj_reg);
load_klass(temp_reg, obj_reg);
ld(temp_reg, in_bytes(Klass::prototype_header_offset()), temp_reg);
andi(temp2_reg, mark_reg, markOopDesc::age_mask_in_place);
orr(temp_reg, temp_reg, temp2_reg);
@ -2213,8 +2211,7 @@ void MacroAssembler::card_table_write(jbyte* byte_map_base, Register Rtmp, Regis
stbx(R0, Rtmp, Robj);
}
#ifndef SERIALGC
#if INCLUDE_ALL_GCS
// General G1 pre-barrier generator.
// Goal: record the previous value if it is not null.
void MacroAssembler::g1_write_barrier_pre(Register Robj, RegisterOrConstant offset, Register Rpre_val,
@ -2328,14 +2325,17 @@ void MacroAssembler::g1_write_barrier_post(Register Rstore_addr, Register Rnew_v
// Get the address of the card.
lbzx(/*card value*/ Rtmp3, Rbase, Rcard_addr);
cmpwi(CCR0, Rtmp3, (int)G1SATBCardTableModRefBS::g1_young_card_val());
beq(CCR0, filtered);
assert(CardTableModRefBS::dirty_card_val() == 0, "otherwise check this code");
cmpwi(CCR0, Rtmp3 /* card value */, 0);
membar(Assembler::StoreLoad);
lbzx(/*card value*/ Rtmp3, Rbase, Rcard_addr); // Reload after membar.
cmpwi(CCR0, Rtmp3 /* card value */, CardTableModRefBS::dirty_card_val());
beq(CCR0, filtered);
// Storing a region crossing, non-NULL oop, card is clean.
// Dirty card and log.
li(Rtmp3, 0); // dirty
li(Rtmp3, CardTableModRefBS::dirty_card_val());
//release(); // G1: oops are allowed to get visible after dirty marking.
stbx(Rtmp3, Rbase, Rcard_addr);
@ -2362,7 +2362,7 @@ void MacroAssembler::g1_write_barrier_post(Register Rstore_addr, Register Rnew_v
bind(filtered_int);
}
#endif // SERIALGC
#endif // INCLUDE_ALL_GCS
// Values for last_Java_pc, and last_Java_sp must comply to the rules
// in frame_ppc64.hpp.
@ -2453,7 +2453,8 @@ void MacroAssembler::get_vm_result_2(Register metadata_result) {
void MacroAssembler::encode_klass_not_null(Register dst, Register src) {
Register current = (src != noreg) ? src : dst; // Klass is in dst if no src provided.
if (Universe::narrow_klass_base() != 0) {
load_const(R0, Universe::narrow_klass_base(), (dst != current) ? dst : noreg); // Use dst as temp if it is free.
// Use dst as temp if it is free.
load_const(R0, Universe::narrow_klass_base(), (dst != current && dst != R0) ? dst : noreg);
sub(dst, current, R0);
current = dst;
}

View File

@ -514,14 +514,14 @@ class MacroAssembler: public Assembler {
void card_write_barrier_post(Register Rstore_addr, Register Rnew_val, Register Rtmp);
void card_table_write(jbyte* byte_map_base, Register Rtmp, Register Robj);
#ifndef SERIALGC
#if INCLUDE_ALL_GCS
// General G1 pre-barrier generator.
void g1_write_barrier_pre(Register Robj, RegisterOrConstant offset, Register Rpre_val,
Register Rtmp1, Register Rtmp2, bool needs_frame = false);
// General G1 post-barrier generator
void g1_write_barrier_post(Register Rstore_addr, Register Rnew_val, Register Rtmp1,
Register Rtmp2, Register Rtmp3, Label *filtered_ext = NULL);
#endif // SERIALGC
#endif
// Support for managing the JavaThread pointer (i.e.; the reference to
// thread-local information).

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright 2012, 2013 SAP AG. All rights reserved.
* Copyright 2012, 2014 SAP AG. 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
@ -119,6 +119,7 @@ void MethodHandles::verify_ref_kind(MacroAssembler* _masm, int ref_kind, Registe
void MethodHandles::jump_from_method_handle(MacroAssembler* _masm, Register method, Register target, Register temp,
bool for_compiler_entry) {
Label L_no_such_method;
assert(method == R19_method, "interpreter calling convention");
assert_different_registers(method, target, temp);
@ -131,17 +132,31 @@ void MethodHandles::jump_from_method_handle(MacroAssembler* _masm, Register meth
__ lwz(temp, in_bytes(JavaThread::interp_only_mode_offset()), R16_thread);
__ cmplwi(CCR0, temp, 0);
__ beq(CCR0, run_compiled_code);
// Null method test is replicated below in compiled case,
// it might be able to address across the verify_thread()
__ cmplwi(CCR0, R19_method, 0);
__ beq(CCR0, L_no_such_method);
__ ld(target, in_bytes(Method::interpreter_entry_offset()), R19_method);
__ mtctr(target);
__ bctr();
__ BIND(run_compiled_code);
}
// Compiled case, either static or fall-through from runtime conditional
__ cmplwi(CCR0, R19_method, 0);
__ beq(CCR0, L_no_such_method);
const ByteSize entry_offset = for_compiler_entry ? Method::from_compiled_offset() :
Method::from_interpreted_offset();
__ ld(target, in_bytes(entry_offset), R19_method);
__ mtctr(target);
__ bctr();
__ bind(L_no_such_method);
assert(StubRoutines::throw_AbstractMethodError_entry() != NULL, "not yet generated!");
__ load_const_optimized(target, StubRoutines::throw_AbstractMethodError_entry());
__ mtctr(target);
__ bctr();
}

View File

@ -891,6 +891,13 @@ definitions %{
// This is a block of C++ code which provides values, functions, and
// definitions necessary in the rest of the architecture description.
source_hpp %{
// Header information of the source block.
// Method declarations/definitions which are used outside
// the ad-scope can conveniently be defined here.
//
// To keep related declarations/definitions/uses close together,
// we switch between source %{ }% and source_hpp %{ }% freely as needed.
// Returns true if Node n is followed by a MemBar node that
// will do an acquire. If so, this node must not do the acquire
// operation.
@ -1114,6 +1121,40 @@ static inline void emit_long(CodeBuffer &cbuf, int value) {
//=============================================================================
%} // interrupt source
source_hpp %{ // Header information of the source block.
//--------------------------------------------------------------
//---< Used for optimization in Compile::Shorten_branches >---
//--------------------------------------------------------------
const uint trampoline_stub_size = 6 * BytesPerInstWord;
class CallStubImpl {
public:
static void emit_trampoline_stub(MacroAssembler &_masm, int destination_toc_offset, int insts_call_instruction_offset);
// Size of call trampoline stub.
// This doesn't need to be accurate to the byte, but it
// must be larger than or equal to the real size of the stub.
static uint size_call_trampoline() {
return trampoline_stub_size;
}
// number of relocations needed by a call trampoline stub
static uint reloc_call_trampoline() {
return 5;
}
};
%} // end source_hpp
source %{
// Emit a trampoline stub for a call to a target which is too far away.
//
// code sequences:
@ -1125,9 +1166,7 @@ static inline void emit_long(CodeBuffer &cbuf, int value) {
// load the call target from the constant pool
// branch via CTR (LR/link still points to the call-site above)
const uint trampoline_stub_size = 6 * BytesPerInstWord;
void emit_trampoline_stub(MacroAssembler &_masm, int destination_toc_offset, int insts_call_instruction_offset) {
void CallStubImpl::emit_trampoline_stub(MacroAssembler &_masm, int destination_toc_offset, int insts_call_instruction_offset) {
// Start the stub.
address stub = __ start_a_stub(Compile::MAX_stubs_size/2);
if (stub == NULL) {
@ -1170,19 +1209,6 @@ void emit_trampoline_stub(MacroAssembler &_masm, int destination_toc_offset, int
__ end_a_stub();
}
// Size of trampoline stub, this doesn't need to be accurate but it must
// be larger or equal to the real size of the stub.
// Used for optimization in Compile::Shorten_branches.
uint size_call_trampoline() {
return trampoline_stub_size;
}
// Number of relocation entries needed by trampoline stub.
// Used for optimization in Compile::Shorten_branches.
uint reloc_call_trampoline() {
return 5;
}
//=============================================================================
// Emit an inline branch-and-link call and a related trampoline stub.
@ -1221,7 +1247,7 @@ EmitCallOffsets emit_call_with_trampoline_stub(MacroAssembler &_masm, address en
const int entry_point_toc_offset = __ offset_to_method_toc(entry_point_toc_addr);
// Emit the trampoline stub which will be related to the branch-and-link below.
emit_trampoline_stub(_masm, entry_point_toc_offset, offsets.insts_call_instruction_offset);
CallStubImpl::emit_trampoline_stub(_masm, entry_point_toc_offset, offsets.insts_call_instruction_offset);
__ relocate(rtype);
}
@ -2023,17 +2049,34 @@ uint MachUEPNode::size(PhaseRegAlloc *ra_) const {
//=============================================================================
uint size_exception_handler() {
// The exception_handler is a b64_patchable.
return MacroAssembler::b64_patchable_size;
}
%} // interrupt source
uint size_deopt_handler() {
// The deopt_handler is a bl64_patchable.
return MacroAssembler::bl64_patchable_size;
}
source_hpp %{ // Header information of the source block.
int emit_exception_handler(CodeBuffer &cbuf) {
class HandlerImpl {
public:
static int emit_exception_handler(CodeBuffer &cbuf);
static int emit_deopt_handler(CodeBuffer& cbuf);
static uint size_exception_handler() {
// The exception_handler is a b64_patchable.
return MacroAssembler::b64_patchable_size;
}
static uint size_deopt_handler() {
// The deopt_handler is a bl64_patchable.
return MacroAssembler::bl64_patchable_size;
}
};
%} // end source_hpp
source %{
int HandlerImpl::emit_exception_handler(CodeBuffer &cbuf) {
MacroAssembler _masm(&cbuf);
address base = __ start_a_stub(size_exception_handler());
@ -2050,7 +2093,7 @@ int emit_exception_handler(CodeBuffer &cbuf) {
// The deopt_handler is like the exception handler, but it calls to
// the deoptimization blob instead of jumping to the exception blob.
int emit_deopt_handler(CodeBuffer& cbuf) {
int HandlerImpl::emit_deopt_handler(CodeBuffer& cbuf) {
MacroAssembler _masm(&cbuf);
address base = __ start_a_stub(size_deopt_handler());
@ -3438,7 +3481,7 @@ encode %{
const int entry_point_toc_offset = __ offset_to_method_toc(entry_point_toc_addr);
// Emit the trampoline stub which will be related to the branch-and-link below.
emit_trampoline_stub(_masm, entry_point_toc_offset, start_offset);
CallStubImpl::emit_trampoline_stub(_masm, entry_point_toc_offset, start_offset);
__ relocate(_optimized_virtual ?
relocInfo::opt_virtual_call_type : relocInfo::static_call_type);
}
@ -3481,7 +3524,7 @@ encode %{
const int entry_point_toc_offset = __ offset_to_method_toc(entry_point_toc_addr);
// Emit the trampoline stub which will be related to the branch-and-link below.
emit_trampoline_stub(_masm, entry_point_toc_offset, start_offset);
CallStubImpl::emit_trampoline_stub(_masm, entry_point_toc_offset, start_offset);
assert(_optimized_virtual, "methodHandle call should be a virtual call");
__ relocate(relocInfo::opt_virtual_call_type);
}
@ -3531,7 +3574,7 @@ encode %{
const address entry_point = !($meth$$method) ? 0 : (address)$meth$$method;
const address entry_point_const = __ address_constant(entry_point, RelocationHolder::none);
const int entry_point_const_toc_offset = __ offset_to_method_toc(entry_point_const);
emit_trampoline_stub(_masm, entry_point_const_toc_offset, __ offset());
CallStubImpl::emit_trampoline_stub(_masm, entry_point_const_toc_offset, __ offset());
if (ra_->C->env()->failing())
return;
@ -8755,6 +8798,7 @@ instruct sqrtD_reg(regD dst, regD src) %{
// Single-precision sqrt.
instruct sqrtF_reg(regF dst, regF src) %{
match(Set dst (ConvD2F (SqrtD (ConvF2D src))));
predicate(VM_Version::has_fsqrts());
ins_cost(DEFAULT_COST);
format %{ "FSQRTS $dst, $src" %}
@ -11550,8 +11594,7 @@ instruct safePoint_poll_conPollAddr(rscratch2RegP poll) %{
// effect no longer needs to be mentioned, since r0 is not contained
// in a reg_class.
format %{ "LD R12, addr of polling page\n\t"
"LD R0, #0, R12 \t// Safepoint poll for GC" %}
format %{ "LD R0, #0, R12 \t// Safepoint poll for GC" %}
ins_encode( enc_poll(0x0, poll) );
ins_pipe(pipe_class_default);
%}

View File

@ -34,6 +34,7 @@
#include "runtime/sharedRuntime.hpp"
#include "runtime/vframeArray.hpp"
#include "vmreg_ppc.inline.hpp"
#include "adfiles/ad_ppc_64.hpp"
#ifdef COMPILER1
#include "c1/c1_Runtime1.hpp"
#endif
@ -52,10 +53,6 @@
#define BIND(label) bind(label); BLOCK_COMMENT(#label ":")
// Used by generate_deopt_blob. Defined in .ad file.
extern uint size_deopt_handler();
class RegisterSaver {
// Used for saving volatile registers.
public:
@ -2782,7 +2779,7 @@ void SharedRuntime::generate_deopt_blob() {
// We can't grab a free register here, because all registers may
// contain live values, so let the RegisterSaver do the adjustment
// of the return pc.
const int return_pc_adjustment_no_exception = -size_deopt_handler();
const int return_pc_adjustment_no_exception = -HandlerImpl::size_deopt_handler();
// Push the "unpack frame"
// Save everything in sight.

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright 2012, 2013 SAP AG. All rights reserved.
* Copyright 2012, 2014 SAP AG. 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
@ -23,17 +23,6 @@
*
*/
#include "precompiled.hpp"
#include "runtime/deoptimization.hpp"
#include "runtime/frame.inline.hpp"
#include "runtime/stubRoutines.hpp"
#ifdef TARGET_OS_FAMILY_aix
# include "thread_aix.inline.hpp"
#endif
#ifdef TARGET_OS_FAMILY_linux
# include "thread_linux.inline.hpp"
#endif
// Implementation of the platform-specific part of StubRoutines - for
// a description of how to extend it, see the stubRoutines.hpp file.

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright 2012, 2013 SAP AG. All rights reserved.
* Copyright 2012, 2014 SAP AG. 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
@ -402,6 +402,9 @@ void VM_Version::determine_features() {
CodeBuffer cb("detect_cpu_features", code_size, 0);
MacroAssembler* a = new MacroAssembler(&cb);
// Must be set to true so we can generate the test code.
_features = VM_Version::all_features_m;
// Emit code.
void (*test)(address addr, uint64_t offset)=(void(*)(address addr, uint64_t offset))(void *)a->function_entry();
uint32_t *code = (uint32_t *)a->pc();
@ -409,14 +412,15 @@ void VM_Version::determine_features() {
// Keep R3_ARG1 unmodified, it contains &field (see below).
// Keep R4_ARG2 unmodified, it contains offset = 0 (see below).
a->fsqrt(F3, F4); // code[0] -> fsqrt_m
a->isel(R7, R5, R6, 0); // code[1] -> isel_m
a->ldarx_unchecked(R7, R3_ARG1, R4_ARG2, 1); // code[2] -> lxarx_m
a->cmpb(R7, R5, R6); // code[3] -> bcmp
//a->mftgpr(R7, F3); // code[4] -> mftgpr
a->popcntb(R7, R5); // code[5] -> popcntb
a->popcntw(R7, R5); // code[6] -> popcntw
a->fcfids(F3, F4); // code[7] -> fcfids
a->vand(VR0, VR0, VR0); // code[8] -> vand
a->fsqrts(F3, F4); // code[1] -> fsqrts_m
a->isel(R7, R5, R6, 0); // code[2] -> isel_m
a->ldarx_unchecked(R7, R3_ARG1, R4_ARG2, 1); // code[3] -> lxarx_m
a->cmpb(R7, R5, R6); // code[4] -> bcmp
//a->mftgpr(R7, F3); // code[5] -> mftgpr
a->popcntb(R7, R5); // code[6] -> popcntb
a->popcntw(R7, R5); // code[7] -> popcntw
a->fcfids(F3, F4); // code[8] -> fcfids
a->vand(VR0, VR0, VR0); // code[9] -> vand
a->blr();
// Emit function to set one cache line to zero. Emit function descriptor and get pointer to it.
@ -426,6 +430,7 @@ void VM_Version::determine_features() {
uint32_t *code_end = (uint32_t *)a->pc();
a->flush();
_features = VM_Version::unknown_m;
// Print the detection code.
if (PrintAssembly) {
@ -450,6 +455,7 @@ void VM_Version::determine_features() {
// determine which instructions are legal.
int feature_cntr = 0;
if (code[feature_cntr++]) features |= fsqrt_m;
if (code[feature_cntr++]) features |= fsqrts_m;
if (code[feature_cntr++]) features |= isel_m;
if (code[feature_cntr++]) features |= lxarxeh_m;
if (code[feature_cntr++]) features |= cmpb_m;

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright 2012, 2013 SAP AG. All rights reserved.
* Copyright 2012, 2014 SAP AG. 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
@ -33,6 +33,7 @@ class VM_Version: public Abstract_VM_Version {
protected:
enum Feature_Flag {
fsqrt,
fsqrts,
isel,
lxarxeh,
cmpb,
@ -46,6 +47,7 @@ protected:
enum Feature_Flag_Set {
unknown_m = 0,
fsqrt_m = (1 << fsqrt ),
fsqrts_m = (1 << fsqrts ),
isel_m = (1 << isel ),
lxarxeh_m = (1 << lxarxeh),
cmpb_m = (1 << cmpb ),
@ -72,6 +74,7 @@ public:
static bool is_determine_features_test_running() { return _is_determine_features_test_running; }
// CPU instruction support
static bool has_fsqrt() { return (_features & fsqrt_m) != 0; }
static bool has_fsqrts() { return (_features & fsqrts_m) != 0; }
static bool has_isel() { return (_features & isel_m) != 0; }
static bool has_lxarxeh() { return (_features & lxarxeh_m) !=0; }
static bool has_cmpb() { return (_features & cmpb_m) != 0; }

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright 2012, 2013 SAP AG. All rights reserved.
* Copyright 2012, 2014 SAP AG. 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
@ -79,7 +79,7 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
address npe_addr = __ pc(); // npe = null pointer exception
__ load_klass_with_trap_null_check(rcvr_klass, R3);
// Set methodOop (in case of interpreted method), and destination address.
// Set method (in case of interpreted method), and destination address.
int entry_offset = InstanceKlass::vtable_start_offset() + vtable_index*vtableEntry::size();
#ifndef PRODUCT
@ -161,8 +161,6 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) {
address npe_addr = __ pc(); // npe = null pointer exception
__ load_klass_with_trap_null_check(rcvr_klass, R3_ARG1);
//__ ld(rcvr_klass, oopDesc::klass_offset_in_bytes(), R3_ARG1);
BLOCK_COMMENT("Load start of itable entries into itable_entry.");
__ lwz(vtable_len, InstanceKlass::vtable_length_offset() * wordSize, rcvr_klass);
__ slwi(vtable_len, vtable_len, exact_log2(vtableEntry::size() * wordSize));
@ -199,7 +197,7 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) {
itable_offset_search_inc;
__ lwz(vtable_offset, vtable_offset_offset, itable_entry_addr);
// Compute itableMethodEntry and get methodOop and entry point for compiler.
// Compute itableMethodEntry and get method and entry point for compiler.
const int method_offset = (itableMethodEntry::size() * wordSize * vtable_index) +
itableMethodEntry::method_offset_in_bytes();
@ -211,7 +209,7 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) {
Label ok;
__ cmpd(CCR0, R19_method, 0);
__ bne(CCR0, ok);
__ stop("methodOop is null", 103);
__ stop("method is null", 103);
__ bind(ok);
}
#endif

View File

@ -3320,7 +3320,7 @@ void LIR_Assembler::rt_call(LIR_Opr result, address dest,
// if tmp is invalid, then the function being called doesn't destroy the thread
if (tmp->is_valid()) {
__ save_thread(tmp->as_register());
__ save_thread(tmp->as_pointer_register());
}
__ call(dest, relocInfo::runtime_call_type);
__ delayed()->nop();
@ -3328,7 +3328,7 @@ void LIR_Assembler::rt_call(LIR_Opr result, address dest,
add_call_info_here(info);
}
if (tmp->is_valid()) {
__ restore_thread(tmp->as_register());
__ restore_thread(tmp->as_pointer_register());
}
#ifdef ASSERT

View File

@ -69,7 +69,7 @@ void LIRItem::load_nonconstant() {
LIR_Opr LIRGenerator::exceptionOopOpr() { return FrameMap::Oexception_opr; }
LIR_Opr LIRGenerator::exceptionPcOpr() { return FrameMap::Oissuing_pc_opr; }
LIR_Opr LIRGenerator::syncTempOpr() { return new_register(T_OBJECT); }
LIR_Opr LIRGenerator::getThreadTemp() { return rlock_callee_saved(T_INT); }
LIR_Opr LIRGenerator::getThreadTemp() { return rlock_callee_saved(NOT_LP64(T_INT) LP64_ONLY(T_LONG)); }
LIR_Opr LIRGenerator::result_register_for(ValueType* type, bool callee) {
LIR_Opr opr;

View File

@ -66,6 +66,4 @@ define_pd_global(bool, OptimizeSinglePrecision, false);
define_pd_global(bool, CSEArrayLength, true );
define_pd_global(bool, TwoOperandLIRForm, false);
define_pd_global(intx, SafepointPollOffset, 0 );
#endif // CPU_SPARC_VM_C1_GLOBALS_SPARC_HPP

View File

@ -457,6 +457,13 @@ definitions %{
// This is a block of C++ code which provides values, functions, and
// definitions necessary in the rest of the architecture description
source_hpp %{
// Header information of the source block.
// Method declarations/definitions which are used outside
// the ad-scope can conveniently be defined here.
//
// To keep related declarations/definitions/uses close together,
// we switch between source %{ }% and source_hpp %{ }% freely as needed.
// Must be visible to the DFA in dfa_sparc.cpp
extern bool can_branch_register( Node *bol, Node *cmp );
@ -468,6 +475,46 @@ extern bool use_block_zeroing(Node* count);
#define LONG_HI_REG(x) (x)
#define LONG_LO_REG(x) (x)
class CallStubImpl {
//--------------------------------------------------------------
//---< Used for optimization in Compile::Shorten_branches >---
//--------------------------------------------------------------
public:
// Size of call trampoline stub.
static uint size_call_trampoline() {
return 0; // no call trampolines on this platform
}
// number of relocations needed by a call trampoline stub
static uint reloc_call_trampoline() {
return 0; // no call trampolines on this platform
}
};
class HandlerImpl {
public:
static int emit_exception_handler(CodeBuffer &cbuf);
static int emit_deopt_handler(CodeBuffer& cbuf);
static uint size_exception_handler() {
if (TraceJumps) {
return (400); // just a guess
}
return ( NativeJump::instruction_size ); // sethi;jmp;nop
}
static uint size_deopt_handler() {
if (TraceJumps) {
return (400); // just a guess
}
return ( 4+ NativeJump::instruction_size ); // save;sethi;jmp;restore
}
};
%}
source %{
@ -1710,22 +1757,9 @@ uint MachUEPNode::size(PhaseRegAlloc *ra_) const {
//=============================================================================
uint size_exception_handler() {
if (TraceJumps) {
return (400); // just a guess
}
return ( NativeJump::instruction_size ); // sethi;jmp;nop
}
uint size_deopt_handler() {
if (TraceJumps) {
return (400); // just a guess
}
return ( 4+ NativeJump::instruction_size ); // save;sethi;jmp;restore
}
// Emit exception handler code.
int emit_exception_handler(CodeBuffer& cbuf) {
int HandlerImpl::emit_exception_handler(CodeBuffer& cbuf) {
Register temp_reg = G3;
AddressLiteral exception_blob(OptoRuntime::exception_blob()->entry_point());
MacroAssembler _masm(&cbuf);
@ -1746,7 +1780,7 @@ int emit_exception_handler(CodeBuffer& cbuf) {
return offset;
}
int emit_deopt_handler(CodeBuffer& cbuf) {
int HandlerImpl::emit_deopt_handler(CodeBuffer& cbuf) {
// Can't use any of the current frame's registers as we may have deopted
// at a poll and everything (including G3) can be live.
Register temp_reg = L0;

View File

@ -1112,7 +1112,6 @@ void Assembler::bsfl(Register dst, Register src) {
}
void Assembler::bsrl(Register dst, Register src) {
assert(!VM_Version::supports_lzcnt(), "encoding is treated as LZCNT");
int encode = prefix_and_encode(dst->encoding(), src->encoding());
emit_int8(0x0F);
emit_int8((unsigned char)0xBD);
@ -2343,6 +2342,11 @@ void Assembler::vpermq(XMMRegister dst, XMMRegister src, int imm8, bool vector25
emit_int8(imm8);
}
void Assembler::pause() {
emit_int8((unsigned char)0xF3);
emit_int8((unsigned char)0x90);
}
void Assembler::pcmpestri(XMMRegister dst, Address src, int imm8) {
assert(VM_Version::supports_sse4_2(), "");
InstructionMark im(this);
@ -2667,6 +2671,11 @@ void Assembler::rcll(Register dst, int imm8) {
}
}
void Assembler::rdtsc() {
emit_int8((unsigned char)0x0F);
emit_int8((unsigned char)0x31);
}
// copies data from [esi] to [edi] using rcx pointer sized words
// generic
void Assembler::rep_mov() {
@ -2976,6 +2985,11 @@ void Assembler::ucomiss(XMMRegister dst, XMMRegister src) {
emit_simd_arith_nonds(0x2E, dst, src, VEX_SIMD_NONE);
}
void Assembler::xabort(int8_t imm8) {
emit_int8((unsigned char)0xC6);
emit_int8((unsigned char)0xF8);
emit_int8((unsigned char)(imm8 & 0xFF));
}
void Assembler::xaddl(Address dst, Register src) {
InstructionMark im(this);
@ -2985,6 +2999,24 @@ void Assembler::xaddl(Address dst, Register src) {
emit_operand(src, dst);
}
void Assembler::xbegin(Label& abort, relocInfo::relocType rtype) {
InstructionMark im(this);
relocate(rtype);
if (abort.is_bound()) {
address entry = target(abort);
assert(entry != NULL, "abort entry NULL");
intptr_t offset = entry - pc();
emit_int8((unsigned char)0xC7);
emit_int8((unsigned char)0xF8);
emit_int32(offset - 6); // 2 opcode + 4 address
} else {
abort.add_patch_at(code(), locator());
emit_int8((unsigned char)0xC7);
emit_int8((unsigned char)0xF8);
emit_int32(0);
}
}
void Assembler::xchgl(Register dst, Address src) { // xchg
InstructionMark im(this);
prefix(src, dst);
@ -2998,6 +3030,12 @@ void Assembler::xchgl(Register dst, Register src) {
emit_int8((unsigned char)(0xC0 | encode));
}
void Assembler::xend() {
emit_int8((unsigned char)0x0F);
emit_int8((unsigned char)0x01);
emit_int8((unsigned char)0xD5);
}
void Assembler::xgetbv() {
emit_int8(0x0F);
emit_int8(0x01);
@ -4938,7 +4976,6 @@ void Assembler::bsfq(Register dst, Register src) {
}
void Assembler::bsrq(Register dst, Register src) {
assert(!VM_Version::supports_lzcnt(), "encoding is treated as LZCNT");
int encode = prefixq_and_encode(dst->encoding(), src->encoding());
emit_int8(0x0F);
emit_int8((unsigned char)0xBD);

View File

@ -1451,6 +1451,8 @@ private:
// Pemutation of 64bit words
void vpermq(XMMRegister dst, XMMRegister src, int imm8, bool vector256);
void pause();
// SSE4.2 string instructions
void pcmpestri(XMMRegister xmm1, XMMRegister xmm2, int imm8);
void pcmpestri(XMMRegister xmm1, Address src, int imm8);
@ -1535,6 +1537,8 @@ private:
void rclq(Register dst, int imm8);
void rdtsc();
void ret(int imm16);
void sahf();
@ -1632,16 +1636,22 @@ private:
void ucomiss(XMMRegister dst, Address src);
void ucomiss(XMMRegister dst, XMMRegister src);
void xabort(int8_t imm8);
void xaddl(Address dst, Register src);
void xaddq(Address dst, Register src);
void xbegin(Label& abort, relocInfo::relocType rtype = relocInfo::none);
void xchgl(Register reg, Address adr);
void xchgl(Register dst, Register src);
void xchgq(Register reg, Address adr);
void xchgq(Register dst, Register src);
void xend();
// Get Value of Extended Control Register
void xgetbv();

View File

@ -604,8 +604,7 @@ void LIR_Assembler::return_op(LIR_Opr result) {
// Note: we do not need to round double result; float result has the right precision
// the poll sets the condition code, but no data registers
AddressLiteral polling_page(os::get_polling_page() + (SafepointPollOffset % os::vm_page_size()),
relocInfo::poll_return_type);
AddressLiteral polling_page(os::get_polling_page(), relocInfo::poll_return_type);
if (Assembler::is_polling_page_far()) {
__ lea(rscratch1, polling_page);
@ -619,8 +618,7 @@ void LIR_Assembler::return_op(LIR_Opr result) {
int LIR_Assembler::safepoint_poll(LIR_Opr tmp, CodeEmitInfo* info) {
AddressLiteral polling_page(os::get_polling_page() + (SafepointPollOffset % os::vm_page_size()),
relocInfo::poll_type);
AddressLiteral polling_page(os::get_polling_page(), relocInfo::poll_type);
guarantee(info != NULL, "Shouldn't be NULL");
int offset = __ offset();
if (Assembler::is_polling_page_far()) {

View File

@ -65,6 +65,4 @@ define_pd_global(bool, OptimizeSinglePrecision, true );
define_pd_global(bool, CSEArrayLength, false);
define_pd_global(bool, TwoOperandLIRForm, true );
define_pd_global(intx, SafepointPollOffset, 256 );
#endif // CPU_X86_VM_C1_GLOBALS_X86_HPP

View File

@ -129,6 +129,42 @@ define_pd_global(uintx, TypeProfileLevel, 111);
product(bool, UseFastStosb, false, \
"Use fast-string operation for zeroing: rep stosb") \
\
/* Use Restricted Transactional Memory for lock eliding */ \
product(bool, UseRTMLocking, false, \
"Enable RTM lock eliding for inflated locks in compiled code") \
\
experimental(bool, UseRTMForStackLocks, false, \
"Enable RTM lock eliding for stack locks in compiled code") \
\
product(bool, UseRTMDeopt, false, \
"Perform deopt and recompilation based on RTM abort ratio") \
\
product(uintx, RTMRetryCount, 5, \
"Number of RTM retries on lock abort or busy") \
\
experimental(intx, RTMSpinLoopCount, 100, \
"Spin count for lock to become free before RTM retry") \
\
experimental(intx, RTMAbortThreshold, 1000, \
"Calculate abort ratio after this number of aborts") \
\
experimental(intx, RTMLockingThreshold, 10000, \
"Lock count at which to do RTM lock eliding without " \
"abort ratio calculation") \
\
experimental(intx, RTMAbortRatio, 50, \
"Lock abort ratio at which to stop use RTM lock eliding") \
\
experimental(intx, RTMTotalCountIncrRate, 64, \
"Increment total RTM attempted lock count once every n times") \
\
experimental(intx, RTMLockingCalculationDelay, 0, \
"Number of milliseconds to wait before start calculating aborts " \
"for RTM locking") \
\
experimental(bool, UseRTMXendForLockBusy, false, \
"Use RTM Xend instead of Xabort when lock busy") \
\
/* assembler */ \
product(bool, Use486InstrsOnly, false, \
"Use 80486 Compliant instruction subset") \

View File

@ -301,7 +301,9 @@ void MacroAssembler::mov_metadata(Address dst, Metadata* obj) {
mov_literal32(dst, (int32_t)obj, metadata_Relocation::spec_for_immediate());
}
void MacroAssembler::movptr(Register dst, AddressLiteral src) {
void MacroAssembler::movptr(Register dst, AddressLiteral src, Register scratch) {
// scratch register is not used,
// it is defined to match parameters of 64-bit version of this method.
if (src.is_lval()) {
mov_literal32(dst, (intptr_t)src.target(), src.rspec());
} else {
@ -613,6 +615,15 @@ void MacroAssembler::decrementq(Address dst, int value) {
/* else */ { subq(dst, value) ; return; }
}
void MacroAssembler::incrementq(AddressLiteral dst) {
if (reachable(dst)) {
incrementq(as_Address(dst));
} else {
lea(rscratch1, dst);
incrementq(Address(rscratch1, 0));
}
}
void MacroAssembler::incrementq(Register reg, int value) {
if (value == min_jint) { addq(reg, value); return; }
if (value < 0) { decrementq(reg, -value); return; }
@ -681,15 +692,15 @@ void MacroAssembler::mov_metadata(Address dst, Metadata* obj) {
movq(dst, rscratch1);
}
void MacroAssembler::movptr(Register dst, AddressLiteral src) {
void MacroAssembler::movptr(Register dst, AddressLiteral src, Register scratch) {
if (src.is_lval()) {
mov_literal64(dst, (intptr_t)src.target(), src.rspec());
} else {
if (reachable(src)) {
movq(dst, as_Address(src));
} else {
lea(rscratch1, src);
movq(dst, Address(rscratch1,0));
lea(scratch, src);
movq(dst, Address(scratch, 0));
}
}
}
@ -988,21 +999,38 @@ void MacroAssembler::andptr(Register dst, int32_t imm32) {
LP64_ONLY(andq(dst, imm32)) NOT_LP64(andl(dst, imm32));
}
void MacroAssembler::atomic_incl(AddressLiteral counter_addr) {
pushf();
if (reachable(counter_addr)) {
if (os::is_MP())
lock();
incrementl(as_Address(counter_addr));
} else {
lea(rscratch1, counter_addr);
if (os::is_MP())
lock();
incrementl(Address(rscratch1, 0));
}
popf();
void MacroAssembler::atomic_incl(Address counter_addr) {
if (os::is_MP())
lock();
incrementl(counter_addr);
}
void MacroAssembler::atomic_incl(AddressLiteral counter_addr, Register scr) {
if (reachable(counter_addr)) {
atomic_incl(as_Address(counter_addr));
} else {
lea(scr, counter_addr);
atomic_incl(Address(scr, 0));
}
}
#ifdef _LP64
void MacroAssembler::atomic_incq(Address counter_addr) {
if (os::is_MP())
lock();
incrementq(counter_addr);
}
void MacroAssembler::atomic_incq(AddressLiteral counter_addr, Register scr) {
if (reachable(counter_addr)) {
atomic_incq(as_Address(counter_addr));
} else {
lea(scr, counter_addr);
atomic_incq(Address(scr, 0));
}
}
#endif
// Writes to stack successive pages until offset reached to check for
// stack overflow + shadow pages. This clobbers tmp.
void MacroAssembler::bang_stack_size(Register size, Register tmp) {
@ -1274,6 +1302,325 @@ void MacroAssembler::biased_locking_exit(Register obj_reg, Register temp_reg, La
}
#ifdef COMPILER2
#if INCLUDE_RTM_OPT
// Update rtm_counters based on abort status
// input: abort_status
// rtm_counters (RTMLockingCounters*)
// flags are killed
void MacroAssembler::rtm_counters_update(Register abort_status, Register rtm_counters) {
atomic_incptr(Address(rtm_counters, RTMLockingCounters::abort_count_offset()));
if (PrintPreciseRTMLockingStatistics) {
for (int i = 0; i < RTMLockingCounters::ABORT_STATUS_LIMIT; i++) {
Label check_abort;
testl(abort_status, (1<<i));
jccb(Assembler::equal, check_abort);
atomic_incptr(Address(rtm_counters, RTMLockingCounters::abortX_count_offset() + (i * sizeof(uintx))));
bind(check_abort);
}
}
}
// Branch if (random & (count-1) != 0), count is 2^n
// tmp, scr and flags are killed
void MacroAssembler::branch_on_random_using_rdtsc(Register tmp, Register scr, int count, Label& brLabel) {
assert(tmp == rax, "");
assert(scr == rdx, "");
rdtsc(); // modifies EDX:EAX
andptr(tmp, count-1);
jccb(Assembler::notZero, brLabel);
}
// Perform abort ratio calculation, set no_rtm bit if high ratio
// input: rtm_counters_Reg (RTMLockingCounters* address)
// tmpReg, rtm_counters_Reg and flags are killed
void MacroAssembler::rtm_abort_ratio_calculation(Register tmpReg,
Register rtm_counters_Reg,
RTMLockingCounters* rtm_counters,
Metadata* method_data) {
Label L_done, L_check_always_rtm1, L_check_always_rtm2;
if (RTMLockingCalculationDelay > 0) {
// Delay calculation
movptr(tmpReg, ExternalAddress((address) RTMLockingCounters::rtm_calculation_flag_addr()), tmpReg);
testptr(tmpReg, tmpReg);
jccb(Assembler::equal, L_done);
}
// Abort ratio calculation only if abort_count > RTMAbortThreshold
// Aborted transactions = abort_count * 100
// All transactions = total_count * RTMTotalCountIncrRate
// Set no_rtm bit if (Aborted transactions >= All transactions * RTMAbortRatio)
movptr(tmpReg, Address(rtm_counters_Reg, RTMLockingCounters::abort_count_offset()));
cmpptr(tmpReg, RTMAbortThreshold);
jccb(Assembler::below, L_check_always_rtm2);
imulptr(tmpReg, tmpReg, 100);
Register scrReg = rtm_counters_Reg;
movptr(scrReg, Address(rtm_counters_Reg, RTMLockingCounters::total_count_offset()));
imulptr(scrReg, scrReg, RTMTotalCountIncrRate);
imulptr(scrReg, scrReg, RTMAbortRatio);
cmpptr(tmpReg, scrReg);
jccb(Assembler::below, L_check_always_rtm1);
if (method_data != NULL) {
// set rtm_state to "no rtm" in MDO
mov_metadata(tmpReg, method_data);
if (os::is_MP()) {
lock();
}
orl(Address(tmpReg, MethodData::rtm_state_offset_in_bytes()), NoRTM);
}
jmpb(L_done);
bind(L_check_always_rtm1);
// Reload RTMLockingCounters* address
lea(rtm_counters_Reg, ExternalAddress((address)rtm_counters));
bind(L_check_always_rtm2);
movptr(tmpReg, Address(rtm_counters_Reg, RTMLockingCounters::total_count_offset()));
cmpptr(tmpReg, RTMLockingThreshold / RTMTotalCountIncrRate);
jccb(Assembler::below, L_done);
if (method_data != NULL) {
// set rtm_state to "always rtm" in MDO
mov_metadata(tmpReg, method_data);
if (os::is_MP()) {
lock();
}
orl(Address(tmpReg, MethodData::rtm_state_offset_in_bytes()), UseRTM);
}
bind(L_done);
}
// Update counters and perform abort ratio calculation
// input: abort_status_Reg
// rtm_counters_Reg, flags are killed
void MacroAssembler::rtm_profiling(Register abort_status_Reg,
Register rtm_counters_Reg,
RTMLockingCounters* rtm_counters,
Metadata* method_data,
bool profile_rtm) {
assert(rtm_counters != NULL, "should not be NULL when profiling RTM");
// update rtm counters based on rax value at abort
// reads abort_status_Reg, updates flags
lea(rtm_counters_Reg, ExternalAddress((address)rtm_counters));
rtm_counters_update(abort_status_Reg, rtm_counters_Reg);
if (profile_rtm) {
// Save abort status because abort_status_Reg is used by following code.
if (RTMRetryCount > 0) {
push(abort_status_Reg);
}
assert(rtm_counters != NULL, "should not be NULL when profiling RTM");
rtm_abort_ratio_calculation(abort_status_Reg, rtm_counters_Reg, rtm_counters, method_data);
// restore abort status
if (RTMRetryCount > 0) {
pop(abort_status_Reg);
}
}
}
// Retry on abort if abort's status is 0x6: can retry (0x2) | memory conflict (0x4)
// inputs: retry_count_Reg
// : abort_status_Reg
// output: retry_count_Reg decremented by 1
// flags are killed
void MacroAssembler::rtm_retry_lock_on_abort(Register retry_count_Reg, Register abort_status_Reg, Label& retryLabel) {
Label doneRetry;
assert(abort_status_Reg == rax, "");
// The abort reason bits are in eax (see all states in rtmLocking.hpp)
// 0x6 = conflict on which we can retry (0x2) | memory conflict (0x4)
// if reason is in 0x6 and retry count != 0 then retry
andptr(abort_status_Reg, 0x6);
jccb(Assembler::zero, doneRetry);
testl(retry_count_Reg, retry_count_Reg);
jccb(Assembler::zero, doneRetry);
pause();
decrementl(retry_count_Reg);
jmp(retryLabel);
bind(doneRetry);
}
// Spin and retry if lock is busy,
// inputs: box_Reg (monitor address)
// : retry_count_Reg
// output: retry_count_Reg decremented by 1
// : clear z flag if retry count exceeded
// tmp_Reg, scr_Reg, flags are killed
void MacroAssembler::rtm_retry_lock_on_busy(Register retry_count_Reg, Register box_Reg,
Register tmp_Reg, Register scr_Reg, Label& retryLabel) {
Label SpinLoop, SpinExit, doneRetry;
// Clean monitor_value bit to get valid pointer
int owner_offset = ObjectMonitor::owner_offset_in_bytes() - markOopDesc::monitor_value;
testl(retry_count_Reg, retry_count_Reg);
jccb(Assembler::zero, doneRetry);
decrementl(retry_count_Reg);
movptr(scr_Reg, RTMSpinLoopCount);
bind(SpinLoop);
pause();
decrementl(scr_Reg);
jccb(Assembler::lessEqual, SpinExit);
movptr(tmp_Reg, Address(box_Reg, owner_offset));
testptr(tmp_Reg, tmp_Reg);
jccb(Assembler::notZero, SpinLoop);
bind(SpinExit);
jmp(retryLabel);
bind(doneRetry);
incrementl(retry_count_Reg); // clear z flag
}
// Use RTM for normal stack locks
// Input: objReg (object to lock)
void MacroAssembler::rtm_stack_locking(Register objReg, Register tmpReg, Register scrReg,
Register retry_on_abort_count_Reg,
RTMLockingCounters* stack_rtm_counters,
Metadata* method_data, bool profile_rtm,
Label& DONE_LABEL, Label& IsInflated) {
assert(UseRTMForStackLocks, "why call this otherwise?");
assert(!UseBiasedLocking, "Biased locking is not supported with RTM locking");
assert(tmpReg == rax, "");
assert(scrReg == rdx, "");
Label L_rtm_retry, L_decrement_retry, L_on_abort;
if (RTMRetryCount > 0) {
movl(retry_on_abort_count_Reg, RTMRetryCount); // Retry on abort
bind(L_rtm_retry);
}
if (!UseRTMXendForLockBusy) {
movptr(tmpReg, Address(objReg, 0));
testptr(tmpReg, markOopDesc::monitor_value); // inflated vs stack-locked|neutral|biased
jcc(Assembler::notZero, IsInflated);
}
if (PrintPreciseRTMLockingStatistics || profile_rtm) {
Label L_noincrement;
if (RTMTotalCountIncrRate > 1) {
// tmpReg, scrReg and flags are killed
branch_on_random_using_rdtsc(tmpReg, scrReg, (int)RTMTotalCountIncrRate, L_noincrement);
}
assert(stack_rtm_counters != NULL, "should not be NULL when profiling RTM");
atomic_incptr(ExternalAddress((address)stack_rtm_counters->total_count_addr()), scrReg);
bind(L_noincrement);
}
xbegin(L_on_abort);
movptr(tmpReg, Address(objReg, 0)); // fetch markword
andptr(tmpReg, markOopDesc::biased_lock_mask_in_place); // look at 3 lock bits
cmpptr(tmpReg, markOopDesc::unlocked_value); // bits = 001 unlocked
jcc(Assembler::equal, DONE_LABEL); // all done if unlocked
Register abort_status_Reg = tmpReg; // status of abort is stored in RAX
if (UseRTMXendForLockBusy) {
xend();
movptr(tmpReg, Address(objReg, 0));
testptr(tmpReg, markOopDesc::monitor_value); // inflated vs stack-locked|neutral|biased
jcc(Assembler::notZero, IsInflated);
movptr(abort_status_Reg, 0x1); // Set the abort status to 1 (as xabort does)
jmp(L_decrement_retry);
}
else {
xabort(0);
}
bind(L_on_abort);
if (PrintPreciseRTMLockingStatistics || profile_rtm) {
rtm_profiling(abort_status_Reg, scrReg, stack_rtm_counters, method_data, profile_rtm);
}
bind(L_decrement_retry);
if (RTMRetryCount > 0) {
// retry on lock abort if abort status is 'can retry' (0x2) or 'memory conflict' (0x4)
rtm_retry_lock_on_abort(retry_on_abort_count_Reg, abort_status_Reg, L_rtm_retry);
}
}
// Use RTM for inflating locks
// inputs: objReg (object to lock)
// boxReg (on-stack box address (displaced header location) - KILLED)
// tmpReg (ObjectMonitor address + 2(monitor_value))
void MacroAssembler::rtm_inflated_locking(Register objReg, Register boxReg, Register tmpReg,
Register scrReg, Register retry_on_busy_count_Reg,
Register retry_on_abort_count_Reg,
RTMLockingCounters* rtm_counters,
Metadata* method_data, bool profile_rtm,
Label& DONE_LABEL) {
assert(UseRTMLocking, "why call this otherwise?");
assert(tmpReg == rax, "");
assert(scrReg == rdx, "");
Label L_rtm_retry, L_decrement_retry, L_on_abort;
// Clean monitor_value bit to get valid pointer
int owner_offset = ObjectMonitor::owner_offset_in_bytes() - markOopDesc::monitor_value;
// Without cast to int32_t a movptr will destroy r10 which is typically obj
movptr(Address(boxReg, 0), (int32_t)intptr_t(markOopDesc::unused_mark()));
movptr(boxReg, tmpReg); // Save ObjectMonitor address
if (RTMRetryCount > 0) {
movl(retry_on_busy_count_Reg, RTMRetryCount); // Retry on lock busy
movl(retry_on_abort_count_Reg, RTMRetryCount); // Retry on abort
bind(L_rtm_retry);
}
if (PrintPreciseRTMLockingStatistics || profile_rtm) {
Label L_noincrement;
if (RTMTotalCountIncrRate > 1) {
// tmpReg, scrReg and flags are killed
branch_on_random_using_rdtsc(tmpReg, scrReg, (int)RTMTotalCountIncrRate, L_noincrement);
}
assert(rtm_counters != NULL, "should not be NULL when profiling RTM");
atomic_incptr(ExternalAddress((address)rtm_counters->total_count_addr()), scrReg);
bind(L_noincrement);
}
xbegin(L_on_abort);
movptr(tmpReg, Address(objReg, 0));
movptr(tmpReg, Address(tmpReg, owner_offset));
testptr(tmpReg, tmpReg);
jcc(Assembler::zero, DONE_LABEL);
if (UseRTMXendForLockBusy) {
xend();
jmp(L_decrement_retry);
}
else {
xabort(0);
}
bind(L_on_abort);
Register abort_status_Reg = tmpReg; // status of abort is stored in RAX
if (PrintPreciseRTMLockingStatistics || profile_rtm) {
rtm_profiling(abort_status_Reg, scrReg, rtm_counters, method_data, profile_rtm);
}
if (RTMRetryCount > 0) {
// retry on lock abort if abort status is 'can retry' (0x2) or 'memory conflict' (0x4)
rtm_retry_lock_on_abort(retry_on_abort_count_Reg, abort_status_Reg, L_rtm_retry);
}
movptr(tmpReg, Address(boxReg, owner_offset)) ;
testptr(tmpReg, tmpReg) ;
jccb(Assembler::notZero, L_decrement_retry) ;
// Appears unlocked - try to swing _owner from null to non-null.
// Invariant: tmpReg == 0. tmpReg is EAX which is the implicit cmpxchg comparand.
#ifdef _LP64
Register threadReg = r15_thread;
#else
get_thread(scrReg);
Register threadReg = scrReg;
#endif
if (os::is_MP()) {
lock();
}
cmpxchgptr(threadReg, Address(boxReg, owner_offset)); // Updates tmpReg
if (RTMRetryCount > 0) {
// success done else retry
jccb(Assembler::equal, DONE_LABEL) ;
bind(L_decrement_retry);
// Spin and retry if lock is busy.
rtm_retry_lock_on_busy(retry_on_busy_count_Reg, boxReg, tmpReg, scrReg, L_rtm_retry);
}
else {
bind(L_decrement_retry);
}
}
#endif // INCLUDE_RTM_OPT
// Fast_Lock and Fast_Unlock used by C2
// Because the transitions from emitted code to the runtime
@ -1350,17 +1697,26 @@ void MacroAssembler::biased_locking_exit(Register obj_reg, Register temp_reg, La
// box: on-stack box address (displaced header location) - KILLED
// rax,: tmp -- KILLED
// scr: tmp -- KILLED
void MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmpReg, Register scrReg, BiasedLockingCounters* counters) {
void MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmpReg,
Register scrReg, Register cx1Reg, Register cx2Reg,
BiasedLockingCounters* counters,
RTMLockingCounters* rtm_counters,
RTMLockingCounters* stack_rtm_counters,
Metadata* method_data,
bool use_rtm, bool profile_rtm) {
// Ensure the register assignents are disjoint
guarantee (objReg != boxReg, "");
guarantee (objReg != tmpReg, "");
guarantee (objReg != scrReg, "");
guarantee (boxReg != tmpReg, "");
guarantee (boxReg != scrReg, "");
guarantee (tmpReg == rax, "");
assert(tmpReg == rax, "");
if (use_rtm) {
assert_different_registers(objReg, boxReg, tmpReg, scrReg, cx1Reg, cx2Reg);
} else {
assert(cx1Reg == noreg, "");
assert(cx2Reg == noreg, "");
assert_different_registers(objReg, boxReg, tmpReg, scrReg);
}
if (counters != NULL) {
atomic_incl(ExternalAddress((address)counters->total_entry_count_addr()));
atomic_incl(ExternalAddress((address)counters->total_entry_count_addr()), scrReg);
}
if (EmitSync & 1) {
// set box->dhw = unused_mark (3)
@ -1419,12 +1775,20 @@ void MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmpReg
biased_locking_enter(boxReg, objReg, tmpReg, scrReg, true, DONE_LABEL, NULL, counters);
}
#if INCLUDE_RTM_OPT
if (UseRTMForStackLocks && use_rtm) {
rtm_stack_locking(objReg, tmpReg, scrReg, cx2Reg,
stack_rtm_counters, method_data, profile_rtm,
DONE_LABEL, IsInflated);
}
#endif // INCLUDE_RTM_OPT
movptr(tmpReg, Address(objReg, 0)); // [FETCH]
testl (tmpReg, markOopDesc::monitor_value); // inflated vs stack-locked|neutral|biased
jccb (Assembler::notZero, IsInflated);
testptr(tmpReg, markOopDesc::monitor_value); // inflated vs stack-locked|neutral|biased
jccb(Assembler::notZero, IsInflated);
// Attempt stack-locking ...
orptr (tmpReg, 0x1);
orptr (tmpReg, markOopDesc::unlocked_value);
movptr(Address(boxReg, 0), tmpReg); // Anticipate successful CAS
if (os::is_MP()) {
lock();
@ -1434,19 +1798,32 @@ void MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmpReg
cond_inc32(Assembler::equal,
ExternalAddress((address)counters->fast_path_entry_count_addr()));
}
jccb(Assembler::equal, DONE_LABEL);
jcc(Assembler::equal, DONE_LABEL); // Success
// Recursive locking
// Recursive locking.
// The object is stack-locked: markword contains stack pointer to BasicLock.
// Locked by current thread if difference with current SP is less than one page.
subptr(tmpReg, rsp);
// Next instruction set ZFlag == 1 (Success) if difference is less then one page.
andptr(tmpReg, (int32_t) (NOT_LP64(0xFFFFF003) LP64_ONLY(7 - os::vm_page_size())) );
movptr(Address(boxReg, 0), tmpReg);
if (counters != NULL) {
cond_inc32(Assembler::equal,
ExternalAddress((address)counters->fast_path_entry_count_addr()));
}
jmpb(DONE_LABEL);
jmp(DONE_LABEL);
bind(IsInflated);
// The object is inflated. tmpReg contains pointer to ObjectMonitor* + 2(monitor_value)
#if INCLUDE_RTM_OPT
// Use the same RTM locking code in 32- and 64-bit VM.
if (use_rtm) {
rtm_inflated_locking(objReg, boxReg, tmpReg, scrReg, cx1Reg, cx2Reg,
rtm_counters, method_data, profile_rtm, DONE_LABEL);
} else {
#endif // INCLUDE_RTM_OPT
#ifndef _LP64
// The object is inflated.
//
@ -1576,7 +1953,7 @@ void MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmpReg
// Without cast to int32_t a movptr will destroy r10 which is typically obj
movptr(Address(boxReg, 0), (int32_t)intptr_t(markOopDesc::unused_mark()));
mov (boxReg, tmpReg);
movptr (boxReg, tmpReg);
movptr (tmpReg, Address(boxReg, ObjectMonitor::owner_offset_in_bytes()-2));
testptr(tmpReg, tmpReg);
jccb (Assembler::notZero, DONE_LABEL);
@ -1587,9 +1964,11 @@ void MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmpReg
}
cmpxchgptr(r15_thread, Address(boxReg, ObjectMonitor::owner_offset_in_bytes()-2));
// Intentional fall-through into DONE_LABEL ...
#endif // _LP64
#if INCLUDE_RTM_OPT
} // use_rtm()
#endif
// DONE_LABEL is a hot target - we'd really like to place it at the
// start of cache line by padding with NOPs.
// See the AMD and Intel software optimization manuals for the
@ -1631,11 +2010,9 @@ void MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmpReg
// should not be unlocked by "normal" java-level locking and vice-versa. The specification
// doesn't specify what will occur if a program engages in such mixed-mode locking, however.
void MacroAssembler::fast_unlock(Register objReg, Register boxReg, Register tmpReg) {
guarantee (objReg != boxReg, "");
guarantee (objReg != tmpReg, "");
guarantee (boxReg != tmpReg, "");
guarantee (boxReg == rax, "");
void MacroAssembler::fast_unlock(Register objReg, Register boxReg, Register tmpReg, bool use_rtm) {
assert(boxReg == rax, "");
assert_different_registers(objReg, boxReg, tmpReg);
if (EmitSync & 4) {
// Disable - inhibit all inlining. Force control through the slow-path
@ -1667,14 +2044,41 @@ void MacroAssembler::fast_unlock(Register objReg, Register boxReg, Register tmpR
biased_locking_exit(objReg, tmpReg, DONE_LABEL);
}
cmpptr(Address(boxReg, 0), (int32_t)NULL_WORD); // Examine the displaced header
movptr(tmpReg, Address(objReg, 0)); // Examine the object's markword
jccb (Assembler::zero, DONE_LABEL); // 0 indicates recursive stack-lock
#if INCLUDE_RTM_OPT
if (UseRTMForStackLocks && use_rtm) {
assert(!UseBiasedLocking, "Biased locking is not supported with RTM locking");
Label L_regular_unlock;
movptr(tmpReg, Address(objReg, 0)); // fetch markword
andptr(tmpReg, markOopDesc::biased_lock_mask_in_place); // look at 3 lock bits
cmpptr(tmpReg, markOopDesc::unlocked_value); // bits = 001 unlocked
jccb(Assembler::notEqual, L_regular_unlock); // if !HLE RegularLock
xend(); // otherwise end...
jmp(DONE_LABEL); // ... and we're done
bind(L_regular_unlock);
}
#endif
testptr(tmpReg, 0x02); // Inflated?
cmpptr(Address(boxReg, 0), (int32_t)NULL_WORD); // Examine the displaced header
jcc (Assembler::zero, DONE_LABEL); // 0 indicates recursive stack-lock
movptr(tmpReg, Address(objReg, 0)); // Examine the object's markword
testptr(tmpReg, markOopDesc::monitor_value); // Inflated?
jccb (Assembler::zero, Stacked);
// It's inflated.
#if INCLUDE_RTM_OPT
if (use_rtm) {
Label L_regular_inflated_unlock;
// Clean monitor_value bit to get valid pointer
int owner_offset = ObjectMonitor::owner_offset_in_bytes() - markOopDesc::monitor_value;
movptr(boxReg, Address(tmpReg, owner_offset));
testptr(boxReg, boxReg);
jccb(Assembler::notZero, L_regular_inflated_unlock);
xend();
jmpb(DONE_LABEL);
bind(L_regular_inflated_unlock);
}
#endif
// Despite our balanced locking property we still check that m->_owner == Self
// as java routines or native JNI code called by this thread might
// have released the lock.
@ -2448,7 +2852,9 @@ void MacroAssembler::cond_inc32(Condition cond, AddressLiteral counter_addr) {
Condition negated_cond = negate_condition(cond);
Label L;
jcc(negated_cond, L);
pushf(); // Preserve flags
atomic_incl(counter_addr);
popf();
bind(L);
}

View File

@ -27,6 +27,7 @@
#include "asm/assembler.hpp"
#include "utilities/macros.hpp"
#include "runtime/rtmLocking.hpp"
// MacroAssembler extends Assembler by frequently used macros.
@ -111,7 +112,8 @@ class MacroAssembler: public Assembler {
op == 0xE9 /* jmp */ ||
op == 0xEB /* short jmp */ ||
(op & 0xF0) == 0x70 /* short jcc */ ||
op == 0x0F && (branch[1] & 0xF0) == 0x80 /* jcc */,
op == 0x0F && (branch[1] & 0xF0) == 0x80 /* jcc */ ||
op == 0xC7 && branch[1] == 0xF8 /* xbegin */,
"Invalid opcode at patch point");
if (op == 0xEB || (op & 0xF0) == 0x70) {
@ -121,7 +123,7 @@ class MacroAssembler: public Assembler {
guarantee(this->is8bit(imm8), "Short forward jump exceeds 8-bit offset");
*disp = imm8;
} else {
int* disp = (int*) &branch[(op == 0x0F)? 2: 1];
int* disp = (int*) &branch[(op == 0x0F || op == 0xC7)? 2: 1];
int imm32 = target - (address) &disp[1];
*disp = imm32;
}
@ -161,7 +163,6 @@ class MacroAssembler: public Assembler {
void incrementq(Register reg, int value = 1);
void incrementq(Address dst, int value = 1);
// Support optimal SSE move instructions.
void movflt(XMMRegister dst, XMMRegister src) {
if (UseXmmRegToRegMoveAll) { movaps(dst, src); return; }
@ -187,6 +188,8 @@ class MacroAssembler: public Assembler {
void incrementl(AddressLiteral dst);
void incrementl(ArrayAddress dst);
void incrementq(AddressLiteral dst);
// Alignment
void align(int modulus);
@ -654,8 +657,36 @@ class MacroAssembler: public Assembler {
#ifdef COMPILER2
// Code used by cmpFastLock and cmpFastUnlock mach instructions in .ad file.
// See full desription in macroAssembler_x86.cpp.
void fast_lock(Register obj, Register box, Register tmp, Register scr, BiasedLockingCounters* counters);
void fast_unlock(Register obj, Register box, Register tmp);
void fast_lock(Register obj, Register box, Register tmp,
Register scr, Register cx1, Register cx2,
BiasedLockingCounters* counters,
RTMLockingCounters* rtm_counters,
RTMLockingCounters* stack_rtm_counters,
Metadata* method_data,
bool use_rtm, bool profile_rtm);
void fast_unlock(Register obj, Register box, Register tmp, bool use_rtm);
#if INCLUDE_RTM_OPT
void rtm_counters_update(Register abort_status, Register rtm_counters);
void branch_on_random_using_rdtsc(Register tmp, Register scr, int count, Label& brLabel);
void rtm_abort_ratio_calculation(Register tmp, Register rtm_counters_reg,
RTMLockingCounters* rtm_counters,
Metadata* method_data);
void rtm_profiling(Register abort_status_Reg, Register rtm_counters_Reg,
RTMLockingCounters* rtm_counters, Metadata* method_data, bool profile_rtm);
void rtm_retry_lock_on_abort(Register retry_count, Register abort_status, Label& retryLabel);
void rtm_retry_lock_on_busy(Register retry_count, Register box, Register tmp, Register scr, Label& retryLabel);
void rtm_stack_locking(Register obj, Register tmp, Register scr,
Register retry_on_abort_count,
RTMLockingCounters* stack_rtm_counters,
Metadata* method_data, bool profile_rtm,
Label& DONE_LABEL, Label& IsInflated);
void rtm_inflated_locking(Register obj, Register box, Register tmp,
Register scr, Register retry_on_busy_count,
Register retry_on_abort_count,
RTMLockingCounters* rtm_counters,
Metadata* method_data, bool profile_rtm,
Label& DONE_LABEL);
#endif
#endif
Condition negate_condition(Condition cond);
@ -721,6 +752,7 @@ class MacroAssembler: public Assembler {
void imulptr(Register dst, Register src) { LP64_ONLY(imulq(dst, src)) NOT_LP64(imull(dst, src)); }
void imulptr(Register dst, Register src, int imm32) { LP64_ONLY(imulq(dst, src, imm32)) NOT_LP64(imull(dst, src, imm32)); }
void negptr(Register dst) { LP64_ONLY(negq(dst)) NOT_LP64(negl(dst)); }
@ -762,7 +794,14 @@ class MacroAssembler: public Assembler {
// Conditionally (atomically, on MPs) increments passed counter address, preserving condition codes.
void cond_inc32(Condition cond, AddressLiteral counter_addr);
// Unconditional atomic increment.
void atomic_incl(AddressLiteral counter_addr);
void atomic_incl(Address counter_addr);
void atomic_incl(AddressLiteral counter_addr, Register scr = rscratch1);
#ifdef _LP64
void atomic_incq(Address counter_addr);
void atomic_incq(AddressLiteral counter_addr, Register scr = rscratch1);
#endif
void atomic_incptr(AddressLiteral counter_addr, Register scr = rscratch1) { LP64_ONLY(atomic_incq(counter_addr, scr)) NOT_LP64(atomic_incl(counter_addr, scr)) ; }
void atomic_incptr(Address counter_addr) { LP64_ONLY(atomic_incq(counter_addr)) NOT_LP64(atomic_incl(counter_addr)) ; }
void lea(Register dst, AddressLiteral adr);
void lea(Address dst, AddressLiteral adr);
@ -1074,7 +1113,11 @@ public:
void movptr(Register dst, Address src);
void movptr(Register dst, AddressLiteral src);
#ifdef _LP64
void movptr(Register dst, AddressLiteral src, Register scratch=rscratch1);
#else
void movptr(Register dst, AddressLiteral src, Register scratch=noreg); // Scratch reg is ignored in 32-bit
#endif
void movptr(Register dst, intptr_t src);
void movptr(Register dst, Register src);

View File

@ -0,0 +1,60 @@
/*
* Copyright (c) 2014, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "memory/allocation.inline.hpp"
#include "runtime/task.hpp"
#include "runtime/rtmLocking.hpp"
// One-shot PeriodicTask subclass for enabling RTM locking
uintx RTMLockingCounters::_calculation_flag = 0;
class RTMLockingCalculationTask : public PeriodicTask {
public:
RTMLockingCalculationTask(size_t interval_time) : PeriodicTask(interval_time){ }
virtual void task() {
RTMLockingCounters::_calculation_flag = 1;
// Reclaim our storage and disenroll ourself
delete this;
}
};
void RTMLockingCounters::init() {
if (UseRTMLocking && RTMLockingCalculationDelay > 0) {
RTMLockingCalculationTask* task = new RTMLockingCalculationTask(RTMLockingCalculationDelay);
task->enroll();
} else {
_calculation_flag = 1;
}
}
//------------------------------print_on-------------------------------
void RTMLockingCounters::print_on(outputStream* st) {
tty->print_cr("# rtm locks total (estimated): " UINTX_FORMAT, _total_count * RTMTotalCountIncrRate);
tty->print_cr("# rtm lock aborts : " UINTX_FORMAT, _abort_count);
for (int i = 0; i < ABORT_STATUS_LIMIT; i++) {
tty->print_cr("# rtm lock aborts %d: " UINTX_FORMAT, i, _abortX_count[i]);
}
}

View File

@ -1817,6 +1817,13 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
// Frame is now completed as far as size and linkage.
int frame_complete = ((intptr_t)__ pc()) - start;
if (UseRTMLocking) {
// Abort RTM transaction before calling JNI
// because critical section will be large and will be
// aborted anyway. Also nmethod could be deoptimized.
__ xabort(0);
}
// Calculate the difference between rsp and rbp,. We need to know it
// after the native call because on windows Java Natives will pop
// the arguments and it is painful to do rsp relative addressing
@ -3170,6 +3177,12 @@ void SharedRuntime::generate_uncommon_trap_blob() {
};
address start = __ pc();
if (UseRTMLocking) {
// Abort RTM transaction before possible nmethod deoptimization.
__ xabort(0);
}
// Push self-frame.
__ subptr(rsp, return_off*wordSize); // Epilog!
@ -3355,6 +3368,14 @@ SafepointBlob* SharedRuntime::generate_handler_blob(address call_ptr, int poll_t
address call_pc = NULL;
bool cause_return = (poll_type == POLL_AT_RETURN);
bool save_vectors = (poll_type == POLL_AT_VECTOR_LOOP);
if (UseRTMLocking) {
// Abort RTM transaction before calling runtime
// because critical section will be large and will be
// aborted anyway. Also nmethod could be deoptimized.
__ xabort(0);
}
// If cause_return is true we are at a poll_return and there is
// the return address on the stack to the caller on the nmethod
// that is safepoint. We can leave this return on the stack and

View File

@ -2012,6 +2012,13 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
// Frame is now completed as far as size and linkage.
int frame_complete = ((intptr_t)__ pc()) - start;
if (UseRTMLocking) {
// Abort RTM transaction before calling JNI
// because critical section will be large and will be
// aborted anyway. Also nmethod could be deoptimized.
__ xabort(0);
}
#ifdef ASSERT
{
Label L;
@ -3612,6 +3619,11 @@ void SharedRuntime::generate_uncommon_trap_blob() {
address start = __ pc();
if (UseRTMLocking) {
// Abort RTM transaction before possible nmethod deoptimization.
__ xabort(0);
}
// Push self-frame. We get here with a return address on the
// stack, so rsp is 8-byte aligned until we allocate our frame.
__ subptr(rsp, SimpleRuntimeFrame::return_off << LogBytesPerInt); // Epilog!
@ -3792,6 +3804,13 @@ SafepointBlob* SharedRuntime::generate_handler_blob(address call_ptr, int poll_t
bool cause_return = (poll_type == POLL_AT_RETURN);
bool save_vectors = (poll_type == POLL_AT_VECTOR_LOOP);
if (UseRTMLocking) {
// Abort RTM transaction before calling runtime
// because critical section will be large and will be
// aborted anyway. Also nmethod could be deoptimized.
__ xabort(0);
}
// Make room for return address (or push it again)
if (!cause_return) {
__ push(rbx);

View File

@ -50,8 +50,13 @@ int VM_Version::_cpuFeatures;
const char* VM_Version::_features_str = "";
VM_Version::CpuidInfo VM_Version::_cpuid_info = { 0, };
// Address of instruction which causes SEGV
address VM_Version::_cpuinfo_segv_addr = 0;
// Address of instruction after the one which causes SEGV
address VM_Version::_cpuinfo_cont_addr = 0;
static BufferBlob* stub_blob;
static const int stub_size = 550;
static const int stub_size = 600;
extern "C" {
typedef void (*getPsrInfo_stub_t)(void*);
@ -234,9 +239,9 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
// Check if OS has enabled XGETBV instruction to access XCR0
// (OSXSAVE feature flag) and CPU supports AVX
//
__ andl(rcx, 0x18000000);
__ andl(rcx, 0x18000000); // cpuid1 bits osxsave | avx
__ cmpl(rcx, 0x18000000);
__ jccb(Assembler::notEqual, sef_cpuid);
__ jccb(Assembler::notEqual, sef_cpuid); // jump if AVX is not supported
//
// XCR0, XFEATURE_ENABLED_MASK register
@ -247,6 +252,47 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
__ movl(Address(rsi, 0), rax);
__ movl(Address(rsi, 4), rdx);
__ andl(rax, 0x6); // xcr0 bits sse | ymm
__ cmpl(rax, 0x6);
__ jccb(Assembler::notEqual, sef_cpuid); // jump if AVX is not supported
//
// Some OSs have a bug when upper 128bits of YMM
// registers are not restored after a signal processing.
// Generate SEGV here (reference through NULL)
// and check upper YMM bits after it.
//
VM_Version::set_avx_cpuFeatures(); // Enable temporary to pass asserts
// load value into all 32 bytes of ymm7 register
__ movl(rcx, VM_Version::ymm_test_value());
__ movdl(xmm0, rcx);
__ pshufd(xmm0, xmm0, 0x00);
__ vinsertf128h(xmm0, xmm0, xmm0);
__ vmovdqu(xmm7, xmm0);
#ifdef _LP64
__ vmovdqu(xmm8, xmm0);
__ vmovdqu(xmm15, xmm0);
#endif
__ xorl(rsi, rsi);
VM_Version::set_cpuinfo_segv_addr( __ pc() );
// Generate SEGV
__ movl(rax, Address(rsi, 0));
VM_Version::set_cpuinfo_cont_addr( __ pc() );
// Returns here after signal. Save xmm0 to check it later.
__ lea(rsi, Address(rbp, in_bytes(VM_Version::ymm_save_offset())));
__ vmovdqu(Address(rsi, 0), xmm0);
__ vmovdqu(Address(rsi, 32), xmm7);
#ifdef _LP64
__ vmovdqu(Address(rsi, 64), xmm8);
__ vmovdqu(Address(rsi, 96), xmm15);
#endif
VM_Version::clean_cpuFeatures();
//
// cpuid(0x7) Structured Extended Features
//
@ -429,7 +475,7 @@ void VM_Version::get_processor_features() {
}
char buf[256];
jio_snprintf(buf, sizeof(buf), "(%u cores per cpu, %u threads per core) family %d model %d stepping %d%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
jio_snprintf(buf, sizeof(buf), "(%u cores per cpu, %u threads per core) family %d model %d stepping %d%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
cores_per_cpu(), threads_per_core(),
cpu_family(), _model, _stepping,
(supports_cmov() ? ", cmov" : ""),
@ -446,8 +492,9 @@ void VM_Version::get_processor_features() {
(supports_avx() ? ", avx" : ""),
(supports_avx2() ? ", avx2" : ""),
(supports_aes() ? ", aes" : ""),
(supports_clmul() ? ", clmul" : ""),
(supports_clmul() ? ", clmul" : ""),
(supports_erms() ? ", erms" : ""),
(supports_rtm() ? ", rtm" : ""),
(supports_mmx_ext() ? ", mmxext" : ""),
(supports_3dnow_prefetch() ? ", 3dnowpref" : ""),
(supports_lzcnt() ? ", lzcnt": ""),
@ -488,7 +535,7 @@ void VM_Version::get_processor_features() {
}
} else if (UseAES) {
if (!FLAG_IS_DEFAULT(UseAES))
warning("AES instructions not available on this CPU");
warning("AES instructions are not available on this CPU");
FLAG_SET_DEFAULT(UseAES, false);
}
@ -521,10 +568,57 @@ void VM_Version::get_processor_features() {
}
} else if (UseAESIntrinsics) {
if (!FLAG_IS_DEFAULT(UseAESIntrinsics))
warning("AES intrinsics not available on this CPU");
warning("AES intrinsics are not available on this CPU");
FLAG_SET_DEFAULT(UseAESIntrinsics, false);
}
// Adjust RTM (Restricted Transactional Memory) flags
if (!supports_rtm() && UseRTMLocking) {
// Can't continue because UseRTMLocking affects UseBiasedLocking flag
// setting during arguments processing. See use_biased_locking().
// VM_Version_init() is executed after UseBiasedLocking is used
// in Thread::allocate().
vm_exit_during_initialization("RTM instructions are not available on this CPU");
}
#if INCLUDE_RTM_OPT
if (UseRTMLocking) {
if (!FLAG_IS_CMDLINE(UseRTMLocking)) {
// RTM locking should be used only for applications with
// high lock contention. For now we do not use it by default.
vm_exit_during_initialization("UseRTMLocking flag should be only set on command line");
}
if (!is_power_of_2(RTMTotalCountIncrRate)) {
warning("RTMTotalCountIncrRate must be a power of 2, resetting it to 64");
FLAG_SET_DEFAULT(RTMTotalCountIncrRate, 64);
}
if (RTMAbortRatio < 0 || RTMAbortRatio > 100) {
warning("RTMAbortRatio must be in the range 0 to 100, resetting it to 50");
FLAG_SET_DEFAULT(RTMAbortRatio, 50);
}
} else { // !UseRTMLocking
if (UseRTMForStackLocks) {
if (!FLAG_IS_DEFAULT(UseRTMForStackLocks)) {
warning("UseRTMForStackLocks flag should be off when UseRTMLocking flag is off");
}
FLAG_SET_DEFAULT(UseRTMForStackLocks, false);
}
if (UseRTMDeopt) {
FLAG_SET_DEFAULT(UseRTMDeopt, false);
}
if (PrintPreciseRTMLockingStatistics) {
FLAG_SET_DEFAULT(PrintPreciseRTMLockingStatistics, false);
}
}
#else
if (UseRTMLocking) {
// Only C2 does RTM locking optimization.
// Can't continue because UseRTMLocking affects UseBiasedLocking flag
// setting during arguments processing. See use_biased_locking().
vm_exit_during_initialization("RTM locking optimization is not supported in this VM");
}
#endif
#ifdef COMPILER2
if (UseFPUForSpilling) {
if (UseSSE < 2) {
@ -540,14 +634,28 @@ void VM_Version::get_processor_features() {
if (MaxVectorSize > 32) {
FLAG_SET_DEFAULT(MaxVectorSize, 32);
}
if (MaxVectorSize > 16 && UseAVX == 0) {
// Only supported with AVX+
if (MaxVectorSize > 16 && (UseAVX == 0 || !os_supports_avx_vectors())) {
// 32 bytes vectors (in YMM) are only supported with AVX+
FLAG_SET_DEFAULT(MaxVectorSize, 16);
}
if (UseSSE < 2) {
// Only supported with SSE2+
// Vectors (in XMM) are only supported with SSE2+
FLAG_SET_DEFAULT(MaxVectorSize, 0);
}
#ifdef ASSERT
if (supports_avx() && PrintMiscellaneous && Verbose && TraceNewVectors) {
tty->print_cr("State of YMM registers after signal handle:");
int nreg = 2 LP64_ONLY(+2);
const char* ymm_name[4] = {"0", "7", "8", "15"};
for (int i = 0; i < nreg; i++) {
tty->print("YMM%s:", ymm_name[i]);
for (int j = 7; j >=0; j--) {
tty->print(" %x", _cpuid_info.ymm_save[i*8 + j]);
}
tty->cr();
}
}
#endif
}
#endif
@ -678,14 +786,6 @@ void VM_Version::get_processor_features() {
}
}
}
#if defined(COMPILER2) && defined(_ALLBSD_SOURCE)
if (MaxVectorSize > 16) {
// Limit vectors size to 16 bytes on BSD until it fixes
// restoring upper 128bit of YMM registers on return
// from signal handler.
FLAG_SET_DEFAULT(MaxVectorSize, 16);
}
#endif // COMPILER2
// Use count leading zeros count instruction if available.
if (supports_lzcnt()) {
@ -814,6 +914,11 @@ void VM_Version::get_processor_features() {
if (UseAES) {
tty->print(" UseAES=1");
}
#ifdef COMPILER2
if (MaxVectorSize > 0) {
tty->print(" MaxVectorSize=%d", MaxVectorSize);
}
#endif
tty->cr();
tty->print("Allocation");
if (AllocatePrefetchStyle <= 0 || UseSSE == 0 && !supports_3dnow_prefetch()) {
@ -856,6 +961,27 @@ void VM_Version::get_processor_features() {
#endif // !PRODUCT
}
bool VM_Version::use_biased_locking() {
#if INCLUDE_RTM_OPT
// RTM locking is most useful when there is high lock contention and
// low data contention. With high lock contention the lock is usually
// inflated and biased locking is not suitable for that case.
// RTM locking code requires that biased locking is off.
// Note: we can't switch off UseBiasedLocking in get_processor_features()
// because it is used by Thread::allocate() which is called before
// VM_Version::initialize().
if (UseRTMLocking && UseBiasedLocking) {
if (FLAG_IS_DEFAULT(UseBiasedLocking)) {
FLAG_SET_DEFAULT(UseBiasedLocking, false);
} else {
warning("Biased locking is not supported with RTM locking; ignoring UseBiasedLocking flag." );
UseBiasedLocking = false;
}
}
#endif
return UseBiasedLocking;
}
void VM_Version::initialize() {
ResourceMark rm;
// Making this stub must be FIRST use of assembler

View File

@ -207,7 +207,9 @@ public:
: 2,
bmi2 : 1,
erms : 1,
: 22;
: 1,
rtm : 1,
: 20;
} bits;
};
@ -229,6 +231,9 @@ protected:
// 0 if this instruction is not available
static const char* _features_str;
static address _cpuinfo_segv_addr; // address of instruction which causes SEGV
static address _cpuinfo_cont_addr; // address of instruction after the one which causes SEGV
enum {
CPU_CX8 = (1 << 0), // next bits are from cpuid 1 (EDX)
CPU_CMOV = (1 << 1),
@ -254,7 +259,8 @@ protected:
CPU_ERMS = (1 << 20), // enhanced 'rep movsb/stosb' instructions
CPU_CLMUL = (1 << 21), // carryless multiply for CRC
CPU_BMI1 = (1 << 22),
CPU_BMI2 = (1 << 23)
CPU_BMI2 = (1 << 23),
CPU_RTM = (1 << 24) // Restricted Transactional Memory instructions
} cpuFeatureFlags;
enum {
@ -361,6 +367,9 @@ protected:
// extended control register XCR0 (the XFEATURE_ENABLED_MASK register)
XemXcr0Eax xem_xcr0_eax;
uint32_t xem_xcr0_edx; // reserved
// Space to save ymm registers after signal handle
int ymm_save[8*4]; // Save ymm0, ymm7, ymm8, ymm15
};
// The actual cpuid info block
@ -438,6 +447,8 @@ protected:
result |= CPU_ERMS;
if (_cpuid_info.std_cpuid1_ecx.bits.clmul != 0)
result |= CPU_CLMUL;
if (_cpuid_info.sef_cpuid7_ebx.bits.rtm != 0)
result |= CPU_RTM;
// AMD features.
if (is_amd()) {
@ -460,6 +471,21 @@ protected:
return result;
}
static bool os_supports_avx_vectors() {
if (!supports_avx()) {
return false;
}
// Verify that OS save/restore all bits of AVX registers
// during signal processing.
int nreg = 2 LP64_ONLY(+2);
for (int i = 0; i < 8 * nreg; i++) { // 32 bytes per ymm register
if (_cpuid_info.ymm_save[i] != ymm_test_value()) {
return false;
}
}
return true;
}
static void get_processor_features();
public:
@ -476,10 +502,26 @@ public:
static ByteSize tpl_cpuidB1_offset() { return byte_offset_of(CpuidInfo, tpl_cpuidB1_eax); }
static ByteSize tpl_cpuidB2_offset() { return byte_offset_of(CpuidInfo, tpl_cpuidB2_eax); }
static ByteSize xem_xcr0_offset() { return byte_offset_of(CpuidInfo, xem_xcr0_eax); }
static ByteSize ymm_save_offset() { return byte_offset_of(CpuidInfo, ymm_save); }
// The value used to check ymm register after signal handle
static int ymm_test_value() { return 0xCAFEBABE; }
static void set_cpuinfo_segv_addr(address pc) { _cpuinfo_segv_addr = pc; }
static bool is_cpuinfo_segv_addr(address pc) { return _cpuinfo_segv_addr == pc; }
static void set_cpuinfo_cont_addr(address pc) { _cpuinfo_cont_addr = pc; }
static address cpuinfo_cont_addr() { return _cpuinfo_cont_addr; }
static void clean_cpuFeatures() { _cpuFeatures = 0; }
static void set_avx_cpuFeatures() { _cpuFeatures = (CPU_SSE | CPU_SSE2 | CPU_AVX); }
// Initialization
static void initialize();
// Override Abstract_VM_Version implementation
static bool use_biased_locking();
// Asserts
static void assert_is_initialized() {
assert(_cpuid_info.std_cpuid1_eax.bits.family != 0, "VM_Version not initialized");
@ -572,6 +614,7 @@ public:
static bool supports_aes() { return (_cpuFeatures & CPU_AES) != 0; }
static bool supports_erms() { return (_cpuFeatures & CPU_ERMS) != 0; }
static bool supports_clmul() { return (_cpuFeatures & CPU_CLMUL) != 0; }
static bool supports_rtm() { return (_cpuFeatures & CPU_RTM) != 0; }
static bool supports_bmi1() { return (_cpuFeatures & CPU_BMI1) != 0; }
static bool supports_bmi2() { return (_cpuFeatures & CPU_BMI2) != 0; }
// Intel features

View File

@ -474,7 +474,125 @@ reg_class vectory_reg(XMM0, XMM0b, XMM0c, XMM0d, XMM0e, XMM0f, XMM0g, XMM
%}
//----------SOURCE BLOCK-------------------------------------------------------
// This is a block of C++ code which provides values, functions, and
// definitions necessary in the rest of the architecture description
source_hpp %{
// Header information of the source block.
// Method declarations/definitions which are used outside
// the ad-scope can conveniently be defined here.
//
// To keep related declarations/definitions/uses close together,
// we switch between source %{ }% and source_hpp %{ }% freely as needed.
class CallStubImpl {
//--------------------------------------------------------------
//---< Used for optimization in Compile::shorten_branches >---
//--------------------------------------------------------------
public:
// Size of call trampoline stub.
static uint size_call_trampoline() {
return 0; // no call trampolines on this platform
}
// number of relocations needed by a call trampoline stub
static uint reloc_call_trampoline() {
return 0; // no call trampolines on this platform
}
};
class HandlerImpl {
public:
static int emit_exception_handler(CodeBuffer &cbuf);
static int emit_deopt_handler(CodeBuffer& cbuf);
static uint size_exception_handler() {
// NativeCall instruction size is the same as NativeJump.
// exception handler starts out as jump and can be patched to
// a call be deoptimization. (4932387)
// Note that this value is also credited (in output.cpp) to
// the size of the code section.
return NativeJump::instruction_size;
}
#ifdef _LP64
static uint size_deopt_handler() {
// three 5 byte instructions
return 15;
}
#else
static uint size_deopt_handler() {
// NativeCall instruction size is the same as NativeJump.
// exception handler starts out as jump and can be patched to
// a call be deoptimization. (4932387)
// Note that this value is also credited (in output.cpp) to
// the size of the code section.
return 5 + NativeJump::instruction_size; // pushl(); jmp;
}
#endif
};
%} // end source_hpp
source %{
// Emit exception handler code.
// Stuff framesize into a register and call a VM stub routine.
int HandlerImpl::emit_exception_handler(CodeBuffer& cbuf) {
// Note that the code buffer's insts_mark is always relative to insts.
// That's why we must use the macroassembler to generate a handler.
MacroAssembler _masm(&cbuf);
address base = __ start_a_stub(size_exception_handler());
if (base == NULL) return 0; // CodeBuffer::expand failed
int offset = __ offset();
__ jump(RuntimeAddress(OptoRuntime::exception_blob()->entry_point()));
assert(__ offset() - offset <= (int) size_exception_handler(), "overflow");
__ end_a_stub();
return offset;
}
// Emit deopt handler code.
int HandlerImpl::emit_deopt_handler(CodeBuffer& cbuf) {
// Note that the code buffer's insts_mark is always relative to insts.
// That's why we must use the macroassembler to generate a handler.
MacroAssembler _masm(&cbuf);
address base = __ start_a_stub(size_deopt_handler());
if (base == NULL) return 0; // CodeBuffer::expand failed
int offset = __ offset();
#ifdef _LP64
address the_pc = (address) __ pc();
Label next;
// push a "the_pc" on the stack without destroying any registers
// as they all may be live.
// push address of "next"
__ call(next, relocInfo::none); // reloc none is fine since it is a disp32
__ bind(next);
// adjust it so it matches "the_pc"
__ subptr(Address(rsp, 0), __ offset() - offset);
#else
InternalAddress here(__ pc());
__ pushptr(here.addr());
#endif
__ jump(RuntimeAddress(SharedRuntime::deopt_blob()->unpack()));
assert(__ offset() - offset <= (int) size_deopt_handler(), "overflow");
__ end_a_stub();
return offset;
}
//=============================================================================
// Float masks come from different places depending on platform.
#ifdef _LP64
static address float_signmask() { return StubRoutines::x86::float_sign_mask(); }

View File

@ -1297,59 +1297,6 @@ uint MachUEPNode::size(PhaseRegAlloc *ra_) const {
//=============================================================================
uint size_exception_handler() {
// NativeCall instruction size is the same as NativeJump.
// exception handler starts out as jump and can be patched to
// a call be deoptimization. (4932387)
// Note that this value is also credited (in output.cpp) to
// the size of the code section.
return NativeJump::instruction_size;
}
// Emit exception handler code. Stuff framesize into a register
// and call a VM stub routine.
int emit_exception_handler(CodeBuffer& cbuf) {
// Note that the code buffer's insts_mark is always relative to insts.
// That's why we must use the macroassembler to generate a handler.
MacroAssembler _masm(&cbuf);
address base =
__ start_a_stub(size_exception_handler());
if (base == NULL) return 0; // CodeBuffer::expand failed
int offset = __ offset();
__ jump(RuntimeAddress(OptoRuntime::exception_blob()->entry_point()));
assert(__ offset() - offset <= (int) size_exception_handler(), "overflow");
__ end_a_stub();
return offset;
}
uint size_deopt_handler() {
// NativeCall instruction size is the same as NativeJump.
// exception handler starts out as jump and can be patched to
// a call be deoptimization. (4932387)
// Note that this value is also credited (in output.cpp) to
// the size of the code section.
return 5 + NativeJump::instruction_size; // pushl(); jmp;
}
// Emit deopt handler code.
int emit_deopt_handler(CodeBuffer& cbuf) {
// Note that the code buffer's insts_mark is always relative to insts.
// That's why we must use the macroassembler to generate a handler.
MacroAssembler _masm(&cbuf);
address base =
__ start_a_stub(size_exception_handler());
if (base == NULL) return 0; // CodeBuffer::expand failed
int offset = __ offset();
InternalAddress here(__ pc());
__ pushptr(here.addr());
__ jump(RuntimeAddress(SharedRuntime::deopt_blob()->unpack()));
assert(__ offset() - offset <= (int) size_deopt_handler(), "overflow");
__ end_a_stub();
return offset;
}
int Matcher::regnum_to_fpu_offset(int regnum) {
return regnum - 32; // The FP registers are in the second chunk
@ -12925,13 +12872,31 @@ instruct RethrowException()
// inlined locking and unlocking
instruct cmpFastLockRTM(eFlagsReg cr, eRegP object, eBXRegP box, eAXRegI tmp, eDXRegI scr, rRegI cx1, rRegI cx2) %{
predicate(Compile::current()->use_rtm());
match(Set cr (FastLock object box));
effect(TEMP tmp, TEMP scr, TEMP cx1, TEMP cx2, USE_KILL box);
ins_cost(300);
format %{ "FASTLOCK $object,$box\t! kills $box,$tmp,$scr,$cx1,$cx2" %}
ins_encode %{
__ fast_lock($object$$Register, $box$$Register, $tmp$$Register,
$scr$$Register, $cx1$$Register, $cx2$$Register,
_counters, _rtm_counters, _stack_rtm_counters,
((Method*)(ra_->C->method()->constant_encoding()))->method_data(),
true, ra_->C->profile_rtm());
%}
ins_pipe(pipe_slow);
%}
instruct cmpFastLock(eFlagsReg cr, eRegP object, eBXRegP box, eAXRegI tmp, eRegP scr) %{
predicate(!Compile::current()->use_rtm());
match(Set cr (FastLock object box));
effect(TEMP tmp, TEMP scr, USE_KILL box);
ins_cost(300);
format %{ "FASTLOCK $object,$box\t! kills $box,$tmp,$scr" %}
ins_encode %{
__ fast_lock($object$$Register, $box$$Register, $tmp$$Register, $scr$$Register, _counters);
__ fast_lock($object$$Register, $box$$Register, $tmp$$Register,
$scr$$Register, noreg, noreg, _counters, NULL, NULL, NULL, false, false);
%}
ins_pipe(pipe_slow);
%}
@ -12942,7 +12907,7 @@ instruct cmpFastUnlock(eFlagsReg cr, eRegP object, eAXRegP box, eRegP tmp ) %{
ins_cost(300);
format %{ "FASTUNLOCK $object,$box\t! kills $box,$tmp" %}
ins_encode %{
__ fast_unlock($object$$Register, $box$$Register, $tmp$$Register);
__ fast_unlock($object$$Register, $box$$Register, $tmp$$Register, ra_->C->use_rtm());
%}
ins_pipe(pipe_slow);
%}

View File

@ -1439,66 +1439,9 @@ uint MachUEPNode::size(PhaseRegAlloc* ra_) const
return MachNode::size(ra_); // too many variables; just compute it
// the hard way
}
//=============================================================================
uint size_exception_handler()
{
// NativeCall instruction size is the same as NativeJump.
// Note that this value is also credited (in output.cpp) to
// the size of the code section.
return NativeJump::instruction_size;
}
// Emit exception handler code.
int emit_exception_handler(CodeBuffer& cbuf)
{
// Note that the code buffer's insts_mark is always relative to insts.
// That's why we must use the macroassembler to generate a handler.
MacroAssembler _masm(&cbuf);
address base =
__ start_a_stub(size_exception_handler());
if (base == NULL) return 0; // CodeBuffer::expand failed
int offset = __ offset();
__ jump(RuntimeAddress(OptoRuntime::exception_blob()->entry_point()));
assert(__ offset() - offset <= (int) size_exception_handler(), "overflow");
__ end_a_stub();
return offset;
}
uint size_deopt_handler()
{
// three 5 byte instructions
return 15;
}
// Emit deopt handler code.
int emit_deopt_handler(CodeBuffer& cbuf)
{
// Note that the code buffer's insts_mark is always relative to insts.
// That's why we must use the macroassembler to generate a handler.
MacroAssembler _masm(&cbuf);
address base =
__ start_a_stub(size_deopt_handler());
if (base == NULL) return 0; // CodeBuffer::expand failed
int offset = __ offset();
address the_pc = (address) __ pc();
Label next;
// push a "the_pc" on the stack without destroying any registers
// as they all may be live.
// push address of "next"
__ call(next, relocInfo::none); // reloc none is fine since it is a disp32
__ bind(next);
// adjust it so it matches "the_pc"
__ subptr(Address(rsp, 0), __ offset() - offset);
__ jump(RuntimeAddress(SharedRuntime::deopt_blob()->unpack()));
assert(__ offset() - offset <= (int) size_deopt_handler(), "overflow");
__ end_a_stub();
return offset;
}
int Matcher::regnum_to_fpu_offset(int regnum)
{
@ -11387,13 +11330,31 @@ instruct jmpConUCF2_short(cmpOpUCF2 cop, rFlagsRegUCF cmp, label labl) %{
// ============================================================================
// inlined locking and unlocking
instruct cmpFastLockRTM(rFlagsReg cr, rRegP object, rbx_RegP box, rax_RegI tmp, rdx_RegI scr, rRegI cx1, rRegI cx2) %{
predicate(Compile::current()->use_rtm());
match(Set cr (FastLock object box));
effect(TEMP tmp, TEMP scr, TEMP cx1, TEMP cx2, USE_KILL box);
ins_cost(300);
format %{ "fastlock $object,$box\t! kills $box,$tmp,$scr,$cx1,$cx2" %}
ins_encode %{
__ fast_lock($object$$Register, $box$$Register, $tmp$$Register,
$scr$$Register, $cx1$$Register, $cx2$$Register,
_counters, _rtm_counters, _stack_rtm_counters,
((Method*)(ra_->C->method()->constant_encoding()))->method_data(),
true, ra_->C->profile_rtm());
%}
ins_pipe(pipe_slow);
%}
instruct cmpFastLock(rFlagsReg cr, rRegP object, rbx_RegP box, rax_RegI tmp, rRegP scr) %{
predicate(!Compile::current()->use_rtm());
match(Set cr (FastLock object box));
effect(TEMP tmp, TEMP scr, USE_KILL box);
ins_cost(300);
format %{ "fastlock $object,$box\t! kills $box,$tmp,$scr" %}
ins_encode %{
__ fast_lock($object$$Register, $box$$Register, $tmp$$Register, $scr$$Register, _counters);
__ fast_lock($object$$Register, $box$$Register, $tmp$$Register,
$scr$$Register, noreg, noreg, _counters, NULL, NULL, NULL, false, false);
%}
ins_pipe(pipe_slow);
%}
@ -11404,7 +11365,7 @@ instruct cmpFastUnlock(rFlagsReg cr, rRegP object, rax_RegP box, rRegP tmp) %{
ins_cost(300);
format %{ "fastunlock $object,$box\t! kills $box,$tmp" %}
ins_encode %{
__ fast_unlock($object$$Register, $box$$Register, $tmp$$Register);
__ fast_unlock($object$$Register, $box$$Register, $tmp$$Register, ra_->C->use_rtm());
%}
ins_pipe(pipe_slow);
%}

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright 2012, 2013 SAP AG. All rights reserved.
* Copyright 2012, 2014 SAP AG. 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
@ -28,6 +28,6 @@
#include "os_aix.inline.hpp"
#include "runtime/interfaceSupport.hpp"
#include "thread_aix.inline.hpp"
#include "runtime/thread.inline.hpp"
#endif // OS_AIX_VM_MUTEX_AIX_INLINE_HPP

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright 2012, 2013 SAP AG. All rights reserved.
* Copyright 2012, 2014 SAP AG. 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
@ -61,10 +61,10 @@
#include "runtime/statSampler.hpp"
#include "runtime/stubRoutines.hpp"
#include "runtime/threadCritical.hpp"
#include "runtime/thread.inline.hpp"
#include "runtime/timer.hpp"
#include "services/attachListener.hpp"
#include "services/runtimeService.hpp"
#include "thread_aix.inline.hpp"
#include "utilities/decoder.hpp"
#include "utilities/defaultStream.hpp"
#include "utilities/events.hpp"

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright 2012, 2013 SAP AG. All rights reserved.
* Copyright 2012, 2014 SAP AG. 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,7 +25,7 @@
#include "precompiled.hpp"
#include "runtime/threadCritical.hpp"
#include "thread_aix.inline.hpp"
#include "runtime/thread.inline.hpp"
// put OS-includes here
# include <pthread.h>

View File

@ -109,6 +109,8 @@
#define MAX_PATH (2 * K)
#define MAX_SECS 100000000
// for timer info max values which include all bits
#define ALL_64_BITS CONST64(0xFFFFFFFFFFFFFFFF)
@ -2434,7 +2436,6 @@ class Semaphore : public StackObj {
sem_t _semaphore;
};
Semaphore::Semaphore() {
sem_init(&_semaphore, 0, 0);
}
@ -2456,8 +2457,22 @@ bool Semaphore::trywait() {
}
bool Semaphore::timedwait(unsigned int sec, int nsec) {
struct timespec ts;
unpackTime(&ts, false, (sec * NANOSECS_PER_SEC) + nsec);
// Semaphore's are always associated with CLOCK_REALTIME
os::Linux::clock_gettime(CLOCK_REALTIME, &ts);
// see unpackTime for discussion on overflow checking
if (sec >= MAX_SECS) {
ts.tv_sec += MAX_SECS;
ts.tv_nsec = 0;
} else {
ts.tv_sec += sec;
ts.tv_nsec += nsec;
if (ts.tv_nsec >= NANOSECS_PER_SEC) {
ts.tv_nsec -= NANOSECS_PER_SEC;
++ts.tv_sec; // note: this must be <= max_secs
}
}
while (1) {
int result = sem_timedwait(&_semaphore, &ts);
@ -5661,7 +5676,6 @@ void os::PlatformEvent::unpark() {
* is no need to track notifications.
*/
#define MAX_SECS 100000000
/*
* This code is common to linux and solaris and will be moved to a
* common place in dolphin.

View File

@ -2425,6 +2425,12 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
}
}
if ((exception_code == EXCEPTION_ACCESS_VIOLATION) &&
VM_Version::is_cpuinfo_segv_addr(pc)) {
// Verify that OS save/restore AVX registers.
return Handle_Exception(exceptionInfo, VM_Version::cpuinfo_cont_addr());
}
if (t != NULL && t->is_Java_thread()) {
JavaThread* thread = (JavaThread*) t;
bool in_java = thread->thread_state() == _thread_in_Java;

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright 2012, 2013 SAP AG. All rights reserved.
* Copyright 2012, 2014 SAP AG. 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
@ -49,8 +49,8 @@
#include "runtime/osThread.hpp"
#include "runtime/sharedRuntime.hpp"
#include "runtime/stubRoutines.hpp"
#include "runtime/thread.inline.hpp"
#include "runtime/timer.hpp"
#include "thread_aix.inline.hpp"
#include "utilities/events.hpp"
#include "utilities/vmError.hpp"
#ifdef COMPILER1

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright 2012, 2013 SAP AG. All rights reserved.
* Copyright 2012, 2014 SAP AG. 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,14 +25,14 @@
#include "precompiled.hpp"
#include "runtime/threadLocalStorage.hpp"
#include "thread_aix.inline.hpp"
#include "runtime/thread.hpp"
void ThreadLocalStorage::generate_code_for_get_thread() {
// nothing we can do here for user-level thread
// Nothing we can do here for user-level thread.
}
void ThreadLocalStorage::pd_init() {
// Nothing to do
// Nothing to do.
}
void ThreadLocalStorage::pd_set_thread(Thread* thread) {

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright 2012, 2013 SAP AG. All rights reserved.
* Copyright 2012, 2014 SAP AG. 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
@ -24,8 +24,8 @@
*/
#include "precompiled.hpp"
#include "runtime/frame.inline.hpp"
#include "thread_aix.inline.hpp"
#include "runtime/frame.hpp"
#include "runtime/thread.hpp"
// Forte Analyzer AsyncGetCallTrace profiling support is not implemented on Aix/PPC.
bool JavaThread::pd_get_top_frame_for_signal_handler(frame* fr_addr, void* ucontext, bool isInJava) {

View File

@ -492,6 +492,11 @@ JVM_handle_bsd_signal(int sig,
}
}
if ((sig == SIGSEGV || sig == SIGBUS) && VM_Version::is_cpuinfo_segv_addr(pc)) {
// Verify that OS save/restore AVX registers.
stub = VM_Version::cpuinfo_cont_addr();
}
// We test if stub is already set (by the stack overflow code
// above) so it is not overwritten by the code that follows. This
// check is not required on other platforms, because on other

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright 2012, 2013 SAP AG. All rights reserved.
* Copyright 2012, 2014 SAP AG. 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
@ -24,8 +24,8 @@
*/
#include "precompiled.hpp"
#include "runtime/frame.inline.hpp"
#include "thread_linux.inline.hpp"
#include "runtime/frame.hpp"
#include "runtime/thread.hpp"
// Forte Analyzer AsyncGetCallTrace profiling support is not implemented on Linux/PPC.
bool JavaThread::pd_get_top_frame_for_signal_handler(frame* fr_addr, void* ucontext, bool isInJava) {

View File

@ -338,6 +338,11 @@ JVM_handle_linux_signal(int sig,
}
}
if ((sig == SIGSEGV) && VM_Version::is_cpuinfo_segv_addr(pc)) {
// Verify that OS save/restore AVX registers.
stub = VM_Version::cpuinfo_cont_addr();
}
if (thread->thread_state() == _thread_in_Java) {
// Java thread running in Java code => find exception handler if any
// a fault inside compiled code, the interpreter, or a stub

View File

@ -459,6 +459,11 @@ JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid,
}
}
if ((sig == SIGSEGV) && VM_Version::is_cpuinfo_segv_addr(pc)) {
// Verify that OS save/restore AVX registers.
stub = VM_Version::cpuinfo_cont_addr();
}
if (thread->thread_state() == _thread_in_vm) {
if (sig == SIGBUS && info->si_code == BUS_OBJERR && thread->doing_unsafe_access()) {
stub = StubRoutines::handler_for_unsafe_access();

View File

@ -1582,6 +1582,8 @@ void ArchDesc::defineExpand(FILE *fp, InstructForm *node) {
if( node->is_ideal_fastlock() && new_inst->is_ideal_fastlock() ) {
fprintf(fp, " ((MachFastLockNode*)n%d)->_counters = _counters;\n",cnt);
fprintf(fp, " ((MachFastLockNode*)n%d)->_rtm_counters = _rtm_counters;\n",cnt);
fprintf(fp, " ((MachFastLockNode*)n%d)->_stack_rtm_counters = _stack_rtm_counters;\n",cnt);
}
// Fill in the bottom_type where requested
@ -3963,6 +3965,8 @@ void ArchDesc::buildMachNode(FILE *fp_cpp, InstructForm *inst, const char *inden
}
if( inst->is_ideal_fastlock() ) {
fprintf(fp_cpp, "%s node->_counters = _leaf->as_FastLock()->counters();\n", indent);
fprintf(fp_cpp, "%s node->_rtm_counters = _leaf->as_FastLock()->rtm_counters();\n", indent);
fprintf(fp_cpp, "%s node->_stack_rtm_counters = _leaf->as_FastLock()->stack_rtm_counters();\n", indent);
}
}

View File

@ -2526,7 +2526,7 @@ void LIRGenerator::do_Goto(Goto* x) {
// need to free up storage used for OSR entry point
LIR_Opr osrBuffer = block()->next()->operand();
BasicTypeList signature;
signature.append(T_INT);
signature.append(NOT_LP64(T_INT) LP64_ONLY(T_LONG)); // pass a pointer to osrBuffer
CallingConvention* cc = frame_map()->c_calling_convention(&signature);
__ move(osrBuffer, cc->args()->at(0));
__ call_runtime_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::OSR_migration_end),

View File

@ -308,9 +308,6 @@
develop(intx, InstructionCountCutoff, 37000, \
"If GraphBuilder adds this many instructions, bails out") \
\
product_pd(intx, SafepointPollOffset, \
"Offset added to polling address (Intel only)") \
\
develop(bool, ComputeExactFPURegisterUsage, true, \
"Compute additional live set for fpu registers to simplify fpu stack merge (Intel only)") \
\

View File

@ -961,7 +961,8 @@ void ciEnv::register_method(ciMethod* target,
AbstractCompiler* compiler,
int comp_level,
bool has_unsafe_access,
bool has_wide_vectors) {
bool has_wide_vectors,
RTMState rtm_state) {
VM_ENTRY_MARK;
nmethod* nm = NULL;
{
@ -1002,6 +1003,15 @@ void ciEnv::register_method(ciMethod* target,
methodHandle method(THREAD, target->get_Method());
#if INCLUDE_RTM_OPT
if (!failing() && (rtm_state != NoRTM) &&
(method()->method_data() != NULL) &&
(method()->method_data()->rtm_state() != rtm_state)) {
// Preemptive decompile if rtm state was changed.
record_failure("RTM state change invalidated rtm code");
}
#endif
if (failing()) {
// While not a true deoptimization, it is a preemptive decompile.
MethodData* mdo = method()->method_data();
@ -1028,13 +1038,15 @@ void ciEnv::register_method(ciMethod* target,
frame_words, oop_map_set,
handler_table, inc_table,
compiler, comp_level);
// Free codeBlobs
code_buffer->free_blob();
if (nm != NULL) {
nm->set_has_unsafe_access(has_unsafe_access);
nm->set_has_wide_vectors(has_wide_vectors);
#if INCLUDE_RTM_OPT
nm->set_rtm_state(rtm_state);
#endif
// Record successful registration.
// (Put nm into the task handle *before* publishing to the Java heap.)

View File

@ -365,7 +365,8 @@ public:
AbstractCompiler* compiler,
int comp_level,
bool has_unsafe_access,
bool has_wide_vectors);
bool has_wide_vectors,
RTMState rtm_state = NoRTM);
// Access to certain well known ciObjects.

View File

@ -478,6 +478,18 @@ public:
int invocation_count() { return _invocation_counter; }
int backedge_count() { return _backedge_counter; }
#if INCLUDE_RTM_OPT
// return cached value
int rtm_state() {
if (is_empty()) {
return NoRTM;
} else {
return get_MethodData()->rtm_state();
}
}
#endif
// Transfer information about the method to MethodData*.
// would_profile means we would like to profile this method,
// meaning it's not trivial.

View File

@ -460,7 +460,9 @@ void nmethod::init_defaults() {
_scavenge_root_link = NULL;
_scavenge_root_state = 0;
_compiler = NULL;
#if INCLUDE_RTM_OPT
_rtm_state = NoRTM;
#endif
#ifdef HAVE_DTRACE_H
_trap_offset = 0;
#endif // def HAVE_DTRACE_H

View File

@ -193,6 +193,12 @@ class nmethod : public CodeBlob {
jbyte _scavenge_root_state;
#if INCLUDE_RTM_OPT
// RTM state at compile time. Used during deoptimization to decide
// whether to restart collecting RTM locking abort statistic again.
RTMState _rtm_state;
#endif
// Nmethod Flushing lock. If non-zero, then the nmethod is not removed
// and is not made into a zombie. However, once the nmethod is made into
// a zombie, it will be locked one final time if CompiledMethodUnload
@ -414,6 +420,12 @@ class nmethod : public CodeBlob {
bool is_zombie() const { return _state == zombie; }
bool is_unloaded() const { return _state == unloaded; }
#if INCLUDE_RTM_OPT
// rtm state accessing and manipulating
RTMState rtm_state() const { return _rtm_state; }
void set_rtm_state(RTMState state) { _rtm_state = state; }
#endif
// Make the nmethod non entrant. The nmethod will continue to be
// alive. It is used when an uncommon trap happens. Returns true
// if this thread changed the state of the nmethod or false if

View File

@ -793,53 +793,6 @@ void CompactibleFreeListSpace::oop_iterate(ExtendedOopClosure* cl) {
}
}
// Apply the given closure to each oop in the space \intersect memory region.
void CompactibleFreeListSpace::oop_iterate(MemRegion mr, ExtendedOopClosure* cl) {
assert_lock_strong(freelistLock());
if (is_empty()) {
return;
}
MemRegion cur = MemRegion(bottom(), end());
mr = mr.intersection(cur);
if (mr.is_empty()) {
return;
}
if (mr.equals(cur)) {
oop_iterate(cl);
return;
}
assert(mr.end() <= end(), "just took an intersection above");
HeapWord* obj_addr = block_start(mr.start());
HeapWord* t = mr.end();
SpaceMemRegionOopsIterClosure smr_blk(cl, mr);
if (block_is_obj(obj_addr)) {
// Handle first object specially.
oop obj = oop(obj_addr);
obj_addr += adjustObjectSize(obj->oop_iterate(&smr_blk));
} else {
FreeChunk* fc = (FreeChunk*)obj_addr;
obj_addr += fc->size();
}
while (obj_addr < t) {
HeapWord* obj = obj_addr;
obj_addr += block_size(obj_addr);
// If "obj_addr" is not greater than top, then the
// entire object "obj" is within the region.
if (obj_addr <= t) {
if (block_is_obj(obj)) {
oop(obj)->oop_iterate(cl);
}
} else {
// "obj" extends beyond end of region
if (block_is_obj(obj)) {
oop(obj)->oop_iterate(&smr_blk);
}
break;
}
}
}
// NOTE: In the following methods, in order to safely be able to
// apply the closure to an object, we need to be sure that the
// object has been initialized. We are guaranteed that an object

View File

@ -351,7 +351,6 @@ class CompactibleFreeListSpace: public CompactibleSpace {
Mutex* freelistLock() const { return &_freelistLock; }
// Iteration support
void oop_iterate(MemRegion mr, ExtendedOopClosure* cl);
void oop_iterate(ExtendedOopClosure* cl);
void object_iterate(ObjectClosure* blk);

View File

@ -3163,16 +3163,6 @@ ConcurrentMarkSweepGeneration::younger_refs_iterate(OopsInGenClosure* cl) {
cl->reset_generation();
}
void
ConcurrentMarkSweepGeneration::oop_iterate(MemRegion mr, ExtendedOopClosure* cl) {
if (freelistLock()->owned_by_self()) {
Generation::oop_iterate(mr, cl);
} else {
MutexLockerEx x(freelistLock(), Mutex::_no_safepoint_check_flag);
Generation::oop_iterate(mr, cl);
}
}
void
ConcurrentMarkSweepGeneration::oop_iterate(ExtendedOopClosure* cl) {
if (freelistLock()->owned_by_self()) {

View File

@ -1285,7 +1285,6 @@ class ConcurrentMarkSweepGeneration: public CardGeneration {
void save_sweep_limit();
// More iteration support
virtual void oop_iterate(MemRegion mr, ExtendedOopClosure* cl);
virtual void oop_iterate(ExtendedOopClosure* cl);
virtual void safe_object_iterate(ObjectClosure* cl);
virtual void object_iterate(ObjectClosure* cl);

View File

@ -2018,8 +2018,8 @@ void ConcurrentMark::cleanup() {
// that calculated by walking the marking bitmap.
// Bitmaps to hold expected values
BitMap expected_region_bm(_region_bm.size(), false);
BitMap expected_card_bm(_card_bm.size(), false);
BitMap expected_region_bm(_region_bm.size(), true);
BitMap expected_card_bm(_card_bm.size(), true);
G1ParVerifyFinalCountTask g1_par_verify_task(g1h,
&_region_bm,

View File

@ -550,7 +550,8 @@ bool PSScavenge::invoke_no_policy() {
if (PrintTenuringDistribution) {
gclog_or_tty->cr();
gclog_or_tty->print_cr("Desired survivor size " SIZE_FORMAT " bytes, new threshold %u (max %u)",
gclog_or_tty->print_cr("Desired survivor size " SIZE_FORMAT " bytes, new threshold "
UINTX_FORMAT " (max threshold " UINTX_FORMAT ")",
size_policy->calculated_survivor_size_in_bytes(),
_tenuring_threshold, MaxTenuringThreshold);
}
@ -829,10 +830,10 @@ GCTaskManager* const PSScavenge::gc_task_manager() {
void PSScavenge::initialize() {
// Arguments must have been parsed
if (AlwaysTenure) {
_tenuring_threshold = 0;
} else if (NeverTenure) {
_tenuring_threshold = markOopDesc::max_age + 1;
if (AlwaysTenure || NeverTenure) {
assert(MaxTenuringThreshold == 0 || MaxTenuringThreshold == markOopDesc::max_age + 1,
err_msg("MaxTenuringThreshold should be 0 or markOopDesc::max_age + 1, but is ", MaxTenuringThreshold));
_tenuring_threshold = MaxTenuringThreshold;
} else {
// We want to smooth out our startup times for the AdaptiveSizePolicy
_tenuring_threshold = (UseAdaptiveSizePolicy) ? InitialTenuringThreshold :

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2014, 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
@ -80,28 +80,37 @@ void ageTable::merge_par(ageTable* subTable) {
uint ageTable::compute_tenuring_threshold(size_t survivor_capacity) {
size_t desired_survivor_size = (size_t)((((double) survivor_capacity)*TargetSurvivorRatio)/100);
size_t total = 0;
uint age = 1;
assert(sizes[0] == 0, "no objects with age zero should be recorded");
while (age < table_size) {
total += sizes[age];
// check if including objects of age 'age' made us pass the desired
// size, if so 'age' is the new threshold
if (total > desired_survivor_size) break;
age++;
uint result;
if (AlwaysTenure || NeverTenure) {
assert(MaxTenuringThreshold == 0 || MaxTenuringThreshold == markOopDesc::max_age + 1,
err_msg("MaxTenuringThreshold should be 0 or markOopDesc::max_age + 1, but is ", MaxTenuringThreshold));
result = MaxTenuringThreshold;
} else {
size_t total = 0;
uint age = 1;
assert(sizes[0] == 0, "no objects with age zero should be recorded");
while (age < table_size) {
total += sizes[age];
// check if including objects of age 'age' made us pass the desired
// size, if so 'age' is the new threshold
if (total > desired_survivor_size) break;
age++;
}
result = age < MaxTenuringThreshold ? age : MaxTenuringThreshold;
}
uint result = age < MaxTenuringThreshold ? age : MaxTenuringThreshold;
if (PrintTenuringDistribution || UsePerfData) {
if (PrintTenuringDistribution) {
gclog_or_tty->cr();
gclog_or_tty->print_cr("Desired survivor size " SIZE_FORMAT " bytes, new threshold %u (max %u)",
gclog_or_tty->print_cr("Desired survivor size " SIZE_FORMAT " bytes, new threshold "
UINTX_FORMAT " (max threshold " UINTX_FORMAT ")",
desired_survivor_size*oopSize, result, MaxTenuringThreshold);
}
total = 0;
age = 1;
size_t total = 0;
uint age = 1;
while (age < table_size) {
total += sizes[age];
if (sizes[age] > 0) {

View File

@ -837,12 +837,6 @@ void GenCollectedHeap::oop_iterate(ExtendedOopClosure* cl) {
}
}
void GenCollectedHeap::oop_iterate(MemRegion mr, ExtendedOopClosure* cl) {
for (int i = 0; i < _n_gens; i++) {
_gens[i]->oop_iterate(mr, cl);
}
}
void GenCollectedHeap::object_iterate(ObjectClosure* cl) {
for (int i = 0; i < _n_gens; i++) {
_gens[i]->object_iterate(cl);

View File

@ -212,7 +212,6 @@ public:
// Iteration functions.
void oop_iterate(ExtendedOopClosure* cl);
void oop_iterate(MemRegion mr, ExtendedOopClosure* cl);
void object_iterate(ObjectClosure* cl);
void safe_object_iterate(ObjectClosure* cl);
Space* space_containing(const void* addr) const;

View File

@ -295,22 +295,16 @@ bool Generation::block_is_obj(const HeapWord* p) const {
class GenerationOopIterateClosure : public SpaceClosure {
public:
ExtendedOopClosure* cl;
MemRegion mr;
ExtendedOopClosure* _cl;
virtual void do_space(Space* s) {
s->oop_iterate(mr, cl);
s->oop_iterate(_cl);
}
GenerationOopIterateClosure(ExtendedOopClosure* _cl, MemRegion _mr) :
cl(_cl), mr(_mr) {}
GenerationOopIterateClosure(ExtendedOopClosure* cl) :
_cl(cl) {}
};
void Generation::oop_iterate(ExtendedOopClosure* cl) {
GenerationOopIterateClosure blk(cl, _reserved);
space_iterate(&blk);
}
void Generation::oop_iterate(MemRegion mr, ExtendedOopClosure* cl) {
GenerationOopIterateClosure blk(cl, mr);
GenerationOopIterateClosure blk(cl);
space_iterate(&blk);
}

View File

@ -543,10 +543,6 @@ class Generation: public CHeapObj<mtGC> {
// generation, calling "cl.do_oop" on each.
virtual void oop_iterate(ExtendedOopClosure* cl);
// Same as above, restricted to the intersection of a memory region and
// the generation.
virtual void oop_iterate(MemRegion mr, ExtendedOopClosure* cl);
// Iterate over all objects in the generation, calling "cl.do_object" on
// each.
virtual void object_iterate(ObjectClosure* cl);

View File

@ -3343,37 +3343,22 @@ size_t Metaspace::capacity_bytes_slow(MetadataType mdtype) const {
}
void Metaspace::deallocate(MetaWord* ptr, size_t word_size, bool is_class) {
if (SafepointSynchronize::is_at_safepoint()) {
assert(Thread::current()->is_VM_thread(), "should be the VM thread");
// Don't take Heap_lock
MutexLockerEx ml(vsm()->lock(), Mutex::_no_safepoint_check_flag);
if (word_size < TreeChunk<Metablock, FreeList<Metablock> >::min_size()) {
// Dark matter. Too small for dictionary.
#ifdef ASSERT
Copy::fill_to_words((HeapWord*)ptr, word_size, 0xf5f5f5f5);
#endif
return;
}
if (is_class && using_class_space()) {
class_vsm()->deallocate(ptr, word_size);
} else {
vsm()->deallocate(ptr, word_size);
}
} else {
MutexLockerEx ml(vsm()->lock(), Mutex::_no_safepoint_check_flag);
assert(!SafepointSynchronize::is_at_safepoint()
|| Thread::current()->is_VM_thread(), "should be the VM thread");
if (word_size < TreeChunk<Metablock, FreeList<Metablock> >::min_size()) {
// Dark matter. Too small for dictionary.
MutexLockerEx ml(vsm()->lock(), Mutex::_no_safepoint_check_flag);
if (word_size < TreeChunk<Metablock, FreeList<Metablock> >::min_size()) {
// Dark matter. Too small for dictionary.
#ifdef ASSERT
Copy::fill_to_words((HeapWord*)ptr, word_size, 0xf5f5f5f5);
Copy::fill_to_words((HeapWord*)ptr, word_size, 0xf5f5f5f5);
#endif
return;
}
if (is_class && using_class_space()) {
class_vsm()->deallocate(ptr, word_size);
} else {
vsm()->deallocate(ptr, word_size);
}
return;
}
if (is_class && using_class_space()) {
class_vsm()->deallocate(ptr, word_size);
} else {
vsm()->deallocate(ptr, word_size);
}
}

View File

@ -163,9 +163,6 @@ public:
// Iteration functions.
void oop_iterate(ExtendedOopClosure* cl) = 0;
// Same as above, restricted to a memory region.
virtual void oop_iterate(MemRegion mr, ExtendedOopClosure* cl) = 0;
// Iterate over all spaces in use in the heap, in an undefined order.
virtual void space_iterate(SpaceClosure* cl) = 0;

View File

@ -42,9 +42,6 @@
#include "utilities/globalDefinitions.hpp"
#include "utilities/macros.hpp"
void SpaceMemRegionOopsIterClosure::do_oop(oop* p) { SpaceMemRegionOopsIterClosure::do_oop_work(p); }
void SpaceMemRegionOopsIterClosure::do_oop(narrowOop* p) { SpaceMemRegionOopsIterClosure::do_oop_work(p); }
HeapWord* DirtyCardToOopClosure::get_actual_top(HeapWord* top,
HeapWord* top_obj) {
if (top_obj != NULL) {
@ -686,43 +683,6 @@ void ContiguousSpace::oop_iterate(ExtendedOopClosure* blk) {
}
}
void ContiguousSpace::oop_iterate(MemRegion mr, ExtendedOopClosure* blk) {
if (is_empty()) {
return;
}
MemRegion cur = MemRegion(bottom(), top());
mr = mr.intersection(cur);
if (mr.is_empty()) {
return;
}
if (mr.equals(cur)) {
oop_iterate(blk);
return;
}
assert(mr.end() <= top(), "just took an intersection above");
HeapWord* obj_addr = block_start(mr.start());
HeapWord* t = mr.end();
// Handle first object specially.
oop obj = oop(obj_addr);
SpaceMemRegionOopsIterClosure smr_blk(blk, mr);
obj_addr += obj->oop_iterate(&smr_blk);
while (obj_addr < t) {
oop obj = oop(obj_addr);
assert(obj->is_oop(), "expected an oop");
obj_addr += obj->size();
// If "obj_addr" is not greater than top, then the
// entire object "obj" is within the region.
if (obj_addr <= t) {
obj->oop_iterate(blk);
} else {
// "obj" extends beyond end of region
obj->oop_iterate(&smr_blk);
break;
}
};
}
void ContiguousSpace::object_iterate(ObjectClosure* blk) {
if (is_empty()) return;
WaterMark bm = bottom_mark();

View File

@ -81,31 +81,6 @@ class GenRemSet;
class CardTableRS;
class DirtyCardToOopClosure;
// An oop closure that is circumscribed by a filtering memory region.
class SpaceMemRegionOopsIterClosure: public ExtendedOopClosure {
private:
ExtendedOopClosure* _cl;
MemRegion _mr;
protected:
template <class T> void do_oop_work(T* p) {
if (_mr.contains(p)) {
_cl->do_oop(p);
}
}
public:
SpaceMemRegionOopsIterClosure(ExtendedOopClosure* cl, MemRegion mr):
_cl(cl), _mr(mr) {}
virtual void do_oop(oop* p);
virtual void do_oop(narrowOop* p);
virtual bool do_metadata() {
// _cl is of type ExtendedOopClosure instead of OopClosure, so that we can check this.
assert(!_cl->do_metadata(), "I've checked all call paths, this shouldn't happen.");
return false;
}
virtual void do_klass(Klass* k) { ShouldNotReachHere(); }
virtual void do_class_loader_data(ClassLoaderData* cld) { ShouldNotReachHere(); }
};
// A Space describes a heap area. Class Space is an abstract
// base class.
//
@ -221,11 +196,6 @@ class Space: public CHeapObj<mtGC> {
// applications of the closure are not included in the iteration.
virtual void oop_iterate(ExtendedOopClosure* cl);
// Same as above, restricted to the intersection of a memory region and
// the space. Fields in objects allocated by applications of the closure
// are not included in the iteration.
virtual void oop_iterate(MemRegion mr, ExtendedOopClosure* cl) = 0;
// Iterate over all objects in the space, calling "cl.do_object" on
// each. Objects allocated by applications of the closure are not
// included in the iteration.
@ -866,7 +836,6 @@ class ContiguousSpace: public CompactibleSpace {
// Iteration
void oop_iterate(ExtendedOopClosure* cl);
void oop_iterate(MemRegion mr, ExtendedOopClosure* cl);
void object_iterate(ObjectClosure* blk);
// For contiguous spaces this method will iterate safely over objects
// in the space (i.e., between bottom and top) when at a safepoint.

View File

@ -273,7 +273,7 @@ int Method::validate_bci_from_bcx(intptr_t bcx) const {
}
address Method::bcp_from(int bci) const {
assert((is_native() && bci == 0) || (!is_native() && 0 <= bci && bci < code_size()), "illegal bci");
assert((is_native() && bci == 0) || (!is_native() && 0 <= bci && bci < code_size()), err_msg("illegal bci: %d", bci));
address bcp = code_base() + bci;
assert(is_native() && bcp == code_base() || contains(bcp), "bcp doesn't belong to this method");
return bcp;

View File

@ -24,6 +24,7 @@
#include "precompiled.hpp"
#include "classfile/systemDictionary.hpp"
#include "compiler/compilerOracle.hpp"
#include "interpreter/bytecode.hpp"
#include "interpreter/bytecodeStream.hpp"
#include "interpreter/linkResolver.hpp"
@ -1153,6 +1154,21 @@ void MethodData::init() {
_highest_osr_comp_level = 0;
_would_profile = true;
#if INCLUDE_RTM_OPT
_rtm_state = NoRTM; // No RTM lock eliding by default
if (UseRTMLocking &&
!CompilerOracle::has_option_string(_method, "NoRTMLockEliding")) {
if (CompilerOracle::has_option_string(_method, "UseRTMLockEliding") || !UseRTMDeopt) {
// Generate RTM lock eliding code without abort ratio calculation code.
_rtm_state = UseRTM;
} else if (UseRTMDeopt) {
// Generate RTM lock eliding code and include abort ratio calculation
// code if UseRTMDeopt is on.
_rtm_state = ProfileRTM;
}
}
#endif
// Initialize flags and trap history.
_nof_decompiles = 0;
_nof_overflow_recompiles = 0;

View File

@ -2052,7 +2052,7 @@ public:
// Whole-method sticky bits and flags
enum {
_trap_hist_limit = 18, // decoupled from Deoptimization::Reason_LIMIT
_trap_hist_limit = 19, // decoupled from Deoptimization::Reason_LIMIT
_trap_hist_mask = max_jubyte,
_extra_data_count = 4 // extra DataLayout headers, for trap history
}; // Public flag values
@ -2083,6 +2083,12 @@ private:
// Counter values at the time profiling started.
int _invocation_counter_start;
int _backedge_counter_start;
#if INCLUDE_RTM_OPT
// State of RTM code generation during compilation of the method
int _rtm_state;
#endif
// Number of loops and blocks is computed when compiling the first
// time with C1. It is used to determine if method is trivial.
short _num_loops;
@ -2246,6 +2252,22 @@ public:
InvocationCounter* invocation_counter() { return &_invocation_counter; }
InvocationCounter* backedge_counter() { return &_backedge_counter; }
#if INCLUDE_RTM_OPT
int rtm_state() const {
return _rtm_state;
}
void set_rtm_state(RTMState rstate) {
_rtm_state = (int)rstate;
}
void atomic_set_rtm_state(RTMState rstate) {
Atomic::store((int)rstate, &_rtm_state);
}
static int rtm_state_offset_in_bytes() {
return offset_of(MethodData, _rtm_state);
}
#endif
void set_would_profile(bool p) { _would_profile = p; }
bool would_profile() const { return _would_profile; }

View File

@ -446,6 +446,9 @@
diagnostic(bool, PrintPreciseBiasedLockingStatistics, false, \
"Print per-lock-site statistics of biased locking in JVM") \
\
diagnostic(bool, PrintPreciseRTMLockingStatistics, false, \
"Print per-lock-site statistics of rtm locking in JVM") \
\
notproduct(bool, PrintEliminateLocks, false, \
"Print out when locks are eliminated") \
\

View File

@ -198,6 +198,7 @@ macro(NegF)
macro(NeverBranch)
macro(Opaque1)
macro(Opaque2)
macro(Opaque3)
macro(OrI)
macro(OrL)
macro(OverflowAddI)

View File

@ -694,9 +694,10 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr
set_print_inlining(PrintInlining || method()->has_option("PrintInlining") NOT_PRODUCT( || PrintOptoInlining));
set_print_intrinsics(PrintIntrinsics || method()->has_option("PrintIntrinsics"));
if (ProfileTraps) {
if (ProfileTraps RTM_OPT_ONLY( || UseRTMLocking )) {
// Make sure the method being compiled gets its own MDO,
// so we can at least track the decompile_count().
// Need MDO to record RTM code generation state.
method()->ensure_method_data();
}
@ -907,7 +908,8 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr
compiler,
env()->comp_level(),
has_unsafe_access(),
SharedRuntime::is_wide_vector(max_vector_size())
SharedRuntime::is_wide_vector(max_vector_size()),
rtm_state()
);
if (log() != NULL) // Print code cache state into compiler log
@ -1073,7 +1075,23 @@ void Compile::Init(int aliaslevel) {
set_do_scheduling(OptoScheduling);
set_do_count_invocations(false);
set_do_method_data_update(false);
set_rtm_state(NoRTM); // No RTM lock eliding by default
#if INCLUDE_RTM_OPT
if (UseRTMLocking && has_method() && (method()->method_data_or_null() != NULL)) {
int rtm_state = method()->method_data()->rtm_state();
if (method_has_option("NoRTMLockEliding") || ((rtm_state & NoRTM) != 0)) {
// Don't generate RTM lock eliding code.
set_rtm_state(NoRTM);
} else if (method_has_option("UseRTMLockEliding") || ((rtm_state & UseRTM) != 0) || !UseRTMDeopt) {
// Generate RTM lock eliding code without abort ratio calculation code.
set_rtm_state(UseRTM);
} else if (UseRTMDeopt) {
// Generate RTM lock eliding code and include abort ratio calculation
// code if UseRTMDeopt is on.
set_rtm_state(ProfileRTM);
}
}
#endif
if (debug_info()->recording_non_safepoints()) {
set_node_note_array(new(comp_arena()) GrowableArray<Node_Notes*>
(comp_arena(), 8, 0, NULL));
@ -2581,6 +2599,7 @@ void Compile::final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc) {
break;
case Op_Opaque1: // Remove Opaque Nodes before matching
case Op_Opaque2: // Remove Opaque Nodes before matching
case Op_Opaque3:
n->subsume_by(n->in(1), this);
break;
case Op_CallStaticJava:

View File

@ -319,9 +319,9 @@ class Compile : public Phase {
bool _trace_opto_output;
bool _parsed_irreducible_loop; // True if ciTypeFlow detected irreducible loops during parsing
#endif
// JSR 292
bool _has_method_handle_invokes; // True if this method has MethodHandle invokes.
RTMState _rtm_state; // State of Restricted Transactional Memory usage
// Compilation environment.
Arena _comp_arena; // Arena with lifetime equivalent to Compile
@ -591,6 +591,10 @@ class Compile : public Phase {
void set_print_inlining(bool z) { _print_inlining = z; }
bool print_intrinsics() const { return _print_intrinsics; }
void set_print_intrinsics(bool z) { _print_intrinsics = z; }
RTMState rtm_state() const { return _rtm_state; }
void set_rtm_state(RTMState s) { _rtm_state = s; }
bool use_rtm() const { return (_rtm_state & NoRTM) == 0; }
bool profile_rtm() const { return _rtm_state == ProfileRTM; }
// check the CompilerOracle for special behaviours for this compile
bool method_has_option(const char * option) {
return method() != NULL && method()->has_option(option);

View File

@ -642,6 +642,19 @@ public:
virtual const Type *bottom_type() const { return TypeInt::INT; }
};
//------------------------------Opaque3Node------------------------------------
// A node to prevent unwanted optimizations. Will be optimized only during
// macro nodes expansion.
class Opaque3Node : public Opaque2Node {
int _opt; // what optimization it was used for
public:
enum { RTM_OPT };
Opaque3Node(Compile* C, Node *n, int opt) : Opaque2Node(C, n), _opt(opt) {}
virtual int Opcode() const;
bool rtm_opt() const { return (_opt == RTM_OPT); }
};
//----------------------PartialSubtypeCheckNode--------------------------------
// The 2nd slow-half of a subtype check. Scan the subklass's 2ndary superklass
// array for an instance of the superklass. Set a hidden internal cache on a

View File

@ -1125,6 +1125,17 @@ Node* GraphKit::ConvI2L(Node* offset) {
}
return _gvn.transform( new (C) ConvI2LNode(offset));
}
Node* GraphKit::ConvI2UL(Node* offset) {
juint offset_con = (juint) find_int_con(offset, Type::OffsetBot);
if (offset_con != (juint) Type::OffsetBot) {
return longcon((julong) offset_con);
}
Node* conv = _gvn.transform( new (C) ConvI2LNode(offset));
Node* mask = _gvn.transform( ConLNode::make(C, (julong) max_juint) );
return _gvn.transform( new (C) AndLNode(conv, mask) );
}
Node* GraphKit::ConvL2I(Node* offset) {
// short-circuit a common case
jlong offset_con = find_long_con(offset, (jlong)Type::OffsetBot);
@ -3151,10 +3162,14 @@ FastLockNode* GraphKit::shared_lock(Node* obj) {
Node* mem = reset_memory();
FastLockNode * flock = _gvn.transform(new (C) FastLockNode(0, obj, box) )->as_FastLock();
if (PrintPreciseBiasedLockingStatistics) {
if (UseBiasedLocking && PrintPreciseBiasedLockingStatistics) {
// Create the counters for this fast lock.
flock->create_lock_counter(sync_jvms()); // sync_jvms used to get current bci
}
// Create the rtm counters for this fast lock if needed.
flock->create_rtm_lock_counter(sync_jvms()); // sync_jvms used to get current bci
// Add monitor to debug info for the slow path. If we block inside the
// slow path and de-opt, we need the monitor hanging around
map()->push_monitor( flock );

View File

@ -338,6 +338,7 @@ class GraphKit : public Phase {
// Convert between int and long, and size_t.
// (See macros ConvI2X, etc., in type.hpp for ConvI2X, etc.)
Node* ConvI2L(Node* offset);
Node* ConvI2UL(Node* offset);
Node* ConvL2I(Node* offset);
// Find out the klass of an object.
Node* load_object_klass(Node* object);

View File

@ -2600,7 +2600,7 @@ bool LibraryCallKit::inline_unsafe_access(bool is_native_ptr, bool is_store, Bas
case T_ADDRESS:
// Cast to an int type.
p = _gvn.transform(new (C) CastP2XNode(NULL, p));
p = ConvX2L(p);
p = ConvX2UL(p);
break;
default:
fatal(err_msg_res("unexpected type %d: %s", type, type2name(type)));

View File

@ -136,6 +136,8 @@ bool BoxLockNode::is_simple_lock_region(LockNode** unique_lock, Node* obj) {
//-----------------------------hash--------------------------------------------
uint FastLockNode::hash() const { return NO_HASH; }
uint FastLockNode::size_of() const { return sizeof(*this); }
//------------------------------cmp--------------------------------------------
uint FastLockNode::cmp( const Node &n ) const {
return (&n == this); // Always fail except on self
@ -159,6 +161,22 @@ void FastLockNode::create_lock_counter(JVMState* state) {
_counters = blnc->counters();
}
void FastLockNode::create_rtm_lock_counter(JVMState* state) {
#if INCLUDE_RTM_OPT
Compile* C = Compile::current();
if (C->profile_rtm() || (PrintPreciseRTMLockingStatistics && C->use_rtm())) {
RTMLockingNamedCounter* rlnc = (RTMLockingNamedCounter*)
OptoRuntime::new_named_counter(state, NamedCounter::RTMLockingCounter);
_rtm_counters = rlnc->counters();
if (UseRTMForStackLocks) {
rlnc = (RTMLockingNamedCounter*)
OptoRuntime::new_named_counter(state, NamedCounter::RTMLockingCounter);
_stack_rtm_counters = rlnc->counters();
}
}
#endif
}
//=============================================================================
//------------------------------do_monitor_enter-------------------------------
void Parse::do_monitor_enter() {

View File

@ -92,13 +92,17 @@ public:
//------------------------------FastLockNode-----------------------------------
class FastLockNode: public CmpNode {
private:
BiasedLockingCounters* _counters;
BiasedLockingCounters* _counters;
RTMLockingCounters* _rtm_counters; // RTM lock counters for inflated locks
RTMLockingCounters* _stack_rtm_counters; // RTM lock counters for stack locks
public:
FastLockNode(Node *ctrl, Node *oop, Node *box) : CmpNode(oop,box) {
init_req(0,ctrl);
init_class_id(Class_FastLock);
_counters = NULL;
_rtm_counters = NULL;
_stack_rtm_counters = NULL;
}
Node* obj_node() const { return in(1); }
Node* box_node() const { return in(2); }
@ -107,13 +111,17 @@ public:
// FastLock and FastUnlockNode do not hash, we need one for each correspoding
// LockNode/UnLockNode to avoid creating Phi's.
virtual uint hash() const ; // { return NO_HASH; }
virtual uint size_of() const;
virtual uint cmp( const Node &n ) const ; // Always fail, except on self
virtual int Opcode() const;
virtual const Type *Value( PhaseTransform *phase ) const { return TypeInt::CC; }
const Type *sub(const Type *t1, const Type *t2) const { return TypeInt::CC;}
void create_lock_counter(JVMState* s);
BiasedLockingCounters* counters() const { return _counters; }
void create_rtm_lock_counter(JVMState* state);
BiasedLockingCounters* counters() const { return _counters; }
RTMLockingCounters* rtm_counters() const { return _rtm_counters; }
RTMLockingCounters* stack_rtm_counters() const { return _stack_rtm_counters; }
};

View File

@ -617,6 +617,15 @@ bool IdealLoopTree::policy_maximally_unroll( PhaseIdealLoop *phase ) const {
case Op_AryEq: {
return false;
}
#if INCLUDE_RTM_OPT
case Op_FastLock:
case Op_FastUnlock: {
// Don't unroll RTM locking code because it is large.
if (UseRTMLocking) {
return false;
}
}
#endif
} // switch
}
@ -722,6 +731,15 @@ bool IdealLoopTree::policy_unroll( PhaseIdealLoop *phase ) const {
// String intrinsics are large and have loops.
return false;
}
#if INCLUDE_RTM_OPT
case Op_FastLock:
case Op_FastUnlock: {
// Don't unroll RTM locking code because it is large.
if (UseRTMLocking) {
return false;
}
}
#endif
} // switch
}

View File

@ -53,6 +53,7 @@ class MachSpillCopyNode;
class Matcher;
class PhaseRegAlloc;
class RegMask;
class RTMLockingCounters;
class State;
//---------------------------MachOper------------------------------------------
@ -714,8 +715,9 @@ public:
class MachFastLockNode : public MachNode {
virtual uint size_of() const { return sizeof(*this); } // Size is bigger
public:
BiasedLockingCounters* _counters;
BiasedLockingCounters* _counters;
RTMLockingCounters* _rtm_counters; // RTM lock counters for inflated locks
RTMLockingCounters* _stack_rtm_counters; // RTM lock counters for stack locks
MachFastLockNode() : MachNode() {}
};

View File

@ -2439,6 +2439,7 @@ void PhaseMacroExpand::eliminate_macro_nodes() {
}
}
// Next, attempt to eliminate allocations
_has_locks = false;
progress = true;
while (progress) {
progress = false;
@ -2457,11 +2458,13 @@ void PhaseMacroExpand::eliminate_macro_nodes() {
case Node::Class_Lock:
case Node::Class_Unlock:
assert(!n->as_AbstractLock()->is_eliminated(), "sanity");
_has_locks = true;
break;
default:
assert(n->Opcode() == Op_LoopLimit ||
n->Opcode() == Op_Opaque1 ||
n->Opcode() == Op_Opaque2, "unknown node type in macro list");
n->Opcode() == Op_Opaque2 ||
n->Opcode() == Op_Opaque3, "unknown node type in macro list");
}
assert(success == (C->macro_count() < old_macro_count), "elimination reduces macro count");
progress = progress || success;
@ -2502,6 +2505,30 @@ bool PhaseMacroExpand::expand_macro_nodes() {
} else if (n->Opcode() == Op_Opaque1 || n->Opcode() == Op_Opaque2) {
_igvn.replace_node(n, n->in(1));
success = true;
#if INCLUDE_RTM_OPT
} else if ((n->Opcode() == Op_Opaque3) && ((Opaque3Node*)n)->rtm_opt()) {
assert(C->profile_rtm(), "should be used only in rtm deoptimization code");
assert((n->outcnt() == 1) && n->unique_out()->is_Cmp(), "");
Node* cmp = n->unique_out();
#ifdef ASSERT
// Validate graph.
assert((cmp->outcnt() == 1) && cmp->unique_out()->is_Bool(), "");
BoolNode* bol = cmp->unique_out()->as_Bool();
assert((bol->outcnt() == 1) && bol->unique_out()->is_If() &&
(bol->_test._test == BoolTest::ne), "");
IfNode* ifn = bol->unique_out()->as_If();
assert((ifn->outcnt() == 2) &&
ifn->proj_out(1)->is_uncommon_trap_proj(Deoptimization::Reason_rtm_state_change), "");
#endif
Node* repl = n->in(1);
if (!_has_locks) {
// Remove RTM state check if there are no locks in the code.
// Replace input to compare the same value.
repl = (cmp->in(1) == n) ? cmp->in(2) : cmp->in(1);
}
_igvn.replace_node(n, repl);
success = true;
#endif
}
assert(success == (C->macro_count() < old_macro_count), "elimination reduces macro count");
progress = progress || success;

View File

@ -76,6 +76,8 @@ private:
ProjNode *_memproj_catchall;
ProjNode *_resproj;
// Additional data collected during macro expansion
bool _has_locks;
void expand_allocate(AllocateNode *alloc);
void expand_allocate_array(AllocateArrayNode *alloc);
@ -118,7 +120,7 @@ private:
Node* length);
public:
PhaseMacroExpand(PhaseIterGVN &igvn) : Phase(Macro_Expand), _igvn(igvn) {
PhaseMacroExpand(PhaseIterGVN &igvn) : Phase(Macro_Expand), _igvn(igvn), _has_locks(false) {
_igvn.set_delay_transform(true);
}
void eliminate_macro_nodes();

View File

@ -42,18 +42,12 @@
#include "runtime/handles.inline.hpp"
#include "utilities/xmlstream.hpp"
extern uint size_exception_handler();
extern uint size_deopt_handler();
#ifndef PRODUCT
#define DEBUG_ARG(x) , x
#else
#define DEBUG_ARG(x)
#endif
extern int emit_exception_handler(CodeBuffer &cbuf);
extern int emit_deopt_handler(CodeBuffer &cbuf);
// Convert Nodes to instruction bits and pass off to the VM
void Compile::Output() {
// RootNode goes
@ -394,6 +388,11 @@ void Compile::shorten_branches(uint* blk_starts, int& code_size, int& reloc_size
blk_size += (mach->alignment_required() - 1) * relocInfo::addr_unit(); // assume worst case padding
reloc_size += mach->reloc();
if (mach->is_MachCall()) {
// add size information for trampoline stub
// class CallStubImpl is platform-specific and defined in the *.ad files.
stub_size += CallStubImpl::size_call_trampoline();
reloc_size += CallStubImpl::reloc_call_trampoline();
MachCallNode *mcall = mach->as_MachCall();
// This destination address is NOT PC-relative
@ -1133,10 +1132,9 @@ CodeBuffer* Compile::init_buffer(uint* blk_starts) {
shorten_branches(blk_starts, code_req, locs_req, stub_req);
// nmethod and CodeBuffer count stubs & constants as part of method's code.
int exception_handler_req = size_exception_handler();
int deopt_handler_req = size_deopt_handler();
exception_handler_req += MAX_stubs_size; // add marginal slop for handler
deopt_handler_req += MAX_stubs_size; // add marginal slop for handler
// class HandlerImpl is platform-specific and defined in the *.ad files.
int exception_handler_req = HandlerImpl::size_exception_handler() + MAX_stubs_size; // add marginal slop for handler
int deopt_handler_req = HandlerImpl::size_deopt_handler() + MAX_stubs_size; // add marginal slop for handler
stub_req += MAX_stubs_size; // ensure per-stub margin
code_req += MAX_inst_size; // ensure per-instruction margin
@ -1622,17 +1620,18 @@ void Compile::fill_buffer(CodeBuffer* cb, uint* blk_starts) {
FillExceptionTables(inct_cnt, call_returns, inct_starts, blk_labels);
// Only java methods have exception handlers and deopt handlers
// class HandlerImpl is platform-specific and defined in the *.ad files.
if (_method) {
// Emit the exception handler code.
_code_offsets.set_value(CodeOffsets::Exceptions, emit_exception_handler(*cb));
_code_offsets.set_value(CodeOffsets::Exceptions, HandlerImpl::emit_exception_handler(*cb));
// Emit the deopt handler code.
_code_offsets.set_value(CodeOffsets::Deopt, emit_deopt_handler(*cb));
_code_offsets.set_value(CodeOffsets::Deopt, HandlerImpl::emit_deopt_handler(*cb));
// Emit the MethodHandle deopt handler code (if required).
if (has_method_handle_invokes()) {
// We can use the same code as for the normal deopt handler, we
// just need a different entry point address.
_code_offsets.set_value(CodeOffsets::DeoptMH, emit_deopt_handler(*cb));
_code_offsets.set_value(CodeOffsets::DeoptMH, HandlerImpl::emit_deopt_handler(*cb));
}
}

View File

@ -486,6 +486,8 @@ class Parse : public GraphKit {
// Helper function to compute array addressing
Node* array_addressing(BasicType type, int vals, const Type* *result2=NULL);
void rtm_deopt();
// Pass current map to exits
void return_current(Node* value);

View File

@ -567,6 +567,10 @@ Parse::Parse(JVMState* caller, ciMethod* parse_method, float expected_uses, Pars
set_map(entry_map);
do_method_entry();
}
if (depth() == 1) {
// Add check to deoptimize the nmethod if RTM state was changed
rtm_deopt();
}
// Check for bailouts during method entry.
if (failing()) {
@ -2006,6 +2010,42 @@ void Parse::call_register_finalizer() {
set_control( _gvn.transform(result_rgn) );
}
// Add check to deoptimize if RTM state is not ProfileRTM
void Parse::rtm_deopt() {
#if INCLUDE_RTM_OPT
if (C->profile_rtm()) {
assert(C->method() != NULL, "only for normal compilations");
assert(!C->method()->method_data()->is_empty(), "MDO is needed to record RTM state");
assert(depth() == 1, "generate check only for main compiled method");
// Set starting bci for uncommon trap.
set_parse_bci(is_osr_parse() ? osr_bci() : 0);
// Load the rtm_state from the MethodData.
const TypePtr* adr_type = TypeMetadataPtr::make(C->method()->method_data());
Node* mdo = makecon(adr_type);
int offset = MethodData::rtm_state_offset_in_bytes();
Node* adr_node = basic_plus_adr(mdo, mdo, offset);
Node* rtm_state = make_load(control(), adr_node, TypeInt::INT, T_INT, adr_type, MemNode::unordered);
// Separate Load from Cmp by Opaque.
// In expand_macro_nodes() it will be replaced either
// with this load when there are locks in the code
// or with ProfileRTM (cmp->in(2)) otherwise so that
// the check will fold.
Node* profile_state = makecon(TypeInt::make(ProfileRTM));
Node* opq = _gvn.transform( new (C) Opaque3Node(C, rtm_state, Opaque3Node::RTM_OPT) );
Node* chk = _gvn.transform( new (C) CmpINode(opq, profile_state) );
Node* tst = _gvn.transform( new (C) BoolNode(chk, BoolTest::eq) );
// Branch to failure if state was changed
{ BuildCutout unless(this, tst, PROB_ALWAYS);
uncommon_trap(Deoptimization::Reason_rtm_state_change,
Deoptimization::Action_make_not_entrant);
}
}
#endif
}
//------------------------------return_current---------------------------------
// Append current _map to _exit_return
void Parse::return_current(Node* value) {

View File

@ -1310,6 +1310,14 @@ void OptoRuntime::print_named_counters() {
tty->print_cr("%s", c->name());
blc->print_on(tty);
}
#if INCLUDE_RTM_OPT
} else if (c->tag() == NamedCounter::RTMLockingCounter) {
RTMLockingCounters* rlc = ((RTMLockingNamedCounter*)c)->counters();
if (rlc->nonzero()) {
tty->print_cr("%s", c->name());
rlc->print_on(tty);
}
#endif
}
c = c->next();
}
@ -1349,6 +1357,8 @@ NamedCounter* OptoRuntime::new_named_counter(JVMState* youngest_jvms, NamedCount
NamedCounter* c;
if (tag == NamedCounter::BiasedLockingCounter) {
c = new BiasedLockingNamedCounter(strdup(st.as_string()));
} else if (tag == NamedCounter::RTMLockingCounter) {
c = new RTMLockingNamedCounter(strdup(st.as_string()));
} else {
c = new NamedCounter(strdup(st.as_string()), tag);
}
@ -1357,6 +1367,7 @@ NamedCounter* OptoRuntime::new_named_counter(JVMState* youngest_jvms, NamedCount
// add counters so this is safe.
NamedCounter* head;
do {
c->set_next(NULL);
head = _named_counters;
c->set_next(head);
} while (Atomic::cmpxchg_ptr(c, &_named_counters, head) != head);

View File

@ -29,6 +29,7 @@
#include "opto/machnode.hpp"
#include "opto/type.hpp"
#include "runtime/biasedLocking.hpp"
#include "runtime/rtmLocking.hpp"
#include "runtime/deoptimization.hpp"
#include "runtime/vframe.hpp"
@ -61,7 +62,8 @@ public:
NoTag,
LockCounter,
EliminatedLockCounter,
BiasedLockingCounter
BiasedLockingCounter,
RTMLockingCounter
};
private:
@ -85,7 +87,7 @@ private:
NamedCounter* next() const { return _next; }
void set_next(NamedCounter* next) {
assert(_next == NULL, "already set");
assert(_next == NULL || next == NULL, "already set");
_next = next;
}
@ -102,6 +104,18 @@ class BiasedLockingNamedCounter : public NamedCounter {
BiasedLockingCounters* counters() { return &_counters; }
};
class RTMLockingNamedCounter : public NamedCounter {
private:
RTMLockingCounters _counters;
public:
RTMLockingNamedCounter(const char *n) :
NamedCounter(n, RTMLockingCounter), _counters() {}
RTMLockingCounters* counters() { return &_counters; }
};
typedef const TypeFunc*(*TypeFunc_generator)();
class OptoRuntime : public AllStatic {

View File

@ -4380,7 +4380,7 @@ const Type *TypeMetadataPtr::xmeet( const Type *t ) const {
// else fall through:
case TopPTR:
case AnyNull: {
return make(ptr, NULL, offset);
return make(ptr, _metadata, offset);
}
case BotPTR:
case NotNull:

View File

@ -1716,6 +1716,7 @@ inline bool Type::is_ptr_to_boxing_obj() const {
#define ConvL2X(x) (x)
#define ConvX2I(x) ConvL2I(x)
#define ConvX2L(x) (x)
#define ConvX2UL(x) (x)
#else
@ -1760,6 +1761,7 @@ inline bool Type::is_ptr_to_boxing_obj() const {
#define ConvL2X(x) ConvL2I(x)
#define ConvX2I(x) (x)
#define ConvX2L(x) ConvI2L(x)
#define ConvX2UL(x) ConvI2UL(x)
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2014, 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
@ -500,6 +500,54 @@ WB_ENTRY(void, WB_ReadReservedMemory(JNIEnv* env, jobject o))
c = *p;
WB_END
WB_ENTRY(jstring, WB_GetCPUFeatures(JNIEnv* env, jobject o))
const char* cpu_features = VM_Version::cpu_features();
ThreadToNativeFromVM ttn(thread);
jstring features_string = env->NewStringUTF(cpu_features);
CHECK_JNI_EXCEPTION_(env, NULL);
return features_string;
WB_END
WB_ENTRY(jobjectArray, WB_GetNMethod(JNIEnv* env, jobject o, jobject method, jboolean is_osr))
ResourceMark rm(THREAD);
jmethodID jmid = reflected_method_to_jmid(thread, env, method);
CHECK_JNI_EXCEPTION_(env, NULL);
methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
nmethod* code = is_osr ? mh->lookup_osr_nmethod_for(InvocationEntryBci, CompLevel_none, false) : mh->code();
jobjectArray result = NULL;
if (code == NULL) {
return result;
}
int insts_size = code->insts_size();
ThreadToNativeFromVM ttn(thread);
jclass clazz = env->FindClass(vmSymbols::java_lang_Object()->as_C_string());
CHECK_JNI_EXCEPTION_(env, NULL);
result = env->NewObjectArray(2, clazz, NULL);
if (result == NULL) {
return result;
}
clazz = env->FindClass(vmSymbols::java_lang_Integer()->as_C_string());
CHECK_JNI_EXCEPTION_(env, NULL);
jmethodID constructor = env->GetMethodID(clazz, vmSymbols::object_initializer_name()->as_C_string(), vmSymbols::int_void_signature()->as_C_string());
CHECK_JNI_EXCEPTION_(env, NULL);
jobject obj = env->NewObject(clazz, constructor, code->comp_level());
CHECK_JNI_EXCEPTION_(env, NULL);
env->SetObjectArrayElement(result, 0, obj);
jbyteArray insts = env->NewByteArray(insts_size);
CHECK_JNI_EXCEPTION_(env, NULL);
env->SetByteArrayRegion(insts, 0, insts_size, (jbyte*) code->insts_begin());
env->SetObjectArrayElement(result, 1, insts);
return result;
WB_END
//Some convenience methods to deal with objects from java
int WhiteBox::offset_for_field(const char* field_name, oop object,
Symbol* signature_symbol) {
@ -611,6 +659,9 @@ static JNINativeMethod methods[] = {
{CC"isInStringTable", CC"(Ljava/lang/String;)Z", (void*)&WB_IsInStringTable },
{CC"fullGC", CC"()V", (void*)&WB_FullGC },
{CC"readReservedMemory", CC"()V", (void*)&WB_ReadReservedMemory },
{CC"getCPUFeatures", CC"()Ljava/lang/String;", (void*)&WB_GetCPUFeatures },
{CC"getNMethod", CC"(Ljava/lang/reflect/Executable;Z)[Ljava/lang/Object;",
(void*)&WB_GetNMethod },
};
#undef CC

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2014, 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
@ -40,7 +40,6 @@
do { \
JavaThread* THREAD = JavaThread::thread_from_jni_environment(env); \
if (HAS_PENDING_EXCEPTION) { \
CLEAR_PENDING_EXCEPTION; \
return(value); \
} \
} while (0)
@ -49,7 +48,6 @@
do { \
JavaThread* THREAD = JavaThread::thread_from_jni_environment(env); \
if (HAS_PENDING_EXCEPTION) { \
CLEAR_PENDING_EXCEPTION; \
return; \
} \
} while (0)

View File

@ -301,6 +301,7 @@ static ObsoleteFlag obsolete_jvm_flags[] = {
{ "UseMPSS", JDK_Version::jdk(8), JDK_Version::jdk(9) },
{ "UseStringCache", JDK_Version::jdk(8), JDK_Version::jdk(9) },
{ "UseOldInlining", JDK_Version::jdk(9), JDK_Version::jdk(10) },
{ "SafepointPollOffset", JDK_Version::jdk(9), JDK_Version::jdk(10) },
#ifdef PRODUCT
{ "DesiredMethodLimit",
JDK_Version::jdk_update(7, 2), JDK_Version::jdk(8) },
@ -1186,11 +1187,6 @@ void Arguments::set_parnew_gc_flags() {
FLAG_SET_DEFAULT(OldPLABSize, (intx)1024);
}
// AlwaysTenure flag should make ParNew promote all at first collection.
// See CR 6362902.
if (AlwaysTenure) {
FLAG_SET_CMDLINE(uintx, MaxTenuringThreshold, 0);
}
// When using compressed oops, we use local overflow stacks,
// rather than using a global overflow list chained through
// the klass word of the object's pre-image.
@ -2343,10 +2339,8 @@ bool Arguments::check_vm_args_consistency() {
status = status && verify_percentage(YoungGenerationSizeSupplement, "YoungGenerationSizeSupplement");
status = status && verify_percentage(TenuredGenerationSizeSupplement, "TenuredGenerationSizeSupplement");
// the "age" field in the oop header is 4 bits; do not want to pull in markOop.hpp
// just for that, so hardcode here.
status = status && verify_interval(MaxTenuringThreshold, 0, 15, "MaxTenuringThreshold");
status = status && verify_interval(InitialTenuringThreshold, 0, MaxTenuringThreshold, "MaxTenuringThreshold");
status = status && verify_interval(MaxTenuringThreshold, 0, markOopDesc::max_age + 1, "MaxTenuringThreshold");
status = status && verify_interval(InitialTenuringThreshold, 0, MaxTenuringThreshold, "InitialTenuringThreshold");
status = status && verify_percentage(TargetSurvivorRatio, "TargetSurvivorRatio");
status = status && verify_percentage(MarkSweepDeadRatio, "MarkSweepDeadRatio");
@ -3072,14 +3066,31 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args,
// but disallow DR and offlining (5008695).
FLAG_SET_CMDLINE(bool, BindGCTaskThreadsToCPUs, true);
// Need to keep consistency of MaxTenuringThreshold and AlwaysTenure/NeverTenure;
// and the last option wins.
} else if (match_option(option, "-XX:+NeverTenure", &tail)) {
// The last option must always win.
FLAG_SET_CMDLINE(bool, AlwaysTenure, false);
FLAG_SET_CMDLINE(bool, NeverTenure, true);
FLAG_SET_CMDLINE(bool, AlwaysTenure, false);
FLAG_SET_CMDLINE(uintx, MaxTenuringThreshold, markOopDesc::max_age + 1);
} else if (match_option(option, "-XX:+AlwaysTenure", &tail)) {
// The last option must always win.
FLAG_SET_CMDLINE(bool, NeverTenure, false);
FLAG_SET_CMDLINE(bool, AlwaysTenure, true);
FLAG_SET_CMDLINE(uintx, MaxTenuringThreshold, 0);
} else if (match_option(option, "-XX:MaxTenuringThreshold=", &tail)) {
uintx max_tenuring_thresh = 0;
if(!parse_uintx(tail, &max_tenuring_thresh, 0)) {
jio_fprintf(defaultStream::error_stream(),
"Invalid MaxTenuringThreshold: %s\n", option->optionString);
}
FLAG_SET_CMDLINE(uintx, MaxTenuringThreshold, max_tenuring_thresh);
if (MaxTenuringThreshold == 0) {
FLAG_SET_CMDLINE(bool, NeverTenure, false);
FLAG_SET_CMDLINE(bool, AlwaysTenure, true);
} else {
FLAG_SET_CMDLINE(bool, NeverTenure, false);
FLAG_SET_CMDLINE(bool, AlwaysTenure, false);
}
} else if (match_option(option, "-XX:+CMSPermGenSweepingEnabled", &tail) ||
match_option(option, "-XX:-CMSPermGenSweepingEnabled", &tail)) {
jio_fprintf(defaultStream::error_stream(),
@ -3779,9 +3790,6 @@ jint Arguments::apply_ergo() {
#endif // CC_INTERP
#ifdef COMPILER2
if (!UseBiasedLocking || EmitSync != 0) {
UseOptoBiasInlining = false;
}
if (!EliminateLocks) {
EliminateNestedLocks = false;
}
@ -3842,6 +3850,11 @@ jint Arguments::apply_ergo() {
UseBiasedLocking = false;
}
}
#ifdef COMPILER2
if (!UseBiasedLocking || EmitSync != 0) {
UseOptoBiasInlining = false;
}
#endif
return JNI_OK;
}

View File

@ -1288,7 +1288,8 @@ JRT_ENTRY(void, Deoptimization::uncommon_trap_inner(JavaThread* thread, jint tra
gather_statistics(reason, action, trap_bc);
// Ensure that we can record deopt. history:
bool create_if_missing = ProfileTraps;
// Need MDO to record RTM code generation state.
bool create_if_missing = ProfileTraps RTM_OPT_ONLY( || UseRTMLocking );
MethodData* trap_mdo =
get_method_data(thread, trap_method, create_if_missing);
@ -1569,6 +1570,17 @@ JRT_ENTRY(void, Deoptimization::uncommon_trap_inner(JavaThread* thread, jint tra
if (tstate1 != tstate0)
pdata->set_trap_state(tstate1);
}
#if INCLUDE_RTM_OPT
// Restart collecting RTM locking abort statistic if the method
// is recompiled for a reason other than RTM state change.
// Assume that in new recompiled code the statistic could be different,
// for example, due to different inlining.
if ((reason != Reason_rtm_state_change) && (trap_mdo != NULL) &&
UseRTMDeopt && (nm->rtm_state() != ProfileRTM)) {
trap_mdo->atomic_set_rtm_state(ProfileRTM);
}
#endif
}
if (inc_recompile_count) {
@ -1826,7 +1838,8 @@ const char* Deoptimization::_trap_reason_name[Reason_LIMIT] = {
"age",
"predicate",
"loop_limit_check",
"speculate_class_check"
"speculate_class_check",
"rtm_state_change"
};
const char* Deoptimization::_trap_action_name[Action_LIMIT] = {
// Note: Keep this in sync. with enum DeoptAction.

View File

@ -60,6 +60,7 @@ class Deoptimization : AllStatic {
Reason_predicate, // compiler generated predicate failed
Reason_loop_limit_check, // compiler generated loop limits check failed
Reason_speculate_class_check, // saw unexpected object class from type speculation
Reason_rtm_state_change, // rtm state change detected
Reason_LIMIT,
// Note: Keep this enum in sync. with _trap_reason_name.
Reason_RECORDED_LIMIT = Reason_bimorphic // some are not recorded per bc

View File

@ -531,13 +531,16 @@ jint frame::interpreter_frame_expression_stack_size() const {
// Number of elements on the interpreter expression stack
// Callers should span by stackElementWords
int element_size = Interpreter::stackElementWords;
size_t stack_size = 0;
if (frame::interpreter_frame_expression_stack_direction() < 0) {
return (interpreter_frame_expression_stack() -
interpreter_frame_tos_address() + 1)/element_size;
stack_size = (interpreter_frame_expression_stack() -
interpreter_frame_tos_address() + 1)/element_size;
} else {
return (interpreter_frame_tos_address() -
interpreter_frame_expression_stack() + 1)/element_size;
stack_size = (interpreter_frame_tos_address() -
interpreter_frame_expression_stack() + 1)/element_size;
}
assert( stack_size <= (size_t)max_jint, "stack size too big");
return ((jint)stack_size);
}

View File

@ -265,7 +265,7 @@ void print_statistics() {
os::print_statistics();
}
if (PrintLockStatistics || PrintPreciseBiasedLockingStatistics) {
if (PrintLockStatistics || PrintPreciseBiasedLockingStatistics || PrintPreciseRTMLockingStatistics) {
OptoRuntime::print_named_counters();
}
@ -387,7 +387,7 @@ void print_statistics() {
}
#ifdef COMPILER2
if (PrintPreciseBiasedLockingStatistics) {
if (PrintPreciseBiasedLockingStatistics || PrintPreciseRTMLockingStatistics) {
OptoRuntime::print_named_counters();
}
#endif

Some files were not shown because too many files have changed in this diff Show More