提交 348d6915 编写于 作者: P phh

7125934: Add a fast unordered timestamp capability to Hotspot on x86/x64

Summary: Add rdtsc detection and inline generation.
Reviewed-by: kamg, dholmes
Contributed-by: karen.kinnear@oracle.com
上级 d788ed06
...@@ -50,7 +50,7 @@ const char* VM_Version::_features_str = ""; ...@@ -50,7 +50,7 @@ const char* VM_Version::_features_str = "";
VM_Version::CpuidInfo VM_Version::_cpuid_info = { 0, }; VM_Version::CpuidInfo VM_Version::_cpuid_info = { 0, };
static BufferBlob* stub_blob; static BufferBlob* stub_blob;
static const int stub_size = 400; static const int stub_size = 500;
extern "C" { extern "C" {
typedef void (*getPsrInfo_stub_t)(void*); typedef void (*getPsrInfo_stub_t)(void*);
...@@ -73,7 +73,7 @@ class VM_Version_StubGenerator: public StubCodeGenerator { ...@@ -73,7 +73,7 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
const uint32_t CPU_FAMILY_486 = (4 << CPU_FAMILY_SHIFT); const uint32_t CPU_FAMILY_486 = (4 << CPU_FAMILY_SHIFT);
Label detect_486, cpu486, detect_586, std_cpuid1, std_cpuid4; Label detect_486, cpu486, detect_586, std_cpuid1, std_cpuid4;
Label ext_cpuid1, ext_cpuid5, done; Label ext_cpuid1, ext_cpuid5, ext_cpuid7, done;
StubCodeMark mark(this, "VM_Version", "getPsrInfo_stub"); StubCodeMark mark(this, "VM_Version", "getPsrInfo_stub");
# define __ _masm-> # define __ _masm->
...@@ -235,8 +235,10 @@ class VM_Version_StubGenerator: public StubCodeGenerator { ...@@ -235,8 +235,10 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
__ jcc(Assembler::belowEqual, done); __ jcc(Assembler::belowEqual, done);
__ cmpl(rax, 0x80000004); // Is cpuid(0x80000005) supported? __ cmpl(rax, 0x80000004); // Is cpuid(0x80000005) supported?
__ jccb(Assembler::belowEqual, ext_cpuid1); __ jccb(Assembler::belowEqual, ext_cpuid1);
__ cmpl(rax, 0x80000007); // Is cpuid(0x80000008) supported? __ cmpl(rax, 0x80000006); // Is cpuid(0x80000007) supported?
__ jccb(Assembler::belowEqual, ext_cpuid5); __ jccb(Assembler::belowEqual, ext_cpuid5);
__ cmpl(rax, 0x80000007); // Is cpuid(0x80000008) supported?
__ jccb(Assembler::belowEqual, ext_cpuid7);
// //
// Extended cpuid(0x80000008) // Extended cpuid(0x80000008)
// //
...@@ -248,6 +250,18 @@ class VM_Version_StubGenerator: public StubCodeGenerator { ...@@ -248,6 +250,18 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
__ movl(Address(rsi, 8), rcx); __ movl(Address(rsi, 8), rcx);
__ movl(Address(rsi,12), rdx); __ movl(Address(rsi,12), rdx);
//
// Extended cpuid(0x80000007)
//
__ bind(ext_cpuid7);
__ movl(rax, 0x80000007);
__ cpuid();
__ lea(rsi, Address(rbp, in_bytes(VM_Version::ext_cpuid7_offset())));
__ movl(Address(rsi, 0), rax);
__ movl(Address(rsi, 4), rbx);
__ movl(Address(rsi, 8), rcx);
__ movl(Address(rsi,12), rdx);
// //
// Extended cpuid(0x80000005) // Extended cpuid(0x80000005)
// //
...@@ -365,7 +379,7 @@ void VM_Version::get_processor_features() { ...@@ -365,7 +379,7 @@ void VM_Version::get_processor_features() {
} }
char buf[256]; char buf[256];
jio_snprintf(buf, sizeof(buf), "(%u cores per cpu, %u threads per core) family %d model %d stepping %d%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", jio_snprintf(buf, sizeof(buf), "(%u cores per cpu, %u threads per core) family %d model %d stepping %d%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
cores_per_cpu(), threads_per_core(), cores_per_cpu(), threads_per_core(),
cpu_family(), _model, _stepping, cpu_family(), _model, _stepping,
(supports_cmov() ? ", cmov" : ""), (supports_cmov() ? ", cmov" : ""),
...@@ -383,7 +397,10 @@ void VM_Version::get_processor_features() { ...@@ -383,7 +397,10 @@ void VM_Version::get_processor_features() {
(supports_3dnow_prefetch() ? ", 3dnowpref" : ""), (supports_3dnow_prefetch() ? ", 3dnowpref" : ""),
(supports_lzcnt() ? ", lzcnt": ""), (supports_lzcnt() ? ", lzcnt": ""),
(supports_sse4a() ? ", sse4a": ""), (supports_sse4a() ? ", sse4a": ""),
(supports_ht() ? ", ht": "")); (supports_ht() ? ", ht": ""),
(supports_tsc() ? ", tsc": ""),
(supports_tscinv_bit() ? ", tscinvbit": ""),
(supports_tscinv() ? ", tscinv": ""));
_features_str = strdup(buf); _features_str = strdup(buf);
// UseSSE is set to the smaller of what hardware supports and what // UseSSE is set to the smaller of what hardware supports and what
......
/* /*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -176,32 +176,54 @@ public: ...@@ -176,32 +176,54 @@ public:
} bits; } bits;
}; };
union ExtCpuid7Edx {
uint32_t value;
struct {
uint32_t : 8,
tsc_invariance : 1,
: 23;
} bits;
};
protected: protected:
static int _cpu; static int _cpu;
static int _model; static int _model;
static int _stepping; static int _stepping;
static int _cpuFeatures; // features returned by the "cpuid" instruction static int _cpuFeatures; // features returned by the "cpuid" instruction
// 0 if this instruction is not available // 0 if this instruction is not available
static const char* _features_str; static const char* _features_str;
enum { enum {
CPU_CX8 = (1 << 0), // next bits are from cpuid 1 (EDX) CPU_CX8 = (1 << 0), // next bits are from cpuid 1 (EDX)
CPU_CMOV = (1 << 1), CPU_CMOV = (1 << 1),
CPU_FXSR = (1 << 2), CPU_FXSR = (1 << 2),
CPU_HT = (1 << 3), CPU_HT = (1 << 3),
CPU_MMX = (1 << 4), CPU_MMX = (1 << 4),
CPU_3DNOW_PREFETCH = (1 << 5), // Processor supports 3dnow prefetch and prefetchw instructions CPU_3DNOW_PREFETCH = (1 << 5), // Processor supports 3dnow prefetch and prefetchw instructions
// may not necessarily support other 3dnow instructions // may not necessarily support other 3dnow instructions
CPU_SSE = (1 << 6), CPU_SSE = (1 << 6),
CPU_SSE2 = (1 << 7), CPU_SSE2 = (1 << 7),
CPU_SSE3 = (1 << 8), // SSE3 comes from cpuid 1 (ECX) CPU_SSE3 = (1 << 8), // SSE3 comes from cpuid 1 (ECX)
CPU_SSSE3 = (1 << 9), CPU_SSSE3 = (1 << 9),
CPU_SSE4A = (1 << 10), CPU_SSE4A = (1 << 10),
CPU_SSE4_1 = (1 << 11), CPU_SSE4_1 = (1 << 11),
CPU_SSE4_2 = (1 << 12), CPU_SSE4_2 = (1 << 12),
CPU_POPCNT = (1 << 13), CPU_POPCNT = (1 << 13),
CPU_LZCNT = (1 << 14) CPU_LZCNT = (1 << 14),
} cpuFeatureFlags; CPU_TSC = (1 << 15),
CPU_TSCINV = (1 << 16)
} cpuFeatureFlags;
enum {
// AMD
CPU_FAMILY_AMD_11H = 17,
// Intel
CPU_FAMILY_INTEL_CORE = 6,
CPU_MODEL_NEHALEM_EP = 26,
CPU_MODEL_WESTMERE_EP = 44,
// CPU_MODEL_IVYBRIDGE_EP = ??, TODO - get real value
CPU_MODEL_SANDYBRIDGE_EP = 45
} cpuExtendedFamily;
// cpuid information block. All info derived from executing cpuid with // cpuid information block. All info derived from executing cpuid with
// various function numbers is stored here. Intel and AMD info is // various function numbers is stored here. Intel and AMD info is
...@@ -270,6 +292,12 @@ protected: ...@@ -270,6 +292,12 @@ protected:
ExtCpuid5Ex ext_cpuid5_ecx; // L1 data cache info (AMD) ExtCpuid5Ex ext_cpuid5_ecx; // L1 data cache info (AMD)
ExtCpuid5Ex ext_cpuid5_edx; // L1 instruction cache info (AMD) ExtCpuid5Ex ext_cpuid5_edx; // L1 instruction cache info (AMD)
// cpuid function 0x80000007
uint32_t ext_cpuid7_eax; // reserved
uint32_t ext_cpuid7_ebx; // reserved
uint32_t ext_cpuid7_ecx; // reserved
ExtCpuid7Edx ext_cpuid7_edx; // tscinv
// cpuid function 0x80000008 // cpuid function 0x80000008
uint32_t ext_cpuid8_eax; // unused currently uint32_t ext_cpuid8_eax; // unused currently
uint32_t ext_cpuid8_ebx; // reserved uint32_t ext_cpuid8_ebx; // reserved
...@@ -286,19 +314,23 @@ protected: ...@@ -286,19 +314,23 @@ protected:
result += _cpuid_info.std_cpuid1_eax.bits.ext_family; result += _cpuid_info.std_cpuid1_eax.bits.ext_family;
return result; return result;
} }
static uint32_t extended_cpu_model() { static uint32_t extended_cpu_model() {
uint32_t result = _cpuid_info.std_cpuid1_eax.bits.model; uint32_t result = _cpuid_info.std_cpuid1_eax.bits.model;
result |= _cpuid_info.std_cpuid1_eax.bits.ext_model << 4; result |= _cpuid_info.std_cpuid1_eax.bits.ext_model << 4;
return result; return result;
} }
static uint32_t cpu_stepping() { static uint32_t cpu_stepping() {
uint32_t result = _cpuid_info.std_cpuid1_eax.bits.stepping; uint32_t result = _cpuid_info.std_cpuid1_eax.bits.stepping;
return result; return result;
} }
static uint logical_processor_count() { static uint logical_processor_count() {
uint result = threads_per_core(); uint result = threads_per_core();
return result; return result;
} }
static uint32_t feature_flags() { static uint32_t feature_flags() {
uint32_t result = 0; uint32_t result = 0;
if (_cpuid_info.std_cpuid1_edx.bits.cmpxchg8 != 0) if (_cpuid_info.std_cpuid1_edx.bits.cmpxchg8 != 0)
...@@ -328,6 +360,10 @@ protected: ...@@ -328,6 +360,10 @@ protected:
result |= CPU_SSE4_2; result |= CPU_SSE4_2;
if (_cpuid_info.std_cpuid1_ecx.bits.popcnt != 0) if (_cpuid_info.std_cpuid1_ecx.bits.popcnt != 0)
result |= CPU_POPCNT; result |= CPU_POPCNT;
if (_cpuid_info.std_cpuid1_edx.bits.tsc != 0)
result |= CPU_TSC;
if (_cpuid_info.ext_cpuid7_edx.bits.tsc_invariance != 0)
result |= CPU_TSCINV;
// AMD features. // AMD features.
if (is_amd()) { if (is_amd()) {
...@@ -352,6 +388,7 @@ public: ...@@ -352,6 +388,7 @@ public:
static ByteSize dcp_cpuid4_offset() { return byte_offset_of(CpuidInfo, dcp_cpuid4_eax); } static ByteSize dcp_cpuid4_offset() { return byte_offset_of(CpuidInfo, dcp_cpuid4_eax); }
static ByteSize ext_cpuid1_offset() { return byte_offset_of(CpuidInfo, ext_cpuid1_eax); } static ByteSize ext_cpuid1_offset() { return byte_offset_of(CpuidInfo, ext_cpuid1_eax); }
static ByteSize ext_cpuid5_offset() { return byte_offset_of(CpuidInfo, ext_cpuid5_eax); } static ByteSize ext_cpuid5_offset() { return byte_offset_of(CpuidInfo, ext_cpuid5_eax); }
static ByteSize ext_cpuid7_offset() { return byte_offset_of(CpuidInfo, ext_cpuid7_eax); }
static ByteSize ext_cpuid8_offset() { return byte_offset_of(CpuidInfo, ext_cpuid8_eax); } static ByteSize ext_cpuid8_offset() { return byte_offset_of(CpuidInfo, ext_cpuid8_eax); }
static ByteSize tpl_cpuidB0_offset() { return byte_offset_of(CpuidInfo, tpl_cpuidB0_eax); } static ByteSize tpl_cpuidB0_offset() { return byte_offset_of(CpuidInfo, tpl_cpuidB0_eax); }
static ByteSize tpl_cpuidB1_offset() { return byte_offset_of(CpuidInfo, tpl_cpuidB1_eax); } static ByteSize tpl_cpuidB1_offset() { return byte_offset_of(CpuidInfo, tpl_cpuidB1_eax); }
...@@ -382,7 +419,6 @@ public: ...@@ -382,7 +419,6 @@ public:
// //
static int cpu_family() { return _cpu;} static int cpu_family() { return _cpu;}
static bool is_P6() { return cpu_family() >= 6; } static bool is_P6() { return cpu_family() >= 6; }
static bool is_amd() { assert_is_initialized(); return _cpuid_info.std_vendor_name_0 == 0x68747541; } // 'htuA' static bool is_amd() { assert_is_initialized(); return _cpuid_info.std_vendor_name_0 == 0x68747541; } // 'htuA'
static bool is_intel() { assert_is_initialized(); return _cpuid_info.std_vendor_name_0 == 0x756e6547; } // 'uneG' static bool is_intel() { assert_is_initialized(); return _cpuid_info.std_vendor_name_0 == 0x756e6547; } // 'uneG'
...@@ -447,14 +483,49 @@ public: ...@@ -447,14 +483,49 @@ public:
static bool supports_sse4_1() { return (_cpuFeatures & CPU_SSE4_1) != 0; } static bool supports_sse4_1() { return (_cpuFeatures & CPU_SSE4_1) != 0; }
static bool supports_sse4_2() { return (_cpuFeatures & CPU_SSE4_2) != 0; } static bool supports_sse4_2() { return (_cpuFeatures & CPU_SSE4_2) != 0; }
static bool supports_popcnt() { return (_cpuFeatures & CPU_POPCNT) != 0; } static bool supports_popcnt() { return (_cpuFeatures & CPU_POPCNT) != 0; }
// static bool supports_tsc() { return (_cpuFeatures & CPU_TSC) != 0; }
// Intel features
static bool is_intel_family_core() { return is_intel() &&
extended_cpu_family() == CPU_FAMILY_INTEL_CORE; }
static bool is_intel_tsc_synched_at_init() {
if (is_intel_family_core()) {
uint32_t ext_model = extended_cpu_model();
if (ext_model == CPU_MODEL_NEHALEM_EP ||
ext_model == CPU_MODEL_WESTMERE_EP ||
// TODO ext_model == CPU_MODEL_IVYBRIDGE_EP ||
ext_model == CPU_MODEL_SANDYBRIDGE_EP) {
// 2-socket invtsc support. EX versions with 4 sockets are not
// guaranteed to synchronize tscs at initialization via a double
// handshake. The tscs can be explicitly set in software. Code
// that uses tsc values must be prepared for them to arbitrarily
// jump backward or forward.
return true;
}
}
return false;
}
// AMD features // AMD features
//
static bool supports_3dnow_prefetch() { return (_cpuFeatures & CPU_3DNOW_PREFETCH) != 0; } static bool supports_3dnow_prefetch() { return (_cpuFeatures & CPU_3DNOW_PREFETCH) != 0; }
static bool supports_mmx_ext() { return is_amd() && _cpuid_info.ext_cpuid1_edx.bits.mmx_amd != 0; } static bool supports_mmx_ext() { return is_amd() && _cpuid_info.ext_cpuid1_edx.bits.mmx_amd != 0; }
static bool supports_lzcnt() { return (_cpuFeatures & CPU_LZCNT) != 0; } static bool supports_lzcnt() { return (_cpuFeatures & CPU_LZCNT) != 0; }
static bool supports_sse4a() { return (_cpuFeatures & CPU_SSE4A) != 0; } static bool supports_sse4a() { return (_cpuFeatures & CPU_SSE4A) != 0; }
static bool is_amd_Barcelona() { return is_amd() &&
extended_cpu_family() == CPU_FAMILY_AMD_11H; }
// Intel and AMD newer cores support fast timestamps well
static bool supports_tscinv_bit() {
return (_cpuFeatures & CPU_TSCINV) != 0;
}
static bool supports_tscinv() {
return supports_tscinv_bit() &&
( (is_amd() && !is_amd_Barcelona()) ||
is_intel_tsc_synched_at_init() );
}
// Intel Core and newer cpus have fast IDIV instruction (excluding Atom). // Intel Core and newer cpus have fast IDIV instruction (excluding Atom).
static bool has_fast_idiv() { return is_intel() && cpu_family() == 6 && static bool has_fast_idiv() { return is_intel() && cpu_family() == 6 &&
supports_sse3() && _model != 0x1C; } supports_sse3() && _model != 0x1C; }
......
...@@ -28,6 +28,8 @@ ...@@ -28,6 +28,8 @@
static void setup_fpu(); static void setup_fpu();
static bool supports_sse(); static bool supports_sse();
static jlong rdtsc();
static bool is_allocatable(size_t bytes); static bool is_allocatable(size_t bytes);
// Used to register dynamic code cache area with the OS // Used to register dynamic code cache area with the OS
......
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* 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 OS_CPU_BSD_X86_VM_OS_BSD_X86_INLINE_HPP
#define OS_CPU_BSD_X86_VM_OS_BSD_X86_INLINE_HPP
#include "runtime/os.hpp"
// See http://www.technovelty.org/code/c/reading-rdtsc.htl for details
inline jlong os::rdtsc() {
#ifndef AMD64
// 64 bit result in edx:eax
uint64_t res;
__asm__ __volatile__ ("rdtsc" : "=A" (res));
return (jlong)res;
#else
uint64_t res;
uint32_t ts1, ts2;
__asm__ __volatile__ ("rdtsc" : "=a" (ts1), "=d" (ts2));
res = ((uint64_t)ts1 | (uint64_t)ts2 << 32);
return (jlong)res;
#endif // AMD64
}
#endif // OS_CPU_BSD_X86_VM_OS_BSD_X86_INLINE_HPP
/* /*
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -28,6 +28,8 @@ ...@@ -28,6 +28,8 @@
static void setup_fpu(); static void setup_fpu();
static bool supports_sse(); static bool supports_sse();
static jlong rdtsc();
static bool is_allocatable(size_t bytes); static bool is_allocatable(size_t bytes);
// Used to register dynamic code cache area with the OS // Used to register dynamic code cache area with the OS
......
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* 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 OS_CPU_LINUX_X86_VM_OS_LINUX_X86_INLINE_HPP
#define OS_CPU_LINUX_X86_VM_OS_LINUX_X86_INLINE_HPP
#include "runtime/os.hpp"
// See http://www.technovelty.org/code/c/reading-rdtsc.htl for details
inline jlong os::rdtsc() {
#ifndef AMD64
// 64 bit result in edx:eax
uint64_t res;
__asm__ __volatile__ ("rdtsc" : "=A" (res));
return (jlong)res;
#else
uint64_t res;
uint32_t ts1, ts2;
__asm__ __volatile__ ("rdtsc" : "=a" (ts1), "=d" (ts2));
res = ((uint64_t)ts1 | (uint64_t)ts2 << 32);
return (jlong)res;
#endif // AMD64
}
#endif // OS_CPU_LINUX_X86_VM_OS_LINUX_X86_INLINE_HPP
...@@ -46,6 +46,8 @@ ...@@ -46,6 +46,8 @@
static bool supports_sse(); static bool supports_sse();
static jlong rdtsc();
static bool is_allocatable(size_t bytes); static bool is_allocatable(size_t bytes);
// Used to register dynamic code cache area with the OS // Used to register dynamic code cache area with the OS
......
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* 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 OS_CPU_SOLARIS_X86_VM_OS_SOLARIS_X86_INLINE_HPP
#define OS_CPU_SOLARIS_X86_VM_OS_SOLARIS_X86_INLINE_HPP
#include "runtime/os.hpp"
inline jlong os::rdtsc() { return _raw_rdtsc(); }
#endif // OS_CPU_SOLARIS_X86_VM_OS_SOLARIS_X86_INLINE_HPP
...@@ -43,6 +43,11 @@ ...@@ -43,6 +43,11 @@
movl %ebp, %eax movl %ebp, %eax
.end .end
// Support for os::rdtsc()
.inline _raw_rdtsc,0
rdtsc
.end
// Support for jint Atomic::add(jint inc, volatile jint* dest) // Support for jint Atomic::add(jint inc, volatile jint* dest)
// An additional bool (os::is_MP()) is passed as the last argument. // An additional bool (os::is_MP()) is passed as the last argument.
.inline _Atomic_add,3 .inline _Atomic_add,3
...@@ -113,7 +118,6 @@ ...@@ -113,7 +118,6 @@
fistpll (%eax) fistpll (%eax)
.end .end
// Support for OrderAccess::acquire() // Support for OrderAccess::acquire()
.inline _OrderAccess_acquire,0 .inline _OrderAccess_acquire,0
movl 0(%esp), %eax movl 0(%esp), %eax
......
...@@ -30,12 +30,19 @@ ...@@ -30,12 +30,19 @@
movq %fs:0, %rax movq %fs:0, %rax
.end .end
// Get the frame pointer from current frame. // Get current fp
.inline _get_current_fp,0 .inline _get_current_fp,0
.volatile .volatile
movq %rbp, %rax movq %rbp, %rax
.end .end
// Support for os::rdtsc()
.inline _raw_rdtsc,0
rdtsc
salq $32, %rdx
orq %rdx, %rax
.end
// Support for jint Atomic::add(jint add_value, volatile jint* dest) // Support for jint Atomic::add(jint add_value, volatile jint* dest)
.inline _Atomic_add,2 .inline _Atomic_add,2
movl %edi, %eax // save add_value for return movl %edi, %eax // save add_value for return
......
...@@ -58,6 +58,8 @@ ...@@ -58,6 +58,8 @@
static void setup_fpu(); static void setup_fpu();
static bool supports_sse() { return true; } static bool supports_sse() { return true; }
static jlong rdtsc();
static bool register_code_area(char *low, char *high); static bool register_code_area(char *low, char *high);
#endif // OS_CPU_WINDOWS_X86_VM_OS_WINDOWS_X86_HPP #endif // OS_CPU_WINDOWS_X86_VM_OS_WINDOWS_X86_HPP
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* 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 OS_CPU_WINDOWS_X86_VM_OS_WINDOWS_X86_INLINE_HPP
#define OS_CPU_WINDOWS_X86_VM_OS_WINDOWS_X86_INLINE_HPP
#include "runtime/os.hpp"
inline jlong os::rdtsc() {
// 32 bit: 64 bit result in edx:eax
// 64 bit: 64 bit value in rax
uint64_t res;
res = (uint64_t)__rdtsc();
return (jlong)res;
}
#endif // OS_CPU_WINDOWS_X86_VM_OS_WINDOWS_X86_INLINE_HPP
/* /*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -47,15 +47,16 @@ void bytecodes_init(); ...@@ -47,15 +47,16 @@ void bytecodes_init();
void classLoader_init(); void classLoader_init();
void codeCache_init(); void codeCache_init();
void VM_Version_init(); void VM_Version_init();
void os_init_globals(); // depends on VM_Version_init, before universe_init
void stubRoutines_init1(); void stubRoutines_init1();
jint universe_init(); // dependent on codeCache_init and stubRoutines_init jint universe_init(); // depends on codeCache_init and stubRoutines_init
void interpreter_init(); // before any methods loaded void interpreter_init(); // before any methods loaded
void invocationCounter_init(); // before any methods loaded void invocationCounter_init(); // before any methods loaded
void marksweep_init(); void marksweep_init();
void accessFlags_init(); void accessFlags_init();
void templateTable_init(); void templateTable_init();
void InterfaceSupport_init(); void InterfaceSupport_init();
void universe2_init(); // dependent on codeCache_init and stubRoutines_init void universe2_init(); // dependent on codeCache_init and stubRoutines_init, loads primordial classes
void referenceProcessor_init(); void referenceProcessor_init();
void jni_handles_init(); void jni_handles_init();
void vmStructs_init(); void vmStructs_init();
...@@ -94,8 +95,10 @@ jint init_globals() { ...@@ -94,8 +95,10 @@ jint init_globals() {
classLoader_init(); classLoader_init();
codeCache_init(); codeCache_init();
VM_Version_init(); VM_Version_init();
os_init_globals();
stubRoutines_init1(); stubRoutines_init1();
jint status = universe_init(); // dependent on codeCache_init and stubRoutines_init jint status = universe_init(); // dependent on codeCache_init and
// stubRoutines_init1
if (status != JNI_OK) if (status != JNI_OK)
return status; return status;
...@@ -106,7 +109,7 @@ jint init_globals() { ...@@ -106,7 +109,7 @@ jint init_globals() {
templateTable_init(); templateTable_init();
InterfaceSupport_init(); InterfaceSupport_init();
SharedRuntime::generate_stubs(); SharedRuntime::generate_stubs();
universe2_init(); // dependent on codeCache_init and stubRoutines_init universe2_init(); // dependent on codeCache_init and stubRoutines_init1
referenceProcessor_init(); referenceProcessor_init();
jni_handles_init(); jni_handles_init();
#ifndef VM_STRUCTS_KERNEL #ifndef VM_STRUCTS_KERNEL
...@@ -122,7 +125,7 @@ jint init_globals() { ...@@ -122,7 +125,7 @@ jint init_globals() {
if (!universe_post_init()) { if (!universe_post_init()) {
return JNI_ERR; return JNI_ERR;
} }
javaClasses_init(); // must happen after vtable initialization javaClasses_init(); // must happen after vtable initialization
stubRoutines_init2(); // note: StubRoutines need 2-phase init stubRoutines_init2(); // note: StubRoutines need 2-phase init
// Although we'd like to, we can't easily do a heap verify // Although we'd like to, we can't easily do a heap verify
......
...@@ -82,6 +82,12 @@ julong os::num_frees = 0; // # of calls to free ...@@ -82,6 +82,12 @@ julong os::num_frees = 0; // # of calls to free
julong os::free_bytes = 0; // # of bytes freed julong os::free_bytes = 0; // # of bytes freed
#endif #endif
void os_init_globals() {
// Called from init_globals().
// See Threads::create_vm() in thread.cpp, and init.cpp.
os::init_globals();
}
// Fill in buffer with current local time as an ISO-8601 string. // Fill in buffer with current local time as an ISO-8601 string.
// E.g., yyyy-mm-ddThh:mm:ss-zzzz. // E.g., yyyy-mm-ddThh:mm:ss-zzzz.
// Returns buffer, or NULL if it failed. // Returns buffer, or NULL if it failed.
......
...@@ -99,9 +99,11 @@ class os: AllStatic { ...@@ -99,9 +99,11 @@ class os: AllStatic {
} }
public: public:
static void init(void); // Called before command line parsing static void init(void); // Called before command line parsing
static jint init_2(void); // Called after command line parsing static jint init_2(void); // Called after command line parsing
static void init_globals(void) { // Called from init_globals() in init.cpp
init_globals_ext();
}
static void init_3(void); // Called at the end of vm init static void init_3(void); // Called at the end of vm init
// File names are case-insensitive on windows only // File names are case-insensitive on windows only
...@@ -671,6 +673,11 @@ class os: AllStatic { ...@@ -671,6 +673,11 @@ class os: AllStatic {
// rest of line is skipped. Returns number of bytes read or -1 on EOF // rest of line is skipped. Returns number of bytes read or -1 on EOF
static int get_line_chars(int fd, char *buf, const size_t bsize); static int get_line_chars(int fd, char *buf, const size_t bsize);
// Extensions
#include "runtime/os_ext.hpp"
public:
// Platform dependent stuff // Platform dependent stuff
#ifdef TARGET_OS_FAMILY_linux #ifdef TARGET_OS_FAMILY_linux
# include "os_linux.hpp" # include "os_linux.hpp"
...@@ -715,6 +722,7 @@ class os: AllStatic { ...@@ -715,6 +722,7 @@ class os: AllStatic {
# include "os_bsd_zero.hpp" # include "os_bsd_zero.hpp"
#endif #endif
public:
// debugging support (mostly used by debug.cpp but also fatal error handler) // debugging support (mostly used by debug.cpp but also fatal error handler)
static bool find(address pc, outputStream* st = tty); // OS specific function to make sense out of an address static bool find(address pc, outputStream* st = tty); // OS specific function to make sense out of an address
......
/*
* Copyright (c) 2011 Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* 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_RUNTIME_OS_EXT_HPP
#define SHARE_VM_RUNTIME_OS_EXT_HPP
public:
static void init_globals_ext() {} // Run from init_globals().
// See os.hpp/cpp and init.cpp.
private:
#endif // SHARE_VM_RUNTIME_OS_EXT_HPP
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册