Skip to content
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 11 additions & 49 deletions src/hotspot/cpu/x86/vm_version_x86.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,10 @@ address VM_Version::_cpuinfo_cont_addr_apx = nullptr;
static BufferBlob* stub_blob;
static const int stub_size = 2000;

uint32_t VM_Features::_features_vector_element_shift_count = 6;
uint32_t VM_Features::_features_vector_size = MAX_FEATURE_VEC_SIZE;
VM_Features VM_Version::_features;
VM_Features VM_Version::_cpu_features;
int VM_Version::VM_Features::_features_bitmap_size_in_bytes = sizeof(VM_Version::VM_Features::_features_bitmap);

VM_Version::VM_Features VM_Version::_features;
VM_Version::VM_Features VM_Version::_cpu_features;

extern "C" {
typedef void (*get_cpu_info_stub_t)(void*);
Expand Down Expand Up @@ -1101,11 +1101,8 @@ void VM_Version::get_processor_features() {
cores_per_cpu(), threads_per_core(),
cpu_family(), _model, _stepping, os::cpu_microcode_revision());
assert(cpu_info_size > 0, "not enough temporary space allocated");
size_t buf_iter = cpu_info_size;
for (uint64_t i = 0; i < VM_Features::features_vector_size(); i++) {
insert_features_names(features_vector_elem(i), buf + buf_iter, sizeof(buf) - buf_iter, _features_names, 64 * i);
buf_iter = strlen(buf);
}

insert_features_names(_features, buf + cpu_info_size, sizeof(buf) - cpu_info_size);

_cpu_info_string = os::strdup(buf);

Expand Down Expand Up @@ -2107,7 +2104,6 @@ static bool _vm_version_initialized = false;

void VM_Version::initialize() {
ResourceMark rm;
assert(VM_Features::is_within_feature_vector_bounds(MAX_CPU_FEATURES), "Feature out of vector bounds");

// Making this stub must be FIRST use of assembler
stub_blob = BufferBlob::create("VM_Version stub", stub_size);
Expand Down Expand Up @@ -2884,7 +2880,7 @@ int64_t VM_Version::maximum_qualified_cpu_frequency(void) {
return _max_qualified_cpu_frequency;
}

VM_Features VM_Version::CpuidInfo::feature_flags() const {
VM_Version::VM_Features VM_Version::CpuidInfo::feature_flags() const {
VM_Features vm_features;
if (std_cpuid1_edx.bits.cmpxchg8 != 0)
vm_features.set_feature(CPU_CX8);
Expand Down Expand Up @@ -3280,47 +3276,13 @@ bool VM_Version::is_intrinsic_supported(vmIntrinsicID id) {
return true;
}

void VM_Features::set_feature(uint32_t feature) {
uint32_t index = feature >> _features_vector_element_shift_count;
uint32_t index_mask = (1 << _features_vector_element_shift_count) - 1;
assert(index < _features_vector_size, "Features array index out of bounds");
_features_vector[index] |= (1ULL << (feature & index_mask));
}

void VM_Features::clear_feature(uint32_t feature) {
uint32_t index = feature >> _features_vector_element_shift_count;
uint32_t index_mask = (1 << _features_vector_element_shift_count) - 1;
assert(index < _features_vector_size, "Features array index out of bounds");
_features_vector[index] &= ~(1ULL << (feature & index_mask));
}

void VM_Features::clear_features() {
for (uint32_t i = 0; i < _features_vector_size; i++) {
_features_vector[i] = 0;
}
}

bool VM_Features::supports_feature(uint32_t feature) {
uint32_t index = feature >> _features_vector_element_shift_count;
uint32_t index_mask = (1 << _features_vector_element_shift_count) - 1;
assert(index < _features_vector_size, "Features array index out of bounds");
return (_features_vector[index] & (1ULL << (feature & index_mask))) != 0;
}

bool VM_Features::is_within_feature_vector_bounds(uint32_t num_features) {
return _features_vector_size >= ((num_features >> _features_vector_element_shift_count) + 1);
}

void VM_Version::insert_features_names(uint64_t features, char* buf, size_t buflen, const char* features_names[],
uint features_names_index) {
while (features != 0) {
if (features & 1) {
int res = jio_snprintf(buf, buflen, ", %s", features_names[features_names_index]);
void VM_Version::insert_features_names(VM_Version::VM_Features features, char* buf, size_t buflen) {
for (int i = 0; i < MAX_CPU_FEATURES; i++) {
if (features.supports_feature((VM_Version::Feature_Flag)i)) {
int res = jio_snprintf(buf, buflen, ", %s", _features_names[i]);
assert(res > 0, "not enough temporary space allocated");
buf += res;
buflen -= res;
}
features >>= 1;
++features_names_index;
}
}
100 changes: 61 additions & 39 deletions src/hotspot/cpu/x86/vm_version_x86.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,35 +30,6 @@
#include "utilities/macros.hpp"
#include "utilities/sizes.hpp"

#define MAX_FEATURE_VEC_SIZE 4

class VM_Features {
public:
using FeatureVector = uint64_t [MAX_FEATURE_VEC_SIZE];

// Feature vector bitmap currently only used by x86 backend.
FeatureVector _features_vector;

// log2 of feature vector element size in bits, used by JVMCI to check enabled feature bits.
// Refer HotSpotJVMCIBackendFactory::convertFeaturesVector.
static uint32_t _features_vector_element_shift_count;

// Size of feature vector bitmap.
static uint32_t _features_vector_size;

VM_Features() {
clear_features();
}

void set_feature(uint32_t feature);
void clear_feature(uint32_t feature);
bool supports_feature(uint32_t feature);
void clear_features();

static bool is_within_feature_vector_bounds(uint32_t num_features);
static uint32_t features_vector_size() { return _features_vector_size;}
};

class VM_Version : public Abstract_VM_Version {
friend class VMStructs;
friend class JVMCIVMStructs;
Expand Down Expand Up @@ -393,7 +364,7 @@ class VM_Version : public Abstract_VM_Version {
* test/lib-test/jdk/test/whitebox/CPUInfoTest.java
* src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/amd64/AMD64.java
*/
enum Feature_Flag : uint32_t {
enum Feature_Flag {
#define CPU_FEATURE_FLAGS(decl) \
decl(CX8, "cx8", 0) /* next bits are from cpuid 1 (EDX) */ \
decl(CMOV, "cmov", 1) \
Expand Down Expand Up @@ -479,22 +450,73 @@ class VM_Version : public Abstract_VM_Version {
MAX_CPU_FEATURES
};

static const char* _features_names[];
class VM_Features {
friend class VMStructs;
friend class JVMCIVMStructs;

private:
uint64_t _features_bitmap[(MAX_CPU_FEATURES >> 6) + 1];

STATIC_ASSERT(sizeof(_features_bitmap) * BitsPerByte > MAX_CPU_FEATURES);

// Number of 8-byte elements in _bitmap.
constexpr static int features_bitmap_element_count() {
return sizeof(_features_bitmap) / sizeof(uint64_t);
}

constexpr static int features_bitmap_element_shift_count() {
return LogBitsPerLong;
}

constexpr static uint64_t features_bitmap_element_mask() {
return (1ULL << features_bitmap_element_shift_count()) - 1;
}

static int index(Feature_Flag feature) {
int idx = feature >> features_bitmap_element_shift_count();
assert(idx < features_bitmap_element_count(), "Features array index out of bounds");
return idx;
}

static uint64_t bit_mask(Feature_Flag feature) {
return (1ULL << (feature & features_bitmap_element_mask()));
}

static int _features_bitmap_size_in_bytes; // for JVMCI purposes
public:
VM_Features() {
for (int i = 0; i < features_bitmap_element_count(); i++) {
_features_bitmap[i] = 0;
}
}

void set_feature(Feature_Flag feature) {
int idx = index(feature);
_features_bitmap[idx] |= bit_mask(feature);
}

void clear_feature(VM_Version::Feature_Flag feature) {
int idx = index(feature);
_features_bitmap[idx] &= ~bit_mask(feature);
}

bool supports_feature(VM_Version::Feature_Flag feature) {
int idx = index(feature);
return (_features_bitmap[idx] & bit_mask(feature)) != 0;
}
};

// CPU feature flags vector, can be affected by VM settings.
static VM_Features _features;

// Original CPU feature flags vector, not affected by VM settings.
static VM_Features _cpu_features;

static void clear_cpu_features() {
_features.clear_features();
_cpu_features.clear_features();
}
static const char* _features_names[];

static uint64_t features_vector_elem(uint32_t elem) {
assert(elem < VM_Features::_features_vector_size, "");
return _features._features_vector[elem];
static void clear_cpu_features() {
_features = VM_Features();
_cpu_features = VM_Features();
}

enum Extended_Family {
Expand Down Expand Up @@ -899,7 +921,7 @@ class VM_Version : public Abstract_VM_Version {

static bool is_intel_tsc_synched_at_init();

static void insert_features_names(uint64_t features, char* buf, size_t buflen, const char* features_names[], uint features_names_index = 0);
static void insert_features_names(VM_Version::VM_Features features, char* buf, size_t buflen);

// This checks if the JVM is potentially affected by an erratum on Intel CPUs (SKX102)
// that causes unpredictable behaviour when jcc crosses 64 byte boundaries. Its microcode
Expand Down
2 changes: 1 addition & 1 deletion src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,7 @@ jobjectArray readConfiguration0(JNIEnv *env, JVMCI_TRAPS) {
strcmp(vmField.typeString, "intptr_t") == 0 ||
strcmp(vmField.typeString, "uintptr_t") == 0 ||
strcmp(vmField.typeString, "OopHandle") == 0 ||
strcmp(vmField.typeString, "VM_Features") == 0 ||
strcmp(vmField.typeString, "VM_Version::VM_Features") == 0 ||
strcmp(vmField.typeString, "size_t") == 0 ||
// All foo* types are addresses.
vmField.typeString[strlen(vmField.typeString) - 1] == '*') {
Expand Down
11 changes: 5 additions & 6 deletions src/hotspot/share/jvmci/vmStructs_jvmci.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -975,12 +975,11 @@

#define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field) \
volatile_nonstatic_field(JavaFrameAnchor, _last_Java_fp, intptr_t*) \
static_field(VM_Version, _features, VM_Features) \
\
nonstatic_field(VM_Features, _features_vector, VM_Features::FeatureVector) \
static_field(VM_Features, _features_vector_size, uint32_t) \
static_field(VM_Features, _features_vector_element_shift_count, uint32_t) \
static_field(VM_Version, _has_intel_jcc_erratum, bool)
static_field(VM_Version, _features, VM_Version::VM_Features) \
\
nonstatic_field(VM_Version::VM_Features, _features_bitmap[0], uint64_t) \
static_field(VM_Version::VM_Features, _features_bitmap_size_in_bytes, int) \
static_field(VM_Version, _has_intel_jcc_erratum, bool)

#define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant) \
LP64_ONLY(declare_constant(frame::arg_reg_save_area_bytes)) \
Expand Down
2 changes: 0 additions & 2 deletions src/hotspot/share/runtime/abstract_vm_version.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,6 @@ class Abstract_VM_Version: AllStatic {
static const char* jdk_debug_level();
static const char* printable_jdk_debug_level();

static uint64_t features() { return _features; }

static const char* features_string() { return _features_string; }

static const char* cpu_info_string() { return _cpu_info_string; }
Expand Down
10 changes: 4 additions & 6 deletions src/hotspot/share/runtime/vmStructs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -708,10 +708,9 @@
static_field(Abstract_VM_Version, _vm_security_version, int) \
static_field(Abstract_VM_Version, _vm_build_number, int) \
\
NOT_ZERO(X86_ONLY(static_field(VM_Version, _features, VM_Features))) \
NOT_ZERO(X86_ONLY(nonstatic_field(VM_Features, _features_vector, VM_Features::FeatureVector))) \
NOT_ZERO(X86_ONLY(static_field(VM_Features, _features_vector_size, uint32_t))) \
NOT_ZERO(X86_ONLY(static_field(VM_Features, _features_vector_element_shift_count, uint32_t))) \
NOT_ZERO(X86_ONLY( static_field(VM_Version, _features, VM_Version::VM_Features))) \
NOT_ZERO(X86_ONLY(nonstatic_field(VM_Version::VM_Features, _features_bitmap[0], uint64_t))) \
NOT_ZERO(X86_ONLY( static_field(VM_Version::VM_Features, _features_bitmap_size_in_bytes, int))) \
\
/*************************/ \
/* JVMTI */ \
Expand Down Expand Up @@ -1169,9 +1168,8 @@
/********************/ \
\
declare_toplevel_type(Abstract_VM_Version) \
NOT_ZERO(X86_ONLY(declare_toplevel_type(VM_Features))) \
NOT_ZERO(declare_toplevel_type(VM_Version)) \
NOT_ZERO(X86_ONLY(declare_toplevel_type(VM_Features::FeatureVector))) \
NOT_ZERO(X86_ONLY(declare_toplevel_type(VM_Version::VM_Features))) \
\
/*************/ \
/* Arguments */ \
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,28 +83,24 @@ static <CPUFeatureType extends Enum<CPUFeatureType>> EnumSet<CPUFeatureType> con
}

/**
* Converts a dynamically sized CPU features vector into enum constants.
* Converts CPU features bit map into enum constants.
*
* @param <CPUFeatureType> CPU feature enum type
* @param enumType the class of {@code CPUFeatureType}
* @param constants VM constants. Each entry whose key starts with {@code "VM_Version::CPU_"}
* specifies a CPU feature and its value is a mask for a bit in {@code features}
* @param features_pointer pointer to {@code _vm_target_features} field of {@code Abstract_VM_Version}
* @param features_vector_offset offset of feature_vector field in {@code VM_Features}
* @param features_vector_size size of feature vector
* @param features_element_shift_count log2 of dynamic feature bit vector lanesize in bits.
* @param featuresBitMapAddress pointer to {@code VM_Features::_features_bitmap} field of {@code VM_Version::_features}
* @param featuresBitMapSize size of feature bit map in bytes
* @param renaming maps from VM feature names to enum constant names where the two differ
* @throws IllegalArgumentException if any VM CPU feature constant cannot be converted to an
* enum value
* @return the set of converted values
*/
static <CPUFeatureType extends Enum<CPUFeatureType>> EnumSet<CPUFeatureType> convertFeaturesVector(
static <CPUFeatureType extends Enum<CPUFeatureType>> EnumSet<CPUFeatureType> convertFeatures(
Class<CPUFeatureType> enumType,
Map<String, Long> constants,
long features_pointer,
long features_vector_offset,
long features_vector_size,
long features_element_shift_count,
long featuresBitMapAddress,
long featuresBitMapSize,
Map<String, String> renaming) {
EnumSet<CPUFeatureType> outFeatures = EnumSet.noneOf(enumType);
List<String> missing = new ArrayList<>();
Expand All @@ -115,19 +111,18 @@ static <CPUFeatureType extends Enum<CPUFeatureType>> EnumSet<CPUFeatureType> con
if (key.startsWith("VM_Version::CPU_")) {
String name = key.substring("VM_Version::CPU_".length());
try {
final long featuresElementShiftCount = 6; // log (# of bits per long)
final long featuresElementMask = (1L << featuresElementShiftCount) - 1;

CPUFeatureType feature = Enum.valueOf(enumType, renaming.getOrDefault(name, name));
long features_vector_index = bitIndex >>> features_element_shift_count;
assert features_vector_index < features_vector_size;

long features_element_bitsize = (1L << features_element_shift_count);
assert (features_element_bitsize & (features_element_bitsize - 1)) == 0;
long featureIndex = bitIndex >>> featuresElementShiftCount;
long featureBitMask = 1L << (bitIndex & featuresElementMask);
assert featureIndex < featuresBitMapSize;

long features_element_size = features_element_bitsize / Byte.SIZE;
long features = UNSAFE.getLong(features_pointer + features_vector_offset +
features_vector_index * features_element_size);
long featuresElement = UNSAFE.getLong(featuresBitMapAddress + featureIndex * Long.BYTES);

long effective_bitMask = 1L << (bitIndex & (features_element_bitsize - 1));
if ((features & effective_bitMask) != 0) {
if ((featuresElement & featureBitMask) != 0) {
outFeatures.add(feature);
}
} catch (IllegalArgumentException iae) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,12 @@ private static EnumSet<CPUFeature> computeFeatures(AMD64HotSpotVMConfig config)
Map<String, Long> constants = config.getStore().getConstants();
Map<String, String> renaming = Map.of("3DNOW_PREFETCH", "AMD_3DNOW_PREFETCH");
assert config.useSSE >= 2 : "minimum config for x64";
EnumSet<CPUFeature> features = HotSpotJVMCIBackendFactory.convertFeaturesVector(CPUFeature.class, constants,
config.vmVersionFeatures,
config.vmFeaturesFeaturesVecOffset,
config.vmFeaturesFeaturesVecSize,
config.vmFeaturesFeaturesElemShiftCnt,
renaming);
long featuresBitMapAddress = config.vmVersionFeatures + config.vmFeaturesFeaturesOffset;
EnumSet<CPUFeature> features = HotSpotJVMCIBackendFactory.convertFeatures(CPUFeature.class,
constants,
featuresBitMapAddress,
config.vmFeaturesFeaturesSize,
renaming);
features.add(AMD64.CPUFeature.SSE);
features.add(AMD64.CPUFeature.SSE2);
return features;
Expand Down
Loading