This commit is contained in:
Christian Tornqvist 2014-08-12 21:18:14 +00:00
commit 0604ebb2bf
1389 changed files with 37852 additions and 16081 deletions

View File

@ -266,3 +266,5 @@ c5495e25c7258ab5f96a1ae14610887d76d2be63 jdk9-b18
28dd0c7beb3cad9cf95f17b4b5ad87eb447a4084 jdk9-b21
9678e0db8ff6ed845d4c2ee4a3baf7f386a777e5 jdk9-b22
39cfdc2dcaf3f195c55398e4e677ab053b07e3d2 jdk9-b23
d9ce05f36ffec3e5e8af62a92455c1c66a63c320 jdk9-b24
13a5c76976fe48e55c9727c25fae2d2ce7c05da0 jdk9-b25

View File

@ -266,3 +266,5 @@ ee4fd72b2ec3d92497f37163352f294aa695c6fb jdk9-b20
9052803f4d01feda28b3d65f2b64dd457d21c7b6 jdk9-b21
8e4bdab4c362aadde2d321f968cd503a2f779e2f jdk9-b22
88567461a2cd9b7fb431fee6440005a694df1f47 jdk9-b23
1d4a293fbec19dc2d5790bbb2c7dd0ed8f265484 jdk9-b24
aefd8899a8d6615fb34ba99b2e38996a7145baa8 jdk9-b25

View File

@ -4311,7 +4311,7 @@ TOOLCHAIN_DESCRIPTION_xlc="IBM XL C/C++"
#CUSTOM_AUTOCONF_INCLUDE
# Do not change or remove the following line, it is needed for consistency checks:
DATE_WHEN_GENERATED=1404942241
DATE_WHEN_GENERATED=1405336663
###############################################################################
#
@ -14548,7 +14548,7 @@ $as_echo "$with_jvm_variants" >&6; }
if test "x$JVM_VARIANT_ZEROSHARK" = xtrue ; then
INCLUDE_SA=false
fi
if test "x$VAR_CPU" = xppc64 ; then
if test "x$OPENJDK_TARGET_OS" = xaix ; then
INCLUDE_SA=false
fi

View File

@ -158,7 +158,7 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_JVM_VARIANTS],
if test "x$JVM_VARIANT_ZEROSHARK" = xtrue ; then
INCLUDE_SA=false
fi
if test "x$VAR_CPU" = xppc64 ; then
if test "x$OPENJDK_TARGET_OS" = xaix ; then
INCLUDE_SA=false
fi
AC_SUBST(INCLUDE_SA)

View File

@ -266,3 +266,5 @@ eecc1b6adc7e193d00a0641eb0963add5a4c06e8 jdk9-b19
3615a4e7f0542ca7552ad6454b742c73ee211d8e jdk9-b21
ddc07abf4307855c0dc904cc5c96cc764023a930 jdk9-b22
57735d66face054440a63ce99789eac5a5ee1dfd jdk9-b23
8a44142bb7fc8118f70f91a1b97c12dfc50563ee jdk9-b24
da08cca6b97f41b7081a3e176dcb400af6e4bb26 jdk9-b25

View File

@ -426,3 +426,5 @@ c1af79d122ec9f715fa29312b5e91763f3a4dfc4 jdk9-b20
17b4a5e831b398738feedb0afe75245744510153 jdk9-b21
518d1fcc0799494f013e00e0a94a91b6f212d54f jdk9-b22
dd472cdacc32e3afc7c5bfa7ef16ea0e0befb7fa jdk9-b23
dde2d03b0ea46a27650839e3a1d212c7c1f7b4c8 jdk9-b24
6de94e8693240cec8aae11f6b42f43433456a733 jdk9-b25

View File

@ -314,7 +314,7 @@ static void * pathmap_dlopen(const char * name, int mode) {
handle = dlopen(name, mode);
}
if (_libsaproc_debug) {
printf("libsaproc DEBUG: pathmap_dlopen %s return 0x%x\n", name, handle);
printf("libsaproc DEBUG: pathmap_dlopen %s return 0x%lx\n", name, (unsigned long) handle);
}
return handle;
}

View File

@ -119,8 +119,8 @@ ifeq ($(INCLUDE_NMT), false)
CFLAGS += -DINCLUDE_NMT=0
Src_Files_EXCLUDE += \
memBaseline.cpp memPtr.cpp memRecorder.cpp memReporter.cpp memSnapshot.cpp memTrackWorker.cpp \
memTracker.cpp nmtDCmd.cpp
memBaseline.cpp memReporter.cpp mallocTracker.cpp virtualMemoryTracker.cpp nmtCommon.cpp \
memTracker.cpp nmtDCmd.cpp mallocSiteTable.cpp
endif
-include $(HS_ALT_MAKE)/excludeSrc.make

View File

@ -356,14 +356,15 @@ jprt.make.rule.test.targets.standard.internalvmtests = \
${jprt.my.windows.x64}-fastdebug-c2-internalvmtests
jprt.make.rule.test.targets.standard.reg.group = \
${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GROUP, \
${jprt.my.solaris.x64}-{product|fastdebug}-c2-GROUP, \
${jprt.my.linux.i586}-{product|fastdebug}-c2-GROUP, \
${jprt.my.linux.x64}-{product|fastdebug}-c2-GROUP, \
${jprt.my.windows.i586}-{product|fastdebug}-c2-GROUP, \
${jprt.my.windows.x64}-{product|fastdebug}-c2-GROUP, \
${jprt.my.linux.i586}-{product|fastdebug}-c1-GROUP, \
${jprt.my.windows.i586}-{product|fastdebug}-c1-GROUP
${jprt.my.solaris.sparcv9}-fastdebug-c2-GROUP, \
${jprt.my.solaris.x64}-fastdebug-c2-GROUP, \
${jprt.my.linux.i586}-fastdebug-c2-GROUP, \
${jprt.my.linux.x64}-fastdebug-c2-GROUP, \
${jprt.my.macosx.x64}-fastdebug-c2-GROUP, \
${jprt.my.windows.i586}-fastdebug-c2-GROUP, \
${jprt.my.windows.x64}-fastdebug-c2-GROUP, \
${jprt.my.linux.i586}-fastdebug-c1-GROUP, \
${jprt.my.windows.i586}-fastdebug-c1-GROUP
jprt.make.rule.test.targets.standard = \
${jprt.make.rule.test.targets.standard.client}, \

View File

@ -298,6 +298,7 @@ class Assembler : public AbstractAssembler {
LWZ_OPCODE = (32u << OPCODE_SHIFT),
LWZX_OPCODE = (31u << OPCODE_SHIFT | 23u << 1),
LWZU_OPCODE = (33u << OPCODE_SHIFT),
LWBRX_OPCODE = (31u << OPCODE_SHIFT | 534 << 1),
LHA_OPCODE = (42u << OPCODE_SHIFT),
LHAX_OPCODE = (31u << OPCODE_SHIFT | 343u << 1),
@ -306,6 +307,7 @@ class Assembler : public AbstractAssembler {
LHZ_OPCODE = (40u << OPCODE_SHIFT),
LHZX_OPCODE = (31u << OPCODE_SHIFT | 279u << 1),
LHZU_OPCODE = (41u << OPCODE_SHIFT),
LHBRX_OPCODE = (31u << OPCODE_SHIFT | 790 << 1),
LBZ_OPCODE = (34u << OPCODE_SHIFT),
LBZX_OPCODE = (31u << OPCODE_SHIFT | 87u << 1),
@ -1364,11 +1366,17 @@ class Assembler : public AbstractAssembler {
inline void lwax( Register d, Register s1, Register s2);
inline void lwa( Register d, int si16, Register s1);
// 4 bytes reversed
inline void lwbrx( Register d, Register s1, Register s2);
// 2 bytes
inline void lhzx( Register d, Register s1, Register s2);
inline void lhz( Register d, int si16, Register s1);
inline void lhzu( Register d, int si16, Register s1);
// 2 bytes reversed
inline void lhbrx( Register d, Register s1, Register s2);
// 2 bytes
inline void lhax( Register d, Register s1, Register s2);
inline void lha( Register d, int si16, Register s1);
@ -1858,10 +1866,12 @@ class Assembler : public AbstractAssembler {
inline void lwz( Register d, int si16);
inline void lwax( Register d, Register s2);
inline void lwa( Register d, int si16);
inline void lwbrx(Register d, Register s2);
inline void lhzx( Register d, Register s2);
inline void lhz( Register d, int si16);
inline void lhax( Register d, Register s2);
inline void lha( Register d, int si16);
inline void lhbrx(Register d, Register s2);
inline void lbzx( Register d, Register s2);
inline void lbz( Register d, int si16);
inline void ldx( Register d, Register s2);

View File

@ -263,10 +263,14 @@ inline void Assembler::lwzu( Register d, int si16, Register s1) { assert(d !=
inline void Assembler::lwax( Register d, Register s1, Register s2) { emit_int32(LWAX_OPCODE | rt(d) | ra0mem(s1) | rb(s2));}
inline void Assembler::lwa( Register d, int si16, Register s1) { emit_int32(LWA_OPCODE | rt(d) | ds(si16) | ra0mem(s1));}
inline void Assembler::lwbrx( Register d, Register s1, Register s2) { emit_int32(LWBRX_OPCODE | rt(d) | ra0mem(s1) | rb(s2));}
inline void Assembler::lhzx( Register d, Register s1, Register s2) { emit_int32(LHZX_OPCODE | rt(d) | ra0mem(s1) | rb(s2));}
inline void Assembler::lhz( Register d, int si16, Register s1) { emit_int32(LHZ_OPCODE | rt(d) | d1(si16) | ra0mem(s1));}
inline void Assembler::lhzu( Register d, int si16, Register s1) { assert(d != s1, "according to ibm manual"); emit_int32(LHZU_OPCODE | rt(d) | d1(si16) | rta0mem(s1));}
inline void Assembler::lhbrx( Register d, Register s1, Register s2) { emit_int32(LHBRX_OPCODE | rt(d) | ra0mem(s1) | rb(s2));}
inline void Assembler::lhax( Register d, Register s1, Register s2) { emit_int32(LHAX_OPCODE | rt(d) | ra0mem(s1) | rb(s2));}
inline void Assembler::lha( Register d, int si16, Register s1) { emit_int32(LHA_OPCODE | rt(d) | d1(si16) | ra0mem(s1));}
inline void Assembler::lhau( Register d, int si16, Register s1) { assert(d != s1, "according to ibm manual"); emit_int32(LHAU_OPCODE | rt(d) | d1(si16) | rta0mem(s1));}
@ -736,10 +740,12 @@ inline void Assembler::lwzx( Register d, Register s2) { emit_int32( LWZX_OPCODE
inline void Assembler::lwz( Register d, int si16 ) { emit_int32( LWZ_OPCODE | rt(d) | d1(si16));}
inline void Assembler::lwax( Register d, Register s2) { emit_int32( LWAX_OPCODE | rt(d) | rb(s2));}
inline void Assembler::lwa( Register d, int si16 ) { emit_int32( LWA_OPCODE | rt(d) | ds(si16));}
inline void Assembler::lwbrx(Register d, Register s2) { emit_int32( LWBRX_OPCODE| rt(d) | rb(s2));}
inline void Assembler::lhzx( Register d, Register s2) { emit_int32( LHZX_OPCODE | rt(d) | rb(s2));}
inline void Assembler::lhz( Register d, int si16 ) { emit_int32( LHZ_OPCODE | rt(d) | d1(si16));}
inline void Assembler::lhax( Register d, Register s2) { emit_int32( LHAX_OPCODE | rt(d) | rb(s2));}
inline void Assembler::lha( Register d, int si16 ) { emit_int32( LHA_OPCODE | rt(d) | d1(si16));}
inline void Assembler::lhbrx(Register d, Register s2) { emit_int32( LHBRX_OPCODE| rt(d) | rb(s2));}
inline void Assembler::lbzx( Register d, Register s2) { emit_int32( LBZX_OPCODE | rt(d) | rb(s2));}
inline void Assembler::lbz( Register d, int si16 ) { emit_int32( LBZ_OPCODE | rt(d) | d1(si16));}
inline void Assembler::ld( Register d, int si16 ) { emit_int32( LD_OPCODE | rt(d) | ds(si16));}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright 2012, 2013 SAP AG. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@ -26,8 +26,9 @@
#ifndef CPU_PPC_VM_CPPINTERPRETERGENERATOR_PPC_HPP
#define CPU_PPC_VM_CPPINTERPRETERGENERATOR_PPC_HPP
address generate_normal_entry(void);
address generate_native_entry(void);
address generate_normal_entry(bool synchronized);
address generate_native_entry(bool synchronized);
address generate_math_entry(AbstractInterpreter::MethodKind kind) { return NULL; }
void lock_method(void);
void unlock_method(void);

View File

@ -938,8 +938,9 @@ void CppInterpreterGenerator::generate_counter_incr(Label& overflow) {
// Interpreter stub for calling a native method. (C++ interpreter)
// This sets up a somewhat different looking stack for calling the native method
// than the typical interpreter frame setup.
// The synchronized parameter is ignored.
//
address CppInterpreterGenerator::generate_native_entry(void) {
address CppInterpreterGenerator::generate_native_entry(bool synchronized) {
if (native_entry != NULL) return native_entry;
address entry = __ pc();
@ -1729,7 +1730,8 @@ void CppInterpreterGenerator::generate_more_monitors() {
__ std(R0, BasicObjectLock::obj_offset_in_bytes(), stack_base); // Mark lock as unused
}
address CppInterpreterGenerator::generate_normal_entry(void) {
// The synchronized parameter is ignored
address CppInterpreterGenerator::generate_normal_entry(bool synchronized) {
if (interpreter_frame_manager != NULL) return interpreter_frame_manager;
address entry = __ pc();
@ -2789,38 +2791,6 @@ address CppInterpreterGenerator::generate_normal_entry(void) {
return interpreter_frame_manager;
}
// Generate code for various sorts of method entries
//
address AbstractInterpreterGenerator::generate_method_entry(AbstractInterpreter::MethodKind kind) {
address entry_point = NULL;
switch (kind) {
case Interpreter::zerolocals : break;
case Interpreter::zerolocals_synchronized : break;
case Interpreter::native : // Fall thru
case Interpreter::native_synchronized : entry_point = ((CppInterpreterGenerator*)this)->generate_native_entry(); break;
case Interpreter::empty : break;
case Interpreter::accessor : entry_point = ((InterpreterGenerator*)this)->generate_accessor_entry(); break;
case Interpreter::abstract : entry_point = ((InterpreterGenerator*)this)->generate_abstract_entry(); break;
// These are special interpreter intrinsics which we don't support so far.
case Interpreter::java_lang_math_sin : break;
case Interpreter::java_lang_math_cos : break;
case Interpreter::java_lang_math_tan : break;
case Interpreter::java_lang_math_abs : break;
case Interpreter::java_lang_math_log : break;
case Interpreter::java_lang_math_log10 : break;
case Interpreter::java_lang_math_sqrt : break;
case Interpreter::java_lang_math_pow : break;
case Interpreter::java_lang_math_exp : break;
case Interpreter::java_lang_ref_reference_get: entry_point = ((InterpreterGenerator*)this)->generate_Reference_get_entry(); break;
default : ShouldNotReachHere(); break;
}
if (entry_point) {
return entry_point;
}
return ((InterpreterGenerator*)this)->generate_normal_entry();
}
InterpreterGenerator::InterpreterGenerator(StubQueue* code)
: CppInterpreterGenerator(code) {

View File

@ -119,9 +119,15 @@ void InterpreterMacroAssembler::check_and_handle_popframe(Register scratch_reg)
// Call the Interpreter::remove_activation_preserving_args_entry()
// func to get the address of the same-named entrypoint in the
// generated interpreter code.
#if defined(ABI_ELFv2)
call_c(CAST_FROM_FN_PTR(address,
Interpreter::remove_activation_preserving_args_entry),
relocInfo::none);
#else
call_c(CAST_FROM_FN_PTR(FunctionDescriptor*,
Interpreter::remove_activation_preserving_args_entry),
relocInfo::none);
#endif
// Jump to Interpreter::_remove_activation_preserving_args_entry.
mtctr(R3_RET);
@ -331,29 +337,40 @@ void InterpreterMacroAssembler::empty_expression_stack() {
void InterpreterMacroAssembler::get_2_byte_integer_at_bcp(int bcp_offset,
Register Rdst,
signedOrNot is_signed) {
#if defined(VM_LITTLE_ENDIAN)
if (bcp_offset) {
load_const_optimized(Rdst, bcp_offset);
lhbrx(Rdst, R14_bcp, Rdst);
} else {
lhbrx(Rdst, R14_bcp);
}
if (is_signed == Signed) {
extsh(Rdst, Rdst);
}
#else
// Read Java big endian format.
if (is_signed == Signed) {
lha(Rdst, bcp_offset, R14_bcp);
} else {
lhz(Rdst, bcp_offset, R14_bcp);
}
#if 0
assert(Rtmp != Rdst, "need separate temp register");
Register Rfirst = Rtmp;
lbz(Rfirst, bcp_offset, R14_bcp); // first byte
lbz(Rdst, bcp_offset+1, R14_bcp); // second byte
// Rdst = ((Rfirst<<8) & 0xFF00) | (Rdst &~ 0xFF00)
rldimi(/*RA=*/Rdst, /*RS=*/Rfirst, /*sh=*/8, /*mb=*/48);
if (is_signed == Signed) {
extsh(Rdst, Rdst);
}
#endif
}
void InterpreterMacroAssembler::get_4_byte_integer_at_bcp(int bcp_offset,
Register Rdst,
signedOrNot is_signed) {
#if defined(VM_LITTLE_ENDIAN)
if (bcp_offset) {
load_const_optimized(Rdst, bcp_offset);
lwbrx(Rdst, R14_bcp, Rdst);
} else {
lwbrx(Rdst, R14_bcp);
}
if (is_signed == Signed) {
extsw(Rdst, Rdst);
}
#else
// Read Java big endian format.
if (bcp_offset & 3) { // Offset unaligned?
load_const_optimized(Rdst, bcp_offset);
@ -369,18 +386,26 @@ void InterpreterMacroAssembler::get_4_byte_integer_at_bcp(int bcp_offset
lwz(Rdst, bcp_offset, R14_bcp);
}
}
#endif
}
// Load the constant pool cache index from the bytecode stream.
//
// Kills / writes:
// - Rdst, Rscratch
void InterpreterMacroAssembler::get_cache_index_at_bcp(Register Rdst, int bcp_offset, size_t index_size) {
assert(bcp_offset > 0, "bcp is still pointing to start of bytecode");
// Cache index is always in the native format, courtesy of Rewriter.
if (index_size == sizeof(u2)) {
get_2_byte_integer_at_bcp(bcp_offset, Rdst, Unsigned);
lhz(Rdst, bcp_offset, R14_bcp);
} else if (index_size == sizeof(u4)) {
get_4_byte_integer_at_bcp(bcp_offset, Rdst, Signed);
if (bcp_offset & 3) {
load_const_optimized(Rdst, bcp_offset);
lwax(Rdst, R14_bcp, Rdst);
} else {
lwa(Rdst, bcp_offset, R14_bcp);
}
assert(ConstantPool::decode_invokedynamic_index(~123) == 123, "else change next line");
nand(Rdst, Rdst, Rdst); // convert to plain index
} else if (index_size == sizeof(u1)) {
@ -397,6 +422,29 @@ void InterpreterMacroAssembler::get_cache_and_index_at_bcp(Register cache, int b
add(cache, R27_constPoolCache, cache);
}
// Load 4-byte signed or unsigned integer in Java format (that is, big-endian format)
// from (Rsrc)+offset.
void InterpreterMacroAssembler::get_u4(Register Rdst, Register Rsrc, int offset,
signedOrNot is_signed) {
#if defined(VM_LITTLE_ENDIAN)
if (offset) {
load_const_optimized(Rdst, offset);
lwbrx(Rdst, Rdst, Rsrc);
} else {
lwbrx(Rdst, Rsrc);
}
if (is_signed == Signed) {
extsw(Rdst, Rdst);
}
#else
if (is_signed == Signed) {
lwa(Rdst, offset, Rsrc);
} else {
lwz(Rdst, offset, Rsrc);
}
#endif
}
// Load object from cpool->resolved_references(index).
void InterpreterMacroAssembler::load_resolved_reference_at_index(Register result, Register index) {
assert_different_registers(result, index);

View File

@ -130,6 +130,7 @@ class InterpreterMacroAssembler: public MacroAssembler {
void get_cache_and_index_at_bcp(Register cache, int bcp_offset, size_t index_size = sizeof(u2));
void get_u4(Register Rdst, Register Rsrc, int offset, signedOrNot is_signed);
// common code

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright 2012, 2013 SAP AG. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@ -31,7 +31,12 @@
private:
address generate_abstract_entry(void);
address generate_accessor_entry(void);
address generate_jump_to_normal_entry(void);
address generate_accessor_entry(void) { return generate_jump_to_normal_entry(); }
address generate_empty_entry(void) { return generate_jump_to_normal_entry(); }
address generate_Reference_get_entry(void);
// Not supported
address generate_CRC32_update_entry() { return NULL; }
address generate_CRC32_updateBytes_entry(AbstractInterpreter::MethodKind kind) { return NULL; }
#endif // CPU_PPC_VM_INTERPRETERGENERATOR_PPC_HPP

View File

@ -428,6 +428,19 @@ address AbstractInterpreterGenerator::generate_result_handler_for(BasicType type
return entry;
}
// Call an accessor method (assuming it is resolved, otherwise drop into
// vanilla (slow path) entry.
address InterpreterGenerator::generate_jump_to_normal_entry(void) {
address entry = __ pc();
address normal_entry = Interpreter::entry_for_kind(Interpreter::zerolocals);
assert(normal_entry != NULL, "should already be generated.");
__ branch_to_entry(normal_entry, R11_scratch1);
__ flush();
return entry;
}
// Abstract method entry.
//
address InterpreterGenerator::generate_abstract_entry(void) {
@ -485,203 +498,6 @@ address InterpreterGenerator::generate_abstract_entry(void) {
return entry;
}
// Call an accessor method (assuming it is resolved, otherwise drop into
// vanilla (slow path) entry.
address InterpreterGenerator::generate_accessor_entry(void) {
if (!UseFastAccessorMethods && (!FLAG_IS_ERGO(UseFastAccessorMethods))) {
return NULL;
}
Label Lslow_path, Lacquire;
const Register
Rclass_or_obj = R3_ARG1,
Rconst_method = R4_ARG2,
Rcodes = Rconst_method,
Rcpool_cache = R5_ARG3,
Rscratch = R11_scratch1,
Rjvmti_mode = Rscratch,
Roffset = R12_scratch2,
Rflags = R6_ARG4,
Rbtable = R7_ARG5;
static address branch_table[number_of_states];
address entry = __ pc();
// Check for safepoint:
// Ditch this, real man don't need safepoint checks.
// Also check for JVMTI mode
// Check for null obj, take slow path if so.
__ ld(Rclass_or_obj, Interpreter::stackElementSize, CC_INTERP_ONLY(R17_tos) NOT_CC_INTERP(R15_esp));
__ lwz(Rjvmti_mode, thread_(interp_only_mode));
__ cmpdi(CCR1, Rclass_or_obj, 0);
__ cmpwi(CCR0, Rjvmti_mode, 0);
__ crorc(/*CCR0 eq*/2, /*CCR1 eq*/4+2, /*CCR0 eq*/2);
__ beq(CCR0, Lslow_path); // this==null or jvmti_mode!=0
// Do 2 things in parallel:
// 1. Load the index out of the first instruction word, which looks like this:
// <0x2a><0xb4><index (2 byte, native endianess)>.
// 2. Load constant pool cache base.
__ ld(Rconst_method, in_bytes(Method::const_offset()), R19_method);
__ ld(Rcpool_cache, in_bytes(ConstMethod::constants_offset()), Rconst_method);
__ lhz(Rcodes, in_bytes(ConstMethod::codes_offset()) + 2, Rconst_method); // Lower half of 32 bit field.
__ ld(Rcpool_cache, ConstantPool::cache_offset_in_bytes(), Rcpool_cache);
// Get the const pool entry by means of <index>.
const int codes_shift = exact_log2(in_words(ConstantPoolCacheEntry::size()) * BytesPerWord);
__ slwi(Rscratch, Rcodes, codes_shift); // (codes&0xFFFF)<<codes_shift
__ add(Rcpool_cache, Rscratch, Rcpool_cache);
// Check if cpool cache entry is resolved.
// We are resolved if the indices offset contains the current bytecode.
ByteSize cp_base_offset = ConstantPoolCache::base_offset();
// Big Endian:
__ lbz(Rscratch, in_bytes(cp_base_offset) + in_bytes(ConstantPoolCacheEntry::indices_offset()) + 7 - 2, Rcpool_cache);
__ cmpwi(CCR0, Rscratch, Bytecodes::_getfield);
__ bne(CCR0, Lslow_path);
__ isync(); // Order succeeding loads wrt. load of _indices field from cpool_cache.
// Finally, start loading the value: Get cp cache entry into regs.
__ ld(Rflags, in_bytes(cp_base_offset) + in_bytes(ConstantPoolCacheEntry::flags_offset()), Rcpool_cache);
__ ld(Roffset, in_bytes(cp_base_offset) + in_bytes(ConstantPoolCacheEntry::f2_offset()), Rcpool_cache);
// Following code is from templateTable::getfield_or_static
// Load pointer to branch table
__ load_const_optimized(Rbtable, (address)branch_table, Rscratch);
// Get volatile flag
__ rldicl(Rscratch, Rflags, 64-ConstantPoolCacheEntry::is_volatile_shift, 63); // extract volatile bit
// note: sync is needed before volatile load on PPC64
// Check field type
__ rldicl(Rflags, Rflags, 64-ConstantPoolCacheEntry::tos_state_shift, 64-ConstantPoolCacheEntry::tos_state_bits);
#ifdef ASSERT
Label LFlagInvalid;
__ cmpldi(CCR0, Rflags, number_of_states);
__ bge(CCR0, LFlagInvalid);
__ ld(R9_ARG7, 0, R1_SP);
__ ld(R10_ARG8, 0, R21_sender_SP);
__ cmpd(CCR0, R9_ARG7, R10_ARG8);
__ asm_assert_eq("backlink", 0x543);
#endif // ASSERT
__ mr(R1_SP, R21_sender_SP); // Cut the stack back to where the caller started.
// Load from branch table and dispatch (volatile case: one instruction ahead)
__ sldi(Rflags, Rflags, LogBytesPerWord);
__ cmpwi(CCR6, Rscratch, 1); // volatile?
if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
__ sldi(Rscratch, Rscratch, exact_log2(BytesPerInstWord)); // volatile ? size of 1 instruction : 0
}
__ ldx(Rbtable, Rbtable, Rflags);
if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
__ subf(Rbtable, Rscratch, Rbtable); // point to volatile/non-volatile entry point
}
__ mtctr(Rbtable);
__ bctr();
#ifdef ASSERT
__ bind(LFlagInvalid);
__ stop("got invalid flag", 0x6541);
bool all_uninitialized = true,
all_initialized = true;
for (int i = 0; i<number_of_states; ++i) {
all_uninitialized = all_uninitialized && (branch_table[i] == NULL);
all_initialized = all_initialized && (branch_table[i] != NULL);
}
assert(all_uninitialized != all_initialized, "consistency"); // either or
__ fence(); // volatile entry point (one instruction before non-volatile_entry point)
if (branch_table[vtos] == 0) branch_table[vtos] = __ pc(); // non-volatile_entry point
if (branch_table[dtos] == 0) branch_table[dtos] = __ pc(); // non-volatile_entry point
if (branch_table[ftos] == 0) branch_table[ftos] = __ pc(); // non-volatile_entry point
__ stop("unexpected type", 0x6551);
#endif
if (branch_table[itos] == 0) { // generate only once
__ align(32, 28, 28); // align load
__ fence(); // volatile entry point (one instruction before non-volatile_entry point)
branch_table[itos] = __ pc(); // non-volatile_entry point
__ lwax(R3_RET, Rclass_or_obj, Roffset);
__ beq(CCR6, Lacquire);
__ blr();
}
if (branch_table[ltos] == 0) { // generate only once
__ align(32, 28, 28); // align load
__ fence(); // volatile entry point (one instruction before non-volatile_entry point)
branch_table[ltos] = __ pc(); // non-volatile_entry point
__ ldx(R3_RET, Rclass_or_obj, Roffset);
__ beq(CCR6, Lacquire);
__ blr();
}
if (branch_table[btos] == 0) { // generate only once
__ align(32, 28, 28); // align load
__ fence(); // volatile entry point (one instruction before non-volatile_entry point)
branch_table[btos] = __ pc(); // non-volatile_entry point
__ lbzx(R3_RET, Rclass_or_obj, Roffset);
__ extsb(R3_RET, R3_RET);
__ beq(CCR6, Lacquire);
__ blr();
}
if (branch_table[ctos] == 0) { // generate only once
__ align(32, 28, 28); // align load
__ fence(); // volatile entry point (one instruction before non-volatile_entry point)
branch_table[ctos] = __ pc(); // non-volatile_entry point
__ lhzx(R3_RET, Rclass_or_obj, Roffset);
__ beq(CCR6, Lacquire);
__ blr();
}
if (branch_table[stos] == 0) { // generate only once
__ align(32, 28, 28); // align load
__ fence(); // volatile entry point (one instruction before non-volatile_entry point)
branch_table[stos] = __ pc(); // non-volatile_entry point
__ lhax(R3_RET, Rclass_or_obj, Roffset);
__ beq(CCR6, Lacquire);
__ blr();
}
if (branch_table[atos] == 0) { // generate only once
__ align(32, 28, 28); // align load
__ fence(); // volatile entry point (one instruction before non-volatile_entry point)
branch_table[atos] = __ pc(); // non-volatile_entry point
__ load_heap_oop(R3_RET, (RegisterOrConstant)Roffset, Rclass_or_obj);
__ verify_oop(R3_RET);
//__ dcbt(R3_RET); // prefetch
__ beq(CCR6, Lacquire);
__ blr();
}
__ align(32, 12);
__ bind(Lacquire);
__ twi_0(R3_RET);
__ isync(); // acquire
__ blr();
#ifdef ASSERT
for (int i = 0; i<number_of_states; ++i) {
assert(branch_table[i], "accessor_entry initialization");
//tty->print_cr("accessor_entry: branch_table[%d] = 0x%llx (opcode 0x%llx)", i, branch_table[i], *((unsigned int*)branch_table[i]));
}
#endif
__ bind(Lslow_path);
__ branch_to_entry(Interpreter::entry_for_kind(Interpreter::zerolocals), Rscratch);
__ flush();
return entry;
}
// Interpreter intrinsic for WeakReference.get().
// 1. Don't push a full blown frame and go on dispatching, but fetch the value
// into R8 and return quickly
@ -713,7 +529,6 @@ address InterpreterGenerator::generate_Reference_get_entry(void) {
// and so we don't need to call the G1 pre-barrier. Thus we can use the
// regular method entry code to generate the NPE.
//
// This code is based on generate_accessor_enty.
address entry = __ pc();
@ -768,7 +583,7 @@ address InterpreterGenerator::generate_Reference_get_entry(void) {
return entry;
} else {
return generate_accessor_entry();
return generate_jump_to_normal_entry();
}
}

View File

@ -1283,8 +1283,6 @@ int Compile::ConstantTable::calculate_table_base_offset() const {
bool MachConstantBaseNode::requires_postalloc_expand() const { return true; }
void MachConstantBaseNode::postalloc_expand(GrowableArray <Node *> *nodes, PhaseRegAlloc *ra_) {
Compile *C = ra_->C;
iRegPdstOper *op_dst = new iRegPdstOper();
MachNode *m1 = new loadToc_hiNode();
MachNode *m2 = new loadToc_loNode();
@ -2229,7 +2227,7 @@ const bool Matcher::isSimpleConstant64(jlong value) {
}
/* TODO: PPC port
// Make a new machine dependent decode node (with its operands).
MachTypeNode *Matcher::make_decode_node(Compile *C) {
MachTypeNode *Matcher::make_decode_node() {
assert(Universe::narrow_oop_base() == NULL && Universe::narrow_oop_shift() == 0,
"This method is only implemented for unscaled cOops mode so far");
MachTypeNode *decode = new decodeN_unscaledNode();
@ -2593,7 +2591,7 @@ typedef struct {
MachNode *_last;
} loadConLNodesTuple;
loadConLNodesTuple loadConLNodesTuple_create(Compile *C, PhaseRegAlloc *ra_, Node *toc, immLOper *immSrc,
loadConLNodesTuple loadConLNodesTuple_create(PhaseRegAlloc *ra_, Node *toc, immLOper *immSrc,
OptoReg::Name reg_second, OptoReg::Name reg_first) {
loadConLNodesTuple nodes;
@ -2669,7 +2667,7 @@ encode %{
enc_class postalloc_expand_load_long_constant(iRegLdst dst, immL src, iRegLdst toc) %{
// Create new nodes.
loadConLNodesTuple loadConLNodes =
loadConLNodesTuple_create(C, ra_, n_toc, op_src,
loadConLNodesTuple_create(ra_, n_toc, op_src,
ra_->get_reg_second(this), ra_->get_reg_first(this));
// Push new nodes.
@ -3391,7 +3389,7 @@ encode %{
immLOper *op_repl = new immLOper((jlong)replicate_immF(op_src->constantF()));
loadConLNodesTuple loadConLNodes =
loadConLNodesTuple_create(C, ra_, n_toc, op_repl,
loadConLNodesTuple_create(ra_, n_toc, op_repl,
ra_->get_reg_second(this), ra_->get_reg_first(this));
// Push new nodes.
@ -3611,7 +3609,7 @@ encode %{
// Create the nodes for loading the IC from the TOC.
loadConLNodesTuple loadConLNodes_IC =
loadConLNodesTuple_create(C, ra_, n_toc, new immLOper((jlong)Universe::non_oop_word()),
loadConLNodesTuple_create(ra_, n_toc, new immLOper((jlong)Universe::non_oop_word()),
OptoReg::Name(R19_H_num), OptoReg::Name(R19_num));
// Create the call node.
@ -3765,7 +3763,7 @@ encode %{
#if defined(ABI_ELFv2)
jlong entry_address = (jlong) this->entry_point();
assert(entry_address, "need address here");
loadConLNodes_Entry = loadConLNodesTuple_create(C, ra_, n_toc, new immLOper(entry_address),
loadConLNodes_Entry = loadConLNodesTuple_create(ra_, n_toc, new immLOper(entry_address),
OptoReg::Name(R12_H_num), OptoReg::Name(R12_num));
#else
// Get the struct that describes the function we are about to call.
@ -3777,13 +3775,13 @@ encode %{
loadConLNodesTuple loadConLNodes_Toc;
// Create nodes and operands for loading the entry point.
loadConLNodes_Entry = loadConLNodesTuple_create(C, ra_, n_toc, new immLOper(entry_address),
loadConLNodes_Entry = loadConLNodesTuple_create(ra_, n_toc, new immLOper(entry_address),
OptoReg::Name(R12_H_num), OptoReg::Name(R12_num));
// Create nodes and operands for loading the env pointer.
if (fd->env() != NULL) {
loadConLNodes_Env = loadConLNodesTuple_create(C, ra_, n_toc, new immLOper((jlong) fd->env()),
loadConLNodes_Env = loadConLNodesTuple_create(ra_, n_toc, new immLOper((jlong) fd->env()),
OptoReg::Name(R11_H_num), OptoReg::Name(R11_num));
} else {
loadConLNodes_Env._large_hi = NULL;
@ -3796,7 +3794,7 @@ encode %{
}
// Create nodes and operands for loading the Toc point.
loadConLNodes_Toc = loadConLNodesTuple_create(C, ra_, n_toc, new immLOper((jlong) fd->toc()),
loadConLNodes_Toc = loadConLNodesTuple_create(ra_, n_toc, new immLOper((jlong) fd->toc()),
OptoReg::Name(R2_H_num), OptoReg::Name(R2_num));
#endif // ABI_ELFv2
// mtctr node

View File

@ -30,7 +30,6 @@
address generate_normal_entry(bool synchronized);
address generate_native_entry(bool synchronized);
address generate_math_entry(AbstractInterpreter::MethodKind kind);
address generate_empty_entry(void);
void lock_method(Register Rflags, Register Rscratch1, Register Rscratch2, bool flags_preloaded=false);
void unlock_method(bool check_exceptions = true);

View File

@ -176,8 +176,12 @@ address TemplateInterpreterGenerator::generate_return_entry_for(TosState state,
const Register size = R12_scratch2;
__ get_cache_and_index_at_bcp(cache, 1, index_size);
// Big Endian (get least significant byte of 64 bit value):
// Get least significant byte of 64 bit value:
#if defined(VM_LITTLE_ENDIAN)
__ lbz(size, in_bytes(ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::flags_offset()), cache);
#else
__ lbz(size, in_bytes(ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::flags_offset()) + 7, cache);
#endif
__ sldi(size, size, Interpreter::logStackElementSize);
__ add(R15_esp, R15_esp, size);
__ dispatch_next(state, step);
@ -598,48 +602,6 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call, Regist
// End of helpers
// ============================================================================
// Various method entries
//
// Empty method, generate a very fast return. We must skip this entry if
// someone's debugging, indicated by the flag
// "interp_mode" in the Thread obj.
// Note: empty methods are generated mostly methods that do assertions, which are
// disabled in the "java opt build".
address TemplateInterpreterGenerator::generate_empty_entry(void) {
if (!UseFastEmptyMethods) {
NOT_PRODUCT(__ should_not_reach_here();)
return Interpreter::entry_for_kind(Interpreter::zerolocals);
}
Label Lslow_path;
const Register Rjvmti_mode = R11_scratch1;
address entry = __ pc();
__ lwz(Rjvmti_mode, thread_(interp_only_mode));
__ cmpwi(CCR0, Rjvmti_mode, 0);
__ bne(CCR0, Lslow_path); // jvmti_mode!=0
// Noone's debuggin: Simply return.
// Pop c2i arguments (if any) off when we return.
#ifdef ASSERT
__ ld(R9_ARG7, 0, R1_SP);
__ ld(R10_ARG8, 0, R21_sender_SP);
__ cmpd(CCR0, R9_ARG7, R10_ARG8);
__ asm_assert_eq("backlink", 0x545);
#endif // ASSERT
__ mr(R1_SP, R21_sender_SP); // Cut the stack back to where the caller started.
// And we're done.
__ blr();
__ bind(Lslow_path);
__ branch_to_entry(Interpreter::entry_for_kind(Interpreter::zerolocals), R11_scratch1);
__ flush();
return entry;
}
// Support abs and sqrt like in compiler.
// For others we can use a normal (native) entry.
@ -858,7 +820,9 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) {
// Our signature handlers copy required arguments to the C stack
// (outgoing C args), R3_ARG1 to R10_ARG8, and FARG1 to FARG13.
__ mr(R3_ARG1, R18_locals);
#if !defined(ABI_ELFv2)
__ ld(signature_handler_fd, 0, signature_handler_fd);
#endif
__ call_stub(signature_handler_fd);
@ -1020,8 +984,13 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) {
// native result across the call. No oop is present.
__ mr(R3_ARG1, R16_thread);
#if defined(ABI_ELFv2)
__ call_c(CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans),
relocInfo::none);
#else
__ call_c(CAST_FROM_FN_PTR(FunctionDescriptor*, JavaThread::check_special_condition_for_native_trans),
relocInfo::none);
#endif
__ bind(sync_check_done);
@ -1278,45 +1247,6 @@ address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized) {
return entry;
}
// =============================================================================
// Entry points
address AbstractInterpreterGenerator::generate_method_entry(
AbstractInterpreter::MethodKind kind) {
// Determine code generation flags.
bool synchronized = false;
address entry_point = NULL;
switch (kind) {
case Interpreter::zerolocals : break;
case Interpreter::zerolocals_synchronized: synchronized = true; break;
case Interpreter::native : entry_point = ((InterpreterGenerator*) this)->generate_native_entry(false); break;
case Interpreter::native_synchronized : entry_point = ((InterpreterGenerator*) this)->generate_native_entry(true); break;
case Interpreter::empty : entry_point = ((InterpreterGenerator*) this)->generate_empty_entry(); break;
case Interpreter::accessor : entry_point = ((InterpreterGenerator*) this)->generate_accessor_entry(); break;
case Interpreter::abstract : entry_point = ((InterpreterGenerator*) this)->generate_abstract_entry(); break;
case Interpreter::java_lang_math_sin : // fall thru
case Interpreter::java_lang_math_cos : // fall thru
case Interpreter::java_lang_math_tan : // fall thru
case Interpreter::java_lang_math_abs : // fall thru
case Interpreter::java_lang_math_log : // fall thru
case Interpreter::java_lang_math_log10 : // fall thru
case Interpreter::java_lang_math_sqrt : // fall thru
case Interpreter::java_lang_math_pow : // fall thru
case Interpreter::java_lang_math_exp : entry_point = ((InterpreterGenerator*) this)->generate_math_entry(kind); break;
case Interpreter::java_lang_ref_reference_get
: entry_point = ((InterpreterGenerator*)this)->generate_Reference_get_entry(); break;
default : ShouldNotReachHere(); break;
}
if (entry_point) {
return entry_point;
}
return ((InterpreterGenerator*) this)->generate_normal_entry(synchronized);
}
// These should never be compiled since the interpreter will prefer
// the compiled version to the intrinsic version.
bool AbstractInterpreter::can_be_compiled(methodHandle m) {
@ -1344,7 +1274,7 @@ int AbstractInterpreter::size_activation(int max_stack,
int callee_locals,
bool is_top_frame) {
// Note: This calculation must exactly parallel the frame setup
// in AbstractInterpreterGenerator::generate_method_entry.
// in InterpreterGenerator::generate_fixed_frame.
assert(Interpreter::stackElementWords == 1, "sanity");
const int max_alignment_space = StackAlignmentInBytes / Interpreter::stackElementSize;
const int abi_scratch = is_top_frame ? (frame::abi_reg_args_size / Interpreter::stackElementSize) :

View File

@ -189,8 +189,12 @@ void TemplateTable::patch_bytecode(Bytecodes::Code new_bc, Register Rnew_bc, Reg
assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range");
assert(load_bc_into_bc_reg, "we use bc_reg as temp");
__ get_cache_and_index_at_bcp(Rtemp /* dst = cache */, 1);
// Big Endian: ((*(cache+indices))>>((1+byte_no)*8))&0xFF
// ((*(cache+indices))>>((1+byte_no)*8))&0xFF:
#if defined(VM_LITTLE_ENDIAN)
__ lbz(Rnew_bc, in_bytes(ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::indices_offset()) + 1 + byte_no, Rtemp);
#else
__ lbz(Rnew_bc, in_bytes(ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::indices_offset()) + 7 - (1 + byte_no), Rtemp);
#endif
__ cmpwi(CCR0, Rnew_bc, 0);
__ li(Rnew_bc, (unsigned int)(unsigned char)new_bc);
__ beq(CCR0, L_patch_done);
@ -1839,8 +1843,8 @@ void TemplateTable::tableswitch() {
__ clrrdi(Rdef_offset_addr, Rdef_offset_addr, log2_long((jlong)BytesPerInt));
// Load lo & hi.
__ lwz(Rlow_byte, BytesPerInt, Rdef_offset_addr);
__ lwz(Rhigh_byte, BytesPerInt * 2, Rdef_offset_addr);
__ get_u4(Rlow_byte, Rdef_offset_addr, BytesPerInt, InterpreterMacroAssembler::Unsigned);
__ get_u4(Rhigh_byte, Rdef_offset_addr, 2 *BytesPerInt, InterpreterMacroAssembler::Unsigned);
// Check for default case (=index outside [low,high]).
__ cmpw(CCR0, R17_tos, Rlow_byte);
@ -1854,12 +1858,17 @@ void TemplateTable::tableswitch() {
__ profile_switch_case(Rindex, Rhigh_byte /* scratch */, Rscratch1, Rscratch2);
__ sldi(Rindex, Rindex, LogBytesPerInt);
__ addi(Rindex, Rindex, 3 * BytesPerInt);
#if defined(VM_LITTLE_ENDIAN)
__ lwbrx(Roffset, Rdef_offset_addr, Rindex);
__ extsw(Roffset, Roffset);
#else
__ lwax(Roffset, Rdef_offset_addr, Rindex);
#endif
__ b(Ldispatch);
__ bind(Ldefault_case);
__ profile_switch_default(Rhigh_byte, Rscratch1);
__ lwa(Roffset, 0, Rdef_offset_addr);
__ get_u4(Roffset, Rdef_offset_addr, 0, InterpreterMacroAssembler::Signed);
__ bind(Ldispatch);
@ -1875,12 +1884,11 @@ void TemplateTable::lookupswitch() {
// Table switch using linear search through cases.
// Bytecode stream format:
// Bytecode (1) | 4-byte padding | default offset (4) | count (4) | value/offset pair1 (8) | value/offset pair2 (8) | ...
// Note: Everything is big-endian format here. So on little endian machines, we have to revers offset and count and cmp value.
// Note: Everything is big-endian format here.
void TemplateTable::fast_linearswitch() {
transition(itos, vtos);
Label Lloop_entry, Lsearch_loop, Lfound, Lcontinue_execution, Ldefault_case;
Label Lloop_entry, Lsearch_loop, Lcontinue_execution, Ldefault_case;
Register Rcount = R3_ARG1,
Rcurrent_pair = R4_ARG2,
Rdef_offset_addr = R5_ARG3, // Is going to contain address of default offset.
@ -1894,47 +1902,40 @@ void TemplateTable::fast_linearswitch() {
__ clrrdi(Rdef_offset_addr, Rdef_offset_addr, log2_long((jlong)BytesPerInt));
// Setup loop counter and limit.
__ lwz(Rcount, BytesPerInt, Rdef_offset_addr); // Load count.
__ get_u4(Rcount, Rdef_offset_addr, BytesPerInt, InterpreterMacroAssembler::Unsigned);
__ addi(Rcurrent_pair, Rdef_offset_addr, 2 * BytesPerInt); // Rcurrent_pair now points to first pair.
// Set up search loop.
__ cmpwi(CCR0, Rcount, 0);
__ beq(CCR0, Ldefault_case);
__ mtctr(Rcount);
__ cmpwi(CCR0, Rcount, 0);
__ bne(CCR0, Lloop_entry);
// linear table search
__ bind(Lsearch_loop);
__ lwz(Rvalue, 0, Rcurrent_pair);
__ lwa(Roffset, 1 * BytesPerInt, Rcurrent_pair);
__ cmpw(CCR0, Rvalue, Rcmp_value);
__ beq(CCR0, Lfound);
__ addi(Rcurrent_pair, Rcurrent_pair, 2 * BytesPerInt);
__ bdnz(Lsearch_loop);
// default case
// Default case
__ bind(Ldefault_case);
__ lwa(Roffset, 0, Rdef_offset_addr);
__ get_u4(Roffset, Rdef_offset_addr, 0, InterpreterMacroAssembler::Signed);
if (ProfileInterpreter) {
__ profile_switch_default(Rdef_offset_addr, Rcount/* scratch */);
__ b(Lcontinue_execution);
}
__ b(Lcontinue_execution);
// Next iteration
__ bind(Lsearch_loop);
__ bdz(Ldefault_case);
__ addi(Rcurrent_pair, Rcurrent_pair, 2 * BytesPerInt);
__ bind(Lloop_entry);
__ get_u4(Rvalue, Rcurrent_pair, 0, InterpreterMacroAssembler::Unsigned);
__ cmpw(CCR0, Rvalue, Rcmp_value);
__ bne(CCR0, Lsearch_loop);
// Found, load offset.
__ get_u4(Roffset, Rcurrent_pair, BytesPerInt, InterpreterMacroAssembler::Signed);
// Calculate case index and profile
__ mfctr(Rcurrent_pair);
if (ProfileInterpreter) {
__ sub(Rcurrent_pair, Rcount, Rcurrent_pair);
__ profile_switch_case(Rcurrent_pair, Rcount /*scratch*/, Rdef_offset_addr/*scratch*/, Rscratch);
}
// Entry found, skip Roffset bytecodes and continue.
__ bind(Lfound);
if (ProfileInterpreter) {
// Calc the num of the pair we hit. Careful, Rcurrent_pair points 2 ints
// beyond the actual current pair due to the auto update load above!
__ sub(Rcurrent_pair, Rcurrent_pair, Rdef_offset_addr);
__ addi(Rcurrent_pair, Rcurrent_pair, - 2 * BytesPerInt);
__ srdi(Rcurrent_pair, Rcurrent_pair, LogBytesPerInt + 1);
__ profile_switch_case(Rcurrent_pair, Rcount /*scratch*/, Rdef_offset_addr/*scratch*/, Rscratch);
__ bind(Lcontinue_execution);
}
__ bind(Lcontinue_execution);
__ add(R14_bcp, Roffset, R14_bcp);
__ dispatch_next(vtos);
}
@ -1990,7 +1991,7 @@ void TemplateTable::fast_binaryswitch() {
// initialize i & j
__ li(Ri,0);
__ lwz(Rj, -BytesPerInt, Rarray);
__ get_u4(Rj, Rarray, -BytesPerInt, InterpreterMacroAssembler::Unsigned);
// and start.
Label entry;
@ -2007,7 +2008,11 @@ void TemplateTable::fast_binaryswitch() {
// i = h;
// }
__ sldi(Rscratch, Rh, log_entry_size);
#if defined(VM_LITTLE_ENDIAN)
__ lwbrx(Rscratch, Rscratch, Rarray);
#else
__ lwzx(Rscratch, Rscratch, Rarray);
#endif
// if (key < current value)
// Rh = Rj
@ -2039,20 +2044,20 @@ void TemplateTable::fast_binaryswitch() {
// Ri = value offset
__ sldi(Ri, Ri, log_entry_size);
__ add(Ri, Ri, Rarray);
__ lwz(Rscratch, 0, Ri);
__ get_u4(Rscratch, Ri, 0, InterpreterMacroAssembler::Unsigned);
Label not_found;
// Ri = offset offset
__ cmpw(CCR0, Rkey, Rscratch);
__ beq(CCR0, not_found);
// entry not found -> j = default offset
__ lwz(Rj, -2 * BytesPerInt, Rarray);
__ get_u4(Rj, Rarray, -2 * BytesPerInt, InterpreterMacroAssembler::Unsigned);
__ b(default_case);
__ bind(not_found);
// entry found -> j = offset
__ profile_switch_case(Rh, Rj, Rscratch, Rkey);
__ lwz(Rj, BytesPerInt, Ri);
__ get_u4(Rj, Ri, BytesPerInt, InterpreterMacroAssembler::Unsigned);
if (ProfileInterpreter) {
__ b(continue_execution);
@ -2147,8 +2152,11 @@ void TemplateTable::resolve_cache_and_index(int byte_no, Register Rcache, Regist
assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range");
// We are resolved if the indices offset contains the current bytecode.
// Big Endian:
#if defined(VM_LITTLE_ENDIAN)
__ lbz(Rscratch, in_bytes(ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::indices_offset()) + byte_no + 1, Rcache);
#else
__ lbz(Rscratch, in_bytes(ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::indices_offset()) + 7 - (byte_no + 1), Rcache);
#endif
// Acquire by cmp-br-isync (see below).
__ cmpdi(CCR0, Rscratch, (int)bytecode());
__ beq(CCR0, Lresolved);

View File

@ -29,6 +29,7 @@
#include "compiler/disassembler.hpp"
#include "memory/resourceArea.hpp"
#include "runtime/java.hpp"
#include "runtime/os.hpp"
#include "runtime/stubCodeGenerator.hpp"
#include "utilities/defaultStream.hpp"
#include "vm_version_ppc.hpp"
@ -108,7 +109,7 @@ void VM_Version::initialize() {
(has_vand() ? " vand" : "")
// Make sure number of %s matches num_features!
);
_features_str = strdup(buf);
_features_str = os::strdup(buf);
NOT_PRODUCT(if (Verbose) print_features(););
// PPC64 supports 8-byte compare-exchange operations (see

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2007, 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
@ -29,6 +29,7 @@
#include "interpreter/interpreter.hpp"
#include "interpreter/interpreterGenerator.hpp"
#include "interpreter/interpreterRuntime.hpp"
#include "interpreter/interp_masm.hpp"
#include "oops/arrayOop.hpp"
#include "oops/methodData.hpp"
#include "oops/method.hpp"
@ -68,9 +69,7 @@ bool CppInterpreter::contains(address pc) {
#define STATE(field_name) Lstate, in_bytes(byte_offset_of(BytecodeInterpreter, field_name))
#define __ _masm->
Label frame_manager_entry;
Label fast_accessor_slow_entry_path; // fast accessor methods need to be able to jmp to unsynchronized
// c++ interpreter entry point this holds that entry point label.
Label frame_manager_entry; // c++ interpreter entry point this holds that entry point label.
static address unctrap_frame_manager_entry = NULL;
@ -452,110 +451,6 @@ address InterpreterGenerator::generate_empty_entry(void) {
return NULL;
}
// Call an accessor method (assuming it is resolved, otherwise drop into
// vanilla (slow path) entry
// Generates code to elide accessor methods
// Uses G3_scratch and G1_scratch as scratch
address InterpreterGenerator::generate_accessor_entry(void) {
// Code: _aload_0, _(i|a)getfield, _(i|a)return or any rewrites thereof;
// parameter size = 1
// Note: We can only use this code if the getfield has been resolved
// and if we don't have a null-pointer exception => check for
// these conditions first and use slow path if necessary.
address entry = __ pc();
Label slow_path;
if ( UseFastAccessorMethods) {
// Check if we need to reach a safepoint and generate full interpreter
// frame if so.
AddressLiteral sync_state(SafepointSynchronize::address_of_state());
__ load_contents(sync_state, G3_scratch);
__ cmp(G3_scratch, SafepointSynchronize::_not_synchronized);
__ br(Assembler::notEqual, false, Assembler::pn, slow_path);
__ delayed()->nop();
// Check if local 0 != NULL
__ ld_ptr(Gargs, G0, Otos_i ); // get local 0
__ tst(Otos_i); // check if local 0 == NULL and go the slow path
__ brx(Assembler::zero, false, Assembler::pn, slow_path);
__ delayed()->nop();
// read first instruction word and extract bytecode @ 1 and index @ 2
// get first 4 bytes of the bytecodes (big endian!)
__ ld_ptr(Address(G5_method, in_bytes(Method::const_offset())), G1_scratch);
__ ld(Address(G1_scratch, in_bytes(ConstMethod::codes_offset())), G1_scratch);
// move index @ 2 far left then to the right most two bytes.
__ sll(G1_scratch, 2*BitsPerByte, G1_scratch);
__ srl(G1_scratch, 2*BitsPerByte - exact_log2(in_words(
ConstantPoolCacheEntry::size()) * BytesPerWord), G1_scratch);
// get constant pool cache
__ ld_ptr(G5_method, in_bytes(Method::const_offset()), G3_scratch);
__ ld_ptr(G3_scratch, in_bytes(ConstMethod::constants_offset()), G3_scratch);
__ ld_ptr(G3_scratch, ConstantPool::cache_offset_in_bytes(), G3_scratch);
// get specific constant pool cache entry
__ add(G3_scratch, G1_scratch, G3_scratch);
// Check the constant Pool cache entry to see if it has been resolved.
// If not, need the slow path.
ByteSize cp_base_offset = ConstantPoolCache::base_offset();
__ ld_ptr(G3_scratch, in_bytes(cp_base_offset + ConstantPoolCacheEntry::indices_offset()), G1_scratch);
__ srl(G1_scratch, 2*BitsPerByte, G1_scratch);
__ and3(G1_scratch, 0xFF, G1_scratch);
__ cmp(G1_scratch, Bytecodes::_getfield);
__ br(Assembler::notEqual, false, Assembler::pn, slow_path);
__ delayed()->nop();
// Get the type and return field offset from the constant pool cache
__ ld_ptr(G3_scratch, in_bytes(cp_base_offset + ConstantPoolCacheEntry::flags_offset()), G1_scratch);
__ ld_ptr(G3_scratch, in_bytes(cp_base_offset + ConstantPoolCacheEntry::f2_offset()), G3_scratch);
Label xreturn_path;
// Need to differentiate between igetfield, agetfield, bgetfield etc.
// because they are different sizes.
// Get the type from the constant pool cache
__ srl(G1_scratch, ConstantPoolCacheEntry::tos_state_shift, G1_scratch);
// Make sure we don't need to mask G1_scratch after the above shift
ConstantPoolCacheEntry::verify_tos_state_shift();
__ cmp(G1_scratch, atos );
__ br(Assembler::equal, true, Assembler::pt, xreturn_path);
__ delayed()->ld_ptr(Otos_i, G3_scratch, Otos_i);
__ cmp(G1_scratch, itos);
__ br(Assembler::equal, true, Assembler::pt, xreturn_path);
__ delayed()->ld(Otos_i, G3_scratch, Otos_i);
__ cmp(G1_scratch, stos);
__ br(Assembler::equal, true, Assembler::pt, xreturn_path);
__ delayed()->ldsh(Otos_i, G3_scratch, Otos_i);
__ cmp(G1_scratch, ctos);
__ br(Assembler::equal, true, Assembler::pt, xreturn_path);
__ delayed()->lduh(Otos_i, G3_scratch, Otos_i);
#ifdef ASSERT
__ cmp(G1_scratch, btos);
__ br(Assembler::equal, true, Assembler::pt, xreturn_path);
__ delayed()->ldsb(Otos_i, G3_scratch, Otos_i);
__ should_not_reach_here();
#endif
__ ldsb(Otos_i, G3_scratch, Otos_i);
__ bind(xreturn_path);
// _ireturn/_areturn
__ retl(); // return from leaf routine
__ delayed()->mov(O5_savedSP, SP);
// Generate regular method entry
__ bind(slow_path);
__ ba(fast_accessor_slow_entry_path);
__ delayed()->nop();
return entry;
}
return NULL;
}
address InterpreterGenerator::generate_Reference_get_entry(void) {
#if INCLUDE_ALL_GCS
if (UseG1GC) {
@ -573,7 +468,7 @@ address InterpreterGenerator::generate_Reference_get_entry(void) {
// If G1 is not enabled then attempt to go through the accessor entry point
// Reference.get is an accessor
return generate_accessor_entry();
return generate_jump_to_normal_entry();
}
//
@ -1870,23 +1765,6 @@ address InterpreterGenerator::generate_normal_entry(bool synchronized) {
__ ba(call_interpreter_2);
__ delayed()->st_ptr(O1, STATE(_stack));
// Fast accessor methods share this entry point.
// This works because frame manager is in the same codelet
// This can either be an entry via call_stub/c1/c2 or a recursive interpreter call
// we need to do a little register fixup here once we distinguish the two of them
if (UseFastAccessorMethods && !synchronized) {
// Call stub_return address still in O7
__ bind(fast_accessor_slow_entry_path);
__ set((intptr_t)return_from_native_method - 8, Gtmp1);
__ cmp(Gtmp1, O7); // returning to interpreter?
__ brx(Assembler::equal, true, Assembler::pt, re_dispatch); // yep
__ delayed()->nop();
__ ba(re_dispatch);
__ delayed()->mov(G0, prevState); // initial entry
}
// interpreter returning to native code (call_stub/c1/c2)
// convert result and unwind initial activation
// L2_scratch - scaled result type index

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2012, 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
@ -32,9 +32,11 @@
address generate_normal_entry(bool synchronized);
address generate_native_entry(bool synchronized);
address generate_abstract_entry(void);
address generate_math_entry(AbstractInterpreter::MethodKind kind);
address generate_empty_entry(void);
address generate_accessor_entry(void);
// there are no math intrinsics on sparc
address generate_math_entry(AbstractInterpreter::MethodKind kind) { return NULL; }
address generate_jump_to_normal_entry(void);
address generate_accessor_entry(void) { return generate_jump_to_normal_entry(); }
address generate_empty_entry(void) { return generate_jump_to_normal_entry(); }
address generate_Reference_get_entry(void);
void lock_method(void);
void save_native_result(void);
@ -43,4 +45,7 @@
void generate_counter_incr(Label* overflow, Label* profile_method, Label* profile_method_continue);
void generate_counter_overflow(Label& Lcontinue);
// Not supported
address generate_CRC32_update_entry() { return NULL; }
address generate_CRC32_updateBytes_entry(AbstractInterpreter::MethodKind kind) { return NULL; }
#endif // CPU_SPARC_VM_INTERPRETERGENERATOR_SPARC_HPP

View File

@ -241,6 +241,15 @@ void InterpreterGenerator::generate_counter_overflow(Label& Lcontinue) {
// Various method entries
address InterpreterGenerator::generate_jump_to_normal_entry(void) {
address entry = __ pc();
assert(Interpreter::entry_for_kind(Interpreter::zerolocals) != NULL, "should already be generated");
AddressLiteral al(Interpreter::entry_for_kind(Interpreter::zerolocals));
__ jump_to(al, G3_scratch);
__ delayed()->nop();
return entry;
}
// Abstract method entry
// Attempt to execute abstract method. Throw exception
//
@ -255,159 +264,6 @@ address InterpreterGenerator::generate_abstract_entry(void) {
}
//----------------------------------------------------------------------------------------------------
// Entry points & stack frame layout
//
// Here we generate the various kind of entries into the interpreter.
// The two main entry type are generic bytecode methods and native call method.
// These both come in synchronized and non-synchronized versions but the
// frame layout they create is very similar. The other method entry
// types are really just special purpose entries that are really entry
// and interpretation all in one. These are for trivial methods like
// accessor, empty, or special math methods.
//
// When control flow reaches any of the entry types for the interpreter
// the following holds ->
//
// C2 Calling Conventions:
//
// The entry code below assumes that the following registers are set
// when coming in:
// G5_method: holds the Method* of the method to call
// Lesp: points to the TOS of the callers expression stack
// after having pushed all the parameters
//
// The entry code does the following to setup an interpreter frame
// pop parameters from the callers stack by adjusting Lesp
// set O0 to Lesp
// compute X = (max_locals - num_parameters)
// bump SP up by X to accomadate the extra locals
// compute X = max_expression_stack
// + vm_local_words
// + 16 words of register save area
// save frame doing a save sp, -X, sp growing towards lower addresses
// set Lbcp, Lmethod, LcpoolCache
// set Llocals to i0
// set Lmonitors to FP - rounded_vm_local_words
// set Lesp to Lmonitors - 4
//
// The frame has now been setup to do the rest of the entry code
// Try this optimization: Most method entries could live in a
// "one size fits all" stack frame without all the dynamic size
// calculations. It might be profitable to do all this calculation
// statically and approximately for "small enough" methods.
//-----------------------------------------------------------------------------------------------
// C1 Calling conventions
//
// Upon method entry, the following registers are setup:
//
// g2 G2_thread: current thread
// g5 G5_method: method to activate
// g4 Gargs : pointer to last argument
//
//
// Stack:
//
// +---------------+ <--- sp
// | |
// : reg save area :
// | |
// +---------------+ <--- sp + 0x40
// | |
// : extra 7 slots : note: these slots are not really needed for the interpreter (fix later)
// | |
// +---------------+ <--- sp + 0x5c
// | |
// : free :
// | |
// +---------------+ <--- Gargs
// | |
// : arguments :
// | |
// +---------------+
// | |
//
//
//
// AFTER FRAME HAS BEEN SETUP for method interpretation the stack looks like:
//
// +---------------+ <--- sp
// | |
// : reg save area :
// | |
// +---------------+ <--- sp + 0x40
// | |
// : extra 7 slots : note: these slots are not really needed for the interpreter (fix later)
// | |
// +---------------+ <--- sp + 0x5c
// | |
// : :
// | | <--- Lesp
// +---------------+ <--- Lmonitors (fp - 0x18)
// | VM locals |
// +---------------+ <--- fp
// | |
// : reg save area :
// | |
// +---------------+ <--- fp + 0x40
// | |
// : extra 7 slots : note: these slots are not really needed for the interpreter (fix later)
// | |
// +---------------+ <--- fp + 0x5c
// | |
// : free :
// | |
// +---------------+
// | |
// : nonarg locals :
// | |
// +---------------+
// | |
// : arguments :
// | | <--- Llocals
// +---------------+ <--- Gargs
// | |
address AbstractInterpreterGenerator::generate_method_entry(AbstractInterpreter::MethodKind kind) {
// determine code generation flags
bool synchronized = false;
address entry_point = NULL;
switch (kind) {
case Interpreter::zerolocals : break;
case Interpreter::zerolocals_synchronized: synchronized = true; break;
case Interpreter::native : entry_point = ((InterpreterGenerator*)this)->generate_native_entry(false); break;
case Interpreter::native_synchronized : entry_point = ((InterpreterGenerator*)this)->generate_native_entry(true); break;
case Interpreter::empty : entry_point = ((InterpreterGenerator*)this)->generate_empty_entry(); break;
case Interpreter::accessor : entry_point = ((InterpreterGenerator*)this)->generate_accessor_entry(); break;
case Interpreter::abstract : entry_point = ((InterpreterGenerator*)this)->generate_abstract_entry(); break;
case Interpreter::java_lang_math_sin : break;
case Interpreter::java_lang_math_cos : break;
case Interpreter::java_lang_math_tan : break;
case Interpreter::java_lang_math_sqrt : break;
case Interpreter::java_lang_math_abs : break;
case Interpreter::java_lang_math_log : break;
case Interpreter::java_lang_math_log10 : break;
case Interpreter::java_lang_math_pow : break;
case Interpreter::java_lang_math_exp : break;
case Interpreter::java_lang_ref_reference_get
: entry_point = ((InterpreterGenerator*)this)->generate_Reference_get_entry(); break;
default:
fatal(err_msg("unexpected method kind: %d", kind));
break;
}
if (entry_point) return entry_point;
return ((InterpreterGenerator*)this)->generate_normal_entry(synchronized);
}
bool AbstractInterpreter::can_be_compiled(methodHandle m) {
// No special entry points that preclude compilation
return true;

View File

@ -6184,7 +6184,11 @@ instruct loadConP_no_oop_cheap(iRegP dst, immP_no_oop_cheap con) %{
ins_cost(DEFAULT_COST * 3/2);
format %{ "SET $con,$dst\t! non-oop ptr" %}
ins_encode %{
__ set($con$$constant, $dst$$Register);
if (_opnds[1]->constant_reloc() == relocInfo::metadata_type) {
__ set_metadata_constant((Metadata*)$con$$constant, $dst$$Register);
} else {
__ set($con$$constant, $dst$$Register);
}
%}
ins_pipe(loadConP);
%}

View File

@ -456,6 +456,115 @@ void TemplateInterpreterGenerator::generate_stack_overflow_check(Register Rframe
// Generate a fixed interpreter frame. This is identical setup for interpreted
// methods and for native methods hence the shared code.
//----------------------------------------------------------------------------------------------------
// Stack frame layout
//
// When control flow reaches any of the entry types for the interpreter
// the following holds ->
//
// C2 Calling Conventions:
//
// The entry code below assumes that the following registers are set
// when coming in:
// G5_method: holds the Method* of the method to call
// Lesp: points to the TOS of the callers expression stack
// after having pushed all the parameters
//
// The entry code does the following to setup an interpreter frame
// pop parameters from the callers stack by adjusting Lesp
// set O0 to Lesp
// compute X = (max_locals - num_parameters)
// bump SP up by X to accomadate the extra locals
// compute X = max_expression_stack
// + vm_local_words
// + 16 words of register save area
// save frame doing a save sp, -X, sp growing towards lower addresses
// set Lbcp, Lmethod, LcpoolCache
// set Llocals to i0
// set Lmonitors to FP - rounded_vm_local_words
// set Lesp to Lmonitors - 4
//
// The frame has now been setup to do the rest of the entry code
// Try this optimization: Most method entries could live in a
// "one size fits all" stack frame without all the dynamic size
// calculations. It might be profitable to do all this calculation
// statically and approximately for "small enough" methods.
//-----------------------------------------------------------------------------------------------
// C1 Calling conventions
//
// Upon method entry, the following registers are setup:
//
// g2 G2_thread: current thread
// g5 G5_method: method to activate
// g4 Gargs : pointer to last argument
//
//
// Stack:
//
// +---------------+ <--- sp
// | |
// : reg save area :
// | |
// +---------------+ <--- sp + 0x40
// | |
// : extra 7 slots : note: these slots are not really needed for the interpreter (fix later)
// | |
// +---------------+ <--- sp + 0x5c
// | |
// : free :
// | |
// +---------------+ <--- Gargs
// | |
// : arguments :
// | |
// +---------------+
// | |
//
//
//
// AFTER FRAME HAS BEEN SETUP for method interpretation the stack looks like:
//
// +---------------+ <--- sp
// | |
// : reg save area :
// | |
// +---------------+ <--- sp + 0x40
// | |
// : extra 7 slots : note: these slots are not really needed for the interpreter (fix later)
// | |
// +---------------+ <--- sp + 0x5c
// | |
// : :
// | | <--- Lesp
// +---------------+ <--- Lmonitors (fp - 0x18)
// | VM locals |
// +---------------+ <--- fp
// | |
// : reg save area :
// | |
// +---------------+ <--- fp + 0x40
// | |
// : extra 7 slots : note: these slots are not really needed for the interpreter (fix later)
// | |
// +---------------+ <--- fp + 0x5c
// | |
// : free :
// | |
// +---------------+
// | |
// : nonarg locals :
// | |
// +---------------+
// | |
// : arguments :
// | | <--- Llocals
// +---------------+ <--- Gargs
// | |
void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) {
//
//
@ -599,136 +708,6 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) {
}
// Empty method, generate a very fast return.
address InterpreterGenerator::generate_empty_entry(void) {
// A method that does nother but return...
address entry = __ pc();
Label slow_path;
// do nothing for empty methods (do not even increment invocation counter)
if ( UseFastEmptyMethods) {
// If we need a safepoint check, generate full interpreter entry.
AddressLiteral sync_state(SafepointSynchronize::address_of_state());
__ set(sync_state, G3_scratch);
__ cmp_and_br_short(G3_scratch, SafepointSynchronize::_not_synchronized, Assembler::notEqual, Assembler::pn, slow_path);
// Code: _return
__ retl();
__ delayed()->mov(O5_savedSP, SP);
__ bind(slow_path);
(void) generate_normal_entry(false);
return entry;
}
return NULL;
}
// Call an accessor method (assuming it is resolved, otherwise drop into
// vanilla (slow path) entry
// Generates code to elide accessor methods
// Uses G3_scratch and G1_scratch as scratch
address InterpreterGenerator::generate_accessor_entry(void) {
// Code: _aload_0, _(i|a)getfield, _(i|a)return or any rewrites thereof;
// parameter size = 1
// Note: We can only use this code if the getfield has been resolved
// and if we don't have a null-pointer exception => check for
// these conditions first and use slow path if necessary.
address entry = __ pc();
Label slow_path;
// XXX: for compressed oops pointer loading and decoding doesn't fit in
// delay slot and damages G1
if ( UseFastAccessorMethods && !UseCompressedOops ) {
// Check if we need to reach a safepoint and generate full interpreter
// frame if so.
AddressLiteral sync_state(SafepointSynchronize::address_of_state());
__ load_contents(sync_state, G3_scratch);
__ cmp(G3_scratch, SafepointSynchronize::_not_synchronized);
__ cmp_and_br_short(G3_scratch, SafepointSynchronize::_not_synchronized, Assembler::notEqual, Assembler::pn, slow_path);
// Check if local 0 != NULL
__ ld_ptr(Gargs, G0, Otos_i ); // get local 0
// check if local 0 == NULL and go the slow path
__ br_null_short(Otos_i, Assembler::pn, slow_path);
// read first instruction word and extract bytecode @ 1 and index @ 2
// get first 4 bytes of the bytecodes (big endian!)
__ ld_ptr(G5_method, Method::const_offset(), G1_scratch);
__ ld(G1_scratch, ConstMethod::codes_offset(), G1_scratch);
// move index @ 2 far left then to the right most two bytes.
__ sll(G1_scratch, 2*BitsPerByte, G1_scratch);
__ srl(G1_scratch, 2*BitsPerByte - exact_log2(in_words(
ConstantPoolCacheEntry::size()) * BytesPerWord), G1_scratch);
// get constant pool cache
__ ld_ptr(G5_method, Method::const_offset(), G3_scratch);
__ ld_ptr(G3_scratch, ConstMethod::constants_offset(), G3_scratch);
__ ld_ptr(G3_scratch, ConstantPool::cache_offset_in_bytes(), G3_scratch);
// get specific constant pool cache entry
__ add(G3_scratch, G1_scratch, G3_scratch);
// Check the constant Pool cache entry to see if it has been resolved.
// If not, need the slow path.
ByteSize cp_base_offset = ConstantPoolCache::base_offset();
__ ld_ptr(G3_scratch, cp_base_offset + ConstantPoolCacheEntry::indices_offset(), G1_scratch);
__ srl(G1_scratch, 2*BitsPerByte, G1_scratch);
__ and3(G1_scratch, 0xFF, G1_scratch);
__ cmp_and_br_short(G1_scratch, Bytecodes::_getfield, Assembler::notEqual, Assembler::pn, slow_path);
// Get the type and return field offset from the constant pool cache
__ ld_ptr(G3_scratch, cp_base_offset + ConstantPoolCacheEntry::flags_offset(), G1_scratch);
__ ld_ptr(G3_scratch, cp_base_offset + ConstantPoolCacheEntry::f2_offset(), G3_scratch);
Label xreturn_path;
// Need to differentiate between igetfield, agetfield, bgetfield etc.
// because they are different sizes.
// Get the type from the constant pool cache
__ srl(G1_scratch, ConstantPoolCacheEntry::tos_state_shift, G1_scratch);
// Make sure we don't need to mask G1_scratch after the above shift
ConstantPoolCacheEntry::verify_tos_state_shift();
__ cmp(G1_scratch, atos );
__ br(Assembler::equal, true, Assembler::pt, xreturn_path);
__ delayed()->ld_ptr(Otos_i, G3_scratch, Otos_i);
__ cmp(G1_scratch, itos);
__ br(Assembler::equal, true, Assembler::pt, xreturn_path);
__ delayed()->ld(Otos_i, G3_scratch, Otos_i);
__ cmp(G1_scratch, stos);
__ br(Assembler::equal, true, Assembler::pt, xreturn_path);
__ delayed()->ldsh(Otos_i, G3_scratch, Otos_i);
__ cmp(G1_scratch, ctos);
__ br(Assembler::equal, true, Assembler::pt, xreturn_path);
__ delayed()->lduh(Otos_i, G3_scratch, Otos_i);
#ifdef ASSERT
__ cmp(G1_scratch, btos);
__ br(Assembler::equal, true, Assembler::pt, xreturn_path);
__ delayed()->ldsb(Otos_i, G3_scratch, Otos_i);
__ should_not_reach_here();
#endif
__ ldsb(Otos_i, G3_scratch, Otos_i);
__ bind(xreturn_path);
// _ireturn/_areturn
__ retl(); // return from leaf routine
__ delayed()->mov(O5_savedSP, SP);
// Generate regular method entry
__ bind(slow_path);
(void) generate_normal_entry(false);
return entry;
}
return NULL;
}
// Method entry for java.lang.ref.Reference.get.
address InterpreterGenerator::generate_Reference_get_entry(void) {
#if INCLUDE_ALL_GCS
@ -806,7 +785,7 @@ address InterpreterGenerator::generate_Reference_get_entry(void) {
// If G1 is not enabled then attempt to go through the accessor entry point
// Reference.get is an accessor
return generate_accessor_entry();
return generate_jump_to_normal_entry();
}
//
@ -1242,8 +1221,6 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) {
// Generic method entry to (asm) interpreter
//------------------------------------------------------------------------------------------------------------------------
//
address InterpreterGenerator::generate_normal_entry(bool synchronized) {
address entry = __ pc();
@ -1410,123 +1387,6 @@ address InterpreterGenerator::generate_normal_entry(bool synchronized) {
return entry;
}
//----------------------------------------------------------------------------------------------------
// Entry points & stack frame layout
//
// Here we generate the various kind of entries into the interpreter.
// The two main entry type are generic bytecode methods and native call method.
// These both come in synchronized and non-synchronized versions but the
// frame layout they create is very similar. The other method entry
// types are really just special purpose entries that are really entry
// and interpretation all in one. These are for trivial methods like
// accessor, empty, or special math methods.
//
// When control flow reaches any of the entry types for the interpreter
// the following holds ->
//
// C2 Calling Conventions:
//
// The entry code below assumes that the following registers are set
// when coming in:
// G5_method: holds the Method* of the method to call
// Lesp: points to the TOS of the callers expression stack
// after having pushed all the parameters
//
// The entry code does the following to setup an interpreter frame
// pop parameters from the callers stack by adjusting Lesp
// set O0 to Lesp
// compute X = (max_locals - num_parameters)
// bump SP up by X to accomadate the extra locals
// compute X = max_expression_stack
// + vm_local_words
// + 16 words of register save area
// save frame doing a save sp, -X, sp growing towards lower addresses
// set Lbcp, Lmethod, LcpoolCache
// set Llocals to i0
// set Lmonitors to FP - rounded_vm_local_words
// set Lesp to Lmonitors - 4
//
// The frame has now been setup to do the rest of the entry code
// Try this optimization: Most method entries could live in a
// "one size fits all" stack frame without all the dynamic size
// calculations. It might be profitable to do all this calculation
// statically and approximately for "small enough" methods.
//-----------------------------------------------------------------------------------------------
// C1 Calling conventions
//
// Upon method entry, the following registers are setup:
//
// g2 G2_thread: current thread
// g5 G5_method: method to activate
// g4 Gargs : pointer to last argument
//
//
// Stack:
//
// +---------------+ <--- sp
// | |
// : reg save area :
// | |
// +---------------+ <--- sp + 0x40
// | |
// : extra 7 slots : note: these slots are not really needed for the interpreter (fix later)
// | |
// +---------------+ <--- sp + 0x5c
// | |
// : free :
// | |
// +---------------+ <--- Gargs
// | |
// : arguments :
// | |
// +---------------+
// | |
//
//
//
// AFTER FRAME HAS BEEN SETUP for method interpretation the stack looks like:
//
// +---------------+ <--- sp
// | |
// : reg save area :
// | |
// +---------------+ <--- sp + 0x40
// | |
// : extra 7 slots : note: these slots are not really needed for the interpreter (fix later)
// | |
// +---------------+ <--- sp + 0x5c
// | |
// : :
// | | <--- Lesp
// +---------------+ <--- Lmonitors (fp - 0x18)
// | VM locals |
// +---------------+ <--- fp
// | |
// : reg save area :
// | |
// +---------------+ <--- fp + 0x40
// | |
// : extra 7 slots : note: these slots are not really needed for the interpreter (fix later)
// | |
// +---------------+ <--- fp + 0x5c
// | |
// : free :
// | |
// +---------------+
// | |
// : nonarg locals :
// | |
// +---------------+
// | |
// : arguments :
// | | <--- Llocals
// +---------------+ <--- Gargs
// | |
static int size_activation_helper(int callee_extra_locals, int max_stack, int monitor_size) {
// Figure out the size of an interpreter frame (in words) given that we have a fully allocated

View File

@ -26,6 +26,7 @@
#include "asm/macroAssembler.inline.hpp"
#include "memory/resourceArea.hpp"
#include "runtime/java.hpp"
#include "runtime/os.hpp"
#include "runtime/stubCodeGenerator.hpp"
#include "vm_version_sparc.hpp"
@ -249,7 +250,7 @@ void VM_Version::initialize() {
(!has_hardware_fsmuld() ? ", no-fsmuld" : ""));
// buf is started with ", " or is empty
_features_str = strdup(strlen(buf) > 2 ? buf + 2 : buf);
_features_str = os::strdup(strlen(buf) > 2 ? buf + 2 : buf);
// There are three 64-bit SPARC families that do not overlap, e.g.,
// both is_ultra3() and is_sparc64() cannot be true at the same time.

View File

@ -3853,6 +3853,15 @@ void Assembler::vpbroadcastd(XMMRegister dst, XMMRegister src) {
emit_int8((unsigned char)(0xC0 | encode));
}
// Carry-Less Multiplication Quadword
void Assembler::pclmulqdq(XMMRegister dst, XMMRegister src, int mask) {
assert(VM_Version::supports_clmul(), "");
int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, VEX_OPCODE_0F_3A);
emit_int8(0x44);
emit_int8((unsigned char)(0xC0 | encode));
emit_int8((unsigned char)mask);
}
// Carry-Less Multiplication Quadword
void Assembler::vpclmulqdq(XMMRegister dst, XMMRegister nds, XMMRegister src, int mask) {
assert(VM_Version::supports_avx() && VM_Version::supports_clmul(), "");

View File

@ -1837,6 +1837,7 @@ private:
void vpbroadcastd(XMMRegister dst, XMMRegister src);
// Carry-Less Multiplication Quadword
void pclmulqdq(XMMRegister dst, XMMRegister src, int mask);
void vpclmulqdq(XMMRegister dst, XMMRegister nds, XMMRegister src, int mask);
// AVX instruction which is used to clear upper 128 bits of YMM registers and

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2011, 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
@ -27,21 +27,6 @@
protected:
#if 0
address generate_asm_interpreter_entry(bool synchronized);
address generate_native_entry(bool synchronized);
address generate_abstract_entry(void);
address generate_math_entry(AbstractInterpreter::MethodKind kind);
address generate_empty_entry(void);
address generate_accessor_entry(void);
address generate_Reference_get_entry(void);
void lock_method(void);
void generate_stack_overflow_check(void);
void generate_counter_incr(Label* overflow, Label* profile_method, Label* profile_method_continue);
void generate_counter_overflow(Label* do_continue);
#endif
void generate_more_monitors();
void generate_deopt_handling();
address generate_interpreter_frame_manager(bool synchronized); // C++ interpreter only

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2007, 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
@ -66,9 +66,6 @@ extern "C" void RecursiveInterpreterActivation(interpreterState istate )
#define __ _masm->
#define STATE(field_name) (Address(state, byte_offset_of(BytecodeInterpreter, field_name)))
Label fast_accessor_slow_entry_path; // fast accessor methods need to be able to jmp to unsynchronized
// c++ interpreter entry point this holds that entry point label.
// default registers for state and sender_sp
// state and sender_sp are the same on 32bit because we have no choice.
// state could be rsi on 64bit but it is an arg reg and not callee save
@ -660,7 +657,6 @@ void InterpreterGenerator::generate_stack_overflow_check(void) {
// generate_method_entry) so the guard should work for them too.
//
// monitor entry size: see picture of stack set (generate_method_entry) and frame_i486.hpp
const int entry_size = frame::interpreter_frame_monitor_size() * wordSize;
// total overhead size: entry_size + (saved rbp, thru expr stack bottom).
@ -794,156 +790,6 @@ void InterpreterGenerator::lock_method(void) {
__ lock_object(monitor);
}
// Call an accessor method (assuming it is resolved, otherwise drop into vanilla (slow path) entry
address InterpreterGenerator::generate_accessor_entry(void) {
// rbx: Method*
// rsi/r13: senderSP must preserved for slow path, set SP to it on fast path
Label xreturn_path;
// do fastpath for resolved accessor methods
if (UseFastAccessorMethods) {
address entry_point = __ pc();
Label slow_path;
// If we need a safepoint check, generate full interpreter entry.
ExternalAddress state(SafepointSynchronize::address_of_state());
__ cmp32(ExternalAddress(SafepointSynchronize::address_of_state()),
SafepointSynchronize::_not_synchronized);
__ jcc(Assembler::notEqual, slow_path);
// ASM/C++ Interpreter
// Code: _aload_0, _(i|a)getfield, _(i|a)return or any rewrites thereof; parameter size = 1
// Note: We can only use this code if the getfield has been resolved
// and if we don't have a null-pointer exception => check for
// these conditions first and use slow path if necessary.
// rbx,: method
// rcx: receiver
__ movptr(rax, Address(rsp, wordSize));
// check if local 0 != NULL and read field
__ testptr(rax, rax);
__ jcc(Assembler::zero, slow_path);
// read first instruction word and extract bytecode @ 1 and index @ 2
__ movptr(rdx, Address(rbx, Method::const_offset()));
__ movptr(rdi, Address(rdx, ConstMethod::constants_offset()));
__ movl(rdx, Address(rdx, ConstMethod::codes_offset()));
// Shift codes right to get the index on the right.
// The bytecode fetched looks like <index><0xb4><0x2a>
__ shrl(rdx, 2*BitsPerByte);
__ shll(rdx, exact_log2(in_words(ConstantPoolCacheEntry::size())));
__ movptr(rdi, Address(rdi, ConstantPool::cache_offset_in_bytes()));
// rax,: local 0
// rbx,: method
// rcx: receiver - do not destroy since it is needed for slow path!
// rcx: scratch
// rdx: constant pool cache index
// rdi: constant pool cache
// rsi/r13: sender sp
// check if getfield has been resolved and read constant pool cache entry
// check the validity of the cache entry by testing whether _indices field
// contains Bytecode::_getfield in b1 byte.
assert(in_words(ConstantPoolCacheEntry::size()) == 4, "adjust shift below");
__ movl(rcx,
Address(rdi,
rdx,
Address::times_ptr, ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::indices_offset()));
__ shrl(rcx, 2*BitsPerByte);
__ andl(rcx, 0xFF);
__ cmpl(rcx, Bytecodes::_getfield);
__ jcc(Assembler::notEqual, slow_path);
// Note: constant pool entry is not valid before bytecode is resolved
__ movptr(rcx,
Address(rdi,
rdx,
Address::times_ptr, ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::f2_offset()));
__ movl(rdx,
Address(rdi,
rdx,
Address::times_ptr, ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::flags_offset()));
Label notByte, notShort, notChar;
const Address field_address (rax, rcx, Address::times_1);
// Need to differentiate between igetfield, agetfield, bgetfield etc.
// because they are different sizes.
// Use the type from the constant pool cache
__ shrl(rdx, ConstantPoolCacheEntry::tos_state_shift);
// Make sure we don't need to mask rdx after the above shift
ConstantPoolCacheEntry::verify_tos_state_shift();
#ifdef _LP64
Label notObj;
__ cmpl(rdx, atos);
__ jcc(Assembler::notEqual, notObj);
// atos
__ movptr(rax, field_address);
__ jmp(xreturn_path);
__ bind(notObj);
#endif // _LP64
__ cmpl(rdx, btos);
__ jcc(Assembler::notEqual, notByte);
__ load_signed_byte(rax, field_address);
__ jmp(xreturn_path);
__ bind(notByte);
__ cmpl(rdx, stos);
__ jcc(Assembler::notEqual, notShort);
__ load_signed_short(rax, field_address);
__ jmp(xreturn_path);
__ bind(notShort);
__ cmpl(rdx, ctos);
__ jcc(Assembler::notEqual, notChar);
__ load_unsigned_short(rax, field_address);
__ jmp(xreturn_path);
__ bind(notChar);
#ifdef ASSERT
Label okay;
#ifndef _LP64
__ cmpl(rdx, atos);
__ jcc(Assembler::equal, okay);
#endif // _LP64
__ cmpl(rdx, itos);
__ jcc(Assembler::equal, okay);
__ stop("what type is this?");
__ bind(okay);
#endif // ASSERT
// All the rest are a 32 bit wordsize
__ movl(rax, field_address);
__ bind(xreturn_path);
// _ireturn/_areturn
__ pop(rdi); // get return address
__ mov(rsp, sender_sp_on_entry); // set sp to sender sp
__ jmp(rdi);
// generate a vanilla interpreter entry as the slow path
__ bind(slow_path);
// We will enter c++ interpreter looking like it was
// called by the call_stub this will cause it to return
// a tosca result to the invoker which might have been
// the c++ interpreter itself.
__ jmp(fast_accessor_slow_entry_path);
return entry_point;
} else {
return NULL;
}
}
address InterpreterGenerator::generate_Reference_get_entry(void) {
#if INCLUDE_ALL_GCS
if (UseG1GC) {
@ -961,7 +807,7 @@ address InterpreterGenerator::generate_Reference_get_entry(void) {
// If G1 is not enabled then attempt to go through the accessor entry point
// Reference.get is an accessor
return generate_accessor_entry();
return generate_jump_to_normal_entry();
}
//
@ -1670,10 +1516,6 @@ address InterpreterGenerator::generate_normal_entry(bool synchronized) {
address entry_point = __ pc();
// Fast accessor methods share this entry point.
// This works because frame manager is in the same codelet
if (UseFastAccessorMethods && !synchronized) __ bind(fast_accessor_slow_entry_path);
Label dispatch_entry_2;
__ movptr(rcx, sender_sp_on_entry);
__ movptr(state, (int32_t)NULL_WORD); // no current activation
@ -2212,40 +2054,6 @@ address InterpreterGenerator::generate_normal_entry(bool synchronized) {
return entry_point;
}
address AbstractInterpreterGenerator::generate_method_entry(AbstractInterpreter::MethodKind kind) {
// determine code generation flags
bool synchronized = false;
address entry_point = NULL;
switch (kind) {
case Interpreter::zerolocals : break;
case Interpreter::zerolocals_synchronized: synchronized = true; break;
case Interpreter::native : entry_point = ((InterpreterGenerator*)this)->generate_native_entry(false); break;
case Interpreter::native_synchronized : entry_point = ((InterpreterGenerator*)this)->generate_native_entry(true); break;
case Interpreter::empty : entry_point = ((InterpreterGenerator*)this)->generate_empty_entry(); break;
case Interpreter::accessor : entry_point = ((InterpreterGenerator*)this)->generate_accessor_entry(); break;
case Interpreter::abstract : entry_point = ((InterpreterGenerator*)this)->generate_abstract_entry(); break;
case Interpreter::java_lang_math_sin : // fall thru
case Interpreter::java_lang_math_cos : // fall thru
case Interpreter::java_lang_math_tan : // fall thru
case Interpreter::java_lang_math_abs : // fall thru
case Interpreter::java_lang_math_log : // fall thru
case Interpreter::java_lang_math_log10 : // fall thru
case Interpreter::java_lang_math_sqrt : // fall thru
case Interpreter::java_lang_math_pow : // fall thru
case Interpreter::java_lang_math_exp : // fall thru
entry_point = ((InterpreterGenerator*)this)->generate_math_entry(kind); break;
case Interpreter::java_lang_ref_reference_get
: entry_point = ((InterpreterGenerator*)this)->generate_Reference_get_entry(); break;
default : ShouldNotReachHere(); break;
}
if (entry_point) return entry_point;
return ((InterpreterGenerator*)this)->generate_normal_entry(synchronized);
}
InterpreterGenerator::InterpreterGenerator(StubQueue* code)
: CppInterpreterGenerator(code) {

View File

@ -0,0 +1,66 @@
/*
* 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 "asm/macroAssembler.hpp"
#include "interpreter/interpreter.hpp"
#include "interpreter/interpreterGenerator.hpp"
#include "interpreter/interpreterRuntime.hpp"
#include "interpreter/interp_masm.hpp"
#define __ _masm->
// Jump into normal path for accessor and empty entry to jump to normal entry
// The "fast" optimization don't update compilation count therefore can disable inlining
// for these functions that should be inlined.
address InterpreterGenerator::generate_jump_to_normal_entry(void) {
address entry_point = __ pc();
assert(Interpreter::entry_for_kind(Interpreter::zerolocals) != NULL, "should already be generated");
__ jump(RuntimeAddress(Interpreter::entry_for_kind(Interpreter::zerolocals)));
return entry_point;
}
// Abstract method entry
// Attempt to execute abstract method. Throw exception
address InterpreterGenerator::generate_abstract_entry(void) {
address entry_point = __ pc();
// abstract method entry
#ifndef CC_INTERP
// pop return address, reset last_sp to NULL
__ empty_expression_stack();
__ restore_bcp(); // rsi must be correct for exception handler (was destroyed)
__ restore_locals(); // make sure locals pointer is correct as well (was destroyed)
#endif
// throw exception
__ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError));
// the call_VM checks for exception, so we should never return here.
__ should_not_reach_here();
return entry_point;
}

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
@ -36,8 +36,9 @@
address generate_native_entry(bool synchronized);
address generate_abstract_entry(void);
address generate_math_entry(AbstractInterpreter::MethodKind kind);
address generate_empty_entry(void);
address generate_accessor_entry(void);
address generate_jump_to_normal_entry(void);
address generate_accessor_entry(void) { return generate_jump_to_normal_entry(); }
address generate_empty_entry(void) { return generate_jump_to_normal_entry(); }
address generate_Reference_get_entry();
address generate_CRC32_update_entry();
address generate_CRC32_updateBytes_entry(AbstractInterpreter::MethodKind kind);

View File

@ -67,45 +67,6 @@ address AbstractInterpreterGenerator::generate_slow_signature_handler() {
}
//
// Various method entries (that c++ and asm interpreter agree upon)
//------------------------------------------------------------------------------------------------------------------------
//
//
// Empty method, generate a very fast return.
address InterpreterGenerator::generate_empty_entry(void) {
// rbx,: Method*
// rcx: receiver (unused)
// rsi: previous interpreter state (C++ interpreter) must preserve
// rsi: sender sp must set sp to this value on return
if (!UseFastEmptyMethods) return NULL;
address entry_point = __ pc();
// If we need a safepoint check, generate full interpreter entry.
Label slow_path;
ExternalAddress state(SafepointSynchronize::address_of_state());
__ cmp32(ExternalAddress(SafepointSynchronize::address_of_state()),
SafepointSynchronize::_not_synchronized);
__ jcc(Assembler::notEqual, slow_path);
// do nothing for empty methods (do not even increment invocation counter)
// Code: _return
// _return
// return w/o popping parameters
__ pop(rax);
__ mov(rsp, rsi);
__ jmp(rax);
__ bind(slow_path);
(void) generate_normal_entry(false);
return entry_point;
}
address InterpreterGenerator::generate_math_entry(AbstractInterpreter::MethodKind kind) {
// rbx,: Method*
@ -216,36 +177,6 @@ address InterpreterGenerator::generate_math_entry(AbstractInterpreter::MethodKin
}
// Abstract method entry
// Attempt to execute abstract method. Throw exception
address InterpreterGenerator::generate_abstract_entry(void) {
// rbx,: Method*
// rcx: receiver (unused)
// rsi: previous interpreter state (C++ interpreter) must preserve
// rsi: sender SP
address entry_point = __ pc();
// abstract method entry
#ifndef CC_INTERP
// pop return address, reset last_sp to NULL
__ empty_expression_stack();
__ restore_bcp(); // rsi must be correct for exception handler (was destroyed)
__ restore_locals(); // make sure locals pointer is correct as well (was destroyed)
#endif
// throw exception
__ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError));
// the call_VM checks for exception, so we should never return here.
__ should_not_reach_here();
return entry_point;
}
void Deoptimization::unwind_callee_save_values(frame* f, vframeArray* vframe_array) {
// This code is sort of the equivalent of C2IAdapter::setup_stack_frame back in

View File

@ -301,66 +301,6 @@ address InterpreterGenerator::generate_math_entry(AbstractInterpreter::MethodKin
return entry_point;
}
// Abstract method entry
// Attempt to execute abstract method. Throw exception
address InterpreterGenerator::generate_abstract_entry(void) {
// rbx: Method*
// r13: sender SP
address entry_point = __ pc();
// abstract method entry
#ifndef CC_INTERP
// pop return address, reset last_sp to NULL
__ empty_expression_stack();
__ restore_bcp(); // rsi must be correct for exception handler (was destroyed)
__ restore_locals(); // make sure locals pointer is correct as well (was destroyed)
#endif
// throw exception
__ call_VM(noreg, CAST_FROM_FN_PTR(address,
InterpreterRuntime::throw_AbstractMethodError));
// the call_VM checks for exception, so we should never return here.
__ should_not_reach_here();
return entry_point;
}
// Empty method, generate a very fast return.
address InterpreterGenerator::generate_empty_entry(void) {
// rbx: Method*
// r13: sender sp must set sp to this value on return
if (!UseFastEmptyMethods) {
return NULL;
}
address entry_point = __ pc();
// If we need a safepoint check, generate full interpreter entry.
Label slow_path;
__ cmp32(ExternalAddress(SafepointSynchronize::address_of_state()),
SafepointSynchronize::_not_synchronized);
__ jcc(Assembler::notEqual, slow_path);
// do nothing for empty methods (do not even increment invocation counter)
// Code: _return
// _return
// return w/o popping parameters
__ pop(rax);
__ mov(rsp, r13);
__ jmp(rax);
__ bind(slow_path);
(void) generate_normal_entry(false);
return entry_point;
}
void Deoptimization::unwind_callee_save_values(frame* f, vframeArray* vframe_array) {
// This code is sort of the equivalent of C2IAdapter::setup_stack_frame back in

View File

@ -7316,17 +7316,34 @@ void MacroAssembler::update_byte_crc32(Register crc, Register val, Register tabl
* Fold 128-bit data chunk
*/
void MacroAssembler::fold_128bit_crc32(XMMRegister xcrc, XMMRegister xK, XMMRegister xtmp, Register buf, int offset) {
vpclmulhdq(xtmp, xK, xcrc); // [123:64]
vpclmulldq(xcrc, xK, xcrc); // [63:0]
vpxor(xcrc, xcrc, Address(buf, offset), false /* vector256 */);
pxor(xcrc, xtmp);
if (UseAVX > 0) {
vpclmulhdq(xtmp, xK, xcrc); // [123:64]
vpclmulldq(xcrc, xK, xcrc); // [63:0]
vpxor(xcrc, xcrc, Address(buf, offset), false /* vector256 */);
pxor(xcrc, xtmp);
} else {
movdqa(xtmp, xcrc);
pclmulhdq(xtmp, xK); // [123:64]
pclmulldq(xcrc, xK); // [63:0]
pxor(xcrc, xtmp);
movdqu(xtmp, Address(buf, offset));
pxor(xcrc, xtmp);
}
}
void MacroAssembler::fold_128bit_crc32(XMMRegister xcrc, XMMRegister xK, XMMRegister xtmp, XMMRegister xbuf) {
vpclmulhdq(xtmp, xK, xcrc);
vpclmulldq(xcrc, xK, xcrc);
pxor(xcrc, xbuf);
pxor(xcrc, xtmp);
if (UseAVX > 0) {
vpclmulhdq(xtmp, xK, xcrc);
vpclmulldq(xcrc, xK, xcrc);
pxor(xcrc, xbuf);
pxor(xcrc, xtmp);
} else {
movdqa(xtmp, xcrc);
pclmulhdq(xtmp, xK);
pclmulldq(xcrc, xK);
pxor(xcrc, xbuf);
pxor(xcrc, xtmp);
}
}
/**
@ -7444,9 +7461,17 @@ void MacroAssembler::kernel_crc32(Register crc, Register buf, Register len, Regi
// Fold 128 bits in xmm1 down into 32 bits in crc register.
BIND(L_fold_128b);
movdqu(xmm0, ExternalAddress(StubRoutines::x86::crc_by128_masks_addr()));
vpclmulqdq(xmm2, xmm0, xmm1, 0x1);
vpand(xmm3, xmm0, xmm2, false /* vector256 */);
vpclmulqdq(xmm0, xmm0, xmm3, 0x1);
if (UseAVX > 0) {
vpclmulqdq(xmm2, xmm0, xmm1, 0x1);
vpand(xmm3, xmm0, xmm2, false /* vector256 */);
vpclmulqdq(xmm0, xmm0, xmm3, 0x1);
} else {
movdqa(xmm2, xmm0);
pclmulqdq(xmm2, xmm1, 0x1);
movdqa(xmm3, xmm0);
pand(xmm3, xmm2);
pclmulqdq(xmm0, xmm3, 0x1);
}
psrldq(xmm1, 8);
psrldq(xmm2, 4);
pxor(xmm0, xmm1);

View File

@ -966,6 +966,16 @@ public:
void mulss(XMMRegister dst, Address src) { Assembler::mulss(dst, src); }
void mulss(XMMRegister dst, AddressLiteral src);
// Carry-Less Multiplication Quadword
void pclmulldq(XMMRegister dst, XMMRegister src) {
// 0x00 - multiply lower 64 bits [0:63]
Assembler::pclmulqdq(dst, src, 0x00);
}
void pclmulhdq(XMMRegister dst, XMMRegister src) {
// 0x11 - multiply upper 64 bits [64:127]
Assembler::pclmulqdq(dst, src, 0x11);
}
void sqrtsd(XMMRegister dst, XMMRegister src) { Assembler::sqrtsd(dst, src); }
void sqrtsd(XMMRegister dst, Address src) { Assembler::sqrtsd(dst, src); }
void sqrtsd(XMMRegister dst, AddressLiteral src);

View File

@ -38,7 +38,7 @@ int AbstractInterpreter::size_activation(int max_stack,
int callee_locals,
bool is_top_frame) {
// Note: This calculation must exactly parallel the frame setup
// in AbstractInterpreterGenerator::generate_method_entry.
// in InterpreterGenerator::generate_fixed_frame.
// fixed size of an interpreter frame:
int overhead = frame::sender_sp_offset -

View File

@ -468,10 +468,10 @@ void InterpreterGenerator::generate_stack_overflow_check(void) {
// rax,
// NOTE: since the additional locals are also always pushed (wasn't obvious in
// generate_method_entry) so the guard should work for them too.
// generate_fixed_frame) so the guard should work for them too.
//
// monitor entry size: see picture of stack set (generate_method_entry) and frame_x86.hpp
// monitor entry size: see picture of stack in frame_x86.hpp
const int entry_size = frame::interpreter_frame_monitor_size() * wordSize;
// total overhead size: entry_size + (saved rbp, thru expr stack bottom).
@ -633,145 +633,6 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) {
__ movptr(Address(rsp, 0), rsp); // set expression stack bottom
}
// End of helpers
//
// Various method entries
//------------------------------------------------------------------------------------------------------------------------
//
//
// Call an accessor method (assuming it is resolved, otherwise drop into vanilla (slow path) entry
address InterpreterGenerator::generate_accessor_entry(void) {
// rbx,: Method*
// rcx: receiver (preserve for slow entry into asm interpreter)
// rsi: senderSP must preserved for slow path, set SP to it on fast path
address entry_point = __ pc();
Label xreturn_path;
// do fastpath for resolved accessor methods
if (UseFastAccessorMethods) {
Label slow_path;
// If we need a safepoint check, generate full interpreter entry.
ExternalAddress state(SafepointSynchronize::address_of_state());
__ cmp32(ExternalAddress(SafepointSynchronize::address_of_state()),
SafepointSynchronize::_not_synchronized);
__ jcc(Assembler::notEqual, slow_path);
// ASM/C++ Interpreter
// Code: _aload_0, _(i|a)getfield, _(i|a)return or any rewrites thereof; parameter size = 1
// Note: We can only use this code if the getfield has been resolved
// and if we don't have a null-pointer exception => check for
// these conditions first and use slow path if necessary.
// rbx,: method
// rcx: receiver
__ movptr(rax, Address(rsp, wordSize));
// check if local 0 != NULL and read field
__ testptr(rax, rax);
__ jcc(Assembler::zero, slow_path);
// read first instruction word and extract bytecode @ 1 and index @ 2
__ movptr(rdx, Address(rbx, Method::const_offset()));
__ movptr(rdi, Address(rdx, ConstMethod::constants_offset()));
__ movl(rdx, Address(rdx, ConstMethod::codes_offset()));
// Shift codes right to get the index on the right.
// The bytecode fetched looks like <index><0xb4><0x2a>
__ shrl(rdx, 2*BitsPerByte);
__ shll(rdx, exact_log2(in_words(ConstantPoolCacheEntry::size())));
__ movptr(rdi, Address(rdi, ConstantPool::cache_offset_in_bytes()));
// rax,: local 0
// rbx,: method
// rcx: receiver - do not destroy since it is needed for slow path!
// rcx: scratch
// rdx: constant pool cache index
// rdi: constant pool cache
// rsi: sender sp
// check if getfield has been resolved and read constant pool cache entry
// check the validity of the cache entry by testing whether _indices field
// contains Bytecode::_getfield in b1 byte.
assert(in_words(ConstantPoolCacheEntry::size()) == 4, "adjust shift below");
__ movl(rcx,
Address(rdi,
rdx,
Address::times_ptr, ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::indices_offset()));
__ shrl(rcx, 2*BitsPerByte);
__ andl(rcx, 0xFF);
__ cmpl(rcx, Bytecodes::_getfield);
__ jcc(Assembler::notEqual, slow_path);
// Note: constant pool entry is not valid before bytecode is resolved
__ movptr(rcx,
Address(rdi,
rdx,
Address::times_ptr, ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::f2_offset()));
__ movl(rdx,
Address(rdi,
rdx,
Address::times_ptr, ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::flags_offset()));
Label notByte, notShort, notChar;
const Address field_address (rax, rcx, Address::times_1);
// Need to differentiate between igetfield, agetfield, bgetfield etc.
// because they are different sizes.
// Use the type from the constant pool cache
__ shrl(rdx, ConstantPoolCacheEntry::tos_state_shift);
// Make sure we don't need to mask rdx after the above shift
ConstantPoolCacheEntry::verify_tos_state_shift();
__ cmpl(rdx, btos);
__ jcc(Assembler::notEqual, notByte);
__ load_signed_byte(rax, field_address);
__ jmp(xreturn_path);
__ bind(notByte);
__ cmpl(rdx, stos);
__ jcc(Assembler::notEqual, notShort);
__ load_signed_short(rax, field_address);
__ jmp(xreturn_path);
__ bind(notShort);
__ cmpl(rdx, ctos);
__ jcc(Assembler::notEqual, notChar);
__ load_unsigned_short(rax, field_address);
__ jmp(xreturn_path);
__ bind(notChar);
#ifdef ASSERT
Label okay;
__ cmpl(rdx, atos);
__ jcc(Assembler::equal, okay);
__ cmpl(rdx, itos);
__ jcc(Assembler::equal, okay);
__ stop("what type is this?");
__ bind(okay);
#endif // ASSERT
// All the rest are a 32 bit wordsize
// This is ok for now. Since fast accessors should be going away
__ movptr(rax, field_address);
__ bind(xreturn_path);
// _ireturn/_areturn
__ pop(rdi); // get return address
__ mov(rsp, rsi); // set sp to sender sp
__ jmp(rdi);
// generate a vanilla interpreter entry as the slow path
__ bind(slow_path);
(void) generate_normal_entry(false);
return entry_point;
}
return NULL;
}
// Method entry for java.lang.ref.Reference.get.
address InterpreterGenerator::generate_Reference_get_entry(void) {
@ -862,7 +723,7 @@ address InterpreterGenerator::generate_Reference_get_entry(void) {
// If G1 is not enabled then attempt to go through the accessor entry point
// Reference.get is an accessor
return generate_accessor_entry();
return generate_jump_to_normal_entry();
}
/**
@ -1557,100 +1418,6 @@ address InterpreterGenerator::generate_normal_entry(bool synchronized) {
return entry_point;
}
//------------------------------------------------------------------------------------------------------------------------
// Entry points
//
// Here we generate the various kind of entries into the interpreter.
// The two main entry type are generic bytecode methods and native call method.
// These both come in synchronized and non-synchronized versions but the
// frame layout they create is very similar. The other method entry
// types are really just special purpose entries that are really entry
// and interpretation all in one. These are for trivial methods like
// accessor, empty, or special math methods.
//
// When control flow reaches any of the entry types for the interpreter
// the following holds ->
//
// Arguments:
//
// rbx,: Method*
// rcx: receiver
//
//
// Stack layout immediately at entry
//
// [ return address ] <--- rsp
// [ parameter n ]
// ...
// [ parameter 1 ]
// [ expression stack ] (caller's java expression stack)
// Assuming that we don't go to one of the trivial specialized
// entries the stack will look like below when we are ready to execute
// the first bytecode (or call the native routine). The register usage
// will be as the template based interpreter expects (see interpreter_x86.hpp).
//
// local variables follow incoming parameters immediately; i.e.
// the return address is moved to the end of the locals).
//
// [ monitor entry ] <--- rsp
// ...
// [ monitor entry ]
// [ expr. stack bottom ]
// [ saved rsi ]
// [ current rdi ]
// [ Method* ]
// [ saved rbp, ] <--- rbp,
// [ return address ]
// [ local variable m ]
// ...
// [ local variable 1 ]
// [ parameter n ]
// ...
// [ parameter 1 ] <--- rdi
address AbstractInterpreterGenerator::generate_method_entry(AbstractInterpreter::MethodKind kind) {
// determine code generation flags
bool synchronized = false;
address entry_point = NULL;
InterpreterGenerator* ig_this = (InterpreterGenerator*)this;
switch (kind) {
case Interpreter::zerolocals : break;
case Interpreter::zerolocals_synchronized: synchronized = true; break;
case Interpreter::native : entry_point = ig_this->generate_native_entry(false); break;
case Interpreter::native_synchronized : entry_point = ig_this->generate_native_entry(true); break;
case Interpreter::empty : entry_point = ig_this->generate_empty_entry(); break;
case Interpreter::accessor : entry_point = ig_this->generate_accessor_entry(); break;
case Interpreter::abstract : entry_point = ig_this->generate_abstract_entry(); break;
case Interpreter::java_lang_math_sin : // fall thru
case Interpreter::java_lang_math_cos : // fall thru
case Interpreter::java_lang_math_tan : // fall thru
case Interpreter::java_lang_math_abs : // fall thru
case Interpreter::java_lang_math_log : // fall thru
case Interpreter::java_lang_math_log10 : // fall thru
case Interpreter::java_lang_math_sqrt : // fall thru
case Interpreter::java_lang_math_pow : // fall thru
case Interpreter::java_lang_math_exp : entry_point = ig_this->generate_math_entry(kind); break;
case Interpreter::java_lang_ref_reference_get
: entry_point = ig_this->generate_Reference_get_entry(); break;
case Interpreter::java_util_zip_CRC32_update
: entry_point = ig_this->generate_CRC32_update_entry(); break;
case Interpreter::java_util_zip_CRC32_updateBytes
: // fall thru
case Interpreter::java_util_zip_CRC32_updateByteBuffer
: entry_point = ig_this->generate_CRC32_updateBytes_entry(kind); break;
default:
fatal(err_msg("unexpected method kind: %d", kind));
break;
}
if (entry_point) return entry_point;
return ig_this->generate_normal_entry(synchronized);
}
// These should never be compiled since the interpreter will prefer
// the compiled version to the intrinsic version.

View File

@ -400,7 +400,7 @@ void InterpreterGenerator::generate_counter_overflow(Label* do_continue) {
// page mechanism will work for that.
//
// NOTE: Since the additional locals are also always pushed (wasn't
// obvious in generate_method_entry) so the guard should work for them
// obvious in generate_fixed_frame) so the guard should work for them
// too.
//
// Args:
@ -411,8 +411,7 @@ void InterpreterGenerator::generate_counter_overflow(Label* do_continue) {
// rax
void InterpreterGenerator::generate_stack_overflow_check(void) {
// monitor entry size: see picture of stack set
// (generate_method_entry) and frame_amd64.hpp
// monitor entry size: see picture of stack in frame_x86.hpp
const int entry_size = frame::interpreter_frame_monitor_size() * wordSize;
// total overhead size: entry_size + (saved rbp through expr stack
@ -600,153 +599,6 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) {
// End of helpers
// Various method entries
//------------------------------------------------------------------------------------------------------------------------
//
//
// Call an accessor method (assuming it is resolved, otherwise drop
// into vanilla (slow path) entry
address InterpreterGenerator::generate_accessor_entry(void) {
// rbx: Method*
// r13: senderSP must preserver for slow path, set SP to it on fast path
address entry_point = __ pc();
Label xreturn_path;
// do fastpath for resolved accessor methods
if (UseFastAccessorMethods) {
// Code: _aload_0, _(i|a)getfield, _(i|a)return or any rewrites
// thereof; parameter size = 1
// Note: We can only use this code if the getfield has been resolved
// and if we don't have a null-pointer exception => check for
// these conditions first and use slow path if necessary.
Label slow_path;
// If we need a safepoint check, generate full interpreter entry.
__ cmp32(ExternalAddress(SafepointSynchronize::address_of_state()),
SafepointSynchronize::_not_synchronized);
__ jcc(Assembler::notEqual, slow_path);
// rbx: method
__ movptr(rax, Address(rsp, wordSize));
// check if local 0 != NULL and read field
__ testptr(rax, rax);
__ jcc(Assembler::zero, slow_path);
// read first instruction word and extract bytecode @ 1 and index @ 2
__ movptr(rdx, Address(rbx, Method::const_offset()));
__ movptr(rdi, Address(rdx, ConstMethod::constants_offset()));
__ movl(rdx, Address(rdx, ConstMethod::codes_offset()));
// Shift codes right to get the index on the right.
// The bytecode fetched looks like <index><0xb4><0x2a>
__ shrl(rdx, 2 * BitsPerByte);
__ shll(rdx, exact_log2(in_words(ConstantPoolCacheEntry::size())));
__ movptr(rdi, Address(rdi, ConstantPool::cache_offset_in_bytes()));
// rax: local 0
// rbx: method
// rdx: constant pool cache index
// rdi: constant pool cache
// check if getfield has been resolved and read constant pool cache entry
// check the validity of the cache entry by testing whether _indices field
// contains Bytecode::_getfield in b1 byte.
assert(in_words(ConstantPoolCacheEntry::size()) == 4,
"adjust shift below");
__ movl(rcx,
Address(rdi,
rdx,
Address::times_8,
ConstantPoolCache::base_offset() +
ConstantPoolCacheEntry::indices_offset()));
__ shrl(rcx, 2 * BitsPerByte);
__ andl(rcx, 0xFF);
__ cmpl(rcx, Bytecodes::_getfield);
__ jcc(Assembler::notEqual, slow_path);
// Note: constant pool entry is not valid before bytecode is resolved
__ movptr(rcx,
Address(rdi,
rdx,
Address::times_8,
ConstantPoolCache::base_offset() +
ConstantPoolCacheEntry::f2_offset()));
// edx: flags
__ movl(rdx,
Address(rdi,
rdx,
Address::times_8,
ConstantPoolCache::base_offset() +
ConstantPoolCacheEntry::flags_offset()));
Label notObj, notInt, notByte, notShort;
const Address field_address(rax, rcx, Address::times_1);
// Need to differentiate between igetfield, agetfield, bgetfield etc.
// because they are different sizes.
// Use the type from the constant pool cache
__ shrl(rdx, ConstantPoolCacheEntry::tos_state_shift);
// Make sure we don't need to mask edx after the above shift
ConstantPoolCacheEntry::verify_tos_state_shift();
__ cmpl(rdx, atos);
__ jcc(Assembler::notEqual, notObj);
// atos
__ load_heap_oop(rax, field_address);
__ jmp(xreturn_path);
__ bind(notObj);
__ cmpl(rdx, itos);
__ jcc(Assembler::notEqual, notInt);
// itos
__ movl(rax, field_address);
__ jmp(xreturn_path);
__ bind(notInt);
__ cmpl(rdx, btos);
__ jcc(Assembler::notEqual, notByte);
// btos
__ load_signed_byte(rax, field_address);
__ jmp(xreturn_path);
__ bind(notByte);
__ cmpl(rdx, stos);
__ jcc(Assembler::notEqual, notShort);
// stos
__ load_signed_short(rax, field_address);
__ jmp(xreturn_path);
__ bind(notShort);
#ifdef ASSERT
Label okay;
__ cmpl(rdx, ctos);
__ jcc(Assembler::equal, okay);
__ stop("what type is this?");
__ bind(okay);
#endif
// ctos
__ load_unsigned_short(rax, field_address);
__ bind(xreturn_path);
// _ireturn/_areturn
__ pop(rdi);
__ mov(rsp, r13);
__ jmp(rdi);
__ ret(0);
// generate a vanilla interpreter entry as the slow path
__ bind(slow_path);
(void) generate_normal_entry(false);
} else {
(void) generate_normal_entry(false);
}
return entry_point;
}
// Method entry for java.lang.ref.Reference.get.
address InterpreterGenerator::generate_Reference_get_entry(void) {
#if INCLUDE_ALL_GCS
@ -773,8 +625,6 @@ address InterpreterGenerator::generate_Reference_get_entry(void) {
// and so we don't need to call the G1 pre-barrier. Thus we can use the
// regular method entry code to generate the NPE.
//
// This code is based on generate_accessor_enty.
//
// rbx: Method*
// r13: senderSP must preserve for slow path, set SP to it on fast path
@ -832,7 +682,7 @@ address InterpreterGenerator::generate_Reference_get_entry(void) {
// If G1 is not enabled then attempt to go through the accessor entry point
// Reference.get is an accessor
return generate_accessor_entry();
return generate_jump_to_normal_entry();
}
/**
@ -1566,100 +1416,6 @@ address InterpreterGenerator::generate_normal_entry(bool synchronized) {
return entry_point;
}
// Entry points
//
// Here we generate the various kind of entries into the interpreter.
// The two main entry type are generic bytecode methods and native
// call method. These both come in synchronized and non-synchronized
// versions but the frame layout they create is very similar. The
// other method entry types are really just special purpose entries
// that are really entry and interpretation all in one. These are for
// trivial methods like accessor, empty, or special math methods.
//
// When control flow reaches any of the entry types for the interpreter
// the following holds ->
//
// Arguments:
//
// rbx: Method*
//
// Stack layout immediately at entry
//
// [ return address ] <--- rsp
// [ parameter n ]
// ...
// [ parameter 1 ]
// [ expression stack ] (caller's java expression stack)
// Assuming that we don't go to one of the trivial specialized entries
// the stack will look like below when we are ready to execute the
// first bytecode (or call the native routine). The register usage
// will be as the template based interpreter expects (see
// interpreter_amd64.hpp).
//
// local variables follow incoming parameters immediately; i.e.
// the return address is moved to the end of the locals).
//
// [ monitor entry ] <--- rsp
// ...
// [ monitor entry ]
// [ expr. stack bottom ]
// [ saved r13 ]
// [ current r14 ]
// [ Method* ]
// [ saved ebp ] <--- rbp
// [ return address ]
// [ local variable m ]
// ...
// [ local variable 1 ]
// [ parameter n ]
// ...
// [ parameter 1 ] <--- r14
address AbstractInterpreterGenerator::generate_method_entry(
AbstractInterpreter::MethodKind kind) {
// determine code generation flags
bool synchronized = false;
address entry_point = NULL;
InterpreterGenerator* ig_this = (InterpreterGenerator*)this;
switch (kind) {
case Interpreter::zerolocals : break;
case Interpreter::zerolocals_synchronized: synchronized = true; break;
case Interpreter::native : entry_point = ig_this->generate_native_entry(false); break;
case Interpreter::native_synchronized : entry_point = ig_this->generate_native_entry(true); break;
case Interpreter::empty : entry_point = ig_this->generate_empty_entry(); break;
case Interpreter::accessor : entry_point = ig_this->generate_accessor_entry(); break;
case Interpreter::abstract : entry_point = ig_this->generate_abstract_entry(); break;
case Interpreter::java_lang_math_sin : // fall thru
case Interpreter::java_lang_math_cos : // fall thru
case Interpreter::java_lang_math_tan : // fall thru
case Interpreter::java_lang_math_abs : // fall thru
case Interpreter::java_lang_math_log : // fall thru
case Interpreter::java_lang_math_log10 : // fall thru
case Interpreter::java_lang_math_sqrt : // fall thru
case Interpreter::java_lang_math_pow : // fall thru
case Interpreter::java_lang_math_exp : entry_point = ig_this->generate_math_entry(kind); break;
case Interpreter::java_lang_ref_reference_get
: entry_point = ig_this->generate_Reference_get_entry(); break;
case Interpreter::java_util_zip_CRC32_update
: entry_point = ig_this->generate_CRC32_update_entry(); break;
case Interpreter::java_util_zip_CRC32_updateBytes
: // fall thru
case Interpreter::java_util_zip_CRC32_updateByteBuffer
: entry_point = ig_this->generate_CRC32_updateBytes_entry(kind); break;
default:
fatal(err_msg("unexpected method kind: %d", kind));
break;
}
if (entry_point) {
return entry_point;
}
return ig_this->generate_normal_entry(synchronized);
}
// These should never be compiled since the interpreter will prefer
// the compiled version to the intrinsic version.

View File

@ -27,6 +27,7 @@
#include "asm/macroAssembler.inline.hpp"
#include "memory/resourceArea.hpp"
#include "runtime/java.hpp"
#include "runtime/os.hpp"
#include "runtime/stubCodeGenerator.hpp"
#include "vm_version_x86.hpp"
@ -514,7 +515,7 @@ void VM_Version::get_processor_features() {
(supports_tscinv() ? ", tscinv": ""),
(supports_bmi1() ? ", bmi1" : ""),
(supports_bmi2() ? ", bmi2" : ""));
_features_str = strdup(buf);
_features_str = os::strdup(buf);
// UseSSE is set to the smaller of what hardware supports and what
// the command line requires. I.e., you cannot set UseSSE to 2 on
@ -559,7 +560,7 @@ void VM_Version::get_processor_features() {
FLAG_SET_DEFAULT(UseCLMUL, false);
}
if (UseCLMUL && (UseAVX > 0) && (UseSSE > 2)) {
if (UseCLMUL && (UseSSE > 2)) {
if (FLAG_IS_DEFAULT(UseCRC32Intrinsics)) {
UseCRC32Intrinsics = true;
}
@ -805,6 +806,21 @@ void VM_Version::get_processor_features() {
}
}
}
if ((cpu_family() == 0x06) &&
((extended_cpu_model() == 0x36) || // Centerton
(extended_cpu_model() == 0x37) || // Silvermont
(extended_cpu_model() == 0x4D))) {
#ifdef COMPILER2
if (FLAG_IS_DEFAULT(OptoScheduling)) {
OptoScheduling = true;
}
#endif
if (supports_sse4_2()) { // Silvermont
if (FLAG_IS_DEFAULT(UseUnalignedLoadStores)) {
UseUnalignedLoadStores = true; // use movdqu on newest Intel cpus
}
}
}
}
// Use count leading zeros count instruction if available.
@ -892,23 +908,25 @@ void VM_Version::get_processor_features() {
AllocatePrefetchDistance = allocate_prefetch_distance();
AllocatePrefetchStyle = allocate_prefetch_style();
if( is_intel() && cpu_family() == 6 && supports_sse3() ) {
if( AllocatePrefetchStyle == 2 ) { // watermark prefetching on Core
if (is_intel() && cpu_family() == 6 && supports_sse3()) {
if (AllocatePrefetchStyle == 2) { // watermark prefetching on Core
#ifdef _LP64
AllocatePrefetchDistance = 384;
#else
AllocatePrefetchDistance = 320;
#endif
}
if( supports_sse4_2() && supports_ht() ) { // Nehalem based cpus
if (supports_sse4_2() && supports_ht()) { // Nehalem based cpus
AllocatePrefetchDistance = 192;
AllocatePrefetchLines = 4;
}
#ifdef COMPILER2
if (AggressiveOpts && FLAG_IS_DEFAULT(UseFPUForSpilling)) {
if (supports_sse4_2()) {
if (FLAG_IS_DEFAULT(UseFPUForSpilling)) {
FLAG_SET_DEFAULT(UseFPUForSpilling, true);
}
#endif
}
#endif
}
assert(AllocatePrefetchDistance % AllocatePrefetchStepSize == 0, "invalid value");

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright 2007, 2008, 2009, 2010, 2011 Red Hat, Inc.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@ -831,60 +831,6 @@ address InterpreterGenerator::generate_normal_entry(bool synchronized) {
return generate_entry((address) CppInterpreter::normal_entry);
}
address AbstractInterpreterGenerator::generate_method_entry(
AbstractInterpreter::MethodKind kind) {
address entry_point = NULL;
switch (kind) {
case Interpreter::zerolocals:
case Interpreter::zerolocals_synchronized:
break;
case Interpreter::native:
entry_point = ((InterpreterGenerator*) this)->generate_native_entry(false);
break;
case Interpreter::native_synchronized:
entry_point = ((InterpreterGenerator*) this)->generate_native_entry(false);
break;
case Interpreter::empty:
entry_point = ((InterpreterGenerator*) this)->generate_empty_entry();
break;
case Interpreter::accessor:
entry_point = ((InterpreterGenerator*) this)->generate_accessor_entry();
break;
case Interpreter::abstract:
entry_point = ((InterpreterGenerator*) this)->generate_abstract_entry();
break;
case Interpreter::java_lang_math_sin:
case Interpreter::java_lang_math_cos:
case Interpreter::java_lang_math_tan:
case Interpreter::java_lang_math_abs:
case Interpreter::java_lang_math_log:
case Interpreter::java_lang_math_log10:
case Interpreter::java_lang_math_sqrt:
case Interpreter::java_lang_math_pow:
case Interpreter::java_lang_math_exp:
entry_point = ((InterpreterGenerator*) this)->generate_math_entry(kind);
break;
case Interpreter::java_lang_ref_reference_get:
entry_point = ((InterpreterGenerator*)this)->generate_Reference_get_entry();
break;
default:
ShouldNotReachHere();
}
if (entry_point == NULL)
entry_point = ((InterpreterGenerator*) this)->generate_normal_entry(false);
return entry_point;
}
InterpreterGenerator::InterpreterGenerator(StubQueue* code)
: CppInterpreterGenerator(code) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright 2007, 2008, 2009, 2010, 2011 Red Hat, Inc.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@ -61,6 +61,12 @@ define_pd_global(uintx, CMSYoungGenPerWorker, 16*M); // default max size of CMS
define_pd_global(uintx, TypeProfileLevel, 0);
#define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct)
#define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct) \
product(bool, UseFastEmptyMethods, true, \
"Use fast method entry code for empty methods") \
\
product(bool, UseFastAccessorMethods, true, \
"Use fast method entry code for accessor methods") \
\
#endif // CPU_ZERO_VM_GLOBALS_ZERO_HPP

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright 2007 Red Hat, Inc.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@ -39,4 +39,7 @@
address generate_accessor_entry();
address generate_Reference_get_entry();
// Not supported
address generate_CRC32_update_entry() { return NULL; }
address generate_CRC32_updateBytes_entry(AbstractInterpreter::MethodKind kind) { return NULL; }
#endif // CPU_ZERO_VM_INTERPRETERGENERATOR_ZERO_HPP

View File

@ -58,6 +58,7 @@
#include "runtime/mutexLocker.hpp"
#include "runtime/objectMonitor.hpp"
#include "runtime/orderAccess.inline.hpp"
#include "runtime/os.hpp"
#include "runtime/osThread.hpp"
#include "runtime/perfMemory.hpp"
#include "runtime/sharedRuntime.hpp"
@ -378,10 +379,10 @@ void os::Aix::query_multipage_support() {
// default should be 4K.
size_t data_page_size = SIZE_4K;
{
void* p = ::malloc(SIZE_16M);
void* p = os::malloc(SIZE_16M, mtInternal);
guarantee(p != NULL, "malloc failed");
data_page_size = os::Aix::query_pagesize(p);
::free(p);
os::free(p);
}
// query default shm page size (LDR_CNTRL SHMPSIZE)

View File

@ -24,6 +24,8 @@
#include "asm/assembler.hpp"
#include "memory/allocation.hpp"
#include "memory/allocation.inline.hpp"
#include "runtime/os.hpp"
#include "loadlib_aix.hpp"
#include "porting_aix.hpp"
#include "utilities/debug.hpp"
@ -83,7 +85,7 @@ class fixed_strings {
while (n) {
node* p = n;
n = n->next;
free(p->v);
os::free(p->v);
delete p;
}
}
@ -95,7 +97,7 @@ class fixed_strings {
}
}
node* p = new node;
p->v = strdup(s);
p->v = os::strdup_check_oom(s);
p->next = first;
first = p;
return p->v;

View File

@ -2439,23 +2439,25 @@ char* os::reserve_memory_special(size_t bytes, size_t alignment, char* req_addr,
}
// The memory is committed
MemTracker::record_virtual_memory_reserve_and_commit((address)addr, bytes, mtNone, CALLER_PC);
MemTracker::record_virtual_memory_reserve_and_commit((address)addr, bytes, CALLER_PC);
return addr;
}
bool os::release_memory_special(char* base, size_t bytes) {
MemTracker::Tracker tkr = MemTracker::get_virtual_memory_release_tracker();
// detaching the SHM segment will also delete it, see reserve_memory_special()
int rslt = shmdt(base);
if (rslt == 0) {
tkr.record((address)base, bytes);
return true;
if (MemTracker::tracking_level() > NMT_minimal) {
Tracker tkr = MemTracker::get_virtual_memory_release_tracker();
// detaching the SHM segment will also delete it, see reserve_memory_special()
int rslt = shmdt(base);
if (rslt == 0) {
tkr.record((address)base, bytes);
return true;
} else {
return false;
}
} else {
tkr.discard();
return false;
return shmdt(base) == 0;
}
}
size_t os::large_page_size() {

View File

@ -753,7 +753,7 @@ static char* mmap_create_shared(size_t size) {
(void)::memset((void*) mapAddress, 0, size);
// it does not go through os api, the operation has to record from here
MemTracker::record_virtual_memory_reserve((address)mapAddress, size, mtInternal, CURRENT_PC);
MemTracker::record_virtual_memory_reserve_and_commit((address)mapAddress, size, CURRENT_PC, mtInternal);
return mapAddress;
}
@ -918,7 +918,7 @@ static void mmap_attach_shared(const char* user, int vmid, PerfMemory::PerfMemor
}
// it does not go through os api, the operation has to record from here
MemTracker::record_virtual_memory_reserve((address)mapAddress, size, mtInternal, CURRENT_PC);
MemTracker::record_virtual_memory_reserve_and_commit((address)mapAddress, size, CURRENT_PC, mtInternal);
*addr = mapAddress;
*sizep = size;

View File

@ -3504,9 +3504,12 @@ char* os::Linux::reserve_memory_special_huge_tlbfs_mixed(size_t bytes, size_t al
assert(is_ptr_aligned(start, alignment), "Must be");
// os::reserve_memory_special will record this memory area.
// Need to release it here to prevent overlapping reservations.
MemTracker::record_virtual_memory_release((address)start, bytes);
if (MemTracker::tracking_level() > NMT_minimal) {
// os::reserve_memory_special will record this memory area.
// Need to release it here to prevent overlapping reservations.
Tracker tkr = MemTracker::get_virtual_memory_release_tracker();
tkr.record((address)start, bytes);
}
char* end = start + bytes;
@ -3601,7 +3604,7 @@ char* os::reserve_memory_special(size_t bytes, size_t alignment, char* req_addr,
}
// The memory is committed
MemTracker::record_virtual_memory_reserve_and_commit((address)addr, bytes, mtNone, CALLER_PC);
MemTracker::record_virtual_memory_reserve_and_commit((address)addr, bytes, CALLER_PC);
}
return addr;
@ -3617,24 +3620,30 @@ bool os::Linux::release_memory_special_huge_tlbfs(char* base, size_t bytes) {
}
bool os::release_memory_special(char* base, size_t bytes) {
assert(UseLargePages, "only for large pages");
MemTracker::Tracker tkr = MemTracker::get_virtual_memory_release_tracker();
bool res;
if (MemTracker::tracking_level() > NMT_minimal) {
Tracker tkr = MemTracker::get_virtual_memory_release_tracker();
res = os::Linux::release_memory_special_impl(base, bytes);
if (res) {
tkr.record((address)base, bytes);
}
} else {
res = os::Linux::release_memory_special_impl(base, bytes);
}
return res;
}
bool os::Linux::release_memory_special_impl(char* base, size_t bytes) {
assert(UseLargePages, "only for large pages");
bool res;
if (UseSHM) {
res = os::Linux::release_memory_special_shm(base, bytes);
} else {
assert(UseHugeTLBFS, "must be");
res = os::Linux::release_memory_special_huge_tlbfs(base, bytes);
}
if (res) {
tkr.record((address)base, bytes);
} else {
tkr.discard();
}
return res;
}

View File

@ -108,6 +108,7 @@ class Linux {
static char* reserve_memory_special_huge_tlbfs_only(size_t bytes, char* req_addr, bool exec);
static char* reserve_memory_special_huge_tlbfs_mixed(size_t bytes, size_t alignment, char* req_addr, bool exec);
static bool release_memory_special_impl(char* base, size_t bytes);
static bool release_memory_special_shm(char* base, size_t bytes);
static bool release_memory_special_huge_tlbfs(char* base, size_t bytes);

View File

@ -753,7 +753,7 @@ static char* mmap_create_shared(size_t size) {
(void)::memset((void*) mapAddress, 0, size);
// it does not go through os api, the operation has to record from here
MemTracker::record_virtual_memory_reserve((address)mapAddress, size, mtInternal, CURRENT_PC);
MemTracker::record_virtual_memory_reserve_and_commit((address)mapAddress, size, CURRENT_PC, mtInternal);
return mapAddress;
}
@ -924,7 +924,7 @@ static void mmap_attach_shared(const char* user, int vmid, PerfMemory::PerfMemor
}
// it does not go through os api, the operation has to record from here
MemTracker::record_virtual_memory_reserve((address)mapAddress, size, mtInternal, CURRENT_PC);
MemTracker::record_virtual_memory_reserve_and_commit((address)mapAddress, size, CURRENT_PC, mtInternal);
*addr = mapAddress;
*sizep = size;

View File

@ -75,21 +75,41 @@ void os::check_or_create_dump(void* exceptionRecord, void* contextRecord, char*
VMError::report_coredump_status(buffer, success);
}
address os::get_caller_pc(int n) {
int os::get_native_stack(address* stack, int frames, int toSkip) {
#ifdef _NMT_NOINLINE_
n ++;
toSkip++;
#endif
int frame_idx = 0;
int num_of_frames; // number of frames captured
frame fr = os::current_frame();
while (n > 0 && fr.pc() &&
!os::is_first_C_frame(&fr) && fr.sender_pc()) {
fr = os::get_sender_for_C_frame(&fr);
n --;
while (fr.pc() && frame_idx < frames) {
if (toSkip > 0) {
toSkip --;
} else {
stack[frame_idx ++] = fr.pc();
}
if (fr.fp() == NULL || os::is_first_C_frame(&fr)
||fr.sender_pc() == NULL || fr.cb() != NULL) break;
if (fr.sender_pc() && !os::is_first_C_frame(&fr)) {
fr = os::get_sender_for_C_frame(&fr);
} else {
break;
}
}
if (n == 0) {
return fr.pc();
} else {
return NULL;
num_of_frames = frame_idx;
for (; frame_idx < frames; frame_idx ++) {
stack[frame_idx] = NULL;
}
return num_of_frames;
}
bool os::unsetenv(const char* name) {
assert(name != NULL, "Null pointer");
return (::unsetenv(name) == 0);
}
int os::get_last_error() {

View File

@ -770,7 +770,8 @@ static char* mmap_create_shared(size_t size) {
(void)::memset((void*) mapAddress, 0, size);
// it does not go through os api, the operation has to record from here
MemTracker::record_virtual_memory_reserve((address)mapAddress, size, mtInternal, CURRENT_PC);
MemTracker::record_virtual_memory_reserve_and_commit((address)mapAddress,
size, CURRENT_PC, mtInternal);
return mapAddress;
}
@ -941,7 +942,8 @@ static void mmap_attach_shared(const char* user, int vmid, PerfMemory::PerfMemor
}
// it does not go through os api, the operation has to record from here
MemTracker::record_virtual_memory_reserve((address)mapAddress, size, mtInternal, CURRENT_PC);
MemTracker::record_virtual_memory_reserve_and_commit((address)mapAddress,
size, CURRENT_PC, mtInternal);
*addr = mapAddress;
*sizep = size;

View File

@ -138,9 +138,8 @@ BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, LPVOID reserved) {
// Workaround for issue when a custom launcher doesn't call
// DestroyJavaVM and NMT is trying to track memory when free is
// called from a static destructor
if (MemTracker::is_on()) {
MemTracker::shutdown(MemTracker::NMT_normal);
}
MemTracker::shutdown();
break;
default:
break;
@ -163,6 +162,10 @@ bool os::getenv(const char* name, char* buffer, int len) {
return result > 0 && result < len;
}
bool os::unsetenv(const char* name) {
assert(name != NULL, "Null pointer");
return (SetEnvironmentVariable(name, NULL) == TRUE);
}
// No setuid programs under Windows.
bool os::have_special_privileges() {
@ -319,15 +322,16 @@ extern "C" void breakpoint() {
* So far, this method is only used by Native Memory Tracking, which is
* only supported on Windows XP or later.
*/
address os::get_caller_pc(int n) {
int os::get_native_stack(address* stack, int frames, int toSkip) {
#ifdef _NMT_NOINLINE_
n++;
toSkip ++;
#endif
address pc;
if (os::Kernel32Dll::RtlCaptureStackBackTrace(n + 1, 1, (PVOID*)&pc, NULL) == 1) {
return pc;
int captured = Kernel32Dll::RtlCaptureStackBackTrace(toSkip + 1, frames,
(PVOID*)stack, NULL);
for (int index = captured; index < frames; index ++) {
stack[index] = NULL;
}
return NULL;
return captured;
}
@ -2901,7 +2905,7 @@ static char* allocate_pages_individually(size_t bytes, char* addr, DWORD flags,
PAGE_READWRITE);
// If reservation failed, return NULL
if (p_buf == NULL) return NULL;
MemTracker::record_virtual_memory_reserve((address)p_buf, size_of_reserve, mtNone, CALLER_PC);
MemTracker::record_virtual_memory_reserve((address)p_buf, size_of_reserve, CALLER_PC);
os::release_memory(p_buf, bytes + chunk_size);
// we still need to round up to a page boundary (in case we are using large pages)
@ -2967,7 +2971,7 @@ static char* allocate_pages_individually(size_t bytes, char* addr, DWORD flags,
// need to create a dummy 'reserve' record to match
// the release.
MemTracker::record_virtual_memory_reserve((address)p_buf,
bytes_to_release, mtNone, CALLER_PC);
bytes_to_release, CALLER_PC);
os::release_memory(p_buf, bytes_to_release);
}
#ifdef ASSERT
@ -2986,11 +2990,10 @@ static char* allocate_pages_individually(size_t bytes, char* addr, DWORD flags,
}
// Although the memory is allocated individually, it is returned as one.
// NMT records it as one block.
address pc = CALLER_PC;
if ((flags & MEM_COMMIT) != 0) {
MemTracker::record_virtual_memory_reserve_and_commit((address)p_buf, bytes, mtNone, pc);
MemTracker::record_virtual_memory_reserve_and_commit((address)p_buf, bytes, CALLER_PC);
} else {
MemTracker::record_virtual_memory_reserve((address)p_buf, bytes, mtNone, pc);
MemTracker::record_virtual_memory_reserve((address)p_buf, bytes, CALLER_PC);
}
// made it this far, success
@ -3188,8 +3191,7 @@ char* os::reserve_memory_special(size_t bytes, size_t alignment, char* addr, boo
DWORD flag = MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES;
char * res = (char *)VirtualAlloc(addr, bytes, flag, prot);
if (res != NULL) {
address pc = CALLER_PC;
MemTracker::record_virtual_memory_reserve_and_commit((address)res, bytes, mtNone, pc);
MemTracker::record_virtual_memory_reserve_and_commit((address)res, bytes, CALLER_PC);
}
return res;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 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
@ -29,6 +29,7 @@
#include "oops/oop.inline.hpp"
#include "os_windows.inline.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/os.hpp"
#include "runtime/perfMemory.hpp"
#include "services/memTracker.hpp"
#include "utilities/exceptions.hpp"
@ -1388,7 +1389,7 @@ static HANDLE create_sharedmem_resources(const char* dirname, const char* filena
// the file has been successfully created and the file mapping
// object has been created.
sharedmem_fileHandle = fh;
sharedmem_fileName = strdup(filename);
sharedmem_fileName = os::strdup(filename);
return fmh;
}
@ -1498,7 +1499,8 @@ static char* mapping_create_shared(size_t size) {
(void)memset(mapAddress, '\0', size);
// it does not go through os api, the operation has to record from here
MemTracker::record_virtual_memory_reserve((address)mapAddress, size, mtInternal, CURRENT_PC);
MemTracker::record_virtual_memory_reserve_and_commit((address)mapAddress,
size, CURRENT_PC, mtInternal);
return (char*) mapAddress;
}
@ -1680,7 +1682,8 @@ static void open_file_mapping(const char* user, int vmid,
}
// it does not go through os api, the operation has to record from here
MemTracker::record_virtual_memory_reserve((address)mapAddress, size, mtInternal, CURRENT_PC);
MemTracker::record_virtual_memory_reserve_and_commit((address)mapAddress, size,
CURRENT_PC, mtInternal);
*addrp = (char*)mapAddress;
@ -1834,10 +1837,14 @@ void PerfMemory::detach(char* addr, size_t bytes, TRAPS) {
return;
}
MemTracker::Tracker tkr = MemTracker::get_virtual_memory_release_tracker();
remove_file_mapping(addr);
// it does not go through os api, the operation has to record from here
tkr.record((address)addr, bytes);
if (MemTracker::tracking_level() > NMT_minimal) {
// it does not go through os api, the operation has to record from here
Tracker tkr = MemTracker::get_virtual_memory_release_tracker();
remove_file_mapping(addr);
tkr.record((address)addr, bytes);
} else {
remove_file_mapping(addr);
}
}
char* PerfMemory::backing_store_filename() {

View File

@ -23,6 +23,8 @@
*/
#include "precompiled.hpp"
#include "memory/allocation.hpp"
#include "memory/allocation.inline.hpp"
#include "runtime/os.hpp"
#include "vm_version_sparc.hpp"
@ -48,7 +50,7 @@ static void do_sysinfo(int si, const char* string, int* features, int mask) {
// All SI defines used below must be supported.
guarantee(bufsize != -1, "must be supported");
char* buf = (char*) malloc(bufsize);
char* buf = (char*) os::malloc(bufsize, mtInternal);
if (buf == NULL)
return;
@ -60,7 +62,7 @@ static void do_sysinfo(int si, const char* string, int* features, int mask) {
}
}
free(buf);
os::free(buf);
}
int VM_Version::platform_features(int features) {
@ -161,7 +163,7 @@ int VM_Version::platform_features(int features) {
char tmp;
size_t bufsize = sysinfo(SI_ISALIST, &tmp, 1);
char* buf = (char*) malloc(bufsize);
char* buf = (char*) os::malloc(bufsize, mtInternal);
if (buf != NULL) {
if (sysinfo(SI_ISALIST, buf, bufsize) == bufsize) {
@ -184,7 +186,7 @@ int VM_Version::platform_features(int features) {
if (vis[3] == '2') features |= vis2_instructions_m;
}
}
free(buf);
os::free(buf);
}
}
@ -228,7 +230,7 @@ int VM_Version::platform_features(int features) {
}
#endif
// Convert to UPPER case before compare.
char* impl = strdup(implementation);
char* impl = os::strdup_check_oom(implementation);
for (int i = 0; impl[i] != 0; i++)
impl[i] = (char)toupper((uint)impl[i]);
@ -252,7 +254,7 @@ int VM_Version::platform_features(int features) {
implementation = "SPARC";
}
}
free((void*)impl);
os::free((void*)impl);
break;
}
} // for(

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 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
@ -997,7 +997,7 @@ void ArchDesc::build_pipe_classes(FILE *fp_cpp) {
int nopcnt = 0;
for ( _pipeline->_noplist.reset(); (nop = _pipeline->_noplist.iter()) != NULL; nopcnt++ );
fprintf(fp_cpp, "void Bundle::initialize_nops(MachNode * nop_list[%d], Compile *C) {\n", nopcnt);
fprintf(fp_cpp, "void Bundle::initialize_nops(MachNode * nop_list[%d]) {\n", nopcnt);
int i = 0;
for ( _pipeline->_noplist.reset(); (nop = _pipeline->_noplist.iter()) != NULL; i++ ) {
fprintf(fp_cpp, " nop_list[%d] = (MachNode *) new %sNode();\n", i, nop);
@ -1369,7 +1369,7 @@ static void generate_peepreplace( FILE *fp, FormDict &globals, PeepMatch *pmatch
fprintf(fp, " ra_->add_reference(root, inst%d);\n", inst_num);
fprintf(fp, " ra_->set_oop (root, ra_->is_oop(inst%d));\n", inst_num);
fprintf(fp, " ra_->set_pair(root->_idx, ra_->get_reg_second(inst%d), ra_->get_reg_first(inst%d));\n", inst_num, inst_num);
fprintf(fp, " root->_opnds[0] = inst%d->_opnds[0]->clone(C); // result\n", inst_num);
fprintf(fp, " root->_opnds[0] = inst%d->_opnds[0]->clone(); // result\n", inst_num);
fprintf(fp, " // ----- Done with initial setup -----\n");
} else {
if( (op_form == NULL) || (op_form->is_base_constant(globals) == Form::none) ) {
@ -1382,7 +1382,7 @@ static void generate_peepreplace( FILE *fp, FormDict &globals, PeepMatch *pmatch
} else {
fprintf(fp, " // no ideal edge for constants after matching\n");
}
fprintf(fp, " root->_opnds[%d] = inst%d->_opnds[%d]->clone(C);\n",
fprintf(fp, " root->_opnds[%d] = inst%d->_opnds[%d]->clone();\n",
opnds_index, inst_num, inst_op_num );
}
++opnds_index;
@ -1402,7 +1402,7 @@ static void generate_peepreplace( FILE *fp, FormDict &globals, PeepMatch *pmatch
// Define the Peephole method for an instruction node
void ArchDesc::definePeephole(FILE *fp, InstructForm *node) {
// Generate Peephole function header
fprintf(fp, "MachNode *%sNode::peephole( Block *block, int block_index, PhaseRegAlloc *ra_, int &deleted, Compile* C ) {\n", node->_ident);
fprintf(fp, "MachNode *%sNode::peephole(Block *block, int block_index, PhaseRegAlloc *ra_, int &deleted) {\n", node->_ident);
fprintf(fp, " bool matches = true;\n");
// Identify the maximum instruction position,
@ -1593,7 +1593,7 @@ void ArchDesc::defineExpand(FILE *fp, InstructForm *node) {
}
const char *resultOper = new_inst->reduce_result();
fprintf(fp," n%d->set_opnd_array(0, state->MachOperGenerator( %s, C ));\n",
fprintf(fp," n%d->set_opnd_array(0, state->MachOperGenerator(%s));\n",
cnt, machOperEnum(resultOper));
// get the formal operand NameList
@ -1634,7 +1634,7 @@ void ArchDesc::defineExpand(FILE *fp, InstructForm *node) {
// If there is no use of the created operand, just skip it
if (new_pos != NameList::Not_in_list) {
//Copy the operand from the original made above
fprintf(fp," n%d->set_opnd_array(%d, op%d->clone(C)); // %s\n",
fprintf(fp," n%d->set_opnd_array(%d, op%d->clone()); // %s\n",
cnt, new_pos, exp_pos-node->num_opnds(), opid);
// Check for who defines this operand & add edge if needed
fprintf(fp," if(tmp%d != NULL)\n", exp_pos);
@ -1662,7 +1662,7 @@ void ArchDesc::defineExpand(FILE *fp, InstructForm *node) {
new_pos = new_inst->operand_position(parameter,Component::USE);
if (new_pos != -1) {
// Copy the operand from the ExpandNode to the new node
fprintf(fp," n%d->set_opnd_array(%d, opnd_array(%d)->clone(C)); // %s\n",
fprintf(fp," n%d->set_opnd_array(%d, opnd_array(%d)->clone()); // %s\n",
cnt, new_pos, exp_pos, opid);
// For each operand add appropriate input edges by looking at tmp's
fprintf(fp," if(tmp%d == this) {\n", exp_pos);
@ -1729,14 +1729,14 @@ void ArchDesc::defineExpand(FILE *fp, InstructForm *node) {
declared_def = true;
}
if (op && op->_interface && op->_interface->is_RegInterface()) {
fprintf(fp," def = new MachTempNode(state->MachOperGenerator( %s, C ));\n",
fprintf(fp," def = new MachTempNode(state->MachOperGenerator(%s));\n",
machOperEnum(op->_ident));
fprintf(fp," add_req(def);\n");
// The operand for TEMP is already constructed during
// this mach node construction, see buildMachNode().
//
// int idx = node->operand_position_format(comp->_name);
// fprintf(fp," set_opnd_array(%d, state->MachOperGenerator( %s, C ));\n",
// fprintf(fp," set_opnd_array(%d, state->MachOperGenerator(%s));\n",
// idx, machOperEnum(op->_ident));
} else {
assert(false, "can't have temps which aren't registers");
@ -1802,7 +1802,7 @@ void ArchDesc::defineExpand(FILE *fp, InstructForm *node) {
uint j = node->unique_opnds_idx(i);
// unique_opnds_idx(i) is unique if unique_opnds_idx(j) is not unique.
if( j != node->unique_opnds_idx(j) ) {
fprintf(fp," set_opnd_array(%d, opnd_array(%d)->clone(C)); // %s\n",
fprintf(fp," set_opnd_array(%d, opnd_array(%d)->clone()); // %s\n",
new_num_opnds, i, comp->_name);
// delete not unique edges here
fprintf(fp," for(unsigned i = 0; i < num%d; i++) {\n", i);
@ -2839,12 +2839,12 @@ static void defineIn_RegMask(FILE *fp, FormDict &globals, OperandForm &oper) {
// generate code to create a clone for a class derived from MachOper
//
// (0) MachOper *MachOperXOper::clone(Compile* C) const {
// (0) MachOper *MachOperXOper::clone() const {
// (1) return new MachXOper( _ccode, _c0, _c1, ..., _cn);
// (2) }
//
static void defineClone(FILE *fp, FormDict &globalNames, OperandForm &oper) {
fprintf(fp,"MachOper *%sOper::clone(Compile* C) const {\n", oper._ident);
fprintf(fp,"MachOper *%sOper::clone() const {\n", oper._ident);
// Check for constants that need to be copied over
const int num_consts = oper.num_consts(globalNames);
const bool is_ideal_bool = oper.is_ideal_bool();
@ -3043,7 +3043,7 @@ void ArchDesc::define_oper_interface(FILE *fp, OperandForm &oper, FormDict &glob
static void define_fill_new_machnode(bool used, FILE *fp_cpp) {
fprintf(fp_cpp, "\n");
fprintf(fp_cpp, "// Copy _idx, inputs and operands to new node\n");
fprintf(fp_cpp, "void MachNode::fill_new_machnode( MachNode* node, Compile* C) const {\n");
fprintf(fp_cpp, "void MachNode::fill_new_machnode(MachNode* node) const {\n");
if( !used ) {
fprintf(fp_cpp, " // This architecture does not have cisc or short branch instructions\n");
fprintf(fp_cpp, " ShouldNotCallThis();\n");
@ -3064,7 +3064,7 @@ static void define_fill_new_machnode(bool used, FILE *fp_cpp) {
fprintf(fp_cpp, " MachOper **to = node->_opnds;\n");
fprintf(fp_cpp, " for( int i = 0; i < nopnds; i++ ) {\n");
fprintf(fp_cpp, " if( i != cisc_operand() ) \n");
fprintf(fp_cpp, " to[i] = _opnds[i]->clone(C);\n");
fprintf(fp_cpp, " to[i] = _opnds[i]->clone();\n");
fprintf(fp_cpp, " }\n");
fprintf(fp_cpp, "}\n");
}
@ -3105,7 +3105,7 @@ void ArchDesc::defineClasses(FILE *fp) {
if ( strcmp(oper->_ident,"label") == 0 ) {
defineIn_RegMask(_CPP_MISC_file._fp, _globalNames, *oper);
fprintf(fp,"MachOper *%sOper::clone(Compile* C) const {\n", oper->_ident);
fprintf(fp,"MachOper *%sOper::clone() const {\n", oper->_ident);
fprintf(fp," return new %sOper(_label, _block_num);\n", oper->_ident);
fprintf(fp,"}\n");
@ -3124,7 +3124,7 @@ void ArchDesc::defineClasses(FILE *fp) {
if ( strcmp(oper->_ident,"method") == 0 ) {
defineIn_RegMask(_CPP_MISC_file._fp, _globalNames, *oper);
fprintf(fp,"MachOper *%sOper::clone(Compile* C) const {\n", oper->_ident);
fprintf(fp,"MachOper *%sOper::clone() const {\n", oper->_ident);
fprintf(fp," return new %sOper(_method);\n", oper->_ident);
fprintf(fp,"}\n");
@ -3845,7 +3845,7 @@ void ArchDesc::buildMachOperGenerator(FILE *fp_cpp) {
"// that invokes 'new' on the corresponding class constructor.\n");
fprintf(fp_cpp, "\n");
fprintf(fp_cpp, "MachOper *State::MachOperGenerator");
fprintf(fp_cpp, "(int opcode, Compile* C)");
fprintf(fp_cpp, "(int opcode)");
fprintf(fp_cpp, "{\n");
fprintf(fp_cpp, "\n");
fprintf(fp_cpp, " switch(opcode) {\n");
@ -3921,7 +3921,7 @@ void ArchDesc::buildMachNode(FILE *fp_cpp, InstructForm *inst, const char *inden
int index = clist.operand_position(comp->_name, comp->_usedef, inst);
const char *opcode = machOperEnum(comp->_type);
fprintf(fp_cpp, "%s node->set_opnd_array(%d, ", indent, index);
fprintf(fp_cpp, "MachOperGenerator(%s, C));\n", opcode);
fprintf(fp_cpp, "MachOperGenerator(%s));\n", opcode);
}
}
else if ( inst->is_chain_of_constant(_globalNames, opType) ) {
@ -3978,7 +3978,7 @@ void InstructForm::declare_cisc_version(ArchDesc &AD, FILE *fp_hpp) {
InstructForm *inst_cisc = cisc_spill_alternate();
if (inst_cisc != NULL) {
fprintf(fp_hpp, " virtual int cisc_operand() const { return %d; }\n", cisc_spill_operand());
fprintf(fp_hpp, " virtual MachNode *cisc_version(int offset, Compile* C);\n");
fprintf(fp_hpp, " virtual MachNode *cisc_version(int offset);\n");
fprintf(fp_hpp, " virtual void use_cisc_RegMask();\n");
fprintf(fp_hpp, " virtual const RegMask *cisc_RegMask() const { return _cisc_RegMask; }\n");
}
@ -4008,7 +4008,7 @@ bool InstructForm::define_cisc_version(ArchDesc &AD, FILE *fp_cpp) {
// Construct CISC version of this instruction
fprintf(fp_cpp, "\n");
fprintf(fp_cpp, "// Build CISC version of this instruction\n");
fprintf(fp_cpp, "MachNode *%sNode::cisc_version( int offset, Compile* C ) {\n", this->_ident);
fprintf(fp_cpp, "MachNode *%sNode::cisc_version(int offset) {\n", this->_ident);
// Create the MachNode object
fprintf(fp_cpp, " %sNode *node = new %sNode();\n", name, name);
// Fill in the bottom_type where requested
@ -4023,7 +4023,7 @@ bool InstructForm::define_cisc_version(ArchDesc &AD, FILE *fp_cpp) {
fprintf(fp_cpp, "\n");
fprintf(fp_cpp, " // Copy _idx, inputs and operands to new node\n");
fprintf(fp_cpp, " fill_new_machnode(node, C);\n");
fprintf(fp_cpp, " fill_new_machnode(node);\n");
// Construct operand to access [stack_pointer + offset]
fprintf(fp_cpp, " // Construct operand to access [stack_pointer + offset]\n");
fprintf(fp_cpp, " node->set_opnd_array(cisc_operand(), new %sOper(offset));\n", cisc_oper_name);
@ -4042,7 +4042,7 @@ bool InstructForm::define_cisc_version(ArchDesc &AD, FILE *fp_cpp) {
// Build prototypes for short branch methods
void InstructForm::declare_short_branch_methods(FILE *fp_hpp) {
if (has_short_branch_form()) {
fprintf(fp_hpp, " virtual MachNode *short_branch_version(Compile* C);\n");
fprintf(fp_hpp, " virtual MachNode *short_branch_version();\n");
}
}
@ -4055,7 +4055,7 @@ bool InstructForm::define_short_branch_methods(ArchDesc &AD, FILE *fp_cpp) {
// Construct short_branch_version() method.
fprintf(fp_cpp, "// Build short branch version of this instruction\n");
fprintf(fp_cpp, "MachNode *%sNode::short_branch_version(Compile* C) {\n", this->_ident);
fprintf(fp_cpp, "MachNode *%sNode::short_branch_version() {\n", this->_ident);
// Create the MachNode object
fprintf(fp_cpp, " %sNode *node = new %sNode();\n", name, name);
if( is_ideal_if() ) {
@ -4071,7 +4071,7 @@ bool InstructForm::define_short_branch_methods(ArchDesc &AD, FILE *fp_cpp) {
// Short branch version must use same node index for access
// through allocator's tables
fprintf(fp_cpp, " // Copy _idx, inputs and operands to new node\n");
fprintf(fp_cpp, " fill_new_machnode(node, C);\n");
fprintf(fp_cpp, " fill_new_machnode(node);\n");
// Return result and exit scope
fprintf(fp_cpp, " return node;\n");
@ -4097,7 +4097,7 @@ void ArchDesc::buildMachNodeGenerator(FILE *fp_cpp) {
"// that invokes 'new' on the corresponding class constructor.\n");
fprintf(fp_cpp, "\n");
fprintf(fp_cpp, "MachNode *State::MachNodeGenerator");
fprintf(fp_cpp, "(int opcode, Compile* C)");
fprintf(fp_cpp, "(int opcode)");
fprintf(fp_cpp, "{\n");
fprintf(fp_cpp, " switch(opcode) {\n");

View File

@ -1119,7 +1119,7 @@ void ArchDesc::declare_pipe_classes(FILE *fp_hpp) {
fprintf(fp_hpp, " _nop_count = %d\n",
_pipeline->_nopcnt);
fprintf(fp_hpp, " };\n\n");
fprintf(fp_hpp, " static void initialize_nops(MachNode *nop_list[%d], Compile* C);\n\n",
fprintf(fp_hpp, " static void initialize_nops(MachNode *nop_list[%d]);\n\n",
_pipeline->_nopcnt);
fprintf(fp_hpp, "#ifndef PRODUCT\n");
fprintf(fp_hpp, " void dump(outputStream *st = tty) const;\n");
@ -1240,7 +1240,7 @@ void ArchDesc::declareClasses(FILE *fp) {
constant_type, _globalNames);
// Clone function
fprintf(fp," virtual MachOper *clone(Compile* C) const;\n");
fprintf(fp," virtual MachOper *clone() const;\n");
// Support setting a spill offset into a constant operand.
// We only support setting an 'int' offset, while in the
@ -1718,7 +1718,7 @@ void ArchDesc::declareClasses(FILE *fp) {
// If there is an explicit peephole rule, build it
if ( instr->peepholes() != NULL ) {
fprintf(fp," virtual MachNode *peephole(Block *block, int block_index, PhaseRegAlloc *ra_, int &deleted, Compile *C);\n");
fprintf(fp," virtual MachNode *peephole(Block *block, int block_index, PhaseRegAlloc *ra_, int &deleted);\n");
}
// Output the declaration for number of relocation entries
@ -1863,7 +1863,7 @@ void ArchDesc::declareClasses(FILE *fp) {
}
if ( instr->num_post_match_opnds() != 0
|| instr->is_chain_of_constant(_globalNames) ) {
fprintf(fp," friend MachNode *State::MachNodeGenerator(int opcode, Compile* C);\n");
fprintf(fp," friend MachNode *State::MachNodeGenerator(int opcode);\n");
}
if ( instr->rematerialize(_globalNames, get_registers()) ) {
fprintf(fp," // Rematerialize %s\n", instr->_ident);
@ -2071,8 +2071,8 @@ void ArchDesc::defineStateClass(FILE *fp) {
fprintf(fp," DEBUG_ONLY( ~State(void); ) // Destructor\n");
fprintf(fp,"\n");
fprintf(fp," // Methods created by ADLC and invoked by Reduce\n");
fprintf(fp," MachOper *MachOperGenerator( int opcode, Compile* C );\n");
fprintf(fp," MachNode *MachNodeGenerator( int opcode, Compile* C );\n");
fprintf(fp," MachOper *MachOperGenerator(int opcode);\n");
fprintf(fp," MachNode *MachNodeGenerator(int opcode);\n");
fprintf(fp,"\n");
fprintf(fp," // Assign a state to a node, definition of method produced by ADLC\n");
fprintf(fp," bool DFA( int opcode, const Node *ideal );\n");

View File

@ -269,7 +269,7 @@ address CodeBuffer::decode_begin() {
GrowableArray<int>* CodeBuffer::create_patch_overflow() {
if (_overflow_arena == NULL) {
_overflow_arena = new (mtCode) Arena();
_overflow_arena = new (mtCode) Arena(mtCode);
}
return new (_overflow_arena) GrowableArray<int>(_overflow_arena, 8, 0, 0);
}

View File

@ -48,7 +48,7 @@ Compiler::Compiler() : AbstractCompiler(c1) {
void Compiler::init_c1_runtime() {
BufferBlob* buffer_blob = CompilerThread::current()->get_buffer_blob();
Arena* arena = new (mtCompiler) Arena();
Arena* arena = new (mtCompiler) Arena(mtCompiler);
Runtime1::initialize(buffer_blob);
FrameMap::initialize();
// initialize data structures

View File

@ -30,6 +30,7 @@
#include "c1/c1_MacroAssembler.hpp"
#include "c1/c1_ValueStack.hpp"
#include "ci/ciInstance.hpp"
#include "runtime/os.hpp"
void LIR_Assembler::patching_epilog(PatchingStub* patch, LIR_PatchCode patch_code, Register obj, CodeEmitInfo* info) {
// we must have enough patching space so that call can be inserted
@ -848,7 +849,7 @@ void LIR_Assembler::verify_oop_map(CodeEmitInfo* info) {
stringStream st;
st.print("bad oop %s at %d", r->as_Register()->name(), _masm->offset());
#ifdef SPARC
_masm->_verify_oop(r->as_Register(), strdup(st.as_string()), __FILE__, __LINE__);
_masm->_verify_oop(r->as_Register(), os::strdup(st.as_string(), mtCompiler), __FILE__, __LINE__);
#else
_masm->verify_oop(r->as_Register());
#endif

View File

@ -1613,25 +1613,22 @@ void LinearScan::allocate_registers() {
Interval* precolored_cpu_intervals, *not_precolored_cpu_intervals;
Interval* precolored_fpu_intervals, *not_precolored_fpu_intervals;
create_unhandled_lists(&precolored_cpu_intervals, &not_precolored_cpu_intervals, is_precolored_cpu_interval, is_virtual_cpu_interval);
if (has_fpu_registers()) {
create_unhandled_lists(&precolored_fpu_intervals, &not_precolored_fpu_intervals, is_precolored_fpu_interval, is_virtual_fpu_interval);
#ifdef ASSERT
} else {
// fpu register allocation is omitted because no virtual fpu registers are present
// just check this again...
create_unhandled_lists(&precolored_fpu_intervals, &not_precolored_fpu_intervals, is_precolored_fpu_interval, is_virtual_fpu_interval);
assert(not_precolored_fpu_intervals == Interval::end(), "missed an uncolored fpu interval");
#endif
}
// allocate cpu registers
create_unhandled_lists(&precolored_cpu_intervals, &not_precolored_cpu_intervals,
is_precolored_cpu_interval, is_virtual_cpu_interval);
// allocate fpu registers
create_unhandled_lists(&precolored_fpu_intervals, &not_precolored_fpu_intervals,
is_precolored_fpu_interval, is_virtual_fpu_interval);
// the fpu interval allocation cannot be moved down below with the fpu section as
// the cpu_lsw.walk() changes interval positions.
LinearScanWalker cpu_lsw(this, precolored_cpu_intervals, not_precolored_cpu_intervals);
cpu_lsw.walk();
cpu_lsw.finish_allocation();
if (has_fpu_registers()) {
// allocate fpu registers
LinearScanWalker fpu_lsw(this, precolored_fpu_intervals, not_precolored_fpu_intervals);
fpu_lsw.walk();
fpu_lsw.finish_allocation();

View File

@ -86,7 +86,8 @@ static bool firstEnv = true;
// ------------------------------------------------------------------
// ciEnv::ciEnv
ciEnv::ciEnv(CompileTask* task, int system_dictionary_modification_counter) {
ciEnv::ciEnv(CompileTask* task, int system_dictionary_modification_counter)
: _ciEnv_arena(mtCompiler) {
VM_ENTRY_MARK;
// Set up ciEnv::current immediately, for the sake of ciObjectFactory, etc.
@ -144,7 +145,7 @@ ciEnv::ciEnv(CompileTask* task, int system_dictionary_modification_counter) {
_jvmti_can_pop_frame = false;
}
ciEnv::ciEnv(Arena* arena) {
ciEnv::ciEnv(Arena* arena) : _ciEnv_arena(mtCompiler) {
ASSERT_IN_VM;
// Set up ciEnv::current immediately, for the sake of ciObjectFactory, etc.

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 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
@ -112,7 +112,7 @@ void ciObjectFactory::initialize() {
// This Arena is long lived and exists in the resource mark of the
// compiler thread that initializes the initial ciObjectFactory which
// creates the shared ciObjects that all later ciObjectFactories use.
Arena* arena = new (mtCompiler) Arena();
Arena* arena = new (mtCompiler) Arena(mtCompiler);
ciEnv initial(arena);
ciEnv* env = ciEnv::current();
env->_factory->init_shared_objects();

View File

@ -273,13 +273,17 @@ void ClassPathZipEntry::contents_do(void f(const char* name, void* context), voi
}
LazyClassPathEntry::LazyClassPathEntry(char* path, const struct stat* st) : ClassPathEntry() {
_path = strdup(path);
_path = os::strdup_check_oom(path);
_st = *st;
_meta_index = NULL;
_resolved_entry = NULL;
_has_error = false;
}
LazyClassPathEntry::~LazyClassPathEntry() {
os::free(_path);
}
bool LazyClassPathEntry::is_jar_file() {
return ((_st.st_mode & S_IFREG) == S_IFREG);
}
@ -416,7 +420,7 @@ void ClassLoader::setup_meta_index() {
default:
{
if (!skipCurrentJar && cur_entry != NULL) {
char* new_name = strdup(package_name);
char* new_name = os::strdup_check_oom(package_name);
boot_class_path_packages.append(new_name);
}
}
@ -438,7 +442,7 @@ void ClassLoader::setup_meta_index() {
void ClassLoader::setup_bootstrap_search_path() {
assert(_first_entry == NULL, "should not setup bootstrap class search path twice");
char* sys_class_path = os::strdup(Arguments::get_sysclasspath());
char* sys_class_path = os::strdup_check_oom(Arguments::get_sysclasspath());
if (TraceClassLoading && Verbose) {
tty->print_cr("[Bootstrap loader class path=%s]", sys_class_path);
}
@ -460,6 +464,7 @@ void ClassLoader::setup_bootstrap_search_path() {
end++;
}
}
os::free(sys_class_path);
}
ClassPathEntry* ClassLoader::create_class_path_entry(char *path, const struct stat* st, bool lazy, TRAPS) {

View File

@ -128,6 +128,8 @@ class LazyClassPathEntry: public ClassPathEntry {
bool is_jar_file();
const char* name() { return _path; }
LazyClassPathEntry(char* path, const struct stat* st);
virtual ~LazyClassPathEntry();
ClassFileStream* open_stream(const char* name, TRAPS);
void set_meta_index(MetaIndex* meta_index) { _meta_index = meta_index; }
virtual bool is_lazy();

View File

@ -70,9 +70,9 @@ Symbol* SymbolTable::allocate_symbol(const u1* name, int len, bool c_heap, TRAPS
void SymbolTable::initialize_symbols(int arena_alloc_size) {
// Initialize the arena for global symbols, size passed in depends on CDS.
if (arena_alloc_size == 0) {
_arena = new (mtSymbol) Arena();
_arena = new (mtSymbol) Arena(mtSymbol);
} else {
_arena = new (mtSymbol) Arena(arena_alloc_size);
_arena = new (mtSymbol) Arena(mtSymbol, arena_alloc_size);
}
}

View File

@ -407,56 +407,66 @@ void Dependencies::check_valid_dependency_type(DepType dept) {
// for the sake of the compiler log, print out current dependencies:
void Dependencies::log_all_dependencies() {
if (log() == NULL) return;
ciBaseObject* args[max_arg_count];
ResourceMark rm;
for (int deptv = (int)FIRST_TYPE; deptv < (int)TYPE_LIMIT; deptv++) {
DepType dept = (DepType)deptv;
GrowableArray<ciBaseObject*>* deps = _deps[dept];
if (deps->length() == 0) continue;
int deplen = deps->length();
if (deplen == 0) {
continue;
}
int stride = dep_args(dept);
GrowableArray<ciBaseObject*>* ciargs = new GrowableArray<ciBaseObject*>(stride);
for (int i = 0; i < deps->length(); i += stride) {
for (int j = 0; j < stride; j++) {
// flush out the identities before printing
args[j] = deps->at(i+j);
ciargs->push(deps->at(i+j));
}
write_dependency_to(log(), dept, stride, args);
write_dependency_to(log(), dept, ciargs);
ciargs->clear();
}
guarantee(deplen == deps->length(), "deps array cannot grow inside nested ResoureMark scope");
}
}
void Dependencies::write_dependency_to(CompileLog* log,
DepType dept,
int nargs, DepArgument args[],
GrowableArray<DepArgument>* args,
Klass* witness) {
if (log == NULL) {
return;
}
ResourceMark rm;
ciEnv* env = ciEnv::current();
ciBaseObject* ciargs[max_arg_count];
assert(nargs <= max_arg_count, "oob");
for (int j = 0; j < nargs; j++) {
if (args[j].is_oop()) {
ciargs[j] = env->get_object(args[j].oop_value());
GrowableArray<ciBaseObject*>* ciargs = new GrowableArray<ciBaseObject*>(args->length());
for (GrowableArrayIterator<DepArgument> it = args->begin(); it != args->end(); ++it) {
DepArgument arg = *it;
if (arg.is_oop()) {
ciargs->push(env->get_object(arg.oop_value()));
} else {
ciargs[j] = env->get_metadata(args[j].metadata_value());
ciargs->push(env->get_metadata(arg.metadata_value()));
}
}
Dependencies::write_dependency_to(log, dept, nargs, ciargs, witness);
int argslen = ciargs->length();
Dependencies::write_dependency_to(log, dept, ciargs, witness);
guarantee(argslen == ciargs->length(), "ciargs array cannot grow inside nested ResoureMark scope");
}
void Dependencies::write_dependency_to(CompileLog* log,
DepType dept,
int nargs, ciBaseObject* args[],
GrowableArray<ciBaseObject*>* args,
Klass* witness) {
if (log == NULL) return;
assert(nargs <= max_arg_count, "oob");
int argids[max_arg_count];
int ctxkj = dep_context_arg(dept); // -1 if no context arg
int j;
for (j = 0; j < nargs; j++) {
if (args[j]->is_object()) {
argids[j] = log->identify(args[j]->as_object());
if (log == NULL) {
return;
}
ResourceMark rm;
GrowableArray<int>* argids = new GrowableArray<int>(args->length());
for (GrowableArrayIterator<ciBaseObject*> it = args->begin(); it != args->end(); ++it) {
ciBaseObject* obj = *it;
if (obj->is_object()) {
argids->push(log->identify(obj->as_object()));
} else {
argids[j] = log->identify(args[j]->as_metadata());
argids->push(log->identify(obj->as_metadata()));
}
}
if (witness != NULL) {
@ -465,16 +475,17 @@ void Dependencies::write_dependency_to(CompileLog* log,
log->begin_elem("dependency");
}
log->print(" type='%s'", dep_name(dept));
if (ctxkj >= 0) {
log->print(" ctxk='%d'", argids[ctxkj]);
const int ctxkj = dep_context_arg(dept); // -1 if no context arg
if (ctxkj >= 0 && ctxkj < argids->length()) {
log->print(" ctxk='%d'", argids->at(ctxkj));
}
// write remaining arguments, if any.
for (j = 0; j < nargs; j++) {
for (int j = 0; j < argids->length(); j++) {
if (j == ctxkj) continue; // already logged
if (j == 1) {
log->print( " x='%d'", argids[j]);
log->print( " x='%d'", argids->at(j));
} else {
log->print(" x%d='%d'", j, argids[j]);
log->print(" x%d='%d'", j, argids->at(j));
}
}
if (witness != NULL) {
@ -486,9 +497,12 @@ void Dependencies::write_dependency_to(CompileLog* log,
void Dependencies::write_dependency_to(xmlStream* xtty,
DepType dept,
int nargs, DepArgument args[],
GrowableArray<DepArgument>* args,
Klass* witness) {
if (xtty == NULL) return;
if (xtty == NULL) {
return;
}
ResourceMark rm;
ttyLocker ttyl;
int ctxkj = dep_context_arg(dept); // -1 if no context arg
if (witness != NULL) {
@ -498,23 +512,24 @@ void Dependencies::write_dependency_to(xmlStream* xtty,
}
xtty->print(" type='%s'", dep_name(dept));
if (ctxkj >= 0) {
xtty->object("ctxk", args[ctxkj].metadata_value());
xtty->object("ctxk", args->at(ctxkj).metadata_value());
}
// write remaining arguments, if any.
for (int j = 0; j < nargs; j++) {
for (int j = 0; j < args->length(); j++) {
if (j == ctxkj) continue; // already logged
DepArgument arg = args->at(j);
if (j == 1) {
if (args[j].is_oop()) {
xtty->object("x", args[j].oop_value());
if (arg.is_oop()) {
xtty->object("x", arg.oop_value());
} else {
xtty->object("x", args[j].metadata_value());
xtty->object("x", arg.metadata_value());
}
} else {
char xn[10]; sprintf(xn, "x%d", j);
if (args[j].is_oop()) {
xtty->object(xn, args[j].oop_value());
if (arg.is_oop()) {
xtty->object(xn, arg.oop_value());
} else {
xtty->object(xn, args[j].metadata_value());
xtty->object(xn, arg.metadata_value());
}
}
}
@ -525,7 +540,7 @@ void Dependencies::write_dependency_to(xmlStream* xtty,
xtty->end_elem();
}
void Dependencies::print_dependency(DepType dept, int nargs, DepArgument args[],
void Dependencies::print_dependency(DepType dept, GrowableArray<DepArgument>* args,
Klass* witness) {
ResourceMark rm;
ttyLocker ttyl; // keep the following output all in one block
@ -534,8 +549,8 @@ void Dependencies::print_dependency(DepType dept, int nargs, DepArgument args[],
dep_name(dept));
// print arguments
int ctxkj = dep_context_arg(dept); // -1 if no context arg
for (int j = 0; j < nargs; j++) {
DepArgument arg = args[j];
for (int j = 0; j < args->length(); j++) {
DepArgument arg = args->at(j);
bool put_star = false;
if (arg.is_null()) continue;
const char* what;
@ -571,31 +586,33 @@ void Dependencies::print_dependency(DepType dept, int nargs, DepArgument args[],
void Dependencies::DepStream::log_dependency(Klass* witness) {
if (_deps == NULL && xtty == NULL) return; // fast cutout for runtime
ResourceMark rm;
int nargs = argument_count();
DepArgument args[max_arg_count];
const int nargs = argument_count();
GrowableArray<DepArgument>* args = new GrowableArray<DepArgument>(nargs);
for (int j = 0; j < nargs; j++) {
if (type() == call_site_target_value) {
args[j] = argument_oop(j);
args->push(argument_oop(j));
} else {
args[j] = argument(j);
args->push(argument(j));
}
}
int argslen = args->length();
if (_deps != NULL && _deps->log() != NULL) {
Dependencies::write_dependency_to(_deps->log(),
type(), nargs, args, witness);
Dependencies::write_dependency_to(_deps->log(), type(), args, witness);
} else {
Dependencies::write_dependency_to(xtty,
type(), nargs, args, witness);
Dependencies::write_dependency_to(xtty, type(), args, witness);
}
guarantee(argslen == args->length(), "args array cannot grow inside nested ResoureMark scope");
}
void Dependencies::DepStream::print_dependency(Klass* witness, bool verbose) {
ResourceMark rm;
int nargs = argument_count();
DepArgument args[max_arg_count];
GrowableArray<DepArgument>* args = new GrowableArray<DepArgument>(nargs);
for (int j = 0; j < nargs; j++) {
args[j] = argument(j);
args->push(argument(j));
}
Dependencies::print_dependency(type(), nargs, args, witness);
int argslen = args->length();
Dependencies::print_dependency(type(), args, witness);
if (verbose) {
if (_code != NULL) {
tty->print(" code: ");
@ -603,6 +620,7 @@ void Dependencies::DepStream::print_dependency(Klass* witness, bool verbose) {
tty->cr();
}
}
guarantee(argslen == args->length(), "args array cannot grow inside nested ResoureMark scope");
}

View File

@ -369,20 +369,36 @@ class Dependencies: public ResourceObj {
void copy_to(nmethod* nm);
void log_all_dependencies();
void log_dependency(DepType dept, int nargs, ciBaseObject* args[]) {
write_dependency_to(log(), dept, nargs, args);
void log_dependency(DepType dept, GrowableArray<ciBaseObject*>* args) {
ResourceMark rm;
int argslen = args->length();
write_dependency_to(log(), dept, args);
guarantee(argslen == args->length(),
"args array cannot grow inside nested ResoureMark scope");
}
void log_dependency(DepType dept,
ciBaseObject* x0,
ciBaseObject* x1 = NULL,
ciBaseObject* x2 = NULL) {
if (log() == NULL) return;
ciBaseObject* args[max_arg_count];
args[0] = x0;
args[1] = x1;
args[2] = x2;
assert(2 < max_arg_count, "");
log_dependency(dept, dep_args(dept), args);
if (log() == NULL) {
return;
}
ResourceMark rm;
GrowableArray<ciBaseObject*>* ciargs =
new GrowableArray<ciBaseObject*>(dep_args(dept));
assert (x0 != NULL, "no log x0");
ciargs->push(x0);
if (x1 != NULL) {
ciargs->push(x1);
}
if (x2 != NULL) {
ciargs->push(x2);
}
assert(ciargs->length() == dep_args(dept), "");
log_dependency(dept, ciargs);
}
class DepArgument : public ResourceObj {
@ -405,20 +421,8 @@ class Dependencies: public ResourceObj {
Metadata* metadata_value() const { assert(!_is_oop && _valid, "must be"); return (Metadata*) _value; }
};
static void write_dependency_to(CompileLog* log,
DepType dept,
int nargs, ciBaseObject* args[],
Klass* witness = NULL);
static void write_dependency_to(CompileLog* log,
DepType dept,
int nargs, DepArgument args[],
Klass* witness = NULL);
static void write_dependency_to(xmlStream* xtty,
DepType dept,
int nargs, DepArgument args[],
Klass* witness = NULL);
static void print_dependency(DepType dept,
int nargs, DepArgument args[],
GrowableArray<DepArgument>* args,
Klass* witness = NULL);
private:
@ -427,6 +431,18 @@ class Dependencies: public ResourceObj {
static Klass* ctxk_encoded_as_null(DepType dept, Metadata* x);
static void write_dependency_to(CompileLog* log,
DepType dept,
GrowableArray<ciBaseObject*>* args,
Klass* witness = NULL);
static void write_dependency_to(CompileLog* log,
DepType dept,
GrowableArray<DepArgument>* args,
Klass* witness = NULL);
static void write_dependency_to(xmlStream* xtty,
DepType dept,
GrowableArray<DepArgument>* args,
Klass* witness = NULL);
public:
// Use this to iterate over an nmethod's dependency set.
// Works on new and old dependency sets.

View File

@ -33,6 +33,7 @@
#include "oops/symbol.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/jniHandles.hpp"
#include "runtime/os.hpp"
class MethodMatcher : public CHeapObj<mtCompiler> {
public:
@ -175,7 +176,11 @@ class MethodOptionMatcher: public MethodMatcher {
Symbol* method_name, Mode method_mode,
Symbol* signature, const char * opt, MethodMatcher* next):
MethodMatcher(class_name, class_mode, method_name, method_mode, signature, next) {
option = opt;
option = os::strdup_check_oom(opt);
}
virtual ~MethodOptionMatcher() {
os::free((void*)option);
}
bool match(methodHandle method, const char* opt) {
@ -498,7 +503,7 @@ void CompilerOracle::parse_from_line(char* line) {
tty->print("CompilerOracle: %s ", command_names[command]);
match->print();
}
match = add_option_string(c_name, c_match, m_name, m_match, signature, strdup(option));
match = add_option_string(c_name, c_match, m_name, m_match, signature, option);
line += bytes_read;
}
} else {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2007, 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
@ -52,7 +52,8 @@ void ConcurrentMarkSweepPolicy::initialize_alignments() {
}
void ConcurrentMarkSweepPolicy::initialize_generations() {
_generations = NEW_C_HEAP_ARRAY3(GenerationSpecPtr, number_of_generations(), mtGC, 0, AllocFailStrategy::RETURN_NULL);
_generations = NEW_C_HEAP_ARRAY3(GenerationSpecPtr, number_of_generations(), mtGC,
CURRENT_PC, AllocFailStrategy::RETURN_NULL);
if (_generations == NULL)
vm_exit_during_initialization("Unable to allocate gen spec");

View File

@ -2167,7 +2167,9 @@ void ConcurrentMark::cleanup() {
g1h->increment_total_collections();
// Clean out dead classes and update Metaspace sizes.
ClassLoaderDataGraph::purge();
if (ClassUnloadingWithConcurrentMark) {
ClassLoaderDataGraph::purge();
}
MetaspaceGC::compute_new_size();
// We reclaimed old regions so we should calculate the sizes to make
@ -2597,24 +2599,27 @@ void ConcurrentMark::weakRefsWork(bool clear_all_soft_refs) {
assert(_markStack.isEmpty(), "Marking should have completed");
// Unload Klasses, String, Symbols, Code Cache, etc.
G1RemarkGCTraceTime trace("Unloading", G1Log::finer());
bool purged_classes;
{
G1RemarkGCTraceTime trace("System Dictionary Unloading", G1Log::finest());
purged_classes = SystemDictionary::do_unloading(&g1_is_alive);
}
G1RemarkGCTraceTime trace("Unloading", G1Log::finer());
{
G1RemarkGCTraceTime trace("Parallel Unloading", G1Log::finest());
weakRefsWorkParallelPart(&g1_is_alive, purged_classes);
}
if (ClassUnloadingWithConcurrentMark) {
bool purged_classes;
if (G1StringDedup::is_enabled()) {
G1RemarkGCTraceTime trace("String Deduplication Unlink", G1Log::finest());
G1StringDedup::unlink(&g1_is_alive);
{
G1RemarkGCTraceTime trace("System Dictionary Unloading", G1Log::finest());
purged_classes = SystemDictionary::do_unloading(&g1_is_alive);
}
{
G1RemarkGCTraceTime trace("Parallel Unloading", G1Log::finest());
weakRefsWorkParallelPart(&g1_is_alive, purged_classes);
}
}
if (G1StringDedup::is_enabled()) {
G1RemarkGCTraceTime trace("String Deduplication Unlink", G1Log::finest());
G1StringDedup::unlink(&g1_is_alive);
}
}
}

View File

@ -4920,10 +4920,15 @@ public:
if (_g1h->g1_policy()->during_initial_mark_pause()) {
// We also need to mark copied objects.
strong_root_cl = &scan_mark_root_cl;
weak_root_cl = &scan_mark_weak_root_cl;
strong_cld_cl = &scan_mark_cld_cl;
weak_cld_cl = &scan_mark_weak_cld_cl;
strong_code_cl = &scan_mark_code_cl;
if (ClassUnloadingWithConcurrentMark) {
weak_root_cl = &scan_mark_weak_root_cl;
weak_cld_cl = &scan_mark_weak_cld_cl;
} else {
weak_root_cl = &scan_mark_root_cl;
weak_cld_cl = &scan_mark_cld_cl;
}
} else {
strong_root_cl = &scan_only_root_cl;
weak_root_cl = &scan_only_root_cl;
@ -4994,6 +4999,7 @@ g1_process_roots(OopClosure* scan_non_heap_roots,
double closure_app_time_sec = 0.0;
bool during_im = _g1h->g1_policy()->during_initial_mark_pause();
bool trace_metadata = during_im && ClassUnloadingWithConcurrentMark;
BufferingOopClosure buf_scan_non_heap_roots(scan_non_heap_roots);
BufferingOopClosure buf_scan_non_heap_weak_roots(scan_non_heap_weak_roots);
@ -5003,8 +5009,8 @@ g1_process_roots(OopClosure* scan_non_heap_roots,
&buf_scan_non_heap_roots,
&buf_scan_non_heap_weak_roots,
scan_strong_clds,
// Initial Mark handles the weak CLDs separately.
(during_im ? NULL : scan_weak_clds),
// Unloading Initial Marks handle the weak CLDs separately.
(trace_metadata ? NULL : scan_weak_clds),
scan_strong_code);
// Now the CM ref_processor roots.
@ -5016,7 +5022,7 @@ g1_process_roots(OopClosure* scan_non_heap_roots,
ref_processor_cm()->weak_oops_do(&buf_scan_non_heap_roots);
}
if (during_im) {
if (trace_metadata) {
// Barrier to make sure all workers passed
// the strong CLD and strong nmethods phases.
active_strong_roots_scope()->wait_until_all_workers_done_with_threads(n_par_threads());
@ -6536,6 +6542,9 @@ class G1FreeHumongousRegionClosure : public HeapRegionClosure {
G1CollectedHeap* g1h = G1CollectedHeap::heap();
oop obj = (oop)r->bottom();
CMBitMap* next_bitmap = g1h->concurrent_mark()->nextMarkBitMap();
// The following checks whether the humongous object is live are sufficient.
// The main additional check (in addition to having a reference from the roots
// or the young gen) is whether the humongous object has a remembered set entry.
@ -6572,37 +6581,41 @@ class G1FreeHumongousRegionClosure : public HeapRegionClosure {
g1h->humongous_region_is_always_live(region_idx)) {
if (G1TraceReclaimDeadHumongousObjectsAtYoungGC) {
gclog_or_tty->print_cr("Live humongous %d region %d with remset "SIZE_FORMAT" code roots "SIZE_FORMAT" is dead-bitmap %d live-other %d obj array %d",
gclog_or_tty->print_cr("Live humongous %d region %d with remset "SIZE_FORMAT" code roots "SIZE_FORMAT" is marked %d live-other %d obj array %d",
r->isHumongous(),
region_idx,
r->rem_set()->occupied(),
r->rem_set()->strong_code_roots_list_length(),
g1h->mark_in_progress() && !g1h->g1_policy()->during_initial_mark_pause(),
next_bitmap->isMarked(r->bottom()),
g1h->humongous_is_live(region_idx),
oop(r->bottom())->is_objArray()
obj->is_objArray()
);
}
return false;
}
guarantee(!((oop)(r->bottom()))->is_objArray(),
guarantee(!obj->is_objArray(),
err_msg("Eagerly reclaiming object arrays is not supported, but the object "PTR_FORMAT" is.",
r->bottom()));
if (G1TraceReclaimDeadHumongousObjectsAtYoungGC) {
gclog_or_tty->print_cr("Reclaim humongous region %d start "PTR_FORMAT" region %d length "UINT32_FORMAT" with remset "SIZE_FORMAT" code roots "SIZE_FORMAT" is dead-bitmap %d live-other %d obj array %d",
gclog_or_tty->print_cr("Reclaim humongous region %d start "PTR_FORMAT" region %d length "UINT32_FORMAT" with remset "SIZE_FORMAT" code roots "SIZE_FORMAT" is marked %d live-other %d obj array %d",
r->isHumongous(),
r->bottom(),
region_idx,
r->region_num(),
r->rem_set()->occupied(),
r->rem_set()->strong_code_roots_list_length(),
g1h->mark_in_progress() && !g1h->g1_policy()->during_initial_mark_pause(),
next_bitmap->isMarked(r->bottom()),
g1h->humongous_is_live(region_idx),
oop(r->bottom())->is_objArray()
obj->is_objArray()
);
}
// Need to clear mark bit of the humongous object if already set.
if (next_bitmap->isMarked(r->bottom())) {
next_bitmap->clear(r->bottom());
}
_freed_bytes += r->used();
r->set_containing_set(NULL);
_humongous_regions_removed.increment(1u, r->capacity());

View File

@ -288,7 +288,12 @@ void G1ParScanThreadState::undo_allocation(GCAllocPurpose purpose, HeapWord* obj
}
HeapWord* G1ParScanThreadState::allocate(GCAllocPurpose purpose, size_t word_sz) {
HeapWord* obj = alloc_buffer(purpose)->allocate(word_sz);
HeapWord* obj = NULL;
if (purpose == GCAllocForSurvived) {
obj = alloc_buffer(GCAllocForSurvived)->allocate_aligned(word_sz, SurvivorAlignmentInBytes);
} else {
obj = alloc_buffer(GCAllocForTenured)->allocate(word_sz);
}
if (obj != NULL) {
return obj;
}

View File

@ -349,23 +349,8 @@ void G1RemSet::oops_into_collection_set_do(OopsInHeapRegionClosure* oc,
assert((ParallelGCThreads > 0) || worker_i == 0, "invariant");
// The two flags below were introduced temporarily to serialize
// the updating and scanning of remembered sets. There are some
// race conditions when these two operations are done in parallel
// and they are causing failures. When we resolve said race
// conditions, we'll revert back to parallel remembered set
// updating and scanning. See CRs 6677707 and 6677708.
if (G1UseParallelRSetUpdating || (worker_i == 0)) {
updateRS(&into_cset_dcq, worker_i);
} else {
_g1p->phase_times()->record_update_rs_processed_buffers(worker_i, 0);
_g1p->phase_times()->record_update_rs_time(worker_i, 0.0);
}
if (G1UseParallelRSetScanning || (worker_i == 0)) {
scanRS(oc, code_root_cl, worker_i);
} else {
_g1p->phase_times()->record_scan_rs_time(worker_i, 0.0);
}
updateRS(&into_cset_dcq, worker_i);
scanRS(oc, code_root_cl, worker_i);
// We now clear the cached values of _cset_rs_update_cl for this worker
_cset_rs_update_cl[worker_i] = NULL;

View File

@ -220,14 +220,6 @@
product(uintx, G1HeapRegionSize, 0, \
"Size of the G1 regions.") \
\
experimental(bool, G1UseParallelRSetUpdating, true, \
"Enables the parallelization of remembered set updating " \
"during evacuation pauses") \
\
experimental(bool, G1UseParallelRSetScanning, true, \
"Enables the parallelization of remembered set scanning " \
"during evacuation pauses") \
\
product(uintx, G1ConcRefinementThreads, 0, \
"If non-0 is the number of parallel rem set update threads, " \
"otherwise the value is determined ergonomically.") \

View File

@ -94,26 +94,37 @@ G1OffsetTableContigSpace::block_start_const(const void* p) const {
inline bool
HeapRegion::block_is_obj(const HeapWord* p) const {
G1CollectedHeap* g1h = G1CollectedHeap::heap();
return !g1h->is_obj_dead(oop(p), this);
if (ClassUnloadingWithConcurrentMark) {
return !g1h->is_obj_dead(oop(p), this);
}
return p < top();
}
inline size_t
HeapRegion::block_size(const HeapWord *addr) const {
if (addr == top()) {
return pointer_delta(end(), addr);
}
if (block_is_obj(addr)) {
return oop(addr)->size();
}
assert(ClassUnloadingWithConcurrentMark,
err_msg("All blocks should be objects if G1 Class Unloading isn't used. "
"HR: ["PTR_FORMAT", "PTR_FORMAT", "PTR_FORMAT") "
"addr: " PTR_FORMAT,
p2i(bottom()), p2i(top()), p2i(end()), p2i(addr)));
// Old regions' dead objects may have dead classes
// We need to find the next live object in some other
// manner than getting the oop size
G1CollectedHeap* g1h = G1CollectedHeap::heap();
if (g1h->is_obj_dead(oop(addr), this)) {
HeapWord* next = g1h->concurrent_mark()->prevMarkBitMap()->
getNextMarkedWordAddress(addr, prev_top_at_mark_start());
HeapWord* next = g1h->concurrent_mark()->prevMarkBitMap()->
getNextMarkedWordAddress(addr, prev_top_at_mark_start());
assert(next > addr, "must get the next live object");
return pointer_delta(next, addr);
} else if (addr == top()) {
return pointer_delta(end(), addr);
}
return oop(addr)->size();
assert(next > addr, "must get the next live object");
return pointer_delta(next, addr);
}
inline HeapWord* HeapRegion::par_allocate_no_bot_updates(size_t word_size) {

View File

@ -289,7 +289,7 @@ OtherRegionsTable::OtherRegionsTable(HeapRegion* hr, Mutex* m) :
}
_fine_grain_regions = NEW_C_HEAP_ARRAY3(PerRegionTablePtr, _max_fine_entries,
mtGC, 0, AllocFailStrategy::RETURN_NULL);
mtGC, CURRENT_PC, AllocFailStrategy::RETURN_NULL);
if (_fine_grain_regions == NULL) {
vm_exit_out_of_memory(sizeof(void*)*_max_fine_entries, OOM_MALLOC_ERROR,

View File

@ -28,12 +28,12 @@
#include "gc_implementation/parNew/parOopClosures.inline.hpp"
#include "gc_implementation/shared/adaptiveSizePolicy.hpp"
#include "gc_implementation/shared/ageTable.hpp"
#include "gc_implementation/shared/parGCAllocBuffer.hpp"
#include "gc_implementation/shared/copyFailedInfo.hpp"
#include "gc_implementation/shared/gcHeapSummary.hpp"
#include "gc_implementation/shared/gcTimer.hpp"
#include "gc_implementation/shared/gcTrace.hpp"
#include "gc_implementation/shared/gcTraceTime.hpp"
#include "gc_implementation/shared/copyFailedInfo.hpp"
#include "gc_implementation/shared/parGCAllocBuffer.inline.hpp"
#include "gc_implementation/shared/spaceDecorator.hpp"
#include "memory/defNewGeneration.inline.hpp"
#include "memory/genCollectedHeap.hpp"
@ -252,7 +252,7 @@ HeapWord* ParScanThreadState::alloc_in_to_space_slow(size_t word_sz) {
plab->set_word_size(buf_size);
plab->set_buf(buf_space);
record_survivor_plab(buf_space, buf_size);
obj = plab->allocate(word_sz);
obj = plab->allocate_aligned(word_sz, SurvivorAlignmentInBytes);
// Note that we cannot compare buf_size < word_sz below
// because of AlignmentReserve (see ParGCAllocBuffer::allocate()).
assert(obj != NULL || plab->words_remaining() < word_sz,

View File

@ -168,7 +168,7 @@ class ParScanThreadState {
HeapWord* alloc_in_to_space_slow(size_t word_sz);
HeapWord* alloc_in_to_space(size_t word_sz) {
HeapWord* obj = to_space_alloc_buffer()->allocate(word_sz);
HeapWord* obj = to_space_alloc_buffer()->allocate_aligned(word_sz, SurvivorAlignmentInBytes);
if (obj != NULL) return obj;
else return alloc_in_to_space_slow(word_sz);
}

View File

@ -26,6 +26,7 @@
#define SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PSPROMOTIONLAB_HPP
#include "gc_implementation/parallelScavenge/objectStartArray.hpp"
#include "gc_interface/collectedHeap.inline.hpp"
#include "memory/allocation.hpp"
//
@ -94,23 +95,9 @@ class PSYoungPromotionLAB : public PSPromotionLAB {
PSYoungPromotionLAB() { }
// Not MT safe
HeapWord* allocate(size_t size) {
// Can't assert this, when young fills, we keep the LAB around, but flushed.
// assert(_state != flushed, "Sanity");
HeapWord* obj = top();
HeapWord* new_top = obj + size;
// The 'new_top>obj' check is needed to detect overflow of obj+size.
if (new_top > obj && new_top <= end()) {
set_top(new_top);
assert(is_object_aligned((intptr_t)obj) && is_object_aligned((intptr_t)new_top),
"checking alignment");
return obj;
}
inline HeapWord* allocate(size_t size);
return NULL;
}
debug_only(virtual bool lab_is_valid(MemRegion lab));
debug_only(virtual bool lab_is_valid(MemRegion lab);)
};
class PSOldPromotionLAB : public PSPromotionLAB {

View File

@ -0,0 +1,52 @@
/*
* 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.
*
*/
#ifndef SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PSPROMOTIONLAB_INLINE_HPP
#define SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PSPROMOTIONLAB_INLINE_HPP
#include "gc_implementation/parallelScavenge/psPromotionLAB.hpp"
#include "gc_interface/collectedHeap.inline.hpp"
HeapWord* PSYoungPromotionLAB::allocate(size_t size) {
// Can't assert this, when young fills, we keep the LAB around, but flushed.
// assert(_state != flushed, "Sanity");
HeapWord* obj = CollectedHeap::align_allocation_or_fail(top(), end(), SurvivorAlignmentInBytes);
if (obj == NULL) {
return NULL;
}
HeapWord* new_top = obj + size;
// The 'new_top>obj' check is needed to detect overflow of obj+size.
if (new_top > obj && new_top <= end()) {
set_top(new_top);
assert(is_ptr_aligned(obj, SurvivorAlignmentInBytes) && is_object_aligned((intptr_t)new_top),
"checking alignment");
return obj;
} else {
set_top(obj);
return NULL;
}
}
#endif // SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PSPROMOTIONLAB_INLINE_HPP

View File

@ -27,6 +27,7 @@
#include "gc_implementation/parallelScavenge/psOldGen.hpp"
#include "gc_implementation/parallelScavenge/psPromotionManager.hpp"
#include "gc_implementation/parallelScavenge/psPromotionLAB.inline.hpp"
#include "gc_implementation/parallelScavenge/psScavenge.hpp"
#include "oops/oop.psgc.inline.hpp"

View File

@ -24,7 +24,7 @@
#ifndef SHARE_VM_GC_IMPLEMENTATION_PARNEW_PARGCALLOCBUFFER_HPP
#define SHARE_VM_GC_IMPLEMENTATION_PARNEW_PARGCALLOCBUFFER_HPP
#include "gc_interface/collectedHeap.hpp"
#include "memory/allocation.hpp"
#include "memory/blockOffsetTable.hpp"
#include "memory/threadLocalAllocBuffer.hpp"
@ -84,6 +84,9 @@ public:
}
}
// Allocate the object aligned to "alignment_in_bytes".
HeapWord* allocate_aligned(size_t word_sz, unsigned short alignment_in_bytes);
// Undo the last allocation in the buffer, which is required to be of the
// "obj" of the given "word_sz".
void undo_allocation(HeapWord* obj, size_t word_sz) {

View File

@ -0,0 +1,44 @@
/*
* 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.
*
*/
#ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_PARGCALLOCBUFFER_INLINE_HPP
#define SHARE_VM_GC_IMPLEMENTATION_SHARED_PARGCALLOCBUFFER_INLINE_HPP
#include "gc_implementation/shared/parGCAllocBuffer.hpp"
#include "gc_interface/collectedHeap.inline.hpp"
HeapWord* ParGCAllocBuffer::allocate_aligned(size_t word_sz, unsigned short alignment_in_bytes) {
HeapWord* res = CollectedHeap::align_allocation_or_fail(_top, _end, alignment_in_bytes);
if (res == NULL) {
return NULL;
}
// Set _top so that allocate(), which expects _top to be correctly set,
// can be used below.
_top = res;
return allocate(word_sz);
}
#endif // SHARE_VM_GC_IMPLEMENTATION_SHARED_PARGCALLOCBUFFER_INLINE_HPP

View File

@ -195,6 +195,7 @@ void VM_GenCollectFull::doit() {
gch->do_full_collection(gch->must_clear_all_soft_refs(), _max_level);
}
// Returns true iff concurrent GCs unloads metadata.
bool VM_CollectForMetadataAllocation::initiate_concurrent_GC() {
#if INCLUDE_ALL_GCS
if (UseConcMarkSweepGC && CMSClassUnloadingEnabled) {
@ -202,7 +203,7 @@ bool VM_CollectForMetadataAllocation::initiate_concurrent_GC() {
return true;
}
if (UseG1GC) {
if (UseG1GC && ClassUnloadingWithConcurrentMark) {
G1CollectedHeap* g1h = G1CollectedHeap::heap();
g1h->g1_policy()->set_initiate_conc_mark_if_possible();

View File

@ -351,6 +351,12 @@ class CollectedHeap : public CHeapObj<mtInternal> {
fill_with_object(start, pointer_delta(end, start), zap);
}
// Return the address "addr" aligned by "alignment_in_bytes" if such
// an address is below "end". Return NULL otherwise.
inline static HeapWord* align_allocation_or_fail(HeapWord* addr,
HeapWord* end,
unsigned short alignment_in_bytes);
// Some heaps may offer a contiguous region for shared non-blocking
// allocation, via inlined code (by exporting the address of the top and
// end fields defining the extent of the contiguous allocation region.)

View File

@ -241,6 +241,44 @@ inline void CollectedHeap::oop_iterate_no_header(OopClosure* cl) {
oop_iterate(&no_header_cl);
}
inline HeapWord* CollectedHeap::align_allocation_or_fail(HeapWord* addr,
HeapWord* end,
unsigned short alignment_in_bytes) {
if (alignment_in_bytes <= ObjectAlignmentInBytes) {
return addr;
}
assert(is_ptr_aligned(addr, HeapWordSize),
err_msg("Address " PTR_FORMAT " is not properly aligned.", p2i(addr)));
assert(is_size_aligned(alignment_in_bytes, HeapWordSize),
err_msg("Alignment size %u is incorrect.", alignment_in_bytes));
HeapWord* new_addr = (HeapWord*) align_pointer_up(addr, alignment_in_bytes);
size_t padding = pointer_delta(new_addr, addr);
if (padding == 0) {
return addr;
}
if (padding < CollectedHeap::min_fill_size()) {
padding += alignment_in_bytes / HeapWordSize;
assert(padding >= CollectedHeap::min_fill_size(),
err_msg("alignment_in_bytes %u is expect to be larger "
"than the minimum object size", alignment_in_bytes));
new_addr = addr + padding;
}
assert(new_addr > addr, err_msg("Unexpected arithmetic overflow "
PTR_FORMAT " not greater than " PTR_FORMAT, p2i(new_addr), p2i(addr)));
if(new_addr < end) {
CollectedHeap::fill_with_object(addr, padding);
return new_addr;
} else {
return NULL;
}
}
#ifndef PRODUCT
inline bool

View File

@ -280,9 +280,6 @@ class AbstractInterpreterGenerator: public StackObj {
address generate_result_handler_for(BasicType type);
address generate_slow_signature_handler();
// entry point generator
address generate_method_entry(AbstractInterpreter::MethodKind kind);
void bang_stack_shadow_pages(bool native_call);
void generate_all();

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2011, 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
@ -108,7 +108,7 @@ void CppInterpreterGenerator::generate_all() {
}
#define method_entry(kind) Interpreter::_entry_table[Interpreter::kind] = generate_method_entry(Interpreter::kind)
#define method_entry(kind) Interpreter::_entry_table[Interpreter::kind] = ((InterpreterGenerator*)this)->generate_method_entry(Interpreter::kind)
{ CodeletMark cm(_masm, "(kind = frame_manager)");
// all non-native method kinds

View File

@ -29,6 +29,7 @@
#include "interpreter/bytecodeHistogram.hpp"
#include "interpreter/bytecodeInterpreter.hpp"
#include "interpreter/interpreter.hpp"
#include "interpreter/interpreterGenerator.hpp"
#include "interpreter/interpreterRuntime.hpp"
#include "interpreter/interp_masm.hpp"
#include "interpreter/templateTable.hpp"
@ -261,7 +262,7 @@ AbstractInterpreter::MethodKind AbstractInterpreter::method_kind(methodHandle m)
// Special intrinsic method?
// Note: This test must come _after_ the test for native methods,
// otherwise we will run into problems with JDK 1.2, see also
// AbstractInterpreterGenerator::generate_method_entry() for
// InterpreterGenerator::generate_method_entry() for
// for details.
switch (m->intrinsic_id()) {
case vmIntrinsics::_dsin : return java_lang_math_sin ;
@ -521,3 +522,50 @@ void AbstractInterpreterGenerator::initialize_method_handle_entries() {
Interpreter::_entry_table[kind] = Interpreter::_entry_table[Interpreter::abstract];
}
}
// Generate method entries
address InterpreterGenerator::generate_method_entry(
AbstractInterpreter::MethodKind kind) {
// determine code generation flags
bool synchronized = false;
address entry_point = NULL;
switch (kind) {
case Interpreter::zerolocals : break;
case Interpreter::zerolocals_synchronized: synchronized = true; break;
case Interpreter::native : entry_point = generate_native_entry(false); break;
case Interpreter::native_synchronized : entry_point = generate_native_entry(true); break;
case Interpreter::empty : entry_point = generate_empty_entry(); break;
case Interpreter::accessor : entry_point = generate_accessor_entry(); break;
case Interpreter::abstract : entry_point = generate_abstract_entry(); break;
case Interpreter::java_lang_math_sin : // fall thru
case Interpreter::java_lang_math_cos : // fall thru
case Interpreter::java_lang_math_tan : // fall thru
case Interpreter::java_lang_math_abs : // fall thru
case Interpreter::java_lang_math_log : // fall thru
case Interpreter::java_lang_math_log10 : // fall thru
case Interpreter::java_lang_math_sqrt : // fall thru
case Interpreter::java_lang_math_pow : // fall thru
case Interpreter::java_lang_math_exp : entry_point = generate_math_entry(kind); break;
case Interpreter::java_lang_ref_reference_get
: entry_point = generate_Reference_get_entry(); break;
#ifndef CC_INTERP
case Interpreter::java_util_zip_CRC32_update
: entry_point = generate_CRC32_update_entry(); break;
case Interpreter::java_util_zip_CRC32_updateBytes
: // fall thru
case Interpreter::java_util_zip_CRC32_updateByteBuffer
: entry_point = generate_CRC32_updateBytes_entry(kind); break;
#endif // CC_INTERP
default:
fatal(err_msg("unexpected method kind: %d", kind));
break;
}
if (entry_point) {
return entry_point;
}
return generate_normal_entry(synchronized);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2011, 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
@ -37,9 +37,11 @@
class InterpreterGenerator: public CC_INTERP_ONLY(CppInterpreterGenerator)
NOT_CC_INTERP(TemplateInterpreterGenerator) {
public:
public:
InterpreterGenerator(StubQueue* _code);
InterpreterGenerator(StubQueue* _code);
// entry point generator
address generate_method_entry(AbstractInterpreter::MethodKind kind);
#ifdef TARGET_ARCH_x86
# include "interpreterGenerator_x86.hpp"

View File

@ -364,7 +364,7 @@ void TemplateInterpreterGenerator::generate_all() {
#define method_entry(kind) \
{ CodeletMark cm(_masm, "method entry point (kind = " #kind ")"); \
Interpreter::_entry_table[Interpreter::kind] = generate_method_entry(Interpreter::kind); \
Interpreter::_entry_table[Interpreter::kind] = ((InterpreterGenerator*)this)->generate_method_entry(Interpreter::kind); \
}
// all non-native method kinds

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
@ -59,9 +59,6 @@ class TemplateInterpreterGenerator: public AbstractInterpreterGenerator {
address generate_safept_entry_for(TosState state, address runtime_entry);
void generate_throw_exception();
// entry point generator
// address generate_method_entry(AbstractInterpreter::MethodKind kind);
// Instruction generation
void generate_and_dispatch (Template* t, TosState tos_out = ilgl);
void set_vtos_entry_points (Template* t, address& bep, address& cep, address& sep, address& aep, address& iep, address& lep, address& fep, address& dep, address& vep);

View File

@ -422,26 +422,23 @@ void Chunk::start_chunk_pool_cleaner_task() {
}
//------------------------------Arena------------------------------------------
NOT_PRODUCT(volatile jint Arena::_instance_count = 0;)
Arena::Arena(size_t init_size) {
Arena::Arena(MEMFLAGS flag, size_t init_size) : _flags(flag), _size_in_bytes(0) {
size_t round_size = (sizeof (char *)) - 1;
init_size = (init_size+round_size) & ~round_size;
_first = _chunk = new (AllocFailStrategy::EXIT_OOM, init_size) Chunk(init_size);
_hwm = _chunk->bottom(); // Save the cached hwm, max
_max = _chunk->top();
_size_in_bytes = 0;
MemTracker::record_new_arena(flag);
set_size_in_bytes(init_size);
NOT_PRODUCT(Atomic::inc(&_instance_count);)
}
Arena::Arena() {
Arena::Arena(MEMFLAGS flag) : _flags(flag), _size_in_bytes(0) {
_first = _chunk = new (AllocFailStrategy::EXIT_OOM, Chunk::init_size) Chunk(Chunk::init_size);
_hwm = _chunk->bottom(); // Save the cached hwm, max
_max = _chunk->top();
_size_in_bytes = 0;
MemTracker::record_new_arena(flag);
set_size_in_bytes(Chunk::init_size);
NOT_PRODUCT(Atomic::inc(&_instance_count);)
}
Arena *Arena::move_contents(Arena *copy) {
@ -463,7 +460,7 @@ Arena *Arena::move_contents(Arena *copy) {
Arena::~Arena() {
destruct_contents();
NOT_PRODUCT(Atomic::dec(&_instance_count);)
MemTracker::record_arena_free(_flags);
}
void* Arena::operator new(size_t size) throw() {
@ -479,21 +476,21 @@ void* Arena::operator new (size_t size, const std::nothrow_t& nothrow_constant)
// dynamic memory type binding
void* Arena::operator new(size_t size, MEMFLAGS flags) throw() {
#ifdef ASSERT
void* p = (void*)AllocateHeap(size, flags|otArena, CALLER_PC);
void* p = (void*)AllocateHeap(size, flags, CALLER_PC);
if (PrintMallocFree) trace_heap_malloc(size, "Arena-new", p);
return p;
#else
return (void *) AllocateHeap(size, flags|otArena, CALLER_PC);
return (void *) AllocateHeap(size, flags, CALLER_PC);
#endif
}
void* Arena::operator new(size_t size, const std::nothrow_t& nothrow_constant, MEMFLAGS flags) throw() {
#ifdef ASSERT
void* p = os::malloc(size, flags|otArena, CALLER_PC);
void* p = os::malloc(size, flags, CALLER_PC);
if (PrintMallocFree) trace_heap_malloc(size, "Arena-new", p);
return p;
#else
return os::malloc(size, flags|otArena, CALLER_PC);
return os::malloc(size, flags, CALLER_PC);
#endif
}
@ -518,8 +515,9 @@ void Arena::destruct_contents() {
// change the size
void Arena::set_size_in_bytes(size_t size) {
if (_size_in_bytes != size) {
long delta = (long)(size - size_in_bytes());
_size_in_bytes = size;
MemTracker::record_arena_size((address)this, size);
MemTracker::record_arena_size_change(delta, _flags);
}
}

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
@ -133,51 +133,34 @@ class AllocatedObj {
/*
* MemoryType bitmap layout:
* | 16 15 14 13 12 11 10 09 | 08 07 06 05 | 04 03 02 01 |
* | memory type | object | reserved |
* | | type | |
* Memory types
*/
enum MemoryType {
// Memory type by sub systems. It occupies lower byte.
mtNone = 0x0000, // undefined
mtClass = 0x0100, // memory class for Java classes
mtThread = 0x0200, // memory for thread objects
mtThreadStack = 0x0300,
mtCode = 0x0400, // memory for generated code
mtGC = 0x0500, // memory for GC
mtCompiler = 0x0600, // memory for compiler
mtInternal = 0x0700, // memory used by VM, but does not belong to
mtJavaHeap = 0x00, // Java heap
mtClass = 0x01, // memory class for Java classes
mtThread = 0x02, // memory for thread objects
mtThreadStack = 0x03,
mtCode = 0x04, // memory for generated code
mtGC = 0x05, // memory for GC
mtCompiler = 0x06, // memory for compiler
mtInternal = 0x07, // memory used by VM, but does not belong to
// any of above categories, and not used for
// native memory tracking
mtOther = 0x0800, // memory not used by VM
mtSymbol = 0x0900, // symbol
mtNMT = 0x0A00, // memory used by native memory tracking
mtChunk = 0x0B00, // chunk that holds content of arenas
mtJavaHeap = 0x0C00, // Java heap
mtClassShared = 0x0D00, // class data sharing
mtTest = 0x0E00, // Test type for verifying NMT
mtTracing = 0x0F00, // memory used for Tracing
mt_number_of_types = 0x000F, // number of memory types (mtDontTrack
mtOther = 0x08, // memory not used by VM
mtSymbol = 0x09, // symbol
mtNMT = 0x0A, // memory used by native memory tracking
mtClassShared = 0x0B, // class data sharing
mtChunk = 0x0C, // chunk that holds content of arenas
mtTest = 0x0D, // Test type for verifying NMT
mtTracing = 0x0E, // memory used for Tracing
mtNone = 0x0F, // undefined
mt_number_of_types = 0x10 // number of memory types (mtDontTrack
// is not included as validate type)
mtDontTrack = 0x0F00, // memory we do not or cannot track
mt_masks = 0x7F00,
// object type mask
otArena = 0x0010, // an arena object
otNMTRecorder = 0x0020, // memory recorder object
ot_masks = 0x00F0
};
#define IS_MEMORY_TYPE(flags, type) ((flags & mt_masks) == type)
#define HAS_VALID_MEMORY_TYPE(flags)((flags & mt_masks) != mtNone)
#define FLAGS_TO_MEMORY_TYPE(flags) (flags & mt_masks)
typedef MemoryType MEMFLAGS;
#define IS_ARENA_OBJ(flags) ((flags & ot_masks) == otArena)
#define IS_NMT_RECORDER(flags) ((flags & ot_masks) == otNMTRecorder)
#define NMT_CAN_TRACK(flags) (!IS_NMT_RECORDER(flags) && !(IS_MEMORY_TYPE(flags, mtDontTrack)))
typedef unsigned short MEMFLAGS;
#if INCLUDE_NMT
@ -189,27 +172,23 @@ const bool NMT_track_callsite = false;
#endif // INCLUDE_NMT
// debug build does not inline
#if defined(_NMT_NOINLINE_)
#define CURRENT_PC (NMT_track_callsite ? os::get_caller_pc(1) : 0)
#define CALLER_PC (NMT_track_callsite ? os::get_caller_pc(2) : 0)
#define CALLER_CALLER_PC (NMT_track_callsite ? os::get_caller_pc(3) : 0)
#else
#define CURRENT_PC (NMT_track_callsite? os::get_caller_pc(0) : 0)
#define CALLER_PC (NMT_track_callsite ? os::get_caller_pc(1) : 0)
#define CALLER_CALLER_PC (NMT_track_callsite ? os::get_caller_pc(2) : 0)
#endif
class NativeCallStack;
template <MEMFLAGS F> class CHeapObj ALLOCATION_SUPER_CLASS_SPEC {
public:
_NOINLINE_ void* operator new(size_t size, address caller_pc = 0) throw();
_NOINLINE_ void* operator new(size_t size, const NativeCallStack& stack) throw();
_NOINLINE_ void* operator new(size_t size) throw();
_NOINLINE_ void* operator new (size_t size, const std::nothrow_t& nothrow_constant,
address caller_pc = 0) throw();
_NOINLINE_ void* operator new [](size_t size, address caller_pc = 0) throw();
const NativeCallStack& stack) throw();
_NOINLINE_ void* operator new (size_t size, const std::nothrow_t& nothrow_constant)
throw();
_NOINLINE_ void* operator new [](size_t size, const NativeCallStack& stack) throw();
_NOINLINE_ void* operator new [](size_t size) throw();
_NOINLINE_ void* operator new [](size_t size, const std::nothrow_t& nothrow_constant,
address caller_pc = 0) throw();
const NativeCallStack& stack) throw();
_NOINLINE_ void* operator new [](size_t size, const std::nothrow_t& nothrow_constant)
throw();
void operator delete(void* p);
void operator delete [] (void* p);
};
@ -384,13 +363,15 @@ class Chunk: CHeapObj<mtChunk> {
//------------------------------Arena------------------------------------------
// Fast allocation of memory
class Arena : public CHeapObj<mtNone|otArena> {
class Arena : public CHeapObj<mtNone> {
protected:
friend class ResourceMark;
friend class HandleMark;
friend class NoHandleMark;
friend class VMStructs;
MEMFLAGS _flags; // Memory tracking flags
Chunk *_first; // First chunk
Chunk *_chunk; // current chunk
char *_hwm, *_max; // High water mark and max in current chunk
@ -418,8 +399,8 @@ protected:
}
public:
Arena();
Arena(size_t init_size);
Arena(MEMFLAGS memflag);
Arena(MEMFLAGS memflag, size_t init_size);
~Arena();
void destruct_contents();
char* hwm() const { return _hwm; }
@ -518,8 +499,6 @@ protected:
static void free_malloced_objects(Chunk* chunk, char* hwm, char* max, char* hwm2) PRODUCT_RETURN;
static void free_all(char** start, char** end) PRODUCT_RETURN;
// how many arena instances
NOT_PRODUCT(static volatile jint _instance_count;)
private:
// Reset this Arena to empty, access will trigger grow if necessary
void reset(void) {
@ -681,7 +660,7 @@ class ResourceObj ALLOCATION_SUPER_CLASS_SPEC {
NEW_C_HEAP_ARRAY3(type, (size), memflags, pc, AllocFailStrategy::RETURN_NULL)
#define NEW_C_HEAP_ARRAY_RETURN_NULL(type, size, memflags)\
NEW_C_HEAP_ARRAY3(type, (size), memflags, (address)0, AllocFailStrategy::RETURN_NULL)
NEW_C_HEAP_ARRAY3(type, (size), memflags, CURRENT_PC, AllocFailStrategy::RETURN_NULL)
#define REALLOC_C_HEAP_ARRAY(type, old, size, memflags)\
(type*) (ReallocateHeap((char*)(old), (size) * sizeof(type), memflags))

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
@ -27,6 +27,7 @@
#include "runtime/atomic.inline.hpp"
#include "runtime/os.hpp"
#include "services/memTracker.hpp"
// Explicit C-heap memory management
@ -49,12 +50,10 @@ inline void inc_stat_counter(volatile julong* dest, julong add_value) {
#endif
// allocate using malloc; will fail if no memory available
inline char* AllocateHeap(size_t size, MEMFLAGS flags, address pc = 0,
inline char* AllocateHeap(size_t size, MEMFLAGS flags,
const NativeCallStack& stack,
AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM) {
if (pc == 0) {
pc = CURRENT_PC;
}
char* p = (char*) os::malloc(size, flags, pc);
char* p = (char*) os::malloc(size, flags, stack);
#ifdef ASSERT
if (PrintMallocFree) trace_heap_malloc(size, "AllocateHeap", p);
#endif
@ -63,10 +62,14 @@ inline char* AllocateHeap(size_t size, MEMFLAGS flags, address pc = 0,
}
return p;
}
inline char* ReallocateHeap(char *old, size_t size, MEMFLAGS flags,
inline char* AllocateHeap(size_t size, MEMFLAGS flags,
AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM) {
char* p = (char*) os::realloc(old, size, flags, CURRENT_PC);
return AllocateHeap(size, flags, CURRENT_PC, alloc_failmode);
}
inline char* ReallocateHeap(char *old, size_t size, MEMFLAGS flag,
AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM) {
char* p = (char*) os::realloc(old, size, flag, CURRENT_PC);
#ifdef ASSERT
if (PrintMallocFree) trace_heap_malloc(size, "ReallocateHeap", p);
#endif
@ -85,8 +88,22 @@ inline void FreeHeap(void* p, MEMFLAGS memflags = mtInternal) {
template <MEMFLAGS F> void* CHeapObj<F>::operator new(size_t size,
address caller_pc) throw() {
void* p = (void*)AllocateHeap(size, F, (caller_pc != 0 ? caller_pc : CALLER_PC));
const NativeCallStack& stack) throw() {
void* p = (void*)AllocateHeap(size, F, stack);
#ifdef ASSERT
if (PrintMallocFree) trace_heap_malloc(size, "CHeapObj-new", p);
#endif
return p;
}
template <MEMFLAGS F> void* CHeapObj<F>::operator new(size_t size) throw() {
return CHeapObj<F>::operator new(size, CALLER_PC);
}
template <MEMFLAGS F> void* CHeapObj<F>::operator new (size_t size,
const std::nothrow_t& nothrow_constant, const NativeCallStack& stack) throw() {
void* p = (void*)AllocateHeap(size, F, stack,
AllocFailStrategy::RETURN_NULL);
#ifdef ASSERT
if (PrintMallocFree) trace_heap_malloc(size, "CHeapObj-new", p);
#endif
@ -94,23 +111,28 @@ template <MEMFLAGS F> void* CHeapObj<F>::operator new(size_t size,
}
template <MEMFLAGS F> void* CHeapObj<F>::operator new (size_t size,
const std::nothrow_t& nothrow_constant, address caller_pc) throw() {
void* p = (void*)AllocateHeap(size, F, (caller_pc != 0 ? caller_pc : CALLER_PC),
AllocFailStrategy::RETURN_NULL);
#ifdef ASSERT
if (PrintMallocFree) trace_heap_malloc(size, "CHeapObj-new", p);
#endif
return p;
const std::nothrow_t& nothrow_constant) throw() {
return CHeapObj<F>::operator new(size, nothrow_constant, CALLER_PC);
}
template <MEMFLAGS F> void* CHeapObj<F>::operator new [](size_t size,
address caller_pc) throw() {
return CHeapObj<F>::operator new(size, caller_pc);
const NativeCallStack& stack) throw() {
return CHeapObj<F>::operator new(size, stack);
}
template <MEMFLAGS F> void* CHeapObj<F>::operator new [](size_t size)
throw() {
return CHeapObj<F>::operator new(size, CALLER_PC);
}
template <MEMFLAGS F> void* CHeapObj<F>::operator new [](size_t size,
const std::nothrow_t& nothrow_constant, address caller_pc) throw() {
return CHeapObj<F>::operator new(size, nothrow_constant, caller_pc);
const std::nothrow_t& nothrow_constant, const NativeCallStack& stack) throw() {
return CHeapObj<F>::operator new(size, nothrow_constant, stack);
}
template <MEMFLAGS F> void* CHeapObj<F>::operator new [](size_t size,
const std::nothrow_t& nothrow_constant) throw() {
return CHeapObj<F>::operator new(size, nothrow_constant, CALLER_PC);
}
template <MEMFLAGS F> void CHeapObj<F>::operator delete(void* p){

View File

@ -56,7 +56,7 @@ CardTableRS::CardTableRS(MemRegion whole_heap,
#endif
set_bs(_ct_bs);
_last_cur_val_in_gen = NEW_C_HEAP_ARRAY3(jbyte, GenCollectedHeap::max_gens + 1,
mtGC, 0, AllocFailStrategy::RETURN_NULL);
mtGC, CURRENT_PC, AllocFailStrategy::RETURN_NULL);
if (_last_cur_val_in_gen == NULL) {
vm_exit_during_initialization("Could not create last_cur_val_in_gen array.");
}

View File

@ -909,7 +909,8 @@ void MarkSweepPolicy::initialize_alignments() {
}
void MarkSweepPolicy::initialize_generations() {
_generations = NEW_C_HEAP_ARRAY3(GenerationSpecPtr, number_of_generations(), mtGC, 0, AllocFailStrategy::RETURN_NULL);
_generations = NEW_C_HEAP_ARRAY3(GenerationSpecPtr, number_of_generations(), mtGC, CURRENT_PC,
AllocFailStrategy::RETURN_NULL);
if (_generations == NULL) {
vm_exit_during_initialization("Unable to allocate gen spec");
}

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