Merge
This commit is contained in:
commit
ff8542fff0
@ -160,3 +160,4 @@ cc771d92284f71765eca14d6d08703c4af254c04 jdk8-b21
|
||||
6a6ba0a07f33d37a2f97b1107e60c6a9a69ec84d jdk8-b36
|
||||
b2972095a4b1e2a97409b7c3df61f3b263a5ce14 jdk8-b37
|
||||
d939bd0ab13c16647ffa38cc4b64fb31b7d44e10 jdk8-b38
|
||||
8927dd68aee3fa54a1a698e2980e1b2f6c7c12c1 jdk8-b39
|
||||
|
@ -246,3 +246,5 @@ bfcf92bfefb82da00f7fdbf0d9273feaa0a9456d jdk8-b37
|
||||
7d5ec8bf38d1b12e0e09ec381f10976b8beede3b hs24-b09
|
||||
637c3f5f068f88fb9ec9c5867341cf59fd5ebedc jdk8-b38
|
||||
73147e6c48813b5fee904aa33f79a77103250ff4 hs24-b10
|
||||
96a403721094ecdaf6a1f4f52ebd0a82e07df199 jdk8-b39
|
||||
14b0e07ab9a6fa1662414496b7e07ac8450cf517 hs24-b11
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2006, 2012, 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
|
||||
@ -31,11 +31,11 @@
|
||||
#
|
||||
|
||||
# Don't put quotes (fail windows build).
|
||||
HOTSPOT_VM_COPYRIGHT=Copyright 2011
|
||||
HOTSPOT_VM_COPYRIGHT=Copyright 2012
|
||||
|
||||
HS_MAJOR_VER=24
|
||||
HS_MINOR_VER=0
|
||||
HS_BUILD_NUMBER=10
|
||||
HS_BUILD_NUMBER=11
|
||||
|
||||
JDK_MAJOR_VER=1
|
||||
JDK_MINOR_VER=8
|
||||
|
@ -102,9 +102,11 @@ CXXFLAGS = \
|
||||
# a time and date.
|
||||
vm_version.o: CXXFLAGS += ${JRE_VERSION}
|
||||
|
||||
ifndef JAVASE_EMBEDDED
|
||||
ifndef JAVASE_EMBEDDED
|
||||
ifneq (${ARCH},arm)
|
||||
CFLAGS += -DINCLUDE_TRACE
|
||||
endif
|
||||
endif
|
||||
|
||||
# CFLAGS_WARN holds compiler options to suppress/enable warnings.
|
||||
CFLAGS += $(CFLAGS_WARN/BYFILE)
|
||||
@ -153,11 +155,13 @@ SOURCE_PATHS+=$(HS_COMMON_SRC)/os/posix/vm
|
||||
SOURCE_PATHS+=$(HS_COMMON_SRC)/cpu/$(Platform_arch)/vm
|
||||
SOURCE_PATHS+=$(HS_COMMON_SRC)/os_cpu/$(Platform_os_arch)/vm
|
||||
|
||||
ifndef JAVASE_EMBEDDED
|
||||
ifndef JAVASE_EMBEDDED
|
||||
ifneq (${ARCH},arm)
|
||||
SOURCE_PATHS+=$(shell if [ -d $(HS_ALT_SRC)/share/vm/jfr ]; then \
|
||||
find $(HS_ALT_SRC)/share/vm/jfr -type d; \
|
||||
fi)
|
||||
endif
|
||||
endif
|
||||
|
||||
CORE_PATHS=$(foreach path,$(SOURCE_PATHS),$(call altsrc,$(path)) $(path))
|
||||
CORE_PATHS+=$(GENERATED)/jvmtifiles
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2012, 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
|
||||
@ -238,9 +238,12 @@ void LIR_Assembler::emit_string_compare(LIR_Opr left, LIR_Opr right, LIR_Opr dst
|
||||
|
||||
Register result = dst->as_register();
|
||||
{
|
||||
// Get a pointer to the first character of string0 in tmp0 and get string0.count in str0
|
||||
// Get a pointer to the first character of string1 in tmp1 and get string1.count in str1
|
||||
// Also, get string0.count-string1.count in o7 and get the condition code set
|
||||
// Get a pointer to the first character of string0 in tmp0
|
||||
// and get string0.length() in str0
|
||||
// Get a pointer to the first character of string1 in tmp1
|
||||
// and get string1.length() in str1
|
||||
// Also, get string0.length()-string1.length() in
|
||||
// o7 and get the condition code set
|
||||
// Note: some instructions have been hoisted for better instruction scheduling
|
||||
|
||||
Register tmp0 = L0;
|
||||
@ -248,27 +251,40 @@ void LIR_Assembler::emit_string_compare(LIR_Opr left, LIR_Opr right, LIR_Opr dst
|
||||
Register tmp2 = L2;
|
||||
|
||||
int value_offset = java_lang_String:: value_offset_in_bytes(); // char array
|
||||
int offset_offset = java_lang_String::offset_offset_in_bytes(); // first character position
|
||||
int count_offset = java_lang_String:: count_offset_in_bytes();
|
||||
|
||||
__ load_heap_oop(str0, value_offset, tmp0);
|
||||
__ ld(str0, offset_offset, tmp2);
|
||||
__ add(tmp0, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp0);
|
||||
__ ld(str0, count_offset, str0);
|
||||
__ sll(tmp2, exact_log2(sizeof(jchar)), tmp2);
|
||||
if (java_lang_String::has_offset_field()) {
|
||||
int offset_offset = java_lang_String::offset_offset_in_bytes(); // first character position
|
||||
int count_offset = java_lang_String:: count_offset_in_bytes();
|
||||
__ load_heap_oop(str0, value_offset, tmp0);
|
||||
__ ld(str0, offset_offset, tmp2);
|
||||
__ add(tmp0, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp0);
|
||||
__ ld(str0, count_offset, str0);
|
||||
__ sll(tmp2, exact_log2(sizeof(jchar)), tmp2);
|
||||
} else {
|
||||
__ load_heap_oop(str0, value_offset, tmp1);
|
||||
__ add(tmp1, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp0);
|
||||
__ ld(tmp1, arrayOopDesc::length_offset_in_bytes(), str0);
|
||||
}
|
||||
|
||||
// str1 may be null
|
||||
add_debug_info_for_null_check_here(info);
|
||||
|
||||
__ load_heap_oop(str1, value_offset, tmp1);
|
||||
__ add(tmp0, tmp2, tmp0);
|
||||
if (java_lang_String::has_offset_field()) {
|
||||
int offset_offset = java_lang_String::offset_offset_in_bytes(); // first character position
|
||||
int count_offset = java_lang_String:: count_offset_in_bytes();
|
||||
__ load_heap_oop(str1, value_offset, tmp1);
|
||||
__ add(tmp0, tmp2, tmp0);
|
||||
|
||||
__ ld(str1, offset_offset, tmp2);
|
||||
__ add(tmp1, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp1);
|
||||
__ ld(str1, count_offset, str1);
|
||||
__ sll(tmp2, exact_log2(sizeof(jchar)), tmp2);
|
||||
__ ld(str1, offset_offset, tmp2);
|
||||
__ add(tmp1, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp1);
|
||||
__ ld(str1, count_offset, str1);
|
||||
__ sll(tmp2, exact_log2(sizeof(jchar)), tmp2);
|
||||
__ add(tmp1, tmp2, tmp1);
|
||||
} else {
|
||||
__ load_heap_oop(str1, value_offset, tmp2);
|
||||
__ add(tmp2, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp1);
|
||||
__ ld(tmp2, arrayOopDesc::length_offset_in_bytes(), str1);
|
||||
}
|
||||
__ subcc(str0, str1, O7);
|
||||
__ add(tmp1, tmp2, tmp1);
|
||||
}
|
||||
|
||||
{
|
||||
@ -302,7 +318,7 @@ void LIR_Assembler::emit_string_compare(LIR_Opr left, LIR_Opr right, LIR_Opr dst
|
||||
// Shift base0 and base1 to the end of the arrays, negate limit
|
||||
__ add(base0, limit, base0);
|
||||
__ add(base1, limit, base1);
|
||||
__ neg(limit); // limit = -min{string0.count, strin1.count}
|
||||
__ neg(limit); // limit = -min{string0.length(), string1.length()}
|
||||
|
||||
__ lduh(base0, limit, chr0);
|
||||
__ bind(Lloop);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2012, 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
|
||||
@ -505,19 +505,28 @@ void LIR_Assembler::emit_string_compare(LIR_Opr arg0, LIR_Opr arg1, LIR_Opr dst,
|
||||
|
||||
// Get addresses of first characters from both Strings
|
||||
__ load_heap_oop(rsi, Address(rax, java_lang_String::value_offset_in_bytes()));
|
||||
__ movptr (rcx, Address(rax, java_lang_String::offset_offset_in_bytes()));
|
||||
__ lea (rsi, Address(rsi, rcx, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR)));
|
||||
|
||||
if (java_lang_String::has_offset_field()) {
|
||||
__ movptr (rcx, Address(rax, java_lang_String::offset_offset_in_bytes()));
|
||||
__ movl (rax, Address(rax, java_lang_String::count_offset_in_bytes()));
|
||||
__ lea (rsi, Address(rsi, rcx, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR)));
|
||||
} else {
|
||||
__ movl (rax, Address(rsi, arrayOopDesc::length_offset_in_bytes()));
|
||||
__ lea (rsi, Address(rsi, arrayOopDesc::base_offset_in_bytes(T_CHAR)));
|
||||
}
|
||||
|
||||
// rbx, may be NULL
|
||||
add_debug_info_for_null_check_here(info);
|
||||
__ load_heap_oop(rdi, Address(rbx, java_lang_String::value_offset_in_bytes()));
|
||||
__ movptr (rcx, Address(rbx, java_lang_String::offset_offset_in_bytes()));
|
||||
__ lea (rdi, Address(rdi, rcx, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR)));
|
||||
if (java_lang_String::has_offset_field()) {
|
||||
__ movptr (rcx, Address(rbx, java_lang_String::offset_offset_in_bytes()));
|
||||
__ movl (rbx, Address(rbx, java_lang_String::count_offset_in_bytes()));
|
||||
__ lea (rdi, Address(rdi, rcx, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR)));
|
||||
} else {
|
||||
__ movl (rbx, Address(rdi, arrayOopDesc::length_offset_in_bytes()));
|
||||
__ lea (rdi, Address(rdi, arrayOopDesc::base_offset_in_bytes(T_CHAR)));
|
||||
}
|
||||
|
||||
// compute minimum length (in rax) and difference of lengths (on top of stack)
|
||||
__ movl (rbx, Address(rbx, java_lang_String::count_offset_in_bytes()));
|
||||
__ movl (rax, Address(rax, java_lang_String::count_offset_in_bytes()));
|
||||
__ mov (rcx, rbx);
|
||||
__ subptr(rbx, rax); // subtract lengths
|
||||
__ push (rbx); // result
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2012, 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
|
||||
@ -143,7 +143,27 @@ compute_optional_offset(int& dest_offset,
|
||||
}
|
||||
|
||||
|
||||
int java_lang_String::value_offset = 0;
|
||||
int java_lang_String::offset_offset = 0;
|
||||
int java_lang_String::count_offset = 0;
|
||||
int java_lang_String::hash_offset = 0;
|
||||
|
||||
bool java_lang_String::initialized = false;
|
||||
|
||||
void java_lang_String::compute_offsets() {
|
||||
assert(!initialized, "offsets should be initialized only once");
|
||||
|
||||
klassOop k = SystemDictionary::String_klass();
|
||||
compute_offset(value_offset, k, vmSymbols::value_name(), vmSymbols::char_array_signature());
|
||||
compute_optional_offset(offset_offset, k, vmSymbols::offset_name(), vmSymbols::int_signature());
|
||||
compute_optional_offset(count_offset, k, vmSymbols::count_name(), vmSymbols::int_signature());
|
||||
compute_optional_offset(hash_offset, k, vmSymbols::hash_name(), vmSymbols::int_signature());
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
Handle java_lang_String::basic_create(int length, bool tenured, TRAPS) {
|
||||
assert(initialized, "Must be initialized");
|
||||
// Create the String object first, so there's a chance that the String
|
||||
// and the char array it points to end up in the same cache line.
|
||||
oop obj;
|
||||
@ -2837,10 +2857,6 @@ int java_lang_System::err_offset_in_bytes() {
|
||||
|
||||
|
||||
|
||||
int java_lang_String::value_offset;
|
||||
int java_lang_String::offset_offset;
|
||||
int java_lang_String::count_offset;
|
||||
int java_lang_String::hash_offset;
|
||||
int java_lang_Class::_klass_offset;
|
||||
int java_lang_Class::_array_klass_offset;
|
||||
int java_lang_Class::_resolved_constructor_offset;
|
||||
@ -3000,12 +3016,6 @@ void JavaClasses::compute_hard_coded_offsets() {
|
||||
const int x = heapOopSize;
|
||||
const int header = instanceOopDesc::base_offset_in_bytes();
|
||||
|
||||
// Do the String Class
|
||||
java_lang_String::value_offset = java_lang_String::hc_value_offset * x + header;
|
||||
java_lang_String::offset_offset = java_lang_String::hc_offset_offset * x + header;
|
||||
java_lang_String::count_offset = java_lang_String::offset_offset + sizeof (jint);
|
||||
java_lang_String::hash_offset = java_lang_String::count_offset + sizeof (jint);
|
||||
|
||||
// Throwable Class
|
||||
java_lang_Throwable::backtrace_offset = java_lang_Throwable::hc_backtrace_offset * x + header;
|
||||
java_lang_Throwable::detailMessage_offset = java_lang_Throwable::hc_detailMessage_offset * x + header;
|
||||
@ -3200,9 +3210,13 @@ void JavaClasses::check_offsets() {
|
||||
// java.lang.String
|
||||
|
||||
CHECK_OFFSET("java/lang/String", java_lang_String, value, "[C");
|
||||
CHECK_OFFSET("java/lang/String", java_lang_String, offset, "I");
|
||||
CHECK_OFFSET("java/lang/String", java_lang_String, count, "I");
|
||||
CHECK_OFFSET("java/lang/String", java_lang_String, hash, "I");
|
||||
if (java_lang_String::has_offset_field()) {
|
||||
CHECK_OFFSET("java/lang/String", java_lang_String, offset, "I");
|
||||
CHECK_OFFSET("java/lang/String", java_lang_String, count, "I");
|
||||
}
|
||||
if (java_lang_String::has_hash_field()) {
|
||||
CHECK_OFFSET("java/lang/String", java_lang_String, hash, "I");
|
||||
}
|
||||
|
||||
// java.lang.Class
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2012, 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,26 +52,36 @@
|
||||
|
||||
class java_lang_String : AllStatic {
|
||||
private:
|
||||
enum {
|
||||
hc_value_offset = 0,
|
||||
hc_offset_offset = 1
|
||||
//hc_count_offset = 2 -- not a word-scaled offset
|
||||
//hc_hash_offset = 3 -- not a word-scaled offset
|
||||
};
|
||||
|
||||
static int value_offset;
|
||||
static int offset_offset;
|
||||
static int count_offset;
|
||||
static int hash_offset;
|
||||
|
||||
static bool initialized;
|
||||
|
||||
static Handle basic_create(int length, bool tenured, TRAPS);
|
||||
static Handle basic_create_from_unicode(jchar* unicode, int length, bool tenured, TRAPS);
|
||||
|
||||
static void set_value( oop string, typeArrayOop buffer) { string->obj_field_put(value_offset, (oop)buffer); }
|
||||
static void set_offset(oop string, int offset) { string->int_field_put(offset_offset, offset); }
|
||||
static void set_count( oop string, int count) { string->int_field_put(count_offset, count); }
|
||||
static void set_value( oop string, typeArrayOop buffer) {
|
||||
assert(initialized, "Must be initialized");
|
||||
string->obj_field_put(value_offset, (oop)buffer);
|
||||
}
|
||||
static void set_offset(oop string, int offset) {
|
||||
assert(initialized, "Must be initialized");
|
||||
if (offset_offset > 0) {
|
||||
string->int_field_put(offset_offset, offset);
|
||||
}
|
||||
}
|
||||
static void set_count( oop string, int count) {
|
||||
assert(initialized, "Must be initialized");
|
||||
if (count_offset > 0) {
|
||||
string->int_field_put(count_offset, count);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
static void compute_offsets();
|
||||
|
||||
// Instance creation
|
||||
static Handle create_from_unicode(jchar* unicode, int len, TRAPS);
|
||||
static Handle create_tenured_from_unicode(jchar* unicode, int len, TRAPS);
|
||||
@ -82,23 +92,61 @@ class java_lang_String : AllStatic {
|
||||
static Handle create_from_platform_dependent_str(const char* str, TRAPS);
|
||||
static Handle char_converter(Handle java_string, jchar from_char, jchar to_char, TRAPS);
|
||||
|
||||
static int value_offset_in_bytes() { return value_offset; }
|
||||
static int count_offset_in_bytes() { return count_offset; }
|
||||
static int offset_offset_in_bytes() { return offset_offset; }
|
||||
static int hash_offset_in_bytes() { return hash_offset; }
|
||||
static bool has_offset_field() {
|
||||
assert(initialized, "Must be initialized");
|
||||
return (offset_offset > 0);
|
||||
}
|
||||
|
||||
static bool has_count_field() {
|
||||
assert(initialized, "Must be initialized");
|
||||
return (count_offset > 0);
|
||||
}
|
||||
|
||||
static bool has_hash_field() {
|
||||
assert(initialized, "Must be initialized");
|
||||
return (hash_offset > 0);
|
||||
}
|
||||
|
||||
static int value_offset_in_bytes() {
|
||||
assert(initialized && (value_offset > 0), "Must be initialized");
|
||||
return value_offset;
|
||||
}
|
||||
static int count_offset_in_bytes() {
|
||||
assert(initialized && (count_offset > 0), "Must be initialized");
|
||||
return count_offset;
|
||||
}
|
||||
static int offset_offset_in_bytes() {
|
||||
assert(initialized && (offset_offset > 0), "Must be initialized");
|
||||
return offset_offset;
|
||||
}
|
||||
static int hash_offset_in_bytes() {
|
||||
assert(initialized && (hash_offset > 0), "Must be initialized");
|
||||
return hash_offset;
|
||||
}
|
||||
|
||||
// Accessors
|
||||
static typeArrayOop value(oop java_string) {
|
||||
assert(initialized && (value_offset > 0), "Must be initialized");
|
||||
assert(is_instance(java_string), "must be java_string");
|
||||
return (typeArrayOop) java_string->obj_field(value_offset);
|
||||
}
|
||||
static int offset(oop java_string) {
|
||||
assert(initialized, "Must be initialized");
|
||||
assert(is_instance(java_string), "must be java_string");
|
||||
return java_string->int_field(offset_offset);
|
||||
if (offset_offset > 0) {
|
||||
return java_string->int_field(offset_offset);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
static int length(oop java_string) {
|
||||
assert(initialized, "Must be initialized");
|
||||
assert(is_instance(java_string), "must be java_string");
|
||||
return java_string->int_field(count_offset);
|
||||
if (count_offset > 0) {
|
||||
return java_string->int_field(count_offset);
|
||||
} else {
|
||||
return ((typeArrayOop)java_string->obj_field(value_offset))->length();
|
||||
}
|
||||
}
|
||||
static int utf8_length(oop java_string);
|
||||
|
||||
|
@ -1971,6 +1971,9 @@ void SystemDictionary::initialize_preloaded_classes(TRAPS) {
|
||||
// first do Object, String, Class
|
||||
initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(Class_klass), scan, CHECK);
|
||||
|
||||
// Calculate offsets for String and Class classes since they are loaded and
|
||||
// can be used after this point.
|
||||
java_lang_String::compute_offsets();
|
||||
java_lang_Class::compute_offsets();
|
||||
|
||||
// Fixup mirrors for classes loaded before java.lang.Class.
|
||||
|
@ -340,6 +340,9 @@
|
||||
template(park_event_name, "nativeParkEventPointer") \
|
||||
template(cache_field_name, "cache") \
|
||||
template(value_name, "value") \
|
||||
template(offset_name, "offset") \
|
||||
template(count_name, "count") \
|
||||
template(hash_name, "hash") \
|
||||
template(frontCacheEnabled_name, "frontCacheEnabled") \
|
||||
template(stringCacheEnabled_name, "stringCacheEnabled") \
|
||||
template(numberOfLeadingZeros_name, "numberOfLeadingZeros") \
|
||||
|
@ -6332,10 +6332,10 @@ void CMSCollector::reset(bool asynch) {
|
||||
)
|
||||
}
|
||||
|
||||
void CMSCollector::do_CMS_operation(CMS_op_type op) {
|
||||
void CMSCollector::do_CMS_operation(CMS_op_type op, GCCause::Cause gc_cause) {
|
||||
gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps);
|
||||
TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
|
||||
TraceTime t("GC", PrintGC, !PrintGCDetails, gclog_or_tty);
|
||||
TraceTime t(GCCauseString("GC", gc_cause), PrintGC, !PrintGCDetails, gclog_or_tty);
|
||||
TraceCollectorStats tcs(counters());
|
||||
|
||||
switch (op) {
|
||||
|
@ -717,7 +717,7 @@ class CMSCollector: public CHeapObj {
|
||||
CMS_op_checkpointRootsFinal
|
||||
};
|
||||
|
||||
void do_CMS_operation(CMS_op_type op);
|
||||
void do_CMS_operation(CMS_op_type op, GCCause::Cause gc_cause);
|
||||
bool stop_world_and_do(CMS_op_type op);
|
||||
|
||||
OopTaskQueueSet* task_queues() { return _task_queues; }
|
||||
|
@ -146,7 +146,7 @@ void VM_CMS_Initial_Mark::doit() {
|
||||
VM_CMS_Operation::verify_before_gc();
|
||||
|
||||
IsGCActiveMark x; // stop-world GC active
|
||||
_collector->do_CMS_operation(CMSCollector::CMS_op_checkpointRootsInitial);
|
||||
_collector->do_CMS_operation(CMSCollector::CMS_op_checkpointRootsInitial, gch->gc_cause());
|
||||
|
||||
VM_CMS_Operation::verify_after_gc();
|
||||
#ifndef USDT2
|
||||
@ -178,7 +178,7 @@ void VM_CMS_Final_Remark::doit() {
|
||||
VM_CMS_Operation::verify_before_gc();
|
||||
|
||||
IsGCActiveMark x; // stop-world GC active
|
||||
_collector->do_CMS_operation(CMSCollector::CMS_op_checkpointRootsFinal);
|
||||
_collector->do_CMS_operation(CMSCollector::CMS_op_checkpointRootsFinal, gch->gc_cause());
|
||||
|
||||
VM_CMS_Operation::verify_after_gc();
|
||||
#ifndef USDT2
|
||||
|
@ -1252,10 +1252,7 @@ bool G1CollectedHeap::do_collection(bool explicit_gc,
|
||||
gclog_or_tty->date_stamp(G1Log::fine() && PrintGCDateStamps);
|
||||
TraceCPUTime tcpu(G1Log::finer(), true, gclog_or_tty);
|
||||
|
||||
char verbose_str[128];
|
||||
sprintf(verbose_str, "Full GC (%s)", GCCause::to_string(gc_cause()));
|
||||
TraceTime t(verbose_str, G1Log::fine(), true, gclog_or_tty);
|
||||
|
||||
TraceTime t(GCCauseString("Full GC", gc_cause()), G1Log::fine(), true, gclog_or_tty);
|
||||
TraceCollectorStats tcs(g1mm()->full_collection_counters());
|
||||
TraceMemoryManagerStats tms(true /* fullGC */, gc_cause());
|
||||
|
||||
@ -3600,12 +3597,10 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
|
||||
gclog_or_tty->date_stamp(G1Log::fine() && PrintGCDateStamps);
|
||||
TraceCPUTime tcpu(G1Log::finer(), true, gclog_or_tty);
|
||||
|
||||
char verbose_str[128];
|
||||
sprintf(verbose_str, "GC pause (%s) (%s)%s",
|
||||
GCCause::to_string(gc_cause()),
|
||||
g1_policy()->gcs_are_young() ? "young" : "mixed",
|
||||
g1_policy()->during_initial_mark_pause() ? " (initial-mark)" : "");
|
||||
TraceTime t(verbose_str, G1Log::fine() && !G1Log::finer(), true, gclog_or_tty);
|
||||
GCCauseString gc_cause_str = GCCauseString("GC pause", gc_cause())
|
||||
.append(g1_policy()->gcs_are_young() ? " (young)" : " (mixed)")
|
||||
.append(g1_policy()->during_initial_mark_pause() ? " (initial-mark)" : "");
|
||||
TraceTime t(gc_cause_str, G1Log::fine() && !G1Log::finer(), true, gclog_or_tty);
|
||||
|
||||
TraceCollectorStats tcs(g1mm()->incremental_collection_counters());
|
||||
TraceMemoryManagerStats tms(false /* fullGC */, gc_cause());
|
||||
@ -5502,7 +5497,7 @@ void G1CollectedHeap::evacuate_collection_set() {
|
||||
if (evacuation_failed()) {
|
||||
remove_self_forwarding_pointers();
|
||||
if (G1Log::finer()) {
|
||||
gclog_or_tty->print(" (to-space overflow)");
|
||||
gclog_or_tty->print(" (to-space exhausted)");
|
||||
} else if (G1Log::fine()) {
|
||||
gclog_or_tty->print("--");
|
||||
}
|
||||
|
@ -886,9 +886,8 @@ void G1CollectorPolicy::record_collection_pause_start(double start_time_sec,
|
||||
size_t start_used) {
|
||||
if (G1Log::finer()) {
|
||||
gclog_or_tty->stamp(PrintGCTimeStamps);
|
||||
gclog_or_tty->print("[GC pause (%s) (%s)",
|
||||
GCCause::to_string(_g1->gc_cause()),
|
||||
gcs_are_young() ? "young" : "mixed");
|
||||
gclog_or_tty->print("[%s", (const char*)GCCauseString("GC pause", _g1->gc_cause())
|
||||
.append(gcs_are_young() ? " (young)" : " (mixed)"));
|
||||
}
|
||||
|
||||
// We only need to do this here as the policy will only be applied
|
||||
@ -1010,7 +1009,8 @@ T sum_of(T* sum_arr, int start, int n, int N) {
|
||||
|
||||
void G1CollectorPolicy::print_par_stats(int level,
|
||||
const char* str,
|
||||
double* data) {
|
||||
double* data,
|
||||
bool showDecimals) {
|
||||
double min = data[0], max = data[0];
|
||||
double total = 0.0;
|
||||
LineBuffer buf(level);
|
||||
@ -1023,7 +1023,11 @@ void G1CollectorPolicy::print_par_stats(int level,
|
||||
max = val;
|
||||
total += val;
|
||||
if (G1Log::finest()) {
|
||||
buf.append(" %.1lf", val);
|
||||
if (showDecimals) {
|
||||
buf.append(" %.1lf", val);
|
||||
} else {
|
||||
buf.append(" %d", (int)val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1031,36 +1035,26 @@ void G1CollectorPolicy::print_par_stats(int level,
|
||||
buf.append_and_print_cr("");
|
||||
}
|
||||
double avg = total / (double) no_of_gc_threads();
|
||||
buf.append_and_print_cr(" Avg: %.1lf Min: %.1lf Max: %.1lf Diff: %.1lf]",
|
||||
avg, min, max, max - min);
|
||||
}
|
||||
|
||||
void G1CollectorPolicy::print_par_sizes(int level,
|
||||
const char* str,
|
||||
double* data) {
|
||||
double min = data[0], max = data[0];
|
||||
double total = 0.0;
|
||||
LineBuffer buf(level);
|
||||
buf.append("[%s :", str);
|
||||
for (uint i = 0; i < no_of_gc_threads(); ++i) {
|
||||
double val = data[i];
|
||||
if (val < min)
|
||||
min = val;
|
||||
if (val > max)
|
||||
max = val;
|
||||
total += val;
|
||||
buf.append(" %d", (int) val);
|
||||
if (showDecimals) {
|
||||
buf.append_and_print_cr(" Min: %.1lf, Avg: %.1lf, Max: %.1lf, Diff: %.1lf, Sum: %.1lf]",
|
||||
min, avg, max, max - min, total);
|
||||
} else {
|
||||
buf.append_and_print_cr(" Min: %d, Avg: %d, Max: %d, Diff: %d, Sum: %d]",
|
||||
(int)min, (int)avg, (int)max, (int)max - (int)min, (int)total);
|
||||
}
|
||||
buf.append_and_print_cr("");
|
||||
double avg = total / (double) no_of_gc_threads();
|
||||
buf.append_and_print_cr(" Sum: %d, Avg: %d, Min: %d, Max: %d, Diff: %d]",
|
||||
(int)total, (int)avg, (int)min, (int)max, (int)max - (int)min);
|
||||
}
|
||||
|
||||
void G1CollectorPolicy::print_stats(int level,
|
||||
const char* str,
|
||||
double value) {
|
||||
LineBuffer(level).append_and_print_cr("[%s: %5.1lf ms]", str, value);
|
||||
LineBuffer(level).append_and_print_cr("[%s: %.1lf ms]", str, value);
|
||||
}
|
||||
|
||||
void G1CollectorPolicy::print_stats(int level,
|
||||
const char* str,
|
||||
double value,
|
||||
int workers) {
|
||||
LineBuffer(level).append_and_print_cr("[%s: %.1lf ms, GC Workers: %d]", str, value, workers);
|
||||
}
|
||||
|
||||
void G1CollectorPolicy::print_stats(int level,
|
||||
@ -1373,7 +1367,7 @@ void G1CollectorPolicy::record_collection_pause_end(int no_of_gc_threads) {
|
||||
print_stats(1, "Root Region Scan Waiting", _root_region_scan_wait_time_ms);
|
||||
}
|
||||
if (parallel) {
|
||||
print_stats(1, "Parallel Time", _cur_collection_par_time_ms);
|
||||
print_stats(1, "Parallel Time", _cur_collection_par_time_ms, no_of_gc_threads);
|
||||
print_par_stats(2, "GC Worker Start", _par_last_gc_worker_start_times_ms);
|
||||
print_par_stats(2, "Ext Root Scanning", _par_last_ext_root_scan_times_ms);
|
||||
if (print_marking_info) {
|
||||
@ -1381,13 +1375,15 @@ void G1CollectorPolicy::record_collection_pause_end(int no_of_gc_threads) {
|
||||
}
|
||||
print_par_stats(2, "Update RS", _par_last_update_rs_times_ms);
|
||||
if (G1Log::finest()) {
|
||||
print_par_sizes(3, "Processed Buffers", _par_last_update_rs_processed_buffers);
|
||||
print_par_stats(3, "Processed Buffers", _par_last_update_rs_processed_buffers,
|
||||
false /* showDecimals */);
|
||||
}
|
||||
print_par_stats(2, "Scan RS", _par_last_scan_rs_times_ms);
|
||||
print_par_stats(2, "Object Copy", _par_last_obj_copy_times_ms);
|
||||
print_par_stats(2, "Termination", _par_last_termination_times_ms);
|
||||
if (G1Log::finest()) {
|
||||
print_par_sizes(3, "Termination Attempts", _par_last_termination_attempts);
|
||||
print_par_stats(3, "Termination Attempts", _par_last_termination_attempts,
|
||||
false /* showDecimals */);
|
||||
}
|
||||
|
||||
for (int i = 0; i < _parallel_gc_threads; i++) {
|
||||
@ -1601,9 +1597,9 @@ void G1CollectorPolicy::record_collection_pause_end(int no_of_gc_threads) {
|
||||
_collectionSetChooser->verify();
|
||||
}
|
||||
|
||||
#define EXT_SIZE_FORMAT "%d%s"
|
||||
#define EXT_SIZE_FORMAT "%.1f%s"
|
||||
#define EXT_SIZE_PARAMS(bytes) \
|
||||
byte_size_in_proper_unit((bytes)), \
|
||||
byte_size_in_proper_unit((double)(bytes)), \
|
||||
proper_unit_for_byte_size((bytes))
|
||||
|
||||
void G1CollectorPolicy::print_heap_transition() {
|
||||
|
@ -552,10 +552,10 @@ public:
|
||||
|
||||
private:
|
||||
void print_stats(int level, const char* str, double value);
|
||||
void print_stats(int level, const char* str, double value, int workers);
|
||||
void print_stats(int level, const char* str, int value);
|
||||
|
||||
void print_par_stats(int level, const char* str, double* data);
|
||||
void print_par_sizes(int level, const char* str, double* data);
|
||||
void print_par_stats(int level, const char* str, double* data, bool showDecimals = true);
|
||||
|
||||
void check_other_times(int level,
|
||||
NumberSeq* other_times_ms,
|
||||
|
@ -42,6 +42,7 @@ VM_G1CollectForAllocation::VM_G1CollectForAllocation(
|
||||
|
||||
void VM_G1CollectForAllocation::doit() {
|
||||
G1CollectedHeap* g1h = G1CollectedHeap::heap();
|
||||
GCCauseSetter x(g1h, _gc_cause);
|
||||
_result = g1h->satisfy_failed_allocation(_word_size, &_pause_succeeded);
|
||||
assert(_result == NULL || _pause_succeeded,
|
||||
"if we get back a result, the pause should have succeeded");
|
||||
|
@ -916,7 +916,7 @@ void ParNewGeneration::collect(bool full,
|
||||
size_policy->minor_collection_begin();
|
||||
}
|
||||
|
||||
TraceTime t1("GC", PrintGC && !PrintGCDetails, true, gclog_or_tty);
|
||||
TraceTime t1(GCCauseString("GC", gch->gc_cause()), PrintGC && !PrintGCDetails, true, gclog_or_tty);
|
||||
// Capture heap used before collection (for printing).
|
||||
size_t gch_prev_used = gch->used();
|
||||
|
||||
|
@ -160,16 +160,10 @@ bool PSMarkSweep::invoke_no_policy(bool clear_all_softrefs) {
|
||||
|
||||
{
|
||||
HandleMark hm;
|
||||
const bool is_system_gc = gc_cause == GCCause::_java_lang_system_gc;
|
||||
// This is useful for debugging but don't change the output the
|
||||
// the customer sees.
|
||||
const char* gc_cause_str = "Full GC";
|
||||
if (is_system_gc && PrintGCDetails) {
|
||||
gc_cause_str = "Full GC (System)";
|
||||
}
|
||||
|
||||
gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps);
|
||||
TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
|
||||
TraceTime t1(gc_cause_str, PrintGC, !PrintGCDetails, gclog_or_tty);
|
||||
TraceTime t1(GCCauseString("Full GC", gc_cause), PrintGC, !PrintGCDetails, gclog_or_tty);
|
||||
TraceCollectorStats tcs(counters());
|
||||
TraceMemoryManagerStats tms(true /* Full GC */,gc_cause);
|
||||
|
||||
|
@ -2047,17 +2047,9 @@ bool PSParallelCompact::invoke_no_policy(bool maximum_heap_compaction) {
|
||||
gc_task_manager()->task_idle_workers();
|
||||
heap->set_par_threads(gc_task_manager()->active_workers());
|
||||
|
||||
const bool is_system_gc = gc_cause == GCCause::_java_lang_system_gc;
|
||||
|
||||
// This is useful for debugging but don't change the output the
|
||||
// the customer sees.
|
||||
const char* gc_cause_str = "Full GC";
|
||||
if (is_system_gc && PrintGCDetails) {
|
||||
gc_cause_str = "Full GC (System)";
|
||||
}
|
||||
gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps);
|
||||
TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
|
||||
TraceTime t1(gc_cause_str, PrintGC, !PrintGCDetails, gclog_or_tty);
|
||||
TraceTime t1(GCCauseString("Full GC", gc_cause), PrintGC, !PrintGCDetails, gclog_or_tty);
|
||||
TraceCollectorStats tcs(counters());
|
||||
TraceMemoryManagerStats tms(true /* Full GC */,gc_cause);
|
||||
|
||||
@ -2090,7 +2082,8 @@ bool PSParallelCompact::invoke_no_policy(bool maximum_heap_compaction) {
|
||||
}
|
||||
#endif // #ifndef PRODUCT
|
||||
|
||||
bool max_on_system_gc = UseMaximumCompactionOnSystemGC && is_system_gc;
|
||||
bool max_on_system_gc = UseMaximumCompactionOnSystemGC
|
||||
&& gc_cause == GCCause::_java_lang_system_gc;
|
||||
summary_phase(vmthread_cm, maximum_heap_compaction || max_on_system_gc);
|
||||
|
||||
COMPILER2_PRESENT(assert(DerivedPointerTable::is_active(), "Sanity"));
|
||||
|
@ -325,7 +325,7 @@ bool PSScavenge::invoke_no_policy() {
|
||||
|
||||
gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps);
|
||||
TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
|
||||
TraceTime t1("GC", PrintGC, !PrintGCDetails, gclog_or_tty);
|
||||
TraceTime t1(GCCauseString("GC", gc_cause), PrintGC, !PrintGCDetails, gclog_or_tty);
|
||||
TraceCollectorStats tcs(counters());
|
||||
TraceMemoryManagerStats tms(false /* not full GC */,gc_cause);
|
||||
|
||||
|
@ -31,9 +31,15 @@ float AdaptiveWeightedAverage::compute_adaptive_average(float new_sample,
|
||||
float average) {
|
||||
// We smooth the samples by not using weight() directly until we've
|
||||
// had enough data to make it meaningful. We'd like the first weight
|
||||
// used to be 1, the second to be 1/2, etc until we have 100/weight
|
||||
// samples.
|
||||
unsigned count_weight = 100/count();
|
||||
// used to be 1, the second to be 1/2, etc until we have
|
||||
// OLD_THRESHOLD/weight samples.
|
||||
unsigned count_weight = 0;
|
||||
|
||||
// Avoid division by zero if the counter wraps (7158457)
|
||||
if (!is_old()) {
|
||||
count_weight = OLD_THRESHOLD/count();
|
||||
}
|
||||
|
||||
unsigned adaptive_weight = (MAX2(weight(), count_weight));
|
||||
|
||||
float new_avg = exp_avg(average, new_sample, adaptive_weight);
|
||||
@ -43,8 +49,6 @@ float AdaptiveWeightedAverage::compute_adaptive_average(float new_sample,
|
||||
|
||||
void AdaptiveWeightedAverage::sample(float new_sample) {
|
||||
increment_count();
|
||||
assert(count() != 0,
|
||||
"Wraparound -- history would be incorrectly discarded");
|
||||
|
||||
// Compute the new weighted average
|
||||
float new_avg = compute_adaptive_average(new_sample, average());
|
||||
|
@ -50,11 +50,20 @@ class AdaptiveWeightedAverage : public CHeapObj {
|
||||
unsigned _weight; // The weight used to smooth the averages
|
||||
// A higher weight favors the most
|
||||
// recent data.
|
||||
bool _is_old; // Has enough historical data
|
||||
|
||||
const static unsigned OLD_THRESHOLD = 100;
|
||||
|
||||
protected:
|
||||
float _last_sample; // The last value sampled.
|
||||
|
||||
void increment_count() { _sample_count++; }
|
||||
void increment_count() {
|
||||
_sample_count++;
|
||||
if (!_is_old && _sample_count > OLD_THRESHOLD) {
|
||||
_is_old = true;
|
||||
}
|
||||
}
|
||||
|
||||
void set_average(float avg) { _average = avg; }
|
||||
|
||||
// Helper function, computes an adaptive weighted average
|
||||
@ -64,13 +73,15 @@ class AdaptiveWeightedAverage : public CHeapObj {
|
||||
public:
|
||||
// Input weight must be between 0 and 100
|
||||
AdaptiveWeightedAverage(unsigned weight, float avg = 0.0) :
|
||||
_average(avg), _sample_count(0), _weight(weight), _last_sample(0.0) {
|
||||
_average(avg), _sample_count(0), _weight(weight), _last_sample(0.0),
|
||||
_is_old(false) {
|
||||
}
|
||||
|
||||
void clear() {
|
||||
_average = 0;
|
||||
_sample_count = 0;
|
||||
_last_sample = 0;
|
||||
_is_old = false;
|
||||
}
|
||||
|
||||
// Useful for modifying static structures after startup.
|
||||
@ -84,7 +95,8 @@ class AdaptiveWeightedAverage : public CHeapObj {
|
||||
float average() const { return _average; }
|
||||
unsigned weight() const { return _weight; }
|
||||
unsigned count() const { return _sample_count; }
|
||||
float last_sample() const { return _last_sample; }
|
||||
float last_sample() const { return _last_sample; }
|
||||
bool is_old() const { return _is_old; }
|
||||
|
||||
// Update data with a new sample.
|
||||
void sample(float new_sample);
|
||||
|
@ -88,4 +88,36 @@ class GCCause : public AllStatic {
|
||||
static const char* to_string(GCCause::Cause cause);
|
||||
};
|
||||
|
||||
// Helper class for doing logging that includes the GC Cause
|
||||
// as a string.
|
||||
class GCCauseString : StackObj {
|
||||
private:
|
||||
static const int _length = 128;
|
||||
char _buffer[_length];
|
||||
int _position;
|
||||
|
||||
public:
|
||||
GCCauseString(const char* prefix, GCCause::Cause cause) {
|
||||
if (PrintGCCause) {
|
||||
_position = jio_snprintf(_buffer, _length, "%s (%s)", prefix, GCCause::to_string(cause));
|
||||
} else {
|
||||
_position = jio_snprintf(_buffer, _length, "%s", prefix);
|
||||
}
|
||||
assert(_position >= 0 && _position <= _length,
|
||||
err_msg("Need to increase the buffer size in GCCauseString? %d", _position));
|
||||
}
|
||||
|
||||
GCCauseString& append(const char* str) {
|
||||
int res = jio_snprintf(_buffer + _position, _length - _position, "%s", str);
|
||||
_position += res;
|
||||
assert(res >= 0 && _position <= _length,
|
||||
err_msg("Need to increase the buffer size in GCCauseString? %d", res));
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator const char*() {
|
||||
return _buffer;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_GC_INTERFACE_GCCAUSE_HPP
|
||||
|
@ -548,7 +548,7 @@ void DefNewGeneration::collect(bool full,
|
||||
|
||||
init_assuming_no_promotion_failure();
|
||||
|
||||
TraceTime t1("GC", PrintGC && !PrintGCDetails, true, gclog_or_tty);
|
||||
TraceTime t1(GCCauseString("GC", gch->gc_cause()), PrintGC && !PrintGCDetails, true, gclog_or_tty);
|
||||
// Capture heap used before collection (for printing).
|
||||
size_t gch_prev_used = gch->used();
|
||||
|
||||
|
@ -78,8 +78,8 @@ public:
|
||||
void do_oop(oop* p) {
|
||||
if (p != NULL) {
|
||||
oop obj = *p;
|
||||
if (obj->klass() == SystemDictionary::String_klass()) {
|
||||
|
||||
if (obj->klass() == SystemDictionary::String_klass() &&
|
||||
java_lang_String::has_hash_field()) {
|
||||
int hash = java_lang_String::hash_string(obj);
|
||||
obj->int_field_put(hash_offset, hash);
|
||||
}
|
||||
|
@ -480,26 +480,15 @@ void GenCollectedHeap::do_collection(bool full,
|
||||
const size_t perm_prev_used = perm_gen()->used();
|
||||
|
||||
print_heap_before_gc();
|
||||
if (Verbose) {
|
||||
gclog_or_tty->print_cr("GC Cause: %s", GCCause::to_string(gc_cause()));
|
||||
}
|
||||
|
||||
{
|
||||
FlagSetting fl(_is_gc_active, true);
|
||||
|
||||
bool complete = full && (max_level == (n_gens()-1));
|
||||
const char* gc_cause_str = "GC ";
|
||||
if (complete) {
|
||||
GCCause::Cause cause = gc_cause();
|
||||
if (cause == GCCause::_java_lang_system_gc) {
|
||||
gc_cause_str = "Full GC (System) ";
|
||||
} else {
|
||||
gc_cause_str = "Full GC ";
|
||||
}
|
||||
}
|
||||
const char* gc_cause_prefix = complete ? "Full GC" : "GC";
|
||||
gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps);
|
||||
TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
|
||||
TraceTime t(gc_cause_str, PrintGCDetails, false, gclog_or_tty);
|
||||
TraceTime t(GCCauseString(gc_cause_prefix, gc_cause()), PrintGCDetails, false, gclog_or_tty);
|
||||
|
||||
gc_prologue(complete);
|
||||
increment_total_collections(complete);
|
||||
|
@ -76,7 +76,7 @@ void GenMarkSweep::invoke_at_safepoint(int level, ReferenceProcessor* rp,
|
||||
_ref_processor = rp;
|
||||
rp->setup_policy(clear_all_softrefs);
|
||||
|
||||
TraceTime t1("Full GC", PrintGC && !PrintGCDetails, true, gclog_or_tty);
|
||||
TraceTime t1(GCCauseString("Full GC", gch->gc_cause()), PrintGC && !PrintGCDetails, true, gclog_or_tty);
|
||||
|
||||
// When collecting the permanent generation methodOops may be moving,
|
||||
// so we either have to flush all bcp data or convert it into bci.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2012, 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
|
||||
@ -3748,3 +3748,81 @@ void GraphKit::g1_write_barrier_post(Node* oop_store,
|
||||
final_sync(ideal);
|
||||
}
|
||||
#undef __
|
||||
|
||||
|
||||
|
||||
Node* GraphKit::load_String_offset(Node* ctrl, Node* str) {
|
||||
if (java_lang_String::has_offset_field()) {
|
||||
int offset_offset = java_lang_String::offset_offset_in_bytes();
|
||||
const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(),
|
||||
false, NULL, 0);
|
||||
const TypePtr* offset_field_type = string_type->add_offset(offset_offset);
|
||||
int offset_field_idx = C->get_alias_index(offset_field_type);
|
||||
return make_load(ctrl,
|
||||
basic_plus_adr(str, str, offset_offset),
|
||||
TypeInt::INT, T_INT, offset_field_idx);
|
||||
} else {
|
||||
return intcon(0);
|
||||
}
|
||||
}
|
||||
|
||||
Node* GraphKit::load_String_length(Node* ctrl, Node* str) {
|
||||
if (java_lang_String::has_count_field()) {
|
||||
int count_offset = java_lang_String::count_offset_in_bytes();
|
||||
const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(),
|
||||
false, NULL, 0);
|
||||
const TypePtr* count_field_type = string_type->add_offset(count_offset);
|
||||
int count_field_idx = C->get_alias_index(count_field_type);
|
||||
return make_load(ctrl,
|
||||
basic_plus_adr(str, str, count_offset),
|
||||
TypeInt::INT, T_INT, count_field_idx);
|
||||
} else {
|
||||
return load_array_length(load_String_value(ctrl, str));
|
||||
}
|
||||
}
|
||||
|
||||
Node* GraphKit::load_String_value(Node* ctrl, Node* str) {
|
||||
int value_offset = java_lang_String::value_offset_in_bytes();
|
||||
const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(),
|
||||
false, NULL, 0);
|
||||
const TypePtr* value_field_type = string_type->add_offset(value_offset);
|
||||
const TypeAryPtr* value_type = TypeAryPtr::make(TypePtr::NotNull,
|
||||
TypeAry::make(TypeInt::CHAR,TypeInt::POS),
|
||||
ciTypeArrayKlass::make(T_CHAR), true, 0);
|
||||
int value_field_idx = C->get_alias_index(value_field_type);
|
||||
return make_load(ctrl, basic_plus_adr(str, str, value_offset),
|
||||
value_type, T_OBJECT, value_field_idx);
|
||||
}
|
||||
|
||||
void GraphKit::store_String_offset(Node* ctrl, Node* str, Node* value) {
|
||||
int offset_offset = java_lang_String::offset_offset_in_bytes();
|
||||
const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(),
|
||||
false, NULL, 0);
|
||||
const TypePtr* offset_field_type = string_type->add_offset(offset_offset);
|
||||
int offset_field_idx = C->get_alias_index(offset_field_type);
|
||||
store_to_memory(ctrl, basic_plus_adr(str, offset_offset),
|
||||
value, T_INT, offset_field_idx);
|
||||
}
|
||||
|
||||
void GraphKit::store_String_value(Node* ctrl, Node* str, Node* value) {
|
||||
int value_offset = java_lang_String::value_offset_in_bytes();
|
||||
const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(),
|
||||
false, NULL, 0);
|
||||
const TypePtr* value_field_type = string_type->add_offset(value_offset);
|
||||
const TypeAryPtr* value_type = TypeAryPtr::make(TypePtr::NotNull,
|
||||
TypeAry::make(TypeInt::CHAR,TypeInt::POS),
|
||||
ciTypeArrayKlass::make(T_CHAR), true, 0);
|
||||
int value_field_idx = C->get_alias_index(value_field_type);
|
||||
store_to_memory(ctrl, basic_plus_adr(str, value_offset),
|
||||
value, T_OBJECT, value_field_idx);
|
||||
}
|
||||
|
||||
void GraphKit::store_String_length(Node* ctrl, Node* str, Node* value) {
|
||||
int count_offset = java_lang_String::count_offset_in_bytes();
|
||||
const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(),
|
||||
false, NULL, 0);
|
||||
const TypePtr* count_field_type = string_type->add_offset(count_offset);
|
||||
int count_field_idx = C->get_alias_index(count_field_type);
|
||||
store_to_memory(ctrl, basic_plus_adr(str, count_offset),
|
||||
value, T_INT, count_field_idx);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2012, 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
|
||||
@ -781,6 +781,14 @@ class GraphKit : public Phase {
|
||||
Node* new_array(Node* klass_node, Node* count_val, int nargs,
|
||||
Node* *return_size_val = NULL);
|
||||
|
||||
// java.lang.String helpers
|
||||
Node* load_String_offset(Node* ctrl, Node* str);
|
||||
Node* load_String_length(Node* ctrl, Node* str);
|
||||
Node* load_String_value(Node* ctrl, Node* str);
|
||||
void store_String_offset(Node* ctrl, Node* str, Node* value);
|
||||
void store_String_length(Node* ctrl, Node* str, Node* value);
|
||||
void store_String_value(Node* ctrl, Node* str, Node* value);
|
||||
|
||||
// Handy for making control flow
|
||||
IfNode* create_and_map_if(Node* ctrl, Node* tst, float prob, float cnt) {
|
||||
IfNode* iff = new (C, 2) IfNode(ctrl, tst, prob, cnt);// New IfNode's
|
||||
|
@ -147,7 +147,8 @@ class LibraryCallKit : public GraphKit {
|
||||
return generate_method_call(method_id, true, false);
|
||||
}
|
||||
|
||||
Node* make_string_method_node(int opcode, Node* str1, Node* cnt1, Node* str2, Node* cnt2);
|
||||
Node* make_string_method_node(int opcode, Node* str1_start, Node* cnt1, Node* str2_start, Node* cnt2);
|
||||
Node* make_string_method_node(int opcode, Node* str1, Node* str2);
|
||||
bool inline_string_compareTo();
|
||||
bool inline_string_indexOf();
|
||||
Node* string_indexOf(Node* string_object, ciTypeArray* target_array, jint offset, jint cache_i, jint md2_i);
|
||||
@ -873,48 +874,76 @@ Node* LibraryCallKit::generate_current_thread(Node* &tls_output) {
|
||||
|
||||
|
||||
//------------------------------make_string_method_node------------------------
|
||||
// Helper method for String intrinsic finctions.
|
||||
Node* LibraryCallKit::make_string_method_node(int opcode, Node* str1, Node* cnt1, Node* str2, Node* cnt2) {
|
||||
const int value_offset = java_lang_String::value_offset_in_bytes();
|
||||
const int count_offset = java_lang_String::count_offset_in_bytes();
|
||||
const int offset_offset = java_lang_String::offset_offset_in_bytes();
|
||||
|
||||
// Helper method for String intrinsic functions. This version is called
|
||||
// with str1 and str2 pointing to String object nodes.
|
||||
//
|
||||
Node* LibraryCallKit::make_string_method_node(int opcode, Node* str1, Node* str2) {
|
||||
Node* no_ctrl = NULL;
|
||||
|
||||
ciInstanceKlass* klass = env()->String_klass();
|
||||
const TypeOopPtr* string_type = TypeOopPtr::make_from_klass(klass);
|
||||
|
||||
const TypeAryPtr* value_type =
|
||||
TypeAryPtr::make(TypePtr::NotNull,
|
||||
TypeAry::make(TypeInt::CHAR,TypeInt::POS),
|
||||
ciTypeArrayKlass::make(T_CHAR), true, 0);
|
||||
|
||||
// Get start addr of string and substring
|
||||
Node* str1_valuea = basic_plus_adr(str1, str1, value_offset);
|
||||
Node* str1_value = make_load(no_ctrl, str1_valuea, value_type, T_OBJECT, string_type->add_offset(value_offset));
|
||||
Node* str1_offseta = basic_plus_adr(str1, str1, offset_offset);
|
||||
Node* str1_offset = make_load(no_ctrl, str1_offseta, TypeInt::INT, T_INT, string_type->add_offset(offset_offset));
|
||||
// Get start addr of string
|
||||
Node* str1_value = load_String_value(no_ctrl, str1);
|
||||
Node* str1_offset = load_String_offset(no_ctrl, str1);
|
||||
Node* str1_start = array_element_address(str1_value, str1_offset, T_CHAR);
|
||||
|
||||
Node* str2_valuea = basic_plus_adr(str2, str2, value_offset);
|
||||
Node* str2_value = make_load(no_ctrl, str2_valuea, value_type, T_OBJECT, string_type->add_offset(value_offset));
|
||||
Node* str2_offseta = basic_plus_adr(str2, str2, offset_offset);
|
||||
Node* str2_offset = make_load(no_ctrl, str2_offseta, TypeInt::INT, T_INT, string_type->add_offset(offset_offset));
|
||||
// Get length of string 1
|
||||
Node* str1_len = load_String_length(no_ctrl, str1);
|
||||
|
||||
Node* str2_value = load_String_value(no_ctrl, str2);
|
||||
Node* str2_offset = load_String_offset(no_ctrl, str2);
|
||||
Node* str2_start = array_element_address(str2_value, str2_offset, T_CHAR);
|
||||
|
||||
Node* str2_len = NULL;
|
||||
Node* result = NULL;
|
||||
|
||||
switch (opcode) {
|
||||
case Op_StrIndexOf:
|
||||
// Get length of string 2
|
||||
str2_len = load_String_length(no_ctrl, str2);
|
||||
|
||||
result = new (C, 6) StrIndexOfNode(control(), memory(TypeAryPtr::CHARS),
|
||||
str1_start, str1_len, str2_start, str2_len);
|
||||
break;
|
||||
case Op_StrComp:
|
||||
// Get length of string 2
|
||||
str2_len = load_String_length(no_ctrl, str2);
|
||||
|
||||
result = new (C, 6) StrCompNode(control(), memory(TypeAryPtr::CHARS),
|
||||
str1_start, str1_len, str2_start, str2_len);
|
||||
break;
|
||||
case Op_StrEquals:
|
||||
result = new (C, 5) StrEqualsNode(control(), memory(TypeAryPtr::CHARS),
|
||||
str1_start, str2_start, str1_len);
|
||||
break;
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// All these intrinsics have checks.
|
||||
C->set_has_split_ifs(true); // Has chance for split-if optimization
|
||||
|
||||
return _gvn.transform(result);
|
||||
}
|
||||
|
||||
// Helper method for String intrinsic functions. This version is called
|
||||
// with str1 and str2 pointing to char[] nodes, with cnt1 and cnt2 pointing
|
||||
// to Int nodes containing the lenghts of str1 and str2.
|
||||
//
|
||||
Node* LibraryCallKit::make_string_method_node(int opcode, Node* str1_start, Node* cnt1, Node* str2_start, Node* cnt2) {
|
||||
|
||||
Node* result = NULL;
|
||||
switch (opcode) {
|
||||
case Op_StrIndexOf:
|
||||
result = new (C, 6) StrIndexOfNode(control(), memory(TypeAryPtr::CHARS),
|
||||
str1_start, cnt1, str2_start, cnt2);
|
||||
str1_start, cnt1, str2_start, cnt2);
|
||||
break;
|
||||
case Op_StrComp:
|
||||
result = new (C, 6) StrCompNode(control(), memory(TypeAryPtr::CHARS),
|
||||
str1_start, cnt1, str2_start, cnt2);
|
||||
str1_start, cnt1, str2_start, cnt2);
|
||||
break;
|
||||
case Op_StrEquals:
|
||||
result = new (C, 5) StrEqualsNode(control(), memory(TypeAryPtr::CHARS),
|
||||
str1_start, str2_start, cnt1);
|
||||
str1_start, str2_start, cnt1);
|
||||
break;
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
@ -932,10 +961,6 @@ bool LibraryCallKit::inline_string_compareTo() {
|
||||
|
||||
if (!Matcher::has_match_rule(Op_StrComp)) return false;
|
||||
|
||||
const int value_offset = java_lang_String::value_offset_in_bytes();
|
||||
const int count_offset = java_lang_String::count_offset_in_bytes();
|
||||
const int offset_offset = java_lang_String::offset_offset_in_bytes();
|
||||
|
||||
_sp += 2;
|
||||
Node *argument = pop(); // pop non-receiver first: it was pushed second
|
||||
Node *receiver = pop();
|
||||
@ -952,18 +977,7 @@ bool LibraryCallKit::inline_string_compareTo() {
|
||||
return true;
|
||||
}
|
||||
|
||||
ciInstanceKlass* klass = env()->String_klass();
|
||||
const TypeOopPtr* string_type = TypeOopPtr::make_from_klass(klass);
|
||||
Node* no_ctrl = NULL;
|
||||
|
||||
// Get counts for string and argument
|
||||
Node* receiver_cnta = basic_plus_adr(receiver, receiver, count_offset);
|
||||
Node* receiver_cnt = make_load(no_ctrl, receiver_cnta, TypeInt::INT, T_INT, string_type->add_offset(count_offset));
|
||||
|
||||
Node* argument_cnta = basic_plus_adr(argument, argument, count_offset);
|
||||
Node* argument_cnt = make_load(no_ctrl, argument_cnta, TypeInt::INT, T_INT, string_type->add_offset(count_offset));
|
||||
|
||||
Node* compare = make_string_method_node(Op_StrComp, receiver, receiver_cnt, argument, argument_cnt);
|
||||
Node* compare = make_string_method_node(Op_StrComp, receiver, argument);
|
||||
push(compare);
|
||||
return true;
|
||||
}
|
||||
@ -973,10 +987,6 @@ bool LibraryCallKit::inline_string_equals() {
|
||||
|
||||
if (!Matcher::has_match_rule(Op_StrEquals)) return false;
|
||||
|
||||
const int value_offset = java_lang_String::value_offset_in_bytes();
|
||||
const int count_offset = java_lang_String::count_offset_in_bytes();
|
||||
const int offset_offset = java_lang_String::offset_offset_in_bytes();
|
||||
|
||||
int nargs = 2;
|
||||
_sp += nargs;
|
||||
Node* argument = pop(); // pop non-receiver first: it was pushed second
|
||||
@ -1030,24 +1040,31 @@ bool LibraryCallKit::inline_string_equals() {
|
||||
}
|
||||
}
|
||||
|
||||
const TypeOopPtr* string_type = TypeOopPtr::make_from_klass(klass);
|
||||
|
||||
Node* no_ctrl = NULL;
|
||||
Node* receiver_cnt;
|
||||
Node* argument_cnt;
|
||||
|
||||
if (!stopped()) {
|
||||
const TypeOopPtr* string_type = TypeOopPtr::make_from_klass(klass);
|
||||
|
||||
// Properly cast the argument to String
|
||||
argument = _gvn.transform(new (C, 2) CheckCastPPNode(control(), argument, string_type));
|
||||
// This path is taken only when argument's type is String:NotNull.
|
||||
argument = cast_not_null(argument, false);
|
||||
|
||||
// Get counts for string and argument
|
||||
Node* receiver_cnta = basic_plus_adr(receiver, receiver, count_offset);
|
||||
receiver_cnt = make_load(no_ctrl, receiver_cnta, TypeInt::INT, T_INT, string_type->add_offset(count_offset));
|
||||
Node* no_ctrl = NULL;
|
||||
|
||||
Node* argument_cnta = basic_plus_adr(argument, argument, count_offset);
|
||||
argument_cnt = make_load(no_ctrl, argument_cnta, TypeInt::INT, T_INT, string_type->add_offset(count_offset));
|
||||
// Get start addr of receiver
|
||||
Node* receiver_val = load_String_value(no_ctrl, receiver);
|
||||
Node* receiver_offset = load_String_offset(no_ctrl, receiver);
|
||||
Node* receiver_start = array_element_address(receiver_val, receiver_offset, T_CHAR);
|
||||
|
||||
// Get length of receiver
|
||||
Node* receiver_cnt = load_String_length(no_ctrl, receiver);
|
||||
|
||||
// Get start addr of argument
|
||||
Node* argument_val = load_String_value(no_ctrl, argument);
|
||||
Node* argument_offset = load_String_offset(no_ctrl, argument);
|
||||
Node* argument_start = array_element_address(argument_val, argument_offset, T_CHAR);
|
||||
|
||||
// Get length of argument
|
||||
Node* argument_cnt = load_String_length(no_ctrl, argument);
|
||||
|
||||
// Check for receiver count != argument count
|
||||
Node* cmp = _gvn.transform( new(C, 3) CmpINode(receiver_cnt, argument_cnt) );
|
||||
@ -1057,14 +1074,14 @@ bool LibraryCallKit::inline_string_equals() {
|
||||
phi->init_req(4, intcon(0));
|
||||
region->init_req(4, if_ne);
|
||||
}
|
||||
}
|
||||
|
||||
// Check for count == 0 is done by mach node StrEquals.
|
||||
// Check for count == 0 is done by assembler code for StrEquals.
|
||||
|
||||
if (!stopped()) {
|
||||
Node* equals = make_string_method_node(Op_StrEquals, receiver, receiver_cnt, argument, argument_cnt);
|
||||
phi->init_req(1, equals);
|
||||
region->init_req(1, control());
|
||||
if (!stopped()) {
|
||||
Node* equals = make_string_method_node(Op_StrEquals, receiver_start, receiver_cnt, argument_start, argument_cnt);
|
||||
phi->init_req(1, equals);
|
||||
region->init_req(1, control());
|
||||
}
|
||||
}
|
||||
|
||||
// post merge
|
||||
@ -1162,20 +1179,9 @@ Node* LibraryCallKit::string_indexOf(Node* string_object, ciTypeArray* target_ar
|
||||
|
||||
const int nargs = 2; // number of arguments to push back for uncommon trap in predicate
|
||||
|
||||
const int value_offset = java_lang_String::value_offset_in_bytes();
|
||||
const int count_offset = java_lang_String::count_offset_in_bytes();
|
||||
const int offset_offset = java_lang_String::offset_offset_in_bytes();
|
||||
|
||||
ciInstanceKlass* klass = env()->String_klass();
|
||||
const TypeOopPtr* string_type = TypeOopPtr::make_from_klass(klass);
|
||||
const TypeAryPtr* source_type = TypeAryPtr::make(TypePtr::NotNull, TypeAry::make(TypeInt::CHAR,TypeInt::POS), ciTypeArrayKlass::make(T_CHAR), true, 0);
|
||||
|
||||
Node* sourceOffseta = basic_plus_adr(string_object, string_object, offset_offset);
|
||||
Node* sourceOffset = make_load(no_ctrl, sourceOffseta, TypeInt::INT, T_INT, string_type->add_offset(offset_offset));
|
||||
Node* sourceCounta = basic_plus_adr(string_object, string_object, count_offset);
|
||||
Node* sourceCount = make_load(no_ctrl, sourceCounta, TypeInt::INT, T_INT, string_type->add_offset(count_offset));
|
||||
Node* sourcea = basic_plus_adr(string_object, string_object, value_offset);
|
||||
Node* source = make_load(no_ctrl, sourcea, source_type, T_OBJECT, string_type->add_offset(value_offset));
|
||||
Node* source = load_String_value(no_ctrl, string_object);
|
||||
Node* sourceOffset = load_String_offset(no_ctrl, string_object);
|
||||
Node* sourceCount = load_String_length(no_ctrl, string_object);
|
||||
|
||||
Node* target = _gvn.transform( makecon(TypeOopPtr::make_from_constant(target_array, true)) );
|
||||
jint target_length = target_array->length();
|
||||
@ -1243,10 +1249,6 @@ Node* LibraryCallKit::string_indexOf(Node* string_object, ciTypeArray* target_ar
|
||||
//------------------------------inline_string_indexOf------------------------
|
||||
bool LibraryCallKit::inline_string_indexOf() {
|
||||
|
||||
const int value_offset = java_lang_String::value_offset_in_bytes();
|
||||
const int count_offset = java_lang_String::count_offset_in_bytes();
|
||||
const int offset_offset = java_lang_String::offset_offset_in_bytes();
|
||||
|
||||
_sp += 2;
|
||||
Node *argument = pop(); // pop non-receiver first: it was pushed second
|
||||
Node *receiver = pop();
|
||||
@ -1280,12 +1282,21 @@ bool LibraryCallKit::inline_string_indexOf() {
|
||||
Node* result_phi = new (C, 4) PhiNode(result_rgn, TypeInt::INT);
|
||||
Node* no_ctrl = NULL;
|
||||
|
||||
// Get counts for string and substr
|
||||
Node* source_cnta = basic_plus_adr(receiver, receiver, count_offset);
|
||||
Node* source_cnt = make_load(no_ctrl, source_cnta, TypeInt::INT, T_INT, string_type->add_offset(count_offset));
|
||||
// Get start addr of source string
|
||||
Node* source = load_String_value(no_ctrl, receiver);
|
||||
Node* source_offset = load_String_offset(no_ctrl, receiver);
|
||||
Node* source_start = array_element_address(source, source_offset, T_CHAR);
|
||||
|
||||
Node* substr_cnta = basic_plus_adr(argument, argument, count_offset);
|
||||
Node* substr_cnt = make_load(no_ctrl, substr_cnta, TypeInt::INT, T_INT, string_type->add_offset(count_offset));
|
||||
// Get length of source string
|
||||
Node* source_cnt = load_String_length(no_ctrl, receiver);
|
||||
|
||||
// Get start addr of substring
|
||||
Node* substr = load_String_value(no_ctrl, argument);
|
||||
Node* substr_offset = load_String_offset(no_ctrl, argument);
|
||||
Node* substr_start = array_element_address(substr, substr_offset, T_CHAR);
|
||||
|
||||
// Get length of source string
|
||||
Node* substr_cnt = load_String_length(no_ctrl, argument);
|
||||
|
||||
// Check for substr count > string count
|
||||
Node* cmp = _gvn.transform( new(C, 3) CmpINode(substr_cnt, source_cnt) );
|
||||
@ -1308,7 +1319,7 @@ bool LibraryCallKit::inline_string_indexOf() {
|
||||
}
|
||||
|
||||
if (!stopped()) {
|
||||
result = make_string_method_node(Op_StrIndexOf, receiver, source_cnt, argument, substr_cnt);
|
||||
result = make_string_method_node(Op_StrIndexOf, source_start, source_cnt, substr_start, substr_cnt);
|
||||
result_phi->init_req(1, result);
|
||||
result_rgn->init_req(1, control());
|
||||
}
|
||||
@ -1333,11 +1344,19 @@ bool LibraryCallKit::inline_string_indexOf() {
|
||||
ciInstance* str = str_const->as_instance();
|
||||
assert(str != NULL, "must be instance");
|
||||
|
||||
ciObject* v = str->field_value_by_offset(value_offset).as_object();
|
||||
int o = str->field_value_by_offset(offset_offset).as_int();
|
||||
int c = str->field_value_by_offset(count_offset).as_int();
|
||||
ciObject* v = str->field_value_by_offset(java_lang_String::value_offset_in_bytes()).as_object();
|
||||
ciTypeArray* pat = v->as_type_array(); // pattern (argument) character array
|
||||
|
||||
int o;
|
||||
int c;
|
||||
if (java_lang_String::has_offset_field()) {
|
||||
o = str->field_value_by_offset(java_lang_String::offset_offset_in_bytes()).as_int();
|
||||
c = str->field_value_by_offset(java_lang_String::count_offset_in_bytes()).as_int();
|
||||
} else {
|
||||
o = 0;
|
||||
c = pat->length();
|
||||
}
|
||||
|
||||
// constant strings have no offset and count == length which
|
||||
// simplifies the resulting code somewhat so lets optimize for that.
|
||||
if (o != 0 || c != pat->length()) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2009, 2012, 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
|
||||
@ -528,16 +528,6 @@ PhaseStringOpts::PhaseStringOpts(PhaseGVN* gvn, Unique_Node_List*):
|
||||
}
|
||||
|
||||
// Collect the types needed to talk about the various slices of memory
|
||||
const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(),
|
||||
false, NULL, 0);
|
||||
|
||||
const TypePtr* value_field_type = string_type->add_offset(java_lang_String::value_offset_in_bytes());
|
||||
const TypePtr* offset_field_type = string_type->add_offset(java_lang_String::offset_offset_in_bytes());
|
||||
const TypePtr* count_field_type = string_type->add_offset(java_lang_String::count_offset_in_bytes());
|
||||
|
||||
value_field_idx = C->get_alias_index(value_field_type);
|
||||
count_field_idx = C->get_alias_index(count_field_type);
|
||||
offset_field_idx = C->get_alias_index(offset_field_type);
|
||||
char_adr_idx = C->get_alias_index(TypeAryPtr::CHARS);
|
||||
|
||||
// For each locally allocated StringBuffer see if the usages can be
|
||||
@ -1174,18 +1164,9 @@ void PhaseStringOpts::int_getChars(GraphKit& kit, Node* arg, Node* char_array, N
|
||||
|
||||
Node* PhaseStringOpts::copy_string(GraphKit& kit, Node* str, Node* char_array, Node* start) {
|
||||
Node* string = str;
|
||||
Node* offset = kit.make_load(kit.control(),
|
||||
kit.basic_plus_adr(string, string, java_lang_String::offset_offset_in_bytes()),
|
||||
TypeInt::INT, T_INT, offset_field_idx);
|
||||
Node* count = kit.make_load(kit.control(),
|
||||
kit.basic_plus_adr(string, string, java_lang_String::count_offset_in_bytes()),
|
||||
TypeInt::INT, T_INT, count_field_idx);
|
||||
const TypeAryPtr* value_type = TypeAryPtr::make(TypePtr::NotNull,
|
||||
TypeAry::make(TypeInt::CHAR,TypeInt::POS),
|
||||
ciTypeArrayKlass::make(T_CHAR), true, 0);
|
||||
Node* value = kit.make_load(kit.control(),
|
||||
kit.basic_plus_adr(string, string, java_lang_String::value_offset_in_bytes()),
|
||||
value_type, T_OBJECT, value_field_idx);
|
||||
Node* offset = kit.load_String_offset(kit.control(), string);
|
||||
Node* count = kit.load_String_length(kit.control(), string);
|
||||
Node* value = kit.load_String_value (kit.control(), string);
|
||||
|
||||
// copy the contents
|
||||
if (offset->is_Con() && count->is_Con() && value->is_Con() && count->get_int() < unroll_string_copy_length) {
|
||||
@ -1342,10 +1323,9 @@ void PhaseStringOpts::replace_string_concat(StringConcat* sc) {
|
||||
arg = phi;
|
||||
sc->set_argument(argi, arg);
|
||||
}
|
||||
// Node* offset = kit.make_load(NULL, kit.basic_plus_adr(arg, arg, offset_offset),
|
||||
// TypeInt::INT, T_INT, offset_field_idx);
|
||||
Node* count = kit.make_load(kit.control(), kit.basic_plus_adr(arg, arg, java_lang_String::count_offset_in_bytes()),
|
||||
TypeInt::INT, T_INT, count_field_idx);
|
||||
|
||||
Node* count = kit.load_String_length(kit.control(), arg);
|
||||
|
||||
length = __ AddI(length, count);
|
||||
string_sizes->init_req(argi, NULL);
|
||||
break;
|
||||
@ -1436,12 +1416,11 @@ void PhaseStringOpts::replace_string_concat(StringConcat* sc) {
|
||||
}
|
||||
|
||||
// Intialize the string
|
||||
kit.store_to_memory(kit.control(), kit.basic_plus_adr(result, java_lang_String::offset_offset_in_bytes()),
|
||||
__ intcon(0), T_INT, offset_field_idx);
|
||||
kit.store_to_memory(kit.control(), kit.basic_plus_adr(result, java_lang_String::count_offset_in_bytes()),
|
||||
length, T_INT, count_field_idx);
|
||||
kit.store_to_memory(kit.control(), kit.basic_plus_adr(result, java_lang_String::value_offset_in_bytes()),
|
||||
char_array, T_OBJECT, value_field_idx);
|
||||
if (java_lang_String::has_offset_field()) {
|
||||
kit.store_String_offset(kit.control(), result, __ intcon(0));
|
||||
kit.store_String_length(kit.control(), result, length);
|
||||
}
|
||||
kit.store_String_value(kit.control(), result, char_array);
|
||||
|
||||
// hook up the outgoing control and result
|
||||
kit.replace_call(sc->end(), result);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2009, 2012, 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
|
||||
@ -41,9 +41,6 @@ class PhaseStringOpts : public Phase {
|
||||
|
||||
// Memory slices needed for code gen
|
||||
int char_adr_idx;
|
||||
int value_field_idx;
|
||||
int count_field_idx;
|
||||
int offset_field_idx;
|
||||
|
||||
// Integer.sizeTable - used for int to String conversion
|
||||
ciField* size_table_field;
|
||||
|
@ -3039,7 +3039,7 @@ jint Arguments::parse(const JavaVMInitArgs* args) {
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef JAVASE_EMBEDDED
|
||||
#if (defined JAVASE_EMBEDDED || defined ARM)
|
||||
UNSUPPORTED_OPTION(UseG1GC, "G1 GC");
|
||||
#endif
|
||||
|
||||
@ -3092,6 +3092,14 @@ jint Arguments::parse(const JavaVMInitArgs* args) {
|
||||
PrintGC = true;
|
||||
}
|
||||
|
||||
if (!JDK_Version::is_gte_jdk18x_version()) {
|
||||
// To avoid changing the log format for 7 updates this flag is only
|
||||
// true by default in JDK8 and above.
|
||||
if (FLAG_IS_DEFAULT(PrintGCCause)) {
|
||||
FLAG_SET_DEFAULT(PrintGCCause, false);
|
||||
}
|
||||
}
|
||||
|
||||
// Set object alignment values.
|
||||
set_object_alignment();
|
||||
|
||||
|
@ -3902,7 +3902,10 @@ class CommandLineFlags {
|
||||
" of this flag is true for JDK 6 and earlier") \
|
||||
\
|
||||
diagnostic(bool, WhiteBoxAPI, false, \
|
||||
"Enable internal testing APIs")
|
||||
"Enable internal testing APIs") \
|
||||
\
|
||||
product(bool, PrintGCCause, true, \
|
||||
"Include GC cause in GC logging")
|
||||
|
||||
/*
|
||||
* Macros for factoring of globals
|
||||
|
@ -206,6 +206,10 @@ class JDK_Version VALUE_OBJ_CLASS_SPEC {
|
||||
return current().compare_major(7) == 0;
|
||||
}
|
||||
|
||||
static bool is_jdk18x_version() {
|
||||
return current().compare_major(8) == 0;
|
||||
}
|
||||
|
||||
static bool is_gte_jdk13x_version() {
|
||||
return current().compare_major(3) >= 0;
|
||||
}
|
||||
@ -225,6 +229,10 @@ class JDK_Version VALUE_OBJ_CLASS_SPEC {
|
||||
static bool is_gte_jdk17x_version() {
|
||||
return current().compare_major(7) >= 0;
|
||||
}
|
||||
|
||||
static bool is_gte_jdk18x_version() {
|
||||
return current().compare_major(8) >= 0;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_RUNTIME_JAVA_HPP
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -179,6 +179,11 @@ const jlong NANOSECS_PER_SEC = CONST64(1000000000);
|
||||
const jint NANOSECS_PER_MILLISEC = 1000000;
|
||||
|
||||
inline const char* proper_unit_for_byte_size(size_t s) {
|
||||
#ifdef _LP64
|
||||
if (s >= 10*G) {
|
||||
return "G";
|
||||
}
|
||||
#endif
|
||||
if (s >= 10*M) {
|
||||
return "M";
|
||||
} else if (s >= 10*K) {
|
||||
@ -188,17 +193,22 @@ inline const char* proper_unit_for_byte_size(size_t s) {
|
||||
}
|
||||
}
|
||||
|
||||
inline size_t byte_size_in_proper_unit(size_t s) {
|
||||
template <class T>
|
||||
inline T byte_size_in_proper_unit(T s) {
|
||||
#ifdef _LP64
|
||||
if (s >= 10*G) {
|
||||
return (T)(s/G);
|
||||
}
|
||||
#endif
|
||||
if (s >= 10*M) {
|
||||
return s/M;
|
||||
return (T)(s/M);
|
||||
} else if (s >= 10*K) {
|
||||
return s/K;
|
||||
return (T)(s/K);
|
||||
} else {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
// VM type definitions
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user