mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-26 22:34:27 +02:00
Merge
This commit is contained in:
commit
115d44f61b
72 changed files with 2342 additions and 1191 deletions
|
@ -136,8 +136,6 @@ include $(MAKEFILES_DIR)/dtrace.make
|
||||||
JVM = jvm
|
JVM = jvm
|
||||||
LIBJVM = lib$(JVM).so
|
LIBJVM = lib$(JVM).so
|
||||||
|
|
||||||
CFLAGS += -DALLOW_OPERATOR_NEW_USAGE
|
|
||||||
|
|
||||||
LIBJVM_DEBUGINFO = lib$(JVM).debuginfo
|
LIBJVM_DEBUGINFO = lib$(JVM).debuginfo
|
||||||
LIBJVM_DIZ = lib$(JVM).diz
|
LIBJVM_DIZ = lib$(JVM).diz
|
||||||
|
|
||||||
|
|
|
@ -146,9 +146,6 @@ JVM = jvm
|
||||||
ifeq ($(OS_VENDOR), Darwin)
|
ifeq ($(OS_VENDOR), Darwin)
|
||||||
LIBJVM = lib$(JVM).dylib
|
LIBJVM = lib$(JVM).dylib
|
||||||
CFLAGS += -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE
|
CFLAGS += -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE
|
||||||
ifeq (${VERSION}, $(filter ${VERSION}, debug fastdebug))
|
|
||||||
CFLAGS += -DALLOW_OPERATOR_NEW_USAGE
|
|
||||||
endif
|
|
||||||
|
|
||||||
LIBJVM_DEBUGINFO = lib$(JVM).dylib.dSYM
|
LIBJVM_DEBUGINFO = lib$(JVM).dylib.dSYM
|
||||||
LIBJVM_DIZ = lib$(JVM).diz
|
LIBJVM_DIZ = lib$(JVM).diz
|
||||||
|
|
|
@ -93,7 +93,7 @@ JRE_RELEASE_VERSION="\\\"$(JDK_MAJOR_VER).$(JDK_MINOR_VER).$(JDK_MICRO_VER)\\\""
|
||||||
!if "$(HOTSPOT_RELEASE_VERSION)" != ""
|
!if "$(HOTSPOT_RELEASE_VERSION)" != ""
|
||||||
HOTSPOT_RELEASE_VERSION="\\\"$(HOTSPOT_RELEASE_VERSION)\\\""
|
HOTSPOT_RELEASE_VERSION="\\\"$(HOTSPOT_RELEASE_VERSION)\\\""
|
||||||
!else
|
!else
|
||||||
HOTSPOT_RELEASE_VERSION="\\\"$(JRE_RELEASE_VERSION)\\\""
|
HOTSPOT_RELEASE_VERSION=$(JRE_RELEASE_VERSION)
|
||||||
!endif
|
!endif
|
||||||
# Define HOTSPOT_VM_DISTRO if HOTSPOT_VM_DISTRO is set,
|
# Define HOTSPOT_VM_DISTRO if HOTSPOT_VM_DISTRO is set,
|
||||||
# and if it is not see if we have the src/closed directory
|
# and if it is not see if we have the src/closed directory
|
||||||
|
@ -105,9 +105,18 @@ HOTSPOT_VM_DISTRO="\\\"Java HotSpot(TM)\\\""
|
||||||
!else
|
!else
|
||||||
HOTSPOT_VM_DISTRO="\\\"OpenJDK\\\""
|
HOTSPOT_VM_DISTRO="\\\"OpenJDK\\\""
|
||||||
!endif
|
!endif
|
||||||
|
!if "$(JDK_BUILD_NUMBER)" != ""
|
||||||
|
JDK_BUILD_NUMBER="\\\"$(JDK_BUILD_NUMBER)\\\""
|
||||||
|
!else
|
||||||
|
JDK_BUILD_NUMBER="\\\"00\\\""
|
||||||
|
!endif
|
||||||
!endif
|
!endif
|
||||||
|
|
||||||
ReleaseOptions = -define HOTSPOT_RELEASE_VERSION=$(HOTSPOT_RELEASE_VERSION) -define JRE_RELEASE_VERSION=$(JRE_RELEASE_VERSION) -define HOTSPOT_VM_DISTRO=$(HOTSPOT_VM_DISTRO)
|
JDK_MAJOR_VERSION="\\\"$(JDK_MAJOR_VER)\\\""
|
||||||
|
JDK_MINOR_VERSION="\\\"$(JDK_MINOR_VER)\\\""
|
||||||
|
JDK_MICRO_VERSION="\\\"$(JDK_MICRO_VER)\\\""
|
||||||
|
|
||||||
|
ReleaseOptions = -define HOTSPOT_RELEASE_VERSION=$(HOTSPOT_RELEASE_VERSION) -define JRE_RELEASE_VERSION=$(JRE_RELEASE_VERSION) -define HOTSPOT_VM_DISTRO=$(HOTSPOT_VM_DISTRO) -define JDK_MAJOR_VERSION=$(JDK_MAJOR_VERSION) -define JDK_MINOR_VERSION=$(JDK_MINOR_VERSION) -define JDK_MICRO_VERSION=$(JDK_MICRO_VERSION) -define JDK_BUILD_NUMBER=$(JDK_BUILD_NUMBER)
|
||||||
ProjectCreatorIDEOptions = $(ProjectCreatorIDEOptions) $(ReleaseOptions)
|
ProjectCreatorIDEOptions = $(ProjectCreatorIDEOptions) $(ReleaseOptions)
|
||||||
|
|
||||||
$(HOTSPOTBUILDSPACE)/$(ProjectFile): $(HOTSPOTBUILDSPACE)/classes/ProjectCreator.class
|
$(HOTSPOTBUILDSPACE)/$(ProjectFile): $(HOTSPOTBUILDSPACE)/classes/ProjectCreator.class
|
||||||
|
|
|
@ -1871,7 +1871,7 @@ public:
|
||||||
// properties.
|
// properties.
|
||||||
|
|
||||||
// ShmBkBlock: base class for all blocks in the shared memory bookkeeping
|
// ShmBkBlock: base class for all blocks in the shared memory bookkeeping
|
||||||
class ShmBkBlock {
|
class ShmBkBlock : public CHeapObj<mtInternal> {
|
||||||
|
|
||||||
ShmBkBlock* _next;
|
ShmBkBlock* _next;
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "asm/assembler.hpp"
|
#include "asm/assembler.hpp"
|
||||||
|
#include "memory/allocation.hpp"
|
||||||
#include "loadlib_aix.hpp"
|
#include "loadlib_aix.hpp"
|
||||||
#include "porting_aix.hpp"
|
#include "porting_aix.hpp"
|
||||||
#include "utilities/debug.hpp"
|
#include "utilities/debug.hpp"
|
||||||
|
@ -67,7 +68,7 @@ inline char* align_ptr_up(char* ptr, intptr_t alignment) {
|
||||||
// a primitive string map. Should this turn out to be a performance
|
// a primitive string map. Should this turn out to be a performance
|
||||||
// problem, a better hashmap has to be used.
|
// problem, a better hashmap has to be used.
|
||||||
class fixed_strings {
|
class fixed_strings {
|
||||||
struct node {
|
struct node : public CHeapObj<mtInternal> {
|
||||||
char* v;
|
char* v;
|
||||||
node* next;
|
node* next;
|
||||||
};
|
};
|
||||||
|
|
|
@ -30,12 +30,13 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
// standard library constants
|
// standard library constants
|
||||||
#include "stdio.h"
|
|
||||||
#include "stdlib.h"
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include "string.h"
|
|
||||||
#include "ctype.h"
|
#include <stdio.h>
|
||||||
#include "stdarg.h"
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <stdarg.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
/* Make sure that we have the intptr_t and uintptr_t definitions */
|
/* Make sure that we have the intptr_t and uintptr_t definitions */
|
||||||
|
|
|
@ -64,8 +64,6 @@ class PeepMatch;
|
||||||
class PeepConstraint;
|
class PeepConstraint;
|
||||||
class PeepReplace;
|
class PeepReplace;
|
||||||
|
|
||||||
// class ostream; // ostream is a typedef in some systems
|
|
||||||
|
|
||||||
extern char *toUpper(const char *str);
|
extern char *toUpper(const char *str);
|
||||||
|
|
||||||
//---------------------------ADLParser-----------------------------------------
|
//---------------------------ADLParser-----------------------------------------
|
||||||
|
|
|
@ -25,8 +25,6 @@
|
||||||
// FILEBUFF.CPP - Routines for handling a parser file buffer
|
// FILEBUFF.CPP - Routines for handling a parser file buffer
|
||||||
#include "adlc.hpp"
|
#include "adlc.hpp"
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
//------------------------------FileBuff---------------------------------------
|
//------------------------------FileBuff---------------------------------------
|
||||||
// Create a new parsing buffer
|
// Create a new parsing buffer
|
||||||
FileBuff::FileBuff( BufferedFile *fptr, ArchDesc& archDesc) : _fp(fptr), _AD(archDesc) {
|
FileBuff::FileBuff( BufferedFile *fptr, ArchDesc& archDesc) : _fp(fptr), _AD(archDesc) {
|
||||||
|
|
|
@ -26,9 +26,6 @@
|
||||||
#define SHARE_VM_ADLC_FILEBUFF_HPP
|
#define SHARE_VM_ADLC_FILEBUFF_HPP
|
||||||
|
|
||||||
// FILEBUFF.HPP - Definitions for parser file buffering routines
|
// FILEBUFF.HPP - Definitions for parser file buffering routines
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
// STRUCTURE FOR HANDLING INPUT AND OUTPUT FILES
|
// STRUCTURE FOR HANDLING INPUT AND OUTPUT FILES
|
||||||
|
|
||||||
|
|
|
@ -211,7 +211,7 @@ static void declareConstStorage(FILE *fp, FormDict &globals, OperandForm *oper)
|
||||||
const char *type = oper->ideal_type(globals);
|
const char *type = oper->ideal_type(globals);
|
||||||
if (!strcmp(type, "ConI")) {
|
if (!strcmp(type, "ConI")) {
|
||||||
if (i > 0) fprintf(fp,", ");
|
if (i > 0) fprintf(fp,", ");
|
||||||
fprintf(fp," int32 _c%d;\n", i);
|
fprintf(fp," int32_t _c%d;\n", i);
|
||||||
}
|
}
|
||||||
else if (!strcmp(type, "ConP")) {
|
else if (!strcmp(type, "ConP")) {
|
||||||
if (i > 0) fprintf(fp,", ");
|
if (i > 0) fprintf(fp,", ");
|
||||||
|
@ -307,7 +307,7 @@ static void defineConstructor(FILE *fp, const char *name, uint num_consts,
|
||||||
assert(num_consts == 1, "Bad component list detected.\n");
|
assert(num_consts == 1, "Bad component list detected.\n");
|
||||||
switch( constant_type ) {
|
switch( constant_type ) {
|
||||||
case Form::idealI : {
|
case Form::idealI : {
|
||||||
fprintf(fp,is_ideal_bool ? "BoolTest::mask c%d" : "int32 c%d", i);
|
fprintf(fp,is_ideal_bool ? "BoolTest::mask c%d" : "int32_t c%d", i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Form::idealN : { fprintf(fp,"const TypeNarrowOop *c%d", i); break; }
|
case Form::idealN : { fprintf(fp,"const TypeNarrowOop *c%d", i); break; }
|
||||||
|
@ -326,7 +326,7 @@ static void defineConstructor(FILE *fp, const char *name, uint num_consts,
|
||||||
while((comp = lst.iter()) != NULL) {
|
while((comp = lst.iter()) != NULL) {
|
||||||
if (!strcmp(comp->base_type(globals), "ConI")) {
|
if (!strcmp(comp->base_type(globals), "ConI")) {
|
||||||
if (i > 0) fprintf(fp,", ");
|
if (i > 0) fprintf(fp,", ");
|
||||||
fprintf(fp,"int32 c%d", i);
|
fprintf(fp,"int32_t c%d", i);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
else if (!strcmp(comp->base_type(globals), "ConP")) {
|
else if (!strcmp(comp->base_type(globals), "ConP")) {
|
||||||
|
|
|
@ -119,7 +119,7 @@ void AbstractAssembler::bind(Label& L) {
|
||||||
L.patch_instructions((MacroAssembler*)this);
|
L.patch_instructions((MacroAssembler*)this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AbstractAssembler::generate_stack_overflow_check( int frame_size_in_bytes) {
|
void AbstractAssembler::generate_stack_overflow_check(int frame_size_in_bytes) {
|
||||||
if (UseStackBanging) {
|
if (UseStackBanging) {
|
||||||
// Each code entry causes one stack bang n pages down the stack where n
|
// Each code entry causes one stack bang n pages down the stack where n
|
||||||
// is configurable by StackShadowPages. The setting depends on the maximum
|
// is configurable by StackShadowPages. The setting depends on the maximum
|
||||||
|
@ -134,7 +134,7 @@ void AbstractAssembler::generate_stack_overflow_check( int frame_size_in_bytes)
|
||||||
// is greater than a page.
|
// is greater than a page.
|
||||||
|
|
||||||
const int page_size = os::vm_page_size();
|
const int page_size = os::vm_page_size();
|
||||||
int bang_end = StackShadowPages*page_size;
|
int bang_end = StackShadowPages * page_size;
|
||||||
|
|
||||||
// This is how far the previous frame's stack banging extended.
|
// This is how far the previous frame's stack banging extended.
|
||||||
const int bang_end_safe = bang_end;
|
const int bang_end_safe = bang_end;
|
||||||
|
|
|
@ -875,6 +875,7 @@ void ClassFileParser::parse_field_attributes(u2 attributes_count,
|
||||||
int runtime_visible_type_annotations_length = 0;
|
int runtime_visible_type_annotations_length = 0;
|
||||||
u1* runtime_invisible_type_annotations = NULL;
|
u1* runtime_invisible_type_annotations = NULL;
|
||||||
int runtime_invisible_type_annotations_length = 0;
|
int runtime_invisible_type_annotations_length = 0;
|
||||||
|
bool runtime_invisible_annotations_exists = false;
|
||||||
bool runtime_invisible_type_annotations_exists = false;
|
bool runtime_invisible_type_annotations_exists = false;
|
||||||
while (attributes_count--) {
|
while (attributes_count--) {
|
||||||
cfs->guarantee_more(6, CHECK); // attribute_name_index, attribute_length
|
cfs->guarantee_more(6, CHECK); // attribute_name_index, attribute_length
|
||||||
|
@ -920,6 +921,10 @@ void ClassFileParser::parse_field_attributes(u2 attributes_count,
|
||||||
}
|
}
|
||||||
generic_signature_index = cfs->get_u2(CHECK);
|
generic_signature_index = cfs->get_u2(CHECK);
|
||||||
} else if (attribute_name == vmSymbols::tag_runtime_visible_annotations()) {
|
} else if (attribute_name == vmSymbols::tag_runtime_visible_annotations()) {
|
||||||
|
if (runtime_visible_annotations != NULL) {
|
||||||
|
classfile_parse_error(
|
||||||
|
"Multiple RuntimeVisibleAnnotations attributes for field in class file %s", CHECK);
|
||||||
|
}
|
||||||
runtime_visible_annotations_length = attribute_length;
|
runtime_visible_annotations_length = attribute_length;
|
||||||
runtime_visible_annotations = cfs->get_u1_buffer();
|
runtime_visible_annotations = cfs->get_u1_buffer();
|
||||||
assert(runtime_visible_annotations != NULL, "null visible annotations");
|
assert(runtime_visible_annotations != NULL, "null visible annotations");
|
||||||
|
@ -928,11 +933,18 @@ void ClassFileParser::parse_field_attributes(u2 attributes_count,
|
||||||
parsed_annotations,
|
parsed_annotations,
|
||||||
CHECK);
|
CHECK);
|
||||||
cfs->skip_u1(runtime_visible_annotations_length, CHECK);
|
cfs->skip_u1(runtime_visible_annotations_length, CHECK);
|
||||||
} else if (PreserveAllAnnotations && attribute_name == vmSymbols::tag_runtime_invisible_annotations()) {
|
} else if (attribute_name == vmSymbols::tag_runtime_invisible_annotations()) {
|
||||||
runtime_invisible_annotations_length = attribute_length;
|
if (runtime_invisible_annotations_exists) {
|
||||||
runtime_invisible_annotations = cfs->get_u1_buffer();
|
classfile_parse_error(
|
||||||
assert(runtime_invisible_annotations != NULL, "null invisible annotations");
|
"Multiple RuntimeInvisibleAnnotations attributes for field in class file %s", CHECK);
|
||||||
cfs->skip_u1(runtime_invisible_annotations_length, CHECK);
|
}
|
||||||
|
runtime_invisible_annotations_exists = true;
|
||||||
|
if (PreserveAllAnnotations) {
|
||||||
|
runtime_invisible_annotations_length = attribute_length;
|
||||||
|
runtime_invisible_annotations = cfs->get_u1_buffer();
|
||||||
|
assert(runtime_invisible_annotations != NULL, "null invisible annotations");
|
||||||
|
}
|
||||||
|
cfs->skip_u1(attribute_length, CHECK);
|
||||||
} else if (attribute_name == vmSymbols::tag_runtime_visible_type_annotations()) {
|
} else if (attribute_name == vmSymbols::tag_runtime_visible_type_annotations()) {
|
||||||
if (runtime_visible_type_annotations != NULL) {
|
if (runtime_visible_type_annotations != NULL) {
|
||||||
classfile_parse_error(
|
classfile_parse_error(
|
||||||
|
@ -2066,7 +2078,9 @@ methodHandle ClassFileParser::parse_method(bool is_interface,
|
||||||
int runtime_visible_type_annotations_length = 0;
|
int runtime_visible_type_annotations_length = 0;
|
||||||
u1* runtime_invisible_type_annotations = NULL;
|
u1* runtime_invisible_type_annotations = NULL;
|
||||||
int runtime_invisible_type_annotations_length = 0;
|
int runtime_invisible_type_annotations_length = 0;
|
||||||
|
bool runtime_invisible_annotations_exists = false;
|
||||||
bool runtime_invisible_type_annotations_exists = false;
|
bool runtime_invisible_type_annotations_exists = false;
|
||||||
|
bool runtime_invisible_parameter_annotations_exists = false;
|
||||||
u1* annotation_default = NULL;
|
u1* annotation_default = NULL;
|
||||||
int annotation_default_length = 0;
|
int annotation_default_length = 0;
|
||||||
|
|
||||||
|
@ -2295,6 +2309,10 @@ methodHandle ClassFileParser::parse_method(bool is_interface,
|
||||||
cfs->guarantee_more(2, CHECK_(nullHandle)); // generic_signature_index
|
cfs->guarantee_more(2, CHECK_(nullHandle)); // generic_signature_index
|
||||||
generic_signature_index = cfs->get_u2_fast();
|
generic_signature_index = cfs->get_u2_fast();
|
||||||
} else if (method_attribute_name == vmSymbols::tag_runtime_visible_annotations()) {
|
} else if (method_attribute_name == vmSymbols::tag_runtime_visible_annotations()) {
|
||||||
|
if (runtime_visible_annotations != NULL) {
|
||||||
|
classfile_parse_error(
|
||||||
|
"Multiple RuntimeVisibleAnnotations attributes for method in class file %s", CHECK_(nullHandle));
|
||||||
|
}
|
||||||
runtime_visible_annotations_length = method_attribute_length;
|
runtime_visible_annotations_length = method_attribute_length;
|
||||||
runtime_visible_annotations = cfs->get_u1_buffer();
|
runtime_visible_annotations = cfs->get_u1_buffer();
|
||||||
assert(runtime_visible_annotations != NULL, "null visible annotations");
|
assert(runtime_visible_annotations != NULL, "null visible annotations");
|
||||||
|
@ -2302,22 +2320,45 @@ methodHandle ClassFileParser::parse_method(bool is_interface,
|
||||||
runtime_visible_annotations_length, &parsed_annotations,
|
runtime_visible_annotations_length, &parsed_annotations,
|
||||||
CHECK_(nullHandle));
|
CHECK_(nullHandle));
|
||||||
cfs->skip_u1(runtime_visible_annotations_length, CHECK_(nullHandle));
|
cfs->skip_u1(runtime_visible_annotations_length, CHECK_(nullHandle));
|
||||||
} else if (PreserveAllAnnotations && method_attribute_name == vmSymbols::tag_runtime_invisible_annotations()) {
|
} else if (method_attribute_name == vmSymbols::tag_runtime_invisible_annotations()) {
|
||||||
runtime_invisible_annotations_length = method_attribute_length;
|
if (runtime_invisible_annotations_exists) {
|
||||||
runtime_invisible_annotations = cfs->get_u1_buffer();
|
classfile_parse_error(
|
||||||
assert(runtime_invisible_annotations != NULL, "null invisible annotations");
|
"Multiple RuntimeInvisibleAnnotations attributes for method in class file %s", CHECK_(nullHandle));
|
||||||
cfs->skip_u1(runtime_invisible_annotations_length, CHECK_(nullHandle));
|
}
|
||||||
|
runtime_invisible_annotations_exists = true;
|
||||||
|
if (PreserveAllAnnotations) {
|
||||||
|
runtime_invisible_annotations_length = method_attribute_length;
|
||||||
|
runtime_invisible_annotations = cfs->get_u1_buffer();
|
||||||
|
assert(runtime_invisible_annotations != NULL, "null invisible annotations");
|
||||||
|
}
|
||||||
|
cfs->skip_u1(method_attribute_length, CHECK_(nullHandle));
|
||||||
} else if (method_attribute_name == vmSymbols::tag_runtime_visible_parameter_annotations()) {
|
} else if (method_attribute_name == vmSymbols::tag_runtime_visible_parameter_annotations()) {
|
||||||
|
if (runtime_visible_parameter_annotations != NULL) {
|
||||||
|
classfile_parse_error(
|
||||||
|
"Multiple RuntimeVisibleParameterAnnotations attributes for method in class file %s", CHECK_(nullHandle));
|
||||||
|
}
|
||||||
runtime_visible_parameter_annotations_length = method_attribute_length;
|
runtime_visible_parameter_annotations_length = method_attribute_length;
|
||||||
runtime_visible_parameter_annotations = cfs->get_u1_buffer();
|
runtime_visible_parameter_annotations = cfs->get_u1_buffer();
|
||||||
assert(runtime_visible_parameter_annotations != NULL, "null visible parameter annotations");
|
assert(runtime_visible_parameter_annotations != NULL, "null visible parameter annotations");
|
||||||
cfs->skip_u1(runtime_visible_parameter_annotations_length, CHECK_(nullHandle));
|
cfs->skip_u1(runtime_visible_parameter_annotations_length, CHECK_(nullHandle));
|
||||||
} else if (PreserveAllAnnotations && method_attribute_name == vmSymbols::tag_runtime_invisible_parameter_annotations()) {
|
} else if (method_attribute_name == vmSymbols::tag_runtime_invisible_parameter_annotations()) {
|
||||||
runtime_invisible_parameter_annotations_length = method_attribute_length;
|
if (runtime_invisible_parameter_annotations_exists) {
|
||||||
runtime_invisible_parameter_annotations = cfs->get_u1_buffer();
|
classfile_parse_error(
|
||||||
assert(runtime_invisible_parameter_annotations != NULL, "null invisible parameter annotations");
|
"Multiple RuntimeInvisibleParameterAnnotations attributes for method in class file %s", CHECK_(nullHandle));
|
||||||
cfs->skip_u1(runtime_invisible_parameter_annotations_length, CHECK_(nullHandle));
|
}
|
||||||
|
runtime_invisible_parameter_annotations_exists = true;
|
||||||
|
if (PreserveAllAnnotations) {
|
||||||
|
runtime_invisible_parameter_annotations_length = method_attribute_length;
|
||||||
|
runtime_invisible_parameter_annotations = cfs->get_u1_buffer();
|
||||||
|
assert(runtime_invisible_parameter_annotations != NULL, "null invisible parameter annotations");
|
||||||
|
}
|
||||||
|
cfs->skip_u1(method_attribute_length, CHECK_(nullHandle));
|
||||||
} else if (method_attribute_name == vmSymbols::tag_annotation_default()) {
|
} else if (method_attribute_name == vmSymbols::tag_annotation_default()) {
|
||||||
|
if (annotation_default != NULL) {
|
||||||
|
classfile_parse_error(
|
||||||
|
"Multiple AnnotationDefault attributes for method in class file %s",
|
||||||
|
CHECK_(nullHandle));
|
||||||
|
}
|
||||||
annotation_default_length = method_attribute_length;
|
annotation_default_length = method_attribute_length;
|
||||||
annotation_default = cfs->get_u1_buffer();
|
annotation_default = cfs->get_u1_buffer();
|
||||||
assert(annotation_default != NULL, "null annotation default");
|
assert(annotation_default != NULL, "null annotation default");
|
||||||
|
@ -2846,6 +2887,8 @@ void ClassFileParser::parse_classfile_attributes(ClassFileParser::ClassAnnotatio
|
||||||
u1* runtime_invisible_type_annotations = NULL;
|
u1* runtime_invisible_type_annotations = NULL;
|
||||||
int runtime_invisible_type_annotations_length = 0;
|
int runtime_invisible_type_annotations_length = 0;
|
||||||
bool runtime_invisible_type_annotations_exists = false;
|
bool runtime_invisible_type_annotations_exists = false;
|
||||||
|
bool runtime_invisible_annotations_exists = false;
|
||||||
|
bool parsed_source_debug_ext_annotations_exist = false;
|
||||||
u1* inner_classes_attribute_start = NULL;
|
u1* inner_classes_attribute_start = NULL;
|
||||||
u4 inner_classes_attribute_length = 0;
|
u4 inner_classes_attribute_length = 0;
|
||||||
u2 enclosing_method_class_index = 0;
|
u2 enclosing_method_class_index = 0;
|
||||||
|
@ -2873,6 +2916,11 @@ void ClassFileParser::parse_classfile_attributes(ClassFileParser::ClassAnnotatio
|
||||||
parse_classfile_sourcefile_attribute(CHECK);
|
parse_classfile_sourcefile_attribute(CHECK);
|
||||||
} else if (tag == vmSymbols::tag_source_debug_extension()) {
|
} else if (tag == vmSymbols::tag_source_debug_extension()) {
|
||||||
// Check for SourceDebugExtension tag
|
// Check for SourceDebugExtension tag
|
||||||
|
if (parsed_source_debug_ext_annotations_exist) {
|
||||||
|
classfile_parse_error(
|
||||||
|
"Multiple SourceDebugExtension attributes in class file %s", CHECK);
|
||||||
|
}
|
||||||
|
parsed_source_debug_ext_annotations_exist = true;
|
||||||
parse_classfile_source_debug_extension_attribute((int)attribute_length, CHECK);
|
parse_classfile_source_debug_extension_attribute((int)attribute_length, CHECK);
|
||||||
} else if (tag == vmSymbols::tag_inner_classes()) {
|
} else if (tag == vmSymbols::tag_inner_classes()) {
|
||||||
// Check for InnerClasses tag
|
// Check for InnerClasses tag
|
||||||
|
@ -2909,6 +2957,10 @@ void ClassFileParser::parse_classfile_attributes(ClassFileParser::ClassAnnotatio
|
||||||
}
|
}
|
||||||
parse_classfile_signature_attribute(CHECK);
|
parse_classfile_signature_attribute(CHECK);
|
||||||
} else if (tag == vmSymbols::tag_runtime_visible_annotations()) {
|
} else if (tag == vmSymbols::tag_runtime_visible_annotations()) {
|
||||||
|
if (runtime_visible_annotations != NULL) {
|
||||||
|
classfile_parse_error(
|
||||||
|
"Multiple RuntimeVisibleAnnotations attributes in class file %s", CHECK);
|
||||||
|
}
|
||||||
runtime_visible_annotations_length = attribute_length;
|
runtime_visible_annotations_length = attribute_length;
|
||||||
runtime_visible_annotations = cfs->get_u1_buffer();
|
runtime_visible_annotations = cfs->get_u1_buffer();
|
||||||
assert(runtime_visible_annotations != NULL, "null visible annotations");
|
assert(runtime_visible_annotations != NULL, "null visible annotations");
|
||||||
|
@ -2917,11 +2969,18 @@ void ClassFileParser::parse_classfile_attributes(ClassFileParser::ClassAnnotatio
|
||||||
parsed_annotations,
|
parsed_annotations,
|
||||||
CHECK);
|
CHECK);
|
||||||
cfs->skip_u1(runtime_visible_annotations_length, CHECK);
|
cfs->skip_u1(runtime_visible_annotations_length, CHECK);
|
||||||
} else if (PreserveAllAnnotations && tag == vmSymbols::tag_runtime_invisible_annotations()) {
|
} else if (tag == vmSymbols::tag_runtime_invisible_annotations()) {
|
||||||
runtime_invisible_annotations_length = attribute_length;
|
if (runtime_invisible_annotations_exists) {
|
||||||
runtime_invisible_annotations = cfs->get_u1_buffer();
|
classfile_parse_error(
|
||||||
assert(runtime_invisible_annotations != NULL, "null invisible annotations");
|
"Multiple RuntimeInvisibleAnnotations attributes in class file %s", CHECK);
|
||||||
cfs->skip_u1(runtime_invisible_annotations_length, CHECK);
|
}
|
||||||
|
runtime_invisible_annotations_exists = true;
|
||||||
|
if (PreserveAllAnnotations) {
|
||||||
|
runtime_invisible_annotations_length = attribute_length;
|
||||||
|
runtime_invisible_annotations = cfs->get_u1_buffer();
|
||||||
|
assert(runtime_invisible_annotations != NULL, "null invisible annotations");
|
||||||
|
}
|
||||||
|
cfs->skip_u1(attribute_length, CHECK);
|
||||||
} else if (tag == vmSymbols::tag_enclosing_method()) {
|
} else if (tag == vmSymbols::tag_enclosing_method()) {
|
||||||
if (parsed_enclosingmethod_attribute) {
|
if (parsed_enclosingmethod_attribute) {
|
||||||
classfile_parse_error("Multiple EnclosingMethod attributes in class file %s", CHECK);
|
classfile_parse_error("Multiple EnclosingMethod attributes in class file %s", CHECK);
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "classfile/altHashing.hpp"
|
#include "classfile/altHashing.hpp"
|
||||||
#include "classfile/javaClasses.hpp"
|
#include "classfile/javaClasses.hpp"
|
||||||
#include "classfile/symbolTable.hpp"
|
#include "classfile/stringTable.hpp"
|
||||||
#include "classfile/vmSymbols.hpp"
|
#include "classfile/vmSymbols.hpp"
|
||||||
#include "code/debugInfo.hpp"
|
#include "code/debugInfo.hpp"
|
||||||
#include "code/pcDesc.hpp"
|
#include "code/pcDesc.hpp"
|
||||||
|
|
533
hotspot/src/share/vm/classfile/stringTable.cpp
Normal file
533
hotspot/src/share/vm/classfile/stringTable.cpp
Normal file
|
@ -0,0 +1,533 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "precompiled.hpp"
|
||||||
|
#include "classfile/altHashing.hpp"
|
||||||
|
#include "classfile/javaClasses.hpp"
|
||||||
|
#include "classfile/stringTable.hpp"
|
||||||
|
#include "classfile/systemDictionary.hpp"
|
||||||
|
#include "gc_interface/collectedHeap.inline.hpp"
|
||||||
|
#include "memory/allocation.inline.hpp"
|
||||||
|
#include "memory/filemap.hpp"
|
||||||
|
#include "memory/gcLocker.inline.hpp"
|
||||||
|
#include "oops/oop.inline.hpp"
|
||||||
|
#include "oops/oop.inline2.hpp"
|
||||||
|
#include "runtime/mutexLocker.hpp"
|
||||||
|
#include "utilities/hashtable.inline.hpp"
|
||||||
|
#if INCLUDE_ALL_GCS
|
||||||
|
#include "gc_implementation/g1/g1StringDedup.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
|
||||||
|
|
||||||
|
// the number of buckets a thread claims
|
||||||
|
const int ClaimChunkSize = 32;
|
||||||
|
|
||||||
|
#ifdef ASSERT
|
||||||
|
class StableMemoryChecker : public StackObj {
|
||||||
|
enum { _bufsize = wordSize*4 };
|
||||||
|
|
||||||
|
address _region;
|
||||||
|
jint _size;
|
||||||
|
u1 _save_buf[_bufsize];
|
||||||
|
|
||||||
|
int sample(u1* save_buf) {
|
||||||
|
if (_size <= _bufsize) {
|
||||||
|
memcpy(save_buf, _region, _size);
|
||||||
|
return _size;
|
||||||
|
} else {
|
||||||
|
// copy head and tail
|
||||||
|
memcpy(&save_buf[0], _region, _bufsize/2);
|
||||||
|
memcpy(&save_buf[_bufsize/2], _region + _size - _bufsize/2, _bufsize/2);
|
||||||
|
return (_bufsize/2)*2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
StableMemoryChecker(const void* region, jint size) {
|
||||||
|
_region = (address) region;
|
||||||
|
_size = size;
|
||||||
|
sample(_save_buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool verify() {
|
||||||
|
u1 check_buf[sizeof(_save_buf)];
|
||||||
|
int check_size = sample(check_buf);
|
||||||
|
return (0 == memcmp(_save_buf, check_buf, check_size));
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_region(const void* region) { _region = (address) region; }
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
StringTable* StringTable::_the_table = NULL;
|
||||||
|
|
||||||
|
bool StringTable::_needs_rehashing = false;
|
||||||
|
|
||||||
|
volatile int StringTable::_parallel_claimed_idx = 0;
|
||||||
|
|
||||||
|
// Pick hashing algorithm
|
||||||
|
unsigned int StringTable::hash_string(const jchar* s, int len) {
|
||||||
|
return use_alternate_hashcode() ? AltHashing::murmur3_32(seed(), s, len) :
|
||||||
|
java_lang_String::hash_code(s, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
oop StringTable::lookup(int index, jchar* name,
|
||||||
|
int len, unsigned int hash) {
|
||||||
|
int count = 0;
|
||||||
|
for (HashtableEntry<oop, mtSymbol>* l = bucket(index); l != NULL; l = l->next()) {
|
||||||
|
count++;
|
||||||
|
if (l->hash() == hash) {
|
||||||
|
if (java_lang_String::equals(l->literal(), name, len)) {
|
||||||
|
return l->literal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If the bucket size is too deep check if this hash code is insufficient.
|
||||||
|
if (count >= BasicHashtable<mtSymbol>::rehash_count && !needs_rehashing()) {
|
||||||
|
_needs_rehashing = check_rehash_table(count);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
oop StringTable::basic_add(int index_arg, Handle string, jchar* name,
|
||||||
|
int len, unsigned int hashValue_arg, TRAPS) {
|
||||||
|
|
||||||
|
assert(java_lang_String::equals(string(), name, len),
|
||||||
|
"string must be properly initialized");
|
||||||
|
// Cannot hit a safepoint in this function because the "this" pointer can move.
|
||||||
|
No_Safepoint_Verifier nsv;
|
||||||
|
|
||||||
|
// Check if the symbol table has been rehashed, if so, need to recalculate
|
||||||
|
// the hash value and index before second lookup.
|
||||||
|
unsigned int hashValue;
|
||||||
|
int index;
|
||||||
|
if (use_alternate_hashcode()) {
|
||||||
|
hashValue = hash_string(name, len);
|
||||||
|
index = hash_to_index(hashValue);
|
||||||
|
} else {
|
||||||
|
hashValue = hashValue_arg;
|
||||||
|
index = index_arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Since look-up was done lock-free, we need to check if another
|
||||||
|
// thread beat us in the race to insert the symbol.
|
||||||
|
|
||||||
|
oop test = lookup(index, name, len, hashValue); // calls lookup(u1*, int)
|
||||||
|
if (test != NULL) {
|
||||||
|
// Entry already added
|
||||||
|
return test;
|
||||||
|
}
|
||||||
|
|
||||||
|
HashtableEntry<oop, mtSymbol>* entry = new_entry(hashValue, string());
|
||||||
|
add_entry(index, entry);
|
||||||
|
return string();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
oop StringTable::lookup(Symbol* symbol) {
|
||||||
|
ResourceMark rm;
|
||||||
|
int length;
|
||||||
|
jchar* chars = symbol->as_unicode(length);
|
||||||
|
return lookup(chars, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
oop StringTable::lookup(jchar* name, int len) {
|
||||||
|
unsigned int hash = hash_string(name, len);
|
||||||
|
int index = the_table()->hash_to_index(hash);
|
||||||
|
return the_table()->lookup(index, name, len, hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
oop StringTable::intern(Handle string_or_null, jchar* name,
|
||||||
|
int len, TRAPS) {
|
||||||
|
unsigned int hashValue = hash_string(name, len);
|
||||||
|
int index = the_table()->hash_to_index(hashValue);
|
||||||
|
oop found_string = the_table()->lookup(index, name, len, hashValue);
|
||||||
|
|
||||||
|
// Found
|
||||||
|
if (found_string != NULL) return found_string;
|
||||||
|
|
||||||
|
debug_only(StableMemoryChecker smc(name, len * sizeof(name[0])));
|
||||||
|
assert(!Universe::heap()->is_in_reserved(name),
|
||||||
|
"proposed name of symbol must be stable");
|
||||||
|
|
||||||
|
Handle string;
|
||||||
|
// try to reuse the string if possible
|
||||||
|
if (!string_or_null.is_null()) {
|
||||||
|
string = string_or_null;
|
||||||
|
} else {
|
||||||
|
string = java_lang_String::create_from_unicode(name, len, CHECK_NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if INCLUDE_ALL_GCS
|
||||||
|
if (G1StringDedup::is_enabled()) {
|
||||||
|
// Deduplicate the string before it is interned. Note that we should never
|
||||||
|
// deduplicate a string after it has been interned. Doing so will counteract
|
||||||
|
// compiler optimizations done on e.g. interned string literals.
|
||||||
|
G1StringDedup::deduplicate(string());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Grab the StringTable_lock before getting the_table() because it could
|
||||||
|
// change at safepoint.
|
||||||
|
MutexLocker ml(StringTable_lock, THREAD);
|
||||||
|
|
||||||
|
// Otherwise, add to symbol to table
|
||||||
|
return the_table()->basic_add(index, string, name, len,
|
||||||
|
hashValue, CHECK_NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
oop StringTable::intern(Symbol* symbol, TRAPS) {
|
||||||
|
if (symbol == NULL) return NULL;
|
||||||
|
ResourceMark rm(THREAD);
|
||||||
|
int length;
|
||||||
|
jchar* chars = symbol->as_unicode(length);
|
||||||
|
Handle string;
|
||||||
|
oop result = intern(string, chars, length, CHECK_NULL);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
oop StringTable::intern(oop string, TRAPS)
|
||||||
|
{
|
||||||
|
if (string == NULL) return NULL;
|
||||||
|
ResourceMark rm(THREAD);
|
||||||
|
int length;
|
||||||
|
Handle h_string (THREAD, string);
|
||||||
|
jchar* chars = java_lang_String::as_unicode_string(string, length, CHECK_NULL);
|
||||||
|
oop result = intern(h_string, chars, length, CHECK_NULL);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
oop StringTable::intern(const char* utf8_string, TRAPS) {
|
||||||
|
if (utf8_string == NULL) return NULL;
|
||||||
|
ResourceMark rm(THREAD);
|
||||||
|
int length = UTF8::unicode_length(utf8_string);
|
||||||
|
jchar* chars = NEW_RESOURCE_ARRAY(jchar, length);
|
||||||
|
UTF8::convert_to_unicode(utf8_string, chars, length);
|
||||||
|
Handle string;
|
||||||
|
oop result = intern(string, chars, length, CHECK_NULL);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StringTable::unlink_or_oops_do(BoolObjectClosure* is_alive, OopClosure* f, int* processed, int* removed) {
|
||||||
|
buckets_unlink_or_oops_do(is_alive, f, 0, the_table()->table_size(), processed, removed);
|
||||||
|
}
|
||||||
|
|
||||||
|
void StringTable::possibly_parallel_unlink_or_oops_do(BoolObjectClosure* is_alive, OopClosure* f, int* processed, int* removed) {
|
||||||
|
// Readers of the table are unlocked, so we should only be removing
|
||||||
|
// entries at a safepoint.
|
||||||
|
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
|
||||||
|
const int limit = the_table()->table_size();
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
// Grab next set of buckets to scan
|
||||||
|
int start_idx = Atomic::add(ClaimChunkSize, &_parallel_claimed_idx) - ClaimChunkSize;
|
||||||
|
if (start_idx >= limit) {
|
||||||
|
// End of table
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
int end_idx = MIN2(limit, start_idx + ClaimChunkSize);
|
||||||
|
buckets_unlink_or_oops_do(is_alive, f, start_idx, end_idx, processed, removed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void StringTable::buckets_oops_do(OopClosure* f, int start_idx, int end_idx) {
|
||||||
|
const int limit = the_table()->table_size();
|
||||||
|
|
||||||
|
assert(0 <= start_idx && start_idx <= limit,
|
||||||
|
err_msg("start_idx (%d) is out of bounds", start_idx));
|
||||||
|
assert(0 <= end_idx && end_idx <= limit,
|
||||||
|
err_msg("end_idx (%d) is out of bounds", end_idx));
|
||||||
|
assert(start_idx <= end_idx,
|
||||||
|
err_msg("Index ordering: start_idx=%d, end_idx=%d",
|
||||||
|
start_idx, end_idx));
|
||||||
|
|
||||||
|
for (int i = start_idx; i < end_idx; i += 1) {
|
||||||
|
HashtableEntry<oop, mtSymbol>* entry = the_table()->bucket(i);
|
||||||
|
while (entry != NULL) {
|
||||||
|
assert(!entry->is_shared(), "CDS not used for the StringTable");
|
||||||
|
|
||||||
|
f->do_oop((oop*)entry->literal_addr());
|
||||||
|
|
||||||
|
entry = entry->next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void StringTable::buckets_unlink_or_oops_do(BoolObjectClosure* is_alive, OopClosure* f, int start_idx, int end_idx, int* processed, int* removed) {
|
||||||
|
const int limit = the_table()->table_size();
|
||||||
|
|
||||||
|
assert(0 <= start_idx && start_idx <= limit,
|
||||||
|
err_msg("start_idx (%d) is out of bounds", start_idx));
|
||||||
|
assert(0 <= end_idx && end_idx <= limit,
|
||||||
|
err_msg("end_idx (%d) is out of bounds", end_idx));
|
||||||
|
assert(start_idx <= end_idx,
|
||||||
|
err_msg("Index ordering: start_idx=%d, end_idx=%d",
|
||||||
|
start_idx, end_idx));
|
||||||
|
|
||||||
|
for (int i = start_idx; i < end_idx; ++i) {
|
||||||
|
HashtableEntry<oop, mtSymbol>** p = the_table()->bucket_addr(i);
|
||||||
|
HashtableEntry<oop, mtSymbol>* entry = the_table()->bucket(i);
|
||||||
|
while (entry != NULL) {
|
||||||
|
assert(!entry->is_shared(), "CDS not used for the StringTable");
|
||||||
|
|
||||||
|
if (is_alive->do_object_b(entry->literal())) {
|
||||||
|
if (f != NULL) {
|
||||||
|
f->do_oop((oop*)entry->literal_addr());
|
||||||
|
}
|
||||||
|
p = entry->next_addr();
|
||||||
|
} else {
|
||||||
|
*p = entry->next();
|
||||||
|
the_table()->free_entry(entry);
|
||||||
|
(*removed)++;
|
||||||
|
}
|
||||||
|
(*processed)++;
|
||||||
|
entry = *p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void StringTable::oops_do(OopClosure* f) {
|
||||||
|
buckets_oops_do(f, 0, the_table()->table_size());
|
||||||
|
}
|
||||||
|
|
||||||
|
void StringTable::possibly_parallel_oops_do(OopClosure* f) {
|
||||||
|
const int limit = the_table()->table_size();
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
// Grab next set of buckets to scan
|
||||||
|
int start_idx = Atomic::add(ClaimChunkSize, &_parallel_claimed_idx) - ClaimChunkSize;
|
||||||
|
if (start_idx >= limit) {
|
||||||
|
// End of table
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
int end_idx = MIN2(limit, start_idx + ClaimChunkSize);
|
||||||
|
buckets_oops_do(f, start_idx, end_idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This verification is part of Universe::verify() and needs to be quick.
|
||||||
|
// See StringTable::verify_and_compare() below for exhaustive verification.
|
||||||
|
void StringTable::verify() {
|
||||||
|
for (int i = 0; i < the_table()->table_size(); ++i) {
|
||||||
|
HashtableEntry<oop, mtSymbol>* p = the_table()->bucket(i);
|
||||||
|
for ( ; p != NULL; p = p->next()) {
|
||||||
|
oop s = p->literal();
|
||||||
|
guarantee(s != NULL, "interned string is NULL");
|
||||||
|
unsigned int h = java_lang_String::hash_string(s);
|
||||||
|
guarantee(p->hash() == h, "broken hash in string table entry");
|
||||||
|
guarantee(the_table()->hash_to_index(h) == i,
|
||||||
|
"wrong index in string table");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void StringTable::dump(outputStream* st) {
|
||||||
|
the_table()->dump_table(st, "StringTable");
|
||||||
|
}
|
||||||
|
|
||||||
|
StringTable::VerifyRetTypes StringTable::compare_entries(
|
||||||
|
int bkt1, int e_cnt1,
|
||||||
|
HashtableEntry<oop, mtSymbol>* e_ptr1,
|
||||||
|
int bkt2, int e_cnt2,
|
||||||
|
HashtableEntry<oop, mtSymbol>* e_ptr2) {
|
||||||
|
// These entries are sanity checked by verify_and_compare_entries()
|
||||||
|
// before this function is called.
|
||||||
|
oop str1 = e_ptr1->literal();
|
||||||
|
oop str2 = e_ptr2->literal();
|
||||||
|
|
||||||
|
if (str1 == str2) {
|
||||||
|
tty->print_cr("ERROR: identical oop values (0x" PTR_FORMAT ") "
|
||||||
|
"in entry @ bucket[%d][%d] and entry @ bucket[%d][%d]",
|
||||||
|
(void *)str1, bkt1, e_cnt1, bkt2, e_cnt2);
|
||||||
|
return _verify_fail_continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (java_lang_String::equals(str1, str2)) {
|
||||||
|
tty->print_cr("ERROR: identical String values in entry @ "
|
||||||
|
"bucket[%d][%d] and entry @ bucket[%d][%d]",
|
||||||
|
bkt1, e_cnt1, bkt2, e_cnt2);
|
||||||
|
return _verify_fail_continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _verify_pass;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringTable::VerifyRetTypes StringTable::verify_entry(int bkt, int e_cnt,
|
||||||
|
HashtableEntry<oop, mtSymbol>* e_ptr,
|
||||||
|
StringTable::VerifyMesgModes mesg_mode) {
|
||||||
|
|
||||||
|
VerifyRetTypes ret = _verify_pass; // be optimistic
|
||||||
|
|
||||||
|
oop str = e_ptr->literal();
|
||||||
|
if (str == NULL) {
|
||||||
|
if (mesg_mode == _verify_with_mesgs) {
|
||||||
|
tty->print_cr("ERROR: NULL oop value in entry @ bucket[%d][%d]", bkt,
|
||||||
|
e_cnt);
|
||||||
|
}
|
||||||
|
// NULL oop means no more verifications are possible
|
||||||
|
return _verify_fail_done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (str->klass() != SystemDictionary::String_klass()) {
|
||||||
|
if (mesg_mode == _verify_with_mesgs) {
|
||||||
|
tty->print_cr("ERROR: oop is not a String in entry @ bucket[%d][%d]",
|
||||||
|
bkt, e_cnt);
|
||||||
|
}
|
||||||
|
// not a String means no more verifications are possible
|
||||||
|
return _verify_fail_done;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int h = java_lang_String::hash_string(str);
|
||||||
|
if (e_ptr->hash() != h) {
|
||||||
|
if (mesg_mode == _verify_with_mesgs) {
|
||||||
|
tty->print_cr("ERROR: broken hash value in entry @ bucket[%d][%d], "
|
||||||
|
"bkt_hash=%d, str_hash=%d", bkt, e_cnt, e_ptr->hash(), h);
|
||||||
|
}
|
||||||
|
ret = _verify_fail_continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (the_table()->hash_to_index(h) != bkt) {
|
||||||
|
if (mesg_mode == _verify_with_mesgs) {
|
||||||
|
tty->print_cr("ERROR: wrong index value for entry @ bucket[%d][%d], "
|
||||||
|
"str_hash=%d, hash_to_index=%d", bkt, e_cnt, h,
|
||||||
|
the_table()->hash_to_index(h));
|
||||||
|
}
|
||||||
|
ret = _verify_fail_continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// See StringTable::verify() above for the quick verification that is
|
||||||
|
// part of Universe::verify(). This verification is exhaustive and
|
||||||
|
// reports on every issue that is found. StringTable::verify() only
|
||||||
|
// reports on the first issue that is found.
|
||||||
|
//
|
||||||
|
// StringTable::verify_entry() checks:
|
||||||
|
// - oop value != NULL (same as verify())
|
||||||
|
// - oop value is a String
|
||||||
|
// - hash(String) == hash in entry (same as verify())
|
||||||
|
// - index for hash == index of entry (same as verify())
|
||||||
|
//
|
||||||
|
// StringTable::compare_entries() checks:
|
||||||
|
// - oops are unique across all entries
|
||||||
|
// - String values are unique across all entries
|
||||||
|
//
|
||||||
|
int StringTable::verify_and_compare_entries() {
|
||||||
|
assert(StringTable_lock->is_locked(), "sanity check");
|
||||||
|
|
||||||
|
int fail_cnt = 0;
|
||||||
|
|
||||||
|
// first, verify all the entries individually:
|
||||||
|
for (int bkt = 0; bkt < the_table()->table_size(); bkt++) {
|
||||||
|
HashtableEntry<oop, mtSymbol>* e_ptr = the_table()->bucket(bkt);
|
||||||
|
for (int e_cnt = 0; e_ptr != NULL; e_ptr = e_ptr->next(), e_cnt++) {
|
||||||
|
VerifyRetTypes ret = verify_entry(bkt, e_cnt, e_ptr, _verify_with_mesgs);
|
||||||
|
if (ret != _verify_pass) {
|
||||||
|
fail_cnt++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Optimization: if the above check did not find any failures, then
|
||||||
|
// the comparison loop below does not need to call verify_entry()
|
||||||
|
// before calling compare_entries(). If there were failures, then we
|
||||||
|
// have to call verify_entry() to see if the entry can be passed to
|
||||||
|
// compare_entries() safely. When we call verify_entry() in the loop
|
||||||
|
// below, we do so quietly to void duplicate messages and we don't
|
||||||
|
// increment fail_cnt because the failures have already been counted.
|
||||||
|
bool need_entry_verify = (fail_cnt != 0);
|
||||||
|
|
||||||
|
// second, verify all entries relative to each other:
|
||||||
|
for (int bkt1 = 0; bkt1 < the_table()->table_size(); bkt1++) {
|
||||||
|
HashtableEntry<oop, mtSymbol>* e_ptr1 = the_table()->bucket(bkt1);
|
||||||
|
for (int e_cnt1 = 0; e_ptr1 != NULL; e_ptr1 = e_ptr1->next(), e_cnt1++) {
|
||||||
|
if (need_entry_verify) {
|
||||||
|
VerifyRetTypes ret = verify_entry(bkt1, e_cnt1, e_ptr1,
|
||||||
|
_verify_quietly);
|
||||||
|
if (ret == _verify_fail_done) {
|
||||||
|
// cannot use the current entry to compare against other entries
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int bkt2 = bkt1; bkt2 < the_table()->table_size(); bkt2++) {
|
||||||
|
HashtableEntry<oop, mtSymbol>* e_ptr2 = the_table()->bucket(bkt2);
|
||||||
|
int e_cnt2;
|
||||||
|
for (e_cnt2 = 0; e_ptr2 != NULL; e_ptr2 = e_ptr2->next(), e_cnt2++) {
|
||||||
|
if (bkt1 == bkt2 && e_cnt2 <= e_cnt1) {
|
||||||
|
// skip the entries up to and including the one that
|
||||||
|
// we're comparing against
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (need_entry_verify) {
|
||||||
|
VerifyRetTypes ret = verify_entry(bkt2, e_cnt2, e_ptr2,
|
||||||
|
_verify_quietly);
|
||||||
|
if (ret == _verify_fail_done) {
|
||||||
|
// cannot compare against this entry
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// compare two entries, report and count any failures:
|
||||||
|
if (compare_entries(bkt1, e_cnt1, e_ptr1, bkt2, e_cnt2, e_ptr2)
|
||||||
|
!= _verify_pass) {
|
||||||
|
fail_cnt++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fail_cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new table and using alternate hash code, populate the new table
|
||||||
|
// with the existing strings. Set flag to use the alternate hash code afterwards.
|
||||||
|
void StringTable::rehash_table() {
|
||||||
|
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
|
||||||
|
// This should never happen with -Xshare:dump but it might in testing mode.
|
||||||
|
if (DumpSharedSpaces) return;
|
||||||
|
StringTable* new_table = new StringTable();
|
||||||
|
|
||||||
|
// Rehash the table
|
||||||
|
the_table()->move_to(new_table);
|
||||||
|
|
||||||
|
// Delete the table and buckets (entries are reused in new table).
|
||||||
|
delete _the_table;
|
||||||
|
// Don't check if we need rehashing until the table gets unbalanced again.
|
||||||
|
// Then rehash with a new global seed.
|
||||||
|
_needs_rehashing = false;
|
||||||
|
_the_table = new_table;
|
||||||
|
}
|
162
hotspot/src/share/vm/classfile/stringTable.hpp
Normal file
162
hotspot/src/share/vm/classfile/stringTable.hpp
Normal file
|
@ -0,0 +1,162 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1997, 2013, 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_CLASSFILE_STRINGTABLE_HPP
|
||||||
|
#define SHARE_VM_CLASSFILE_STRINGTABLE_HPP
|
||||||
|
|
||||||
|
#include "memory/allocation.inline.hpp"
|
||||||
|
#include "utilities/hashtable.hpp"
|
||||||
|
|
||||||
|
class StringTable : public Hashtable<oop, mtSymbol> {
|
||||||
|
friend class VMStructs;
|
||||||
|
friend class Symbol;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// The string table
|
||||||
|
static StringTable* _the_table;
|
||||||
|
|
||||||
|
// Set if one bucket is out of balance due to hash algorithm deficiency
|
||||||
|
static bool _needs_rehashing;
|
||||||
|
|
||||||
|
// Claimed high water mark for parallel chunked scanning
|
||||||
|
static volatile int _parallel_claimed_idx;
|
||||||
|
|
||||||
|
static oop intern(Handle string_or_null, jchar* chars, int length, TRAPS);
|
||||||
|
oop basic_add(int index, Handle string_or_null, jchar* name, int len,
|
||||||
|
unsigned int hashValue, TRAPS);
|
||||||
|
|
||||||
|
oop lookup(int index, jchar* chars, int length, unsigned int hashValue);
|
||||||
|
|
||||||
|
// Apply the give oop closure to the entries to the buckets
|
||||||
|
// in the range [start_idx, end_idx).
|
||||||
|
static void buckets_oops_do(OopClosure* f, int start_idx, int end_idx);
|
||||||
|
// Unlink or apply the give oop closure to the entries to the buckets
|
||||||
|
// in the range [start_idx, end_idx).
|
||||||
|
static void buckets_unlink_or_oops_do(BoolObjectClosure* is_alive, OopClosure* f, int start_idx, int end_idx, int* processed, int* removed);
|
||||||
|
|
||||||
|
StringTable() : Hashtable<oop, mtSymbol>((int)StringTableSize,
|
||||||
|
sizeof (HashtableEntry<oop, mtSymbol>)) {}
|
||||||
|
|
||||||
|
StringTable(HashtableBucket<mtSymbol>* t, int number_of_entries)
|
||||||
|
: Hashtable<oop, mtSymbol>((int)StringTableSize, sizeof (HashtableEntry<oop, mtSymbol>), t,
|
||||||
|
number_of_entries) {}
|
||||||
|
public:
|
||||||
|
// The string table
|
||||||
|
static StringTable* the_table() { return _the_table; }
|
||||||
|
|
||||||
|
// Size of one bucket in the string table. Used when checking for rollover.
|
||||||
|
static uint bucket_size() { return sizeof(HashtableBucket<mtSymbol>); }
|
||||||
|
|
||||||
|
static void create_table() {
|
||||||
|
assert(_the_table == NULL, "One string table allowed.");
|
||||||
|
_the_table = new StringTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
// GC support
|
||||||
|
// Delete pointers to otherwise-unreachable objects.
|
||||||
|
static void unlink_or_oops_do(BoolObjectClosure* cl, OopClosure* f) {
|
||||||
|
int processed = 0;
|
||||||
|
int removed = 0;
|
||||||
|
unlink_or_oops_do(cl, f, &processed, &removed);
|
||||||
|
}
|
||||||
|
static void unlink(BoolObjectClosure* cl) {
|
||||||
|
int processed = 0;
|
||||||
|
int removed = 0;
|
||||||
|
unlink_or_oops_do(cl, NULL, &processed, &removed);
|
||||||
|
}
|
||||||
|
static void unlink_or_oops_do(BoolObjectClosure* cl, OopClosure* f, int* processed, int* removed);
|
||||||
|
static void unlink(BoolObjectClosure* cl, int* processed, int* removed) {
|
||||||
|
unlink_or_oops_do(cl, NULL, processed, removed);
|
||||||
|
}
|
||||||
|
// Serially invoke "f->do_oop" on the locations of all oops in the table.
|
||||||
|
static void oops_do(OopClosure* f);
|
||||||
|
|
||||||
|
// Possibly parallel versions of the above
|
||||||
|
static void possibly_parallel_unlink_or_oops_do(BoolObjectClosure* cl, OopClosure* f, int* processed, int* removed);
|
||||||
|
static void possibly_parallel_unlink(BoolObjectClosure* cl, int* processed, int* removed) {
|
||||||
|
possibly_parallel_unlink_or_oops_do(cl, NULL, processed, removed);
|
||||||
|
}
|
||||||
|
static void possibly_parallel_oops_do(OopClosure* f);
|
||||||
|
|
||||||
|
// Hashing algorithm, used as the hash value used by the
|
||||||
|
// StringTable for bucket selection and comparison (stored in the
|
||||||
|
// HashtableEntry structures). This is used in the String.intern() method.
|
||||||
|
static unsigned int hash_string(const jchar* s, int len);
|
||||||
|
|
||||||
|
// Internal test.
|
||||||
|
static void test_alt_hash() PRODUCT_RETURN;
|
||||||
|
|
||||||
|
// Probing
|
||||||
|
static oop lookup(Symbol* symbol);
|
||||||
|
static oop lookup(jchar* chars, int length);
|
||||||
|
|
||||||
|
// Interning
|
||||||
|
static oop intern(Symbol* symbol, TRAPS);
|
||||||
|
static oop intern(oop string, TRAPS);
|
||||||
|
static oop intern(const char *utf8_string, TRAPS);
|
||||||
|
|
||||||
|
// Debugging
|
||||||
|
static void verify();
|
||||||
|
static void dump(outputStream* st);
|
||||||
|
|
||||||
|
enum VerifyMesgModes {
|
||||||
|
_verify_quietly = 0,
|
||||||
|
_verify_with_mesgs = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
enum VerifyRetTypes {
|
||||||
|
_verify_pass = 0,
|
||||||
|
_verify_fail_continue = 1,
|
||||||
|
_verify_fail_done = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
static VerifyRetTypes compare_entries(int bkt1, int e_cnt1,
|
||||||
|
HashtableEntry<oop, mtSymbol>* e_ptr1,
|
||||||
|
int bkt2, int e_cnt2,
|
||||||
|
HashtableEntry<oop, mtSymbol>* e_ptr2);
|
||||||
|
static VerifyRetTypes verify_entry(int bkt, int e_cnt,
|
||||||
|
HashtableEntry<oop, mtSymbol>* e_ptr,
|
||||||
|
VerifyMesgModes mesg_mode);
|
||||||
|
static int verify_and_compare_entries();
|
||||||
|
|
||||||
|
// Sharing
|
||||||
|
static void copy_buckets(char** top, char*end) {
|
||||||
|
the_table()->Hashtable<oop, mtSymbol>::copy_buckets(top, end);
|
||||||
|
}
|
||||||
|
static void copy_table(char** top, char*end) {
|
||||||
|
the_table()->Hashtable<oop, mtSymbol>::copy_table(top, end);
|
||||||
|
}
|
||||||
|
static void reverse() {
|
||||||
|
the_table()->Hashtable<oop, mtSymbol>::reverse();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rehash the symbol table if it gets out of balance
|
||||||
|
static void rehash_table();
|
||||||
|
static bool needs_rehashing() { return _needs_rehashing; }
|
||||||
|
|
||||||
|
// Parallel chunked scanning
|
||||||
|
static void clear_parallel_claimed_index() { _parallel_claimed_idx = 0; }
|
||||||
|
static int parallel_claimed_index() { return _parallel_claimed_idx; }
|
||||||
|
};
|
||||||
|
#endif // SHARE_VM_CLASSFILE_STRINGTABLE_HPP
|
|
@ -35,14 +35,10 @@
|
||||||
#include "oops/oop.inline2.hpp"
|
#include "oops/oop.inline2.hpp"
|
||||||
#include "runtime/mutexLocker.hpp"
|
#include "runtime/mutexLocker.hpp"
|
||||||
#include "utilities/hashtable.inline.hpp"
|
#include "utilities/hashtable.inline.hpp"
|
||||||
#if INCLUDE_ALL_GCS
|
|
||||||
#include "gc_implementation/g1/g1StringDedup.hpp"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
|
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
// the number of buckets a thread claims
|
// the number of buckets a thread claims
|
||||||
const int ClaimChunkSize = 32;
|
const int ClaimChunkSize = 32;
|
||||||
|
|
||||||
|
@ -589,493 +585,3 @@ void SymbolTable::print() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // PRODUCT
|
#endif // PRODUCT
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
|
||||||
|
|
||||||
#ifdef ASSERT
|
|
||||||
class StableMemoryChecker : public StackObj {
|
|
||||||
enum { _bufsize = wordSize*4 };
|
|
||||||
|
|
||||||
address _region;
|
|
||||||
jint _size;
|
|
||||||
u1 _save_buf[_bufsize];
|
|
||||||
|
|
||||||
int sample(u1* save_buf) {
|
|
||||||
if (_size <= _bufsize) {
|
|
||||||
memcpy(save_buf, _region, _size);
|
|
||||||
return _size;
|
|
||||||
} else {
|
|
||||||
// copy head and tail
|
|
||||||
memcpy(&save_buf[0], _region, _bufsize/2);
|
|
||||||
memcpy(&save_buf[_bufsize/2], _region + _size - _bufsize/2, _bufsize/2);
|
|
||||||
return (_bufsize/2)*2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
StableMemoryChecker(const void* region, jint size) {
|
|
||||||
_region = (address) region;
|
|
||||||
_size = size;
|
|
||||||
sample(_save_buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool verify() {
|
|
||||||
u1 check_buf[sizeof(_save_buf)];
|
|
||||||
int check_size = sample(check_buf);
|
|
||||||
return (0 == memcmp(_save_buf, check_buf, check_size));
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_region(const void* region) { _region = (address) region; }
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
|
||||||
StringTable* StringTable::_the_table = NULL;
|
|
||||||
|
|
||||||
bool StringTable::_needs_rehashing = false;
|
|
||||||
|
|
||||||
volatile int StringTable::_parallel_claimed_idx = 0;
|
|
||||||
|
|
||||||
// Pick hashing algorithm
|
|
||||||
unsigned int StringTable::hash_string(const jchar* s, int len) {
|
|
||||||
return use_alternate_hashcode() ? AltHashing::murmur3_32(seed(), s, len) :
|
|
||||||
java_lang_String::hash_code(s, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
oop StringTable::lookup(int index, jchar* name,
|
|
||||||
int len, unsigned int hash) {
|
|
||||||
int count = 0;
|
|
||||||
for (HashtableEntry<oop, mtSymbol>* l = bucket(index); l != NULL; l = l->next()) {
|
|
||||||
count++;
|
|
||||||
if (l->hash() == hash) {
|
|
||||||
if (java_lang_String::equals(l->literal(), name, len)) {
|
|
||||||
return l->literal();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// If the bucket size is too deep check if this hash code is insufficient.
|
|
||||||
if (count >= BasicHashtable<mtSymbol>::rehash_count && !needs_rehashing()) {
|
|
||||||
_needs_rehashing = check_rehash_table(count);
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
oop StringTable::basic_add(int index_arg, Handle string, jchar* name,
|
|
||||||
int len, unsigned int hashValue_arg, TRAPS) {
|
|
||||||
|
|
||||||
assert(java_lang_String::equals(string(), name, len),
|
|
||||||
"string must be properly initialized");
|
|
||||||
// Cannot hit a safepoint in this function because the "this" pointer can move.
|
|
||||||
No_Safepoint_Verifier nsv;
|
|
||||||
|
|
||||||
// Check if the symbol table has been rehashed, if so, need to recalculate
|
|
||||||
// the hash value and index before second lookup.
|
|
||||||
unsigned int hashValue;
|
|
||||||
int index;
|
|
||||||
if (use_alternate_hashcode()) {
|
|
||||||
hashValue = hash_string(name, len);
|
|
||||||
index = hash_to_index(hashValue);
|
|
||||||
} else {
|
|
||||||
hashValue = hashValue_arg;
|
|
||||||
index = index_arg;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Since look-up was done lock-free, we need to check if another
|
|
||||||
// thread beat us in the race to insert the symbol.
|
|
||||||
|
|
||||||
oop test = lookup(index, name, len, hashValue); // calls lookup(u1*, int)
|
|
||||||
if (test != NULL) {
|
|
||||||
// Entry already added
|
|
||||||
return test;
|
|
||||||
}
|
|
||||||
|
|
||||||
HashtableEntry<oop, mtSymbol>* entry = new_entry(hashValue, string());
|
|
||||||
add_entry(index, entry);
|
|
||||||
return string();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
oop StringTable::lookup(Symbol* symbol) {
|
|
||||||
ResourceMark rm;
|
|
||||||
int length;
|
|
||||||
jchar* chars = symbol->as_unicode(length);
|
|
||||||
return lookup(chars, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
oop StringTable::lookup(jchar* name, int len) {
|
|
||||||
unsigned int hash = hash_string(name, len);
|
|
||||||
int index = the_table()->hash_to_index(hash);
|
|
||||||
return the_table()->lookup(index, name, len, hash);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
oop StringTable::intern(Handle string_or_null, jchar* name,
|
|
||||||
int len, TRAPS) {
|
|
||||||
unsigned int hashValue = hash_string(name, len);
|
|
||||||
int index = the_table()->hash_to_index(hashValue);
|
|
||||||
oop found_string = the_table()->lookup(index, name, len, hashValue);
|
|
||||||
|
|
||||||
// Found
|
|
||||||
if (found_string != NULL) return found_string;
|
|
||||||
|
|
||||||
debug_only(StableMemoryChecker smc(name, len * sizeof(name[0])));
|
|
||||||
assert(!Universe::heap()->is_in_reserved(name),
|
|
||||||
"proposed name of symbol must be stable");
|
|
||||||
|
|
||||||
Handle string;
|
|
||||||
// try to reuse the string if possible
|
|
||||||
if (!string_or_null.is_null()) {
|
|
||||||
string = string_or_null;
|
|
||||||
} else {
|
|
||||||
string = java_lang_String::create_from_unicode(name, len, CHECK_NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if INCLUDE_ALL_GCS
|
|
||||||
if (G1StringDedup::is_enabled()) {
|
|
||||||
// Deduplicate the string before it is interned. Note that we should never
|
|
||||||
// deduplicate a string after it has been interned. Doing so will counteract
|
|
||||||
// compiler optimizations done on e.g. interned string literals.
|
|
||||||
G1StringDedup::deduplicate(string());
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Grab the StringTable_lock before getting the_table() because it could
|
|
||||||
// change at safepoint.
|
|
||||||
MutexLocker ml(StringTable_lock, THREAD);
|
|
||||||
|
|
||||||
// Otherwise, add to symbol to table
|
|
||||||
return the_table()->basic_add(index, string, name, len,
|
|
||||||
hashValue, CHECK_NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
oop StringTable::intern(Symbol* symbol, TRAPS) {
|
|
||||||
if (symbol == NULL) return NULL;
|
|
||||||
ResourceMark rm(THREAD);
|
|
||||||
int length;
|
|
||||||
jchar* chars = symbol->as_unicode(length);
|
|
||||||
Handle string;
|
|
||||||
oop result = intern(string, chars, length, CHECK_NULL);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
oop StringTable::intern(oop string, TRAPS)
|
|
||||||
{
|
|
||||||
if (string == NULL) return NULL;
|
|
||||||
ResourceMark rm(THREAD);
|
|
||||||
int length;
|
|
||||||
Handle h_string (THREAD, string);
|
|
||||||
jchar* chars = java_lang_String::as_unicode_string(string, length, CHECK_NULL);
|
|
||||||
oop result = intern(h_string, chars, length, CHECK_NULL);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
oop StringTable::intern(const char* utf8_string, TRAPS) {
|
|
||||||
if (utf8_string == NULL) return NULL;
|
|
||||||
ResourceMark rm(THREAD);
|
|
||||||
int length = UTF8::unicode_length(utf8_string);
|
|
||||||
jchar* chars = NEW_RESOURCE_ARRAY(jchar, length);
|
|
||||||
UTF8::convert_to_unicode(utf8_string, chars, length);
|
|
||||||
Handle string;
|
|
||||||
oop result = intern(string, chars, length, CHECK_NULL);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void StringTable::unlink_or_oops_do(BoolObjectClosure* is_alive, OopClosure* f, int* processed, int* removed) {
|
|
||||||
buckets_unlink_or_oops_do(is_alive, f, 0, the_table()->table_size(), processed, removed);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StringTable::possibly_parallel_unlink_or_oops_do(BoolObjectClosure* is_alive, OopClosure* f, int* processed, int* removed) {
|
|
||||||
// Readers of the table are unlocked, so we should only be removing
|
|
||||||
// entries at a safepoint.
|
|
||||||
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
|
|
||||||
const int limit = the_table()->table_size();
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
// Grab next set of buckets to scan
|
|
||||||
int start_idx = Atomic::add(ClaimChunkSize, &_parallel_claimed_idx) - ClaimChunkSize;
|
|
||||||
if (start_idx >= limit) {
|
|
||||||
// End of table
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
int end_idx = MIN2(limit, start_idx + ClaimChunkSize);
|
|
||||||
buckets_unlink_or_oops_do(is_alive, f, start_idx, end_idx, processed, removed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void StringTable::buckets_oops_do(OopClosure* f, int start_idx, int end_idx) {
|
|
||||||
const int limit = the_table()->table_size();
|
|
||||||
|
|
||||||
assert(0 <= start_idx && start_idx <= limit,
|
|
||||||
err_msg("start_idx (%d) is out of bounds", start_idx));
|
|
||||||
assert(0 <= end_idx && end_idx <= limit,
|
|
||||||
err_msg("end_idx (%d) is out of bounds", end_idx));
|
|
||||||
assert(start_idx <= end_idx,
|
|
||||||
err_msg("Index ordering: start_idx=%d, end_idx=%d",
|
|
||||||
start_idx, end_idx));
|
|
||||||
|
|
||||||
for (int i = start_idx; i < end_idx; i += 1) {
|
|
||||||
HashtableEntry<oop, mtSymbol>* entry = the_table()->bucket(i);
|
|
||||||
while (entry != NULL) {
|
|
||||||
assert(!entry->is_shared(), "CDS not used for the StringTable");
|
|
||||||
|
|
||||||
f->do_oop((oop*)entry->literal_addr());
|
|
||||||
|
|
||||||
entry = entry->next();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void StringTable::buckets_unlink_or_oops_do(BoolObjectClosure* is_alive, OopClosure* f, int start_idx, int end_idx, int* processed, int* removed) {
|
|
||||||
const int limit = the_table()->table_size();
|
|
||||||
|
|
||||||
assert(0 <= start_idx && start_idx <= limit,
|
|
||||||
err_msg("start_idx (%d) is out of bounds", start_idx));
|
|
||||||
assert(0 <= end_idx && end_idx <= limit,
|
|
||||||
err_msg("end_idx (%d) is out of bounds", end_idx));
|
|
||||||
assert(start_idx <= end_idx,
|
|
||||||
err_msg("Index ordering: start_idx=%d, end_idx=%d",
|
|
||||||
start_idx, end_idx));
|
|
||||||
|
|
||||||
for (int i = start_idx; i < end_idx; ++i) {
|
|
||||||
HashtableEntry<oop, mtSymbol>** p = the_table()->bucket_addr(i);
|
|
||||||
HashtableEntry<oop, mtSymbol>* entry = the_table()->bucket(i);
|
|
||||||
while (entry != NULL) {
|
|
||||||
assert(!entry->is_shared(), "CDS not used for the StringTable");
|
|
||||||
|
|
||||||
if (is_alive->do_object_b(entry->literal())) {
|
|
||||||
if (f != NULL) {
|
|
||||||
f->do_oop((oop*)entry->literal_addr());
|
|
||||||
}
|
|
||||||
p = entry->next_addr();
|
|
||||||
} else {
|
|
||||||
*p = entry->next();
|
|
||||||
the_table()->free_entry(entry);
|
|
||||||
(*removed)++;
|
|
||||||
}
|
|
||||||
(*processed)++;
|
|
||||||
entry = *p;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void StringTable::oops_do(OopClosure* f) {
|
|
||||||
buckets_oops_do(f, 0, the_table()->table_size());
|
|
||||||
}
|
|
||||||
|
|
||||||
void StringTable::possibly_parallel_oops_do(OopClosure* f) {
|
|
||||||
const int limit = the_table()->table_size();
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
// Grab next set of buckets to scan
|
|
||||||
int start_idx = Atomic::add(ClaimChunkSize, &_parallel_claimed_idx) - ClaimChunkSize;
|
|
||||||
if (start_idx >= limit) {
|
|
||||||
// End of table
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
int end_idx = MIN2(limit, start_idx + ClaimChunkSize);
|
|
||||||
buckets_oops_do(f, start_idx, end_idx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This verification is part of Universe::verify() and needs to be quick.
|
|
||||||
// See StringTable::verify_and_compare() below for exhaustive verification.
|
|
||||||
void StringTable::verify() {
|
|
||||||
for (int i = 0; i < the_table()->table_size(); ++i) {
|
|
||||||
HashtableEntry<oop, mtSymbol>* p = the_table()->bucket(i);
|
|
||||||
for ( ; p != NULL; p = p->next()) {
|
|
||||||
oop s = p->literal();
|
|
||||||
guarantee(s != NULL, "interned string is NULL");
|
|
||||||
unsigned int h = java_lang_String::hash_string(s);
|
|
||||||
guarantee(p->hash() == h, "broken hash in string table entry");
|
|
||||||
guarantee(the_table()->hash_to_index(h) == i,
|
|
||||||
"wrong index in string table");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void StringTable::dump(outputStream* st) {
|
|
||||||
the_table()->dump_table(st, "StringTable");
|
|
||||||
}
|
|
||||||
|
|
||||||
StringTable::VerifyRetTypes StringTable::compare_entries(
|
|
||||||
int bkt1, int e_cnt1,
|
|
||||||
HashtableEntry<oop, mtSymbol>* e_ptr1,
|
|
||||||
int bkt2, int e_cnt2,
|
|
||||||
HashtableEntry<oop, mtSymbol>* e_ptr2) {
|
|
||||||
// These entries are sanity checked by verify_and_compare_entries()
|
|
||||||
// before this function is called.
|
|
||||||
oop str1 = e_ptr1->literal();
|
|
||||||
oop str2 = e_ptr2->literal();
|
|
||||||
|
|
||||||
if (str1 == str2) {
|
|
||||||
tty->print_cr("ERROR: identical oop values (0x" PTR_FORMAT ") "
|
|
||||||
"in entry @ bucket[%d][%d] and entry @ bucket[%d][%d]",
|
|
||||||
(void *)str1, bkt1, e_cnt1, bkt2, e_cnt2);
|
|
||||||
return _verify_fail_continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (java_lang_String::equals(str1, str2)) {
|
|
||||||
tty->print_cr("ERROR: identical String values in entry @ "
|
|
||||||
"bucket[%d][%d] and entry @ bucket[%d][%d]",
|
|
||||||
bkt1, e_cnt1, bkt2, e_cnt2);
|
|
||||||
return _verify_fail_continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
return _verify_pass;
|
|
||||||
}
|
|
||||||
|
|
||||||
StringTable::VerifyRetTypes StringTable::verify_entry(int bkt, int e_cnt,
|
|
||||||
HashtableEntry<oop, mtSymbol>* e_ptr,
|
|
||||||
StringTable::VerifyMesgModes mesg_mode) {
|
|
||||||
|
|
||||||
VerifyRetTypes ret = _verify_pass; // be optimistic
|
|
||||||
|
|
||||||
oop str = e_ptr->literal();
|
|
||||||
if (str == NULL) {
|
|
||||||
if (mesg_mode == _verify_with_mesgs) {
|
|
||||||
tty->print_cr("ERROR: NULL oop value in entry @ bucket[%d][%d]", bkt,
|
|
||||||
e_cnt);
|
|
||||||
}
|
|
||||||
// NULL oop means no more verifications are possible
|
|
||||||
return _verify_fail_done;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (str->klass() != SystemDictionary::String_klass()) {
|
|
||||||
if (mesg_mode == _verify_with_mesgs) {
|
|
||||||
tty->print_cr("ERROR: oop is not a String in entry @ bucket[%d][%d]",
|
|
||||||
bkt, e_cnt);
|
|
||||||
}
|
|
||||||
// not a String means no more verifications are possible
|
|
||||||
return _verify_fail_done;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int h = java_lang_String::hash_string(str);
|
|
||||||
if (e_ptr->hash() != h) {
|
|
||||||
if (mesg_mode == _verify_with_mesgs) {
|
|
||||||
tty->print_cr("ERROR: broken hash value in entry @ bucket[%d][%d], "
|
|
||||||
"bkt_hash=%d, str_hash=%d", bkt, e_cnt, e_ptr->hash(), h);
|
|
||||||
}
|
|
||||||
ret = _verify_fail_continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (the_table()->hash_to_index(h) != bkt) {
|
|
||||||
if (mesg_mode == _verify_with_mesgs) {
|
|
||||||
tty->print_cr("ERROR: wrong index value for entry @ bucket[%d][%d], "
|
|
||||||
"str_hash=%d, hash_to_index=%d", bkt, e_cnt, h,
|
|
||||||
the_table()->hash_to_index(h));
|
|
||||||
}
|
|
||||||
ret = _verify_fail_continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
// See StringTable::verify() above for the quick verification that is
|
|
||||||
// part of Universe::verify(). This verification is exhaustive and
|
|
||||||
// reports on every issue that is found. StringTable::verify() only
|
|
||||||
// reports on the first issue that is found.
|
|
||||||
//
|
|
||||||
// StringTable::verify_entry() checks:
|
|
||||||
// - oop value != NULL (same as verify())
|
|
||||||
// - oop value is a String
|
|
||||||
// - hash(String) == hash in entry (same as verify())
|
|
||||||
// - index for hash == index of entry (same as verify())
|
|
||||||
//
|
|
||||||
// StringTable::compare_entries() checks:
|
|
||||||
// - oops are unique across all entries
|
|
||||||
// - String values are unique across all entries
|
|
||||||
//
|
|
||||||
int StringTable::verify_and_compare_entries() {
|
|
||||||
assert(StringTable_lock->is_locked(), "sanity check");
|
|
||||||
|
|
||||||
int fail_cnt = 0;
|
|
||||||
|
|
||||||
// first, verify all the entries individually:
|
|
||||||
for (int bkt = 0; bkt < the_table()->table_size(); bkt++) {
|
|
||||||
HashtableEntry<oop, mtSymbol>* e_ptr = the_table()->bucket(bkt);
|
|
||||||
for (int e_cnt = 0; e_ptr != NULL; e_ptr = e_ptr->next(), e_cnt++) {
|
|
||||||
VerifyRetTypes ret = verify_entry(bkt, e_cnt, e_ptr, _verify_with_mesgs);
|
|
||||||
if (ret != _verify_pass) {
|
|
||||||
fail_cnt++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Optimization: if the above check did not find any failures, then
|
|
||||||
// the comparison loop below does not need to call verify_entry()
|
|
||||||
// before calling compare_entries(). If there were failures, then we
|
|
||||||
// have to call verify_entry() to see if the entry can be passed to
|
|
||||||
// compare_entries() safely. When we call verify_entry() in the loop
|
|
||||||
// below, we do so quietly to void duplicate messages and we don't
|
|
||||||
// increment fail_cnt because the failures have already been counted.
|
|
||||||
bool need_entry_verify = (fail_cnt != 0);
|
|
||||||
|
|
||||||
// second, verify all entries relative to each other:
|
|
||||||
for (int bkt1 = 0; bkt1 < the_table()->table_size(); bkt1++) {
|
|
||||||
HashtableEntry<oop, mtSymbol>* e_ptr1 = the_table()->bucket(bkt1);
|
|
||||||
for (int e_cnt1 = 0; e_ptr1 != NULL; e_ptr1 = e_ptr1->next(), e_cnt1++) {
|
|
||||||
if (need_entry_verify) {
|
|
||||||
VerifyRetTypes ret = verify_entry(bkt1, e_cnt1, e_ptr1,
|
|
||||||
_verify_quietly);
|
|
||||||
if (ret == _verify_fail_done) {
|
|
||||||
// cannot use the current entry to compare against other entries
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int bkt2 = bkt1; bkt2 < the_table()->table_size(); bkt2++) {
|
|
||||||
HashtableEntry<oop, mtSymbol>* e_ptr2 = the_table()->bucket(bkt2);
|
|
||||||
int e_cnt2;
|
|
||||||
for (e_cnt2 = 0; e_ptr2 != NULL; e_ptr2 = e_ptr2->next(), e_cnt2++) {
|
|
||||||
if (bkt1 == bkt2 && e_cnt2 <= e_cnt1) {
|
|
||||||
// skip the entries up to and including the one that
|
|
||||||
// we're comparing against
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (need_entry_verify) {
|
|
||||||
VerifyRetTypes ret = verify_entry(bkt2, e_cnt2, e_ptr2,
|
|
||||||
_verify_quietly);
|
|
||||||
if (ret == _verify_fail_done) {
|
|
||||||
// cannot compare against this entry
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// compare two entries, report and count any failures:
|
|
||||||
if (compare_entries(bkt1, e_cnt1, e_ptr1, bkt2, e_cnt2, e_ptr2)
|
|
||||||
!= _verify_pass) {
|
|
||||||
fail_cnt++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return fail_cnt;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a new table and using alternate hash code, populate the new table
|
|
||||||
// with the existing strings. Set flag to use the alternate hash code afterwards.
|
|
||||||
void StringTable::rehash_table() {
|
|
||||||
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
|
|
||||||
// This should never happen with -Xshare:dump but it might in testing mode.
|
|
||||||
if (DumpSharedSpaces) return;
|
|
||||||
StringTable* new_table = new StringTable();
|
|
||||||
|
|
||||||
// Rehash the table
|
|
||||||
the_table()->move_to(new_table);
|
|
||||||
|
|
||||||
// Delete the table and buckets (entries are reused in new table).
|
|
||||||
delete _the_table;
|
|
||||||
// Don't check if we need rehashing until the table gets unbalanced again.
|
|
||||||
// Then rehash with a new global seed.
|
|
||||||
_needs_rehashing = false;
|
|
||||||
_the_table = new_table;
|
|
||||||
}
|
|
||||||
|
|
|
@ -42,7 +42,6 @@
|
||||||
class BoolObjectClosure;
|
class BoolObjectClosure;
|
||||||
class outputStream;
|
class outputStream;
|
||||||
|
|
||||||
|
|
||||||
// Class to hold a newly created or referenced Symbol* temporarily in scope.
|
// Class to hold a newly created or referenced Symbol* temporarily in scope.
|
||||||
// new_symbol() and lookup() will create a Symbol* if not already in the
|
// new_symbol() and lookup() will create a Symbol* if not already in the
|
||||||
// symbol table and add to the symbol's reference count.
|
// symbol table and add to the symbol's reference count.
|
||||||
|
@ -252,134 +251,4 @@ public:
|
||||||
static int parallel_claimed_index() { return _parallel_claimed_idx; }
|
static int parallel_claimed_index() { return _parallel_claimed_idx; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class StringTable : public Hashtable<oop, mtSymbol> {
|
|
||||||
friend class VMStructs;
|
|
||||||
|
|
||||||
private:
|
|
||||||
// The string table
|
|
||||||
static StringTable* _the_table;
|
|
||||||
|
|
||||||
// Set if one bucket is out of balance due to hash algorithm deficiency
|
|
||||||
static bool _needs_rehashing;
|
|
||||||
|
|
||||||
// Claimed high water mark for parallel chunked scanning
|
|
||||||
static volatile int _parallel_claimed_idx;
|
|
||||||
|
|
||||||
static oop intern(Handle string_or_null, jchar* chars, int length, TRAPS);
|
|
||||||
oop basic_add(int index, Handle string_or_null, jchar* name, int len,
|
|
||||||
unsigned int hashValue, TRAPS);
|
|
||||||
|
|
||||||
oop lookup(int index, jchar* chars, int length, unsigned int hashValue);
|
|
||||||
|
|
||||||
// Apply the give oop closure to the entries to the buckets
|
|
||||||
// in the range [start_idx, end_idx).
|
|
||||||
static void buckets_oops_do(OopClosure* f, int start_idx, int end_idx);
|
|
||||||
// Unlink or apply the give oop closure to the entries to the buckets
|
|
||||||
// in the range [start_idx, end_idx).
|
|
||||||
static void buckets_unlink_or_oops_do(BoolObjectClosure* is_alive, OopClosure* f, int start_idx, int end_idx, int* processed, int* removed);
|
|
||||||
|
|
||||||
StringTable() : Hashtable<oop, mtSymbol>((int)StringTableSize,
|
|
||||||
sizeof (HashtableEntry<oop, mtSymbol>)) {}
|
|
||||||
|
|
||||||
StringTable(HashtableBucket<mtSymbol>* t, int number_of_entries)
|
|
||||||
: Hashtable<oop, mtSymbol>((int)StringTableSize, sizeof (HashtableEntry<oop, mtSymbol>), t,
|
|
||||||
number_of_entries) {}
|
|
||||||
public:
|
|
||||||
// The string table
|
|
||||||
static StringTable* the_table() { return _the_table; }
|
|
||||||
|
|
||||||
// Size of one bucket in the string table. Used when checking for rollover.
|
|
||||||
static uint bucket_size() { return sizeof(HashtableBucket<mtSymbol>); }
|
|
||||||
|
|
||||||
static void create_table() {
|
|
||||||
assert(_the_table == NULL, "One string table allowed.");
|
|
||||||
_the_table = new StringTable();
|
|
||||||
}
|
|
||||||
|
|
||||||
// GC support
|
|
||||||
// Delete pointers to otherwise-unreachable objects.
|
|
||||||
static void unlink_or_oops_do(BoolObjectClosure* cl, OopClosure* f) {
|
|
||||||
int processed = 0;
|
|
||||||
int removed = 0;
|
|
||||||
unlink_or_oops_do(cl, f, &processed, &removed);
|
|
||||||
}
|
|
||||||
static void unlink(BoolObjectClosure* cl) {
|
|
||||||
int processed = 0;
|
|
||||||
int removed = 0;
|
|
||||||
unlink_or_oops_do(cl, NULL, &processed, &removed);
|
|
||||||
}
|
|
||||||
static void unlink_or_oops_do(BoolObjectClosure* cl, OopClosure* f, int* processed, int* removed);
|
|
||||||
static void unlink(BoolObjectClosure* cl, int* processed, int* removed) {
|
|
||||||
unlink_or_oops_do(cl, NULL, processed, removed);
|
|
||||||
}
|
|
||||||
// Serially invoke "f->do_oop" on the locations of all oops in the table.
|
|
||||||
static void oops_do(OopClosure* f);
|
|
||||||
|
|
||||||
// Possibly parallel versions of the above
|
|
||||||
static void possibly_parallel_unlink_or_oops_do(BoolObjectClosure* cl, OopClosure* f, int* processed, int* removed);
|
|
||||||
static void possibly_parallel_unlink(BoolObjectClosure* cl, int* processed, int* removed) {
|
|
||||||
possibly_parallel_unlink_or_oops_do(cl, NULL, processed, removed);
|
|
||||||
}
|
|
||||||
static void possibly_parallel_oops_do(OopClosure* f);
|
|
||||||
|
|
||||||
// Hashing algorithm, used as the hash value used by the
|
|
||||||
// StringTable for bucket selection and comparison (stored in the
|
|
||||||
// HashtableEntry structures). This is used in the String.intern() method.
|
|
||||||
static unsigned int hash_string(const jchar* s, int len);
|
|
||||||
|
|
||||||
// Internal test.
|
|
||||||
static void test_alt_hash() PRODUCT_RETURN;
|
|
||||||
|
|
||||||
// Probing
|
|
||||||
static oop lookup(Symbol* symbol);
|
|
||||||
static oop lookup(jchar* chars, int length);
|
|
||||||
|
|
||||||
// Interning
|
|
||||||
static oop intern(Symbol* symbol, TRAPS);
|
|
||||||
static oop intern(oop string, TRAPS);
|
|
||||||
static oop intern(const char *utf8_string, TRAPS);
|
|
||||||
|
|
||||||
// Debugging
|
|
||||||
static void verify();
|
|
||||||
static void dump(outputStream* st);
|
|
||||||
|
|
||||||
enum VerifyMesgModes {
|
|
||||||
_verify_quietly = 0,
|
|
||||||
_verify_with_mesgs = 1
|
|
||||||
};
|
|
||||||
|
|
||||||
enum VerifyRetTypes {
|
|
||||||
_verify_pass = 0,
|
|
||||||
_verify_fail_continue = 1,
|
|
||||||
_verify_fail_done = 2
|
|
||||||
};
|
|
||||||
|
|
||||||
static VerifyRetTypes compare_entries(int bkt1, int e_cnt1,
|
|
||||||
HashtableEntry<oop, mtSymbol>* e_ptr1,
|
|
||||||
int bkt2, int e_cnt2,
|
|
||||||
HashtableEntry<oop, mtSymbol>* e_ptr2);
|
|
||||||
static VerifyRetTypes verify_entry(int bkt, int e_cnt,
|
|
||||||
HashtableEntry<oop, mtSymbol>* e_ptr,
|
|
||||||
VerifyMesgModes mesg_mode);
|
|
||||||
static int verify_and_compare_entries();
|
|
||||||
|
|
||||||
// Sharing
|
|
||||||
static void copy_buckets(char** top, char*end) {
|
|
||||||
the_table()->Hashtable<oop, mtSymbol>::copy_buckets(top, end);
|
|
||||||
}
|
|
||||||
static void copy_table(char** top, char*end) {
|
|
||||||
the_table()->Hashtable<oop, mtSymbol>::copy_table(top, end);
|
|
||||||
}
|
|
||||||
static void reverse() {
|
|
||||||
the_table()->Hashtable<oop, mtSymbol>::reverse();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rehash the symbol table if it gets out of balance
|
|
||||||
static void rehash_table();
|
|
||||||
static bool needs_rehashing() { return _needs_rehashing; }
|
|
||||||
|
|
||||||
// Parallel chunked scanning
|
|
||||||
static void clear_parallel_claimed_index() { _parallel_claimed_idx = 0; }
|
|
||||||
static int parallel_claimed_index() { return _parallel_claimed_idx; }
|
|
||||||
};
|
|
||||||
#endif // SHARE_VM_CLASSFILE_SYMBOLTABLE_HPP
|
#endif // SHARE_VM_CLASSFILE_SYMBOLTABLE_HPP
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include "classfile/loaderConstraints.hpp"
|
#include "classfile/loaderConstraints.hpp"
|
||||||
#include "classfile/placeholders.hpp"
|
#include "classfile/placeholders.hpp"
|
||||||
#include "classfile/resolutionErrors.hpp"
|
#include "classfile/resolutionErrors.hpp"
|
||||||
|
#include "classfile/stringTable.hpp"
|
||||||
#include "classfile/systemDictionary.hpp"
|
#include "classfile/systemDictionary.hpp"
|
||||||
#include "classfile/vmSymbols.hpp"
|
#include "classfile/vmSymbols.hpp"
|
||||||
#include "compiler/compileBroker.hpp"
|
#include "compiler/compileBroker.hpp"
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "classfile/classLoaderData.hpp"
|
#include "classfile/classLoaderData.hpp"
|
||||||
#include "classfile/symbolTable.hpp"
|
#include "classfile/stringTable.hpp"
|
||||||
#include "classfile/systemDictionary.hpp"
|
#include "classfile/systemDictionary.hpp"
|
||||||
#include "code/codeCache.hpp"
|
#include "code/codeCache.hpp"
|
||||||
#include "gc_implementation/concurrentMarkSweep/cmsAdaptiveSizePolicy.hpp"
|
#include "gc_implementation/concurrentMarkSweep/cmsAdaptiveSizePolicy.hpp"
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
|
#include "classfile/stringTable.hpp"
|
||||||
#include "code/codeCache.hpp"
|
#include "code/codeCache.hpp"
|
||||||
#include "code/icBuffer.hpp"
|
#include "code/icBuffer.hpp"
|
||||||
#include "gc_implementation/g1/bufferingOopClosure.hpp"
|
#include "gc_implementation/g1/bufferingOopClosure.hpp"
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
@ -23,7 +24,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "classfile/symbolTable.hpp"
|
#include "classfile/stringTable.hpp"
|
||||||
#include "classfile/systemDictionary.hpp"
|
#include "classfile/systemDictionary.hpp"
|
||||||
#include "code/codeCache.hpp"
|
#include "code/codeCache.hpp"
|
||||||
#include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp"
|
#include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp"
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "classfile/symbolTable.hpp"
|
#include "classfile/stringTable.hpp"
|
||||||
#include "classfile/systemDictionary.hpp"
|
#include "classfile/systemDictionary.hpp"
|
||||||
#include "code/codeCache.hpp"
|
#include "code/codeCache.hpp"
|
||||||
#include "gc_implementation/parallelScavenge/gcTaskManager.hpp"
|
#include "gc_implementation/parallelScavenge/gcTaskManager.hpp"
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2002, 2014, 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.
|
||||||
|
@ -23,7 +24,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "classfile/symbolTable.hpp"
|
#include "classfile/stringTable.hpp"
|
||||||
#include "code/codeCache.hpp"
|
#include "code/codeCache.hpp"
|
||||||
#include "gc_implementation/parallelScavenge/cardTableExtension.hpp"
|
#include "gc_implementation/parallelScavenge/cardTableExtension.hpp"
|
||||||
#include "gc_implementation/parallelScavenge/gcTaskManager.hpp"
|
#include "gc_implementation/parallelScavenge/gcTaskManager.hpp"
|
||||||
|
|
|
@ -24,31 +24,19 @@
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "libadt/dict.hpp"
|
#include "libadt/dict.hpp"
|
||||||
#include "memory/allocation.inline.hpp"
|
|
||||||
#include "memory/resourceArea.hpp"
|
|
||||||
#include "runtime/thread.hpp"
|
|
||||||
|
|
||||||
// Dictionaries - An Abstract Data Type
|
// Dictionaries - An Abstract Data Type
|
||||||
|
|
||||||
// %%%%% includes not needed with AVM framework - Ungar
|
// %%%%% includes not needed with AVM framework - Ungar
|
||||||
|
|
||||||
// #include "port.hpp"
|
|
||||||
//IMPLEMENTATION
|
|
||||||
// #include "dict.hpp"
|
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
|
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
|
||||||
|
|
||||||
// The iostream is not needed and it gets confused for gcc by the
|
|
||||||
// define of bool.
|
|
||||||
//
|
|
||||||
// #include <iostream.h>
|
|
||||||
|
|
||||||
//------------------------------data-----------------------------------------
|
//------------------------------data-----------------------------------------
|
||||||
// String hash tables
|
// String hash tables
|
||||||
#define MAXID 20
|
#define MAXID 20
|
||||||
static byte initflag = 0; // True after 1st initialization
|
static uint8_t initflag = 0; // True after 1st initialization
|
||||||
static const char shft[MAXID] = {1,2,3,4,5,6,7,1,2,3,4,5,6,7,1,2,3,4,5,6};
|
static const char shft[MAXID] = {1,2,3,4,5,6,7,1,2,3,4,5,6,7,1,2,3,4,5,6};
|
||||||
static short xsum[MAXID];
|
static short xsum[MAXID];
|
||||||
|
|
||||||
|
@ -283,7 +271,7 @@ void *Dict::operator [](const void *key) const {
|
||||||
// CmpDict compares two dictionaries; they must have the same keys (their
|
// CmpDict compares two dictionaries; they must have the same keys (their
|
||||||
// keys must match using CmpKey) and they must have the same values (pointer
|
// keys must match using CmpKey) and they must have the same values (pointer
|
||||||
// comparison). If so 1 is returned, if not 0 is returned.
|
// comparison). If so 1 is returned, if not 0 is returned.
|
||||||
int32 Dict::operator ==(const Dict &d2) const {
|
int32_t Dict::operator ==(const Dict &d2) const {
|
||||||
if( _cnt != d2._cnt ) return 0;
|
if( _cnt != d2._cnt ) return 0;
|
||||||
if( _hash != d2._hash ) return 0;
|
if( _hash != d2._hash ) return 0;
|
||||||
if( _cmp != d2._cmp ) return 0;
|
if( _cmp != d2._cmp ) return 0;
|
||||||
|
@ -320,7 +308,7 @@ void Dict::print() {
|
||||||
// C text shows excellent spreading of values for any size hash table.
|
// C text shows excellent spreading of values for any size hash table.
|
||||||
int hashstr(const void *t) {
|
int hashstr(const void *t) {
|
||||||
register char c, k = 0;
|
register char c, k = 0;
|
||||||
register int32 sum = 0;
|
register int32_t sum = 0;
|
||||||
register const char *s = (const char *)t;
|
register const char *s = (const char *)t;
|
||||||
|
|
||||||
while( ((c = *s++) != '\0') && (k < MAXID-1) ) { // Get characters till null or MAXID-1
|
while( ((c = *s++) != '\0') && (k < MAXID-1) ) { // Get characters till null or MAXID-1
|
||||||
|
@ -334,11 +322,7 @@ int hashstr(const void *t) {
|
||||||
// Slimey cheap hash function; no guaranteed performance. Better than the
|
// Slimey cheap hash function; no guaranteed performance. Better than the
|
||||||
// default for pointers, especially on MS-DOS machines.
|
// default for pointers, especially on MS-DOS machines.
|
||||||
int hashptr(const void *key) {
|
int hashptr(const void *key) {
|
||||||
#ifdef __TURBOC__
|
return ((intptr_t)key >> 2);
|
||||||
return ((intptr_t)key >> 16);
|
|
||||||
#else // __TURBOC__
|
|
||||||
return ((intptr_t)key >> 2);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Slimey cheap hash function; no guaranteed performance.
|
// Slimey cheap hash function; no guaranteed performance.
|
||||||
|
@ -347,12 +331,12 @@ int hashkey(const void *key) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------Key Comparator Functions---------------------
|
//------------------------------Key Comparator Functions---------------------
|
||||||
int32 cmpstr(const void *k1, const void *k2) {
|
int32_t cmpstr(const void *k1, const void *k2) {
|
||||||
return strcmp((const char *)k1,(const char *)k2);
|
return strcmp((const char *)k1,(const char *)k2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cheap key comparator.
|
// Cheap key comparator.
|
||||||
int32 cmpkey(const void *key1, const void *key2) {
|
int32_t cmpkey(const void *key1, const void *key2) {
|
||||||
if (key1 == key2) return 0;
|
if (key1 == key2) return 0;
|
||||||
intptr_t delta = (intptr_t)key1 - (intptr_t)key2;
|
intptr_t delta = (intptr_t)key1 - (intptr_t)key2;
|
||||||
if (delta > 0) return 1;
|
if (delta > 0) return 1;
|
||||||
|
|
|
@ -25,11 +25,12 @@
|
||||||
#ifndef SHARE_VM_LIBADT_DICT_HPP
|
#ifndef SHARE_VM_LIBADT_DICT_HPP
|
||||||
#define SHARE_VM_LIBADT_DICT_HPP
|
#define SHARE_VM_LIBADT_DICT_HPP
|
||||||
|
|
||||||
#include "libadt/port.hpp"
|
|
||||||
|
|
||||||
// Dictionaries - An Abstract Data Type
|
// Dictionaries - An Abstract Data Type
|
||||||
//INTERFACE
|
|
||||||
class ostream;
|
#include "memory/allocation.inline.hpp"
|
||||||
|
#include "memory/resourceArea.hpp"
|
||||||
|
#include "runtime/thread.hpp"
|
||||||
|
|
||||||
class Dict;
|
class Dict;
|
||||||
|
|
||||||
// These dictionaries define a key-value mapping. They can be inserted to,
|
// These dictionaries define a key-value mapping. They can be inserted to,
|
||||||
|
@ -38,7 +39,7 @@ class Dict;
|
||||||
// key comparison routine determines if two keys are equal or not. A hash
|
// key comparison routine determines if two keys are equal or not. A hash
|
||||||
// function can be provided; if it's not provided the key itself is used
|
// function can be provided; if it's not provided the key itself is used
|
||||||
// instead. A nice string hash function is included.
|
// instead. A nice string hash function is included.
|
||||||
typedef int32 (*CmpKey)(const void *key1, const void *key2);
|
typedef int32_t (*CmpKey)(const void *key1, const void *key2);
|
||||||
typedef int (*Hash)(const void *key);
|
typedef int (*Hash)(const void *key);
|
||||||
typedef void (*FuncDict)(const void *key, const void *val, Dict *d);
|
typedef void (*FuncDict)(const void *key, const void *val, Dict *d);
|
||||||
|
|
||||||
|
@ -47,7 +48,7 @@ class Dict : public ResourceObj { // Dictionary structure
|
||||||
class Arena *_arena; // Where to draw storage from
|
class Arena *_arena; // Where to draw storage from
|
||||||
class bucket *_bin; // Hash table is array of buckets
|
class bucket *_bin; // Hash table is array of buckets
|
||||||
uint _size; // Size (# of slots) in hash table
|
uint _size; // Size (# of slots) in hash table
|
||||||
uint32 _cnt; // Number of key-value pairs in hash table
|
uint32_t _cnt; // Number of key-value pairs in hash table
|
||||||
const Hash _hash; // Hashing function
|
const Hash _hash; // Hashing function
|
||||||
const CmpKey _cmp; // Key comparison function
|
const CmpKey _cmp; // Key comparison function
|
||||||
void doubhash( void ); // Double hash table size
|
void doubhash( void ); // Double hash table size
|
||||||
|
@ -67,7 +68,7 @@ class Dict : public ResourceObj { // Dictionary structure
|
||||||
void Clear();
|
void Clear();
|
||||||
|
|
||||||
// Return # of key-value pairs in dict
|
// Return # of key-value pairs in dict
|
||||||
uint32 Size(void) const { return _cnt; }
|
uint32_t Size(void) const { return _cnt; }
|
||||||
|
|
||||||
// Insert inserts the given key-value pair into the dictionary. The prior
|
// Insert inserts the given key-value pair into the dictionary. The prior
|
||||||
// value of the key is returned; NULL if the key was not previously defined.
|
// value of the key is returned; NULL if the key was not previously defined.
|
||||||
|
@ -81,7 +82,7 @@ class Dict : public ResourceObj { // Dictionary structure
|
||||||
// == compares two dictionaries; they must have the same keys (their keys
|
// == compares two dictionaries; they must have the same keys (their keys
|
||||||
// must match using CmpKey) and they must have the same values (pointer
|
// must match using CmpKey) and they must have the same values (pointer
|
||||||
// comparison). If so 1 is returned, if not 0 is returned.
|
// comparison). If so 1 is returned, if not 0 is returned.
|
||||||
int32 operator ==(const Dict &d) const; // Compare dictionaries for equal
|
int32_t operator ==(const Dict &d) const; // Compare dictionaries for equal
|
||||||
|
|
||||||
// Print out the dictionary contents as key-value pairs
|
// Print out the dictionary contents as key-value pairs
|
||||||
void print();
|
void print();
|
||||||
|
@ -96,9 +97,9 @@ int hashptr(const void *key);
|
||||||
int hashkey(const void *key);
|
int hashkey(const void *key);
|
||||||
|
|
||||||
// Key comparators
|
// Key comparators
|
||||||
int32 cmpstr(const void *k1, const void *k2);
|
int32_t cmpstr(const void *k1, const void *k2);
|
||||||
// Slimey cheap key comparator.
|
// Slimey cheap key comparator.
|
||||||
int32 cmpkey(const void *key1, const void *key2);
|
int32_t cmpkey(const void *key1, const void *key2);
|
||||||
|
|
||||||
//------------------------------Iteration--------------------------------------
|
//------------------------------Iteration--------------------------------------
|
||||||
// The class of dictionary iterators. Fails in the presences of modifications
|
// The class of dictionary iterators. Fails in the presences of modifications
|
||||||
|
|
|
@ -1,123 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
|
||||||
#include "libadt/port.hpp"
|
|
||||||
|
|
||||||
// Code for portable compiling
|
|
||||||
|
|
||||||
#ifdef __GNUC__
|
|
||||||
#pragma implementation
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// %%%%% includes not needed with AVM framework - Ungar
|
|
||||||
// #include "port.hpp"
|
|
||||||
|
|
||||||
// This is only used if turboc is used and it causes problems with
|
|
||||||
// gcc.
|
|
||||||
#ifdef __TURBOC__
|
|
||||||
#include <iostream.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
//------------------------------gcd--------------------------------------------
|
|
||||||
// Greatest common divisor
|
|
||||||
uint32 gcd( register uint32 x, register uint32 y )
|
|
||||||
{
|
|
||||||
register uint32 tmp;
|
|
||||||
while( x ) { // While not zero
|
|
||||||
tmp = x; // Hold onto smaller x value
|
|
||||||
x = y % x; // Compute modulus; since y>=x, 0 <= mod < x
|
|
||||||
y = tmp; // y = old x
|
|
||||||
}
|
|
||||||
return y;
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Find first 1, or return 32 if empty
|
|
||||||
int ff1( uint32 mask )
|
|
||||||
{
|
|
||||||
unsigned i, n = 0;
|
|
||||||
|
|
||||||
for( i=1, n=0; i; i<<=1, n++)
|
|
||||||
if( mask&i ) return n;
|
|
||||||
return 32;
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Find highest 1, or return 32 if empty
|
|
||||||
int fh1( uint32 mask )
|
|
||||||
{
|
|
||||||
unsigned i, n = 0;
|
|
||||||
|
|
||||||
for( i=((uint32)1<<31), n=31; i; i>>=1, n--)
|
|
||||||
if( mask&i ) return n;
|
|
||||||
return 32;
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------rotate32---------------------------------------
|
|
||||||
// Rotate 32bits. Postive rotates left (bits move toward high-order bit),
|
|
||||||
// negative rotates right.
|
|
||||||
uint32 rotate32( register uint32 x, register int32 cnt )
|
|
||||||
{
|
|
||||||
if( cnt >= 0 ) { // Positive rotates left
|
|
||||||
cnt &= 31; // Mask off extra shift bits
|
|
||||||
} else { // Negative rotates right
|
|
||||||
cnt = (-cnt)&31; // Flip sign; mask extra shift bits
|
|
||||||
cnt = 32-cnt; // Rotate right by big left rotation
|
|
||||||
}
|
|
||||||
return (x << cnt) | (x >> (32-cnt));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Disabled - we have another log2 in the system.
|
|
||||||
This function doesn't work if used as substitute
|
|
||||||
for the existing log2. Keep around until we have
|
|
||||||
verified all uses of log2 do the correct thing!
|
|
||||||
//------------------------------log2-------------------------------------------
|
|
||||||
// Log base 2. Might also be called 'count leading zeros'. Log2(x) returns
|
|
||||||
// an l such that (1L<<l) <= x < (2L<<l). log2(x) returns 32.
|
|
||||||
uint log2( uint32 x )
|
|
||||||
{
|
|
||||||
register uint l = 32; // Log bits
|
|
||||||
register int32 sx = x; // Treat as signed number
|
|
||||||
while( sx >= 0 ) // While high bit is clear
|
|
||||||
sx <<= 1, l--; // Shift bits left, count down log2
|
|
||||||
return l;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
//------------------------------print------------------------------------------
|
|
||||||
// Print a pointer without modifying the contents
|
|
||||||
#ifdef __TURBOC__
|
|
||||||
ostream &ostream::operator << (const void *ptr)
|
|
||||||
{
|
|
||||||
return (*this) << "0x" << hex << (uint)ptr << dec;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
/*ostream &operator << (ostream &os, const void *ptr)
|
|
||||||
{
|
|
||||||
return os << "0x" << hex << (uint)ptr << dec;
|
|
||||||
}*/
|
|
||||||
#endif
|
|
|
@ -1,208 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 1997, 2013, 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_LIBADT_PORT_HPP
|
|
||||||
#define SHARE_VM_LIBADT_PORT_HPP
|
|
||||||
|
|
||||||
#include "utilities/top.hpp"
|
|
||||||
|
|
||||||
// Typedefs for portable compiling
|
|
||||||
|
|
||||||
#if defined(__GNUC__)
|
|
||||||
|
|
||||||
#define INTERFACE #pragma interface
|
|
||||||
#define IMPLEMENTATION #pragma implementation
|
|
||||||
//INTERFACE
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
// Access to the C++ class virtual function pointer
|
|
||||||
// Put the class in the macro
|
|
||||||
typedef void *VPTR;
|
|
||||||
// G++ puts it at the end of the base class
|
|
||||||
#define ACCESS_VPTR(class) VPTR&vptr(){return*(VPTR*)((char*)this+sizeof(class)-sizeof(void*));}
|
|
||||||
|
|
||||||
#elif defined(__TURBOC__)
|
|
||||||
|
|
||||||
#include <mem.h>
|
|
||||||
#include <string.h>
|
|
||||||
extern "C" int stricmp(const char *, const char *);
|
|
||||||
inline void bcopy(const void *s, void *d, int l) { memmove(d,s,l); }
|
|
||||||
inline void bzero(void *p, int l) { memset(p,0,l); }
|
|
||||||
inline int bcmp(const void *s, const void *d, int l) { return memcmp(s,d,l); }
|
|
||||||
inline int min( int a, int b) { return a < b ? a : b; }
|
|
||||||
inline int max( int a, int b) { return a > b ? a : b; }
|
|
||||||
//strcasecmp moved to globalDefinitions_visCPP.hpp
|
|
||||||
//inline int strcasecmp(const char *s1, const char *s2) { return stricmp(s1,s2); }
|
|
||||||
inline long abs( long x ) { return x < 0 ? -x : x; }
|
|
||||||
// Access to the C++ class virtual function pointer
|
|
||||||
// Put the class in the macro
|
|
||||||
typedef void near *VPTR;
|
|
||||||
// BorlandC puts it up front
|
|
||||||
#define ACCESS_VPTR(class) VPTR&vptr(){return*(VPTR*)this;}
|
|
||||||
|
|
||||||
#elif defined(__hpux)
|
|
||||||
|
|
||||||
#define INTERFACE
|
|
||||||
#define IMPLEMENTATION
|
|
||||||
#define signed
|
|
||||||
#include <strings.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
inline long min( long a, long b) { return a < b ? a : b; }
|
|
||||||
inline long max( long a, long b) { return a > b ? a : b; }
|
|
||||||
inline int min( int a, int b) { return a < b ? a : b; }
|
|
||||||
inline int max( int a, int b) { return a > b ? a : b; }
|
|
||||||
inline long abs( long x ) { return x < 0 ? -x : x; }
|
|
||||||
|
|
||||||
#elif defined(__MOTO__)
|
|
||||||
// Motorola's mcc
|
|
||||||
#define INTERFACE
|
|
||||||
#define IMPLEMENTATION
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <memory.h>
|
|
||||||
inline int min( int a, int b) { return a < b ? a : b; }
|
|
||||||
inline int max( int a, int b) { return a > b ? a : b; }
|
|
||||||
|
|
||||||
#elif defined(_AIX)
|
|
||||||
// IBM's xlC compiler
|
|
||||||
#define INTERFACE
|
|
||||||
#define IMPLEMENTATION
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <memory.h>
|
|
||||||
|
|
||||||
#elif defined(_MSC_VER)
|
|
||||||
// Microsoft Visual C++
|
|
||||||
//#define INTERFACE
|
|
||||||
#define IMPLEMENTATION
|
|
||||||
#include <stdlib.h>
|
|
||||||
#undef small
|
|
||||||
//strcasecmp moved to globalDefinitions_visCPP.hpp
|
|
||||||
//inline int strcasecmp(const char *s1, const char *s2) { return stricmp(s1,s2); }
|
|
||||||
|
|
||||||
|
|
||||||
#elif defined(SPARC_WORKS)
|
|
||||||
|
|
||||||
#define INTERFACE
|
|
||||||
#define IMPLEMENTATION
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#elif defined(SOLARIS)
|
|
||||||
|
|
||||||
#define INTERFACE
|
|
||||||
#define IMPLEMENTATION
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
|
|
||||||
#elif defined(__TANDEM)
|
|
||||||
|
|
||||||
// This case is for the Tandem Business Unit of Compaq Computer Corporation.
|
|
||||||
// The Tandem case must precede the AT&T case,
|
|
||||||
// because the Tandem c89 compiler also defines __cplusplus.
|
|
||||||
|
|
||||||
#include "port_tandem.hpp"
|
|
||||||
|
|
||||||
#elif defined(__cplusplus)
|
|
||||||
// AT&Ts cfront
|
|
||||||
#define INTERFACE
|
|
||||||
#define IMPLEMENTATION
|
|
||||||
#include <unistd.h>
|
|
||||||
#define signed
|
|
||||||
// #include <bstring.h>
|
|
||||||
inline int min( int a, int b) { return a < b ? a : b; }
|
|
||||||
inline int max( int a, int b) { return a > b ? a : b; }
|
|
||||||
|
|
||||||
#else // All other machines
|
|
||||||
|
|
||||||
#define signed
|
|
||||||
extern "C" void bcopy(void *b1, void *b2, int len);
|
|
||||||
inline int min( int a, int b) { return a < b ? a : b; }
|
|
||||||
inline int max( int a, int b) { return a > b ? a : b; }
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Safer memory allocations
|
|
||||||
#ifdef SAFE_MEMORY
|
|
||||||
#define malloc(size) safe_malloc(__FILE__,__LINE__,size)
|
|
||||||
#define free(ptr) safe_free(__FILE__,__LINE__,ptr)
|
|
||||||
#define realloc(ptr,size) safe_realloc(__FILE__,__LINE__,ptr,size)
|
|
||||||
#define calloc(nitems,size) safe_calloc(__FILE__,__LINE__,nitems,size)
|
|
||||||
#define strdup(ptr) safe_strdup(__FILE__,__LINE__,ptr)
|
|
||||||
extern void *safe_malloc (const char *file, unsigned line, unsigned size);
|
|
||||||
extern void safe_free (const char *file, unsigned line, void *ptr);
|
|
||||||
extern void *safe_calloc (const char *file, unsigned line, unsigned nitems, unsigned size);
|
|
||||||
extern void *safe_realloc(const char *file, unsigned line, void *ptr, unsigned size);
|
|
||||||
extern char *safe_strdup (const char *file, unsigned line, const char *src);
|
|
||||||
inline void *operator new( size_t size ) throw() { return malloc(size); }
|
|
||||||
inline void operator delete( void *ptr ) { free(ptr); }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// And now, the bit-size-specified integer sizes
|
|
||||||
typedef signed char int8;
|
|
||||||
typedef unsigned char uint8;
|
|
||||||
typedef unsigned char byte;
|
|
||||||
|
|
||||||
// All uses of *int16 changed to 32-bit to speed up compiler on Intel
|
|
||||||
//typedef signed short int16; // Exactly 16bits signed
|
|
||||||
//typedef unsigned short uint16; // Exactly 16bits unsigned
|
|
||||||
//const unsigned int min_uint16 = 0x0000; // smallest uint16
|
|
||||||
//const unsigned int max_uint16 = 0xFFFF; // largest uint16
|
|
||||||
|
|
||||||
typedef unsigned int uint; // When you need a fast >=16bit unsigned value
|
|
||||||
/*typedef int int; */ // When you need a fast >=16bit value
|
|
||||||
const unsigned int max_uint = (uint)-1;
|
|
||||||
typedef int32_t int32; // Exactly 32bits signed
|
|
||||||
typedef uint32_t uint32; // Exactly 32bits unsigned
|
|
||||||
|
|
||||||
// Bit-sized floating point and long thingies
|
|
||||||
#ifndef __TANDEM
|
|
||||||
// Do not define these for Tandem, because they conflict with typedefs in softieee.h.
|
|
||||||
typedef float float32; // 32-bit float
|
|
||||||
typedef double float64; // 64-bit float
|
|
||||||
#endif // __TANDEM
|
|
||||||
|
|
||||||
typedef jlong int64; // Java long for my 64-bit type
|
|
||||||
typedef julong uint64; // Java long for my 64-bit type
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Nice constants
|
|
||||||
uint32 gcd( uint32 x, uint32 y );
|
|
||||||
int ff1( uint32 mask );
|
|
||||||
int fh1( uint32 mask );
|
|
||||||
uint32 rotate32( uint32 x, int32 cnt );
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
extern uint32 heap_totalmem; // Current total memory allocation
|
|
||||||
extern uint32 heap_highwater; // Highwater mark to date for memory usage
|
|
||||||
|
|
||||||
#endif // SHARE_VM_LIBADT_PORT_HPP
|
|
|
@ -28,20 +28,11 @@
|
||||||
|
|
||||||
// Sets - An Abstract Data Type
|
// Sets - An Abstract Data Type
|
||||||
|
|
||||||
// %%%%% includes not needed with AVM framework - Ungar
|
|
||||||
// #include "port.hpp"
|
|
||||||
//IMPLEMENTATION
|
|
||||||
// #include "set.hpp"
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
// Not needed and it causes terouble for gcc.
|
|
||||||
//
|
|
||||||
// #include <iostream.h>
|
|
||||||
|
|
||||||
//-------------------------Virtual Functions-----------------------------------
|
//-------------------------Virtual Functions-----------------------------------
|
||||||
// These functions MUST be implemented by the inheriting class.
|
// These functions MUST be implemented by the inheriting class.
|
||||||
class SparseSet;
|
class SparseSet;
|
||||||
|
|
|
@ -25,13 +25,10 @@
|
||||||
#ifndef SHARE_VM_LIBADT_SET_HPP
|
#ifndef SHARE_VM_LIBADT_SET_HPP
|
||||||
#define SHARE_VM_LIBADT_SET_HPP
|
#define SHARE_VM_LIBADT_SET_HPP
|
||||||
|
|
||||||
#include "libadt/port.hpp"
|
|
||||||
#include "memory/allocation.hpp"
|
#include "memory/allocation.hpp"
|
||||||
|
|
||||||
// Sets - An Abstract Data Type
|
// Sets - An Abstract Data Type
|
||||||
|
|
||||||
//INTERFACE
|
|
||||||
|
|
||||||
class SparseSet;
|
class SparseSet;
|
||||||
class VectorSet;
|
class VectorSet;
|
||||||
class ListSet;
|
class ListSet;
|
||||||
|
|
|
@ -28,15 +28,10 @@
|
||||||
|
|
||||||
// Vector Sets - An Abstract Data Type
|
// Vector Sets - An Abstract Data Type
|
||||||
|
|
||||||
// %%%%% includes not needed with AVM framework - Ungar
|
|
||||||
// #include "port.hpp"
|
|
||||||
//IMPLEMENTATION
|
|
||||||
// #include "vectset.hpp"
|
|
||||||
|
|
||||||
// BitsInByte is a lookup table which tells the number of bits that
|
// BitsInByte is a lookup table which tells the number of bits that
|
||||||
// are in the looked-up number. It is very useful in VectorSet_Size.
|
// are in the looked-up number. It is very useful in VectorSet_Size.
|
||||||
|
|
||||||
uint8 bitsInByte[256] = {
|
uint8_t bitsInByte[256] = {
|
||||||
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
|
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
|
||||||
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
|
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
|
||||||
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
|
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
|
||||||
|
@ -59,7 +54,7 @@ uint8 bitsInByte[256] = {
|
||||||
// Create a new, empty Set.
|
// Create a new, empty Set.
|
||||||
VectorSet::VectorSet(Arena *arena) : Set(arena) {
|
VectorSet::VectorSet(Arena *arena) : Set(arena) {
|
||||||
size = 2; // Small initial size
|
size = 2; // Small initial size
|
||||||
data = (uint32 *)_set_arena->Amalloc(size*sizeof(uint32));
|
data = (uint32_t *)_set_arena->Amalloc(size*sizeof(uint32_t));
|
||||||
data[0] = 0; // No elements
|
data[0] = 0; // No elements
|
||||||
data[1] = 0;
|
data[1] = 0;
|
||||||
}
|
}
|
||||||
|
@ -85,8 +80,8 @@ Set &VectorSet::operator = (const Set &set)
|
||||||
void VectorSet::slamin(const VectorSet& s)
|
void VectorSet::slamin(const VectorSet& s)
|
||||||
{
|
{
|
||||||
size = s.size; // Use new size
|
size = s.size; // Use new size
|
||||||
data = (uint32*)s._set_arena->Amalloc(size*sizeof(uint32)); // Make array of required size
|
data = (uint32_t*)s._set_arena->Amalloc(size*sizeof(uint32_t)); // Make array of required size
|
||||||
memcpy( data, s.data, size*sizeof(uint32) ); // Fill the array
|
memcpy( data, s.data, size*sizeof(uint32_t) ); // Fill the array
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------grow-------------------------------------------
|
//------------------------------grow-------------------------------------------
|
||||||
|
@ -96,8 +91,8 @@ void VectorSet::grow( uint newsize )
|
||||||
newsize = (newsize+31) >> 5; // Convert to longwords
|
newsize = (newsize+31) >> 5; // Convert to longwords
|
||||||
uint x = size;
|
uint x = size;
|
||||||
while( x < newsize ) x <<= 1;
|
while( x < newsize ) x <<= 1;
|
||||||
data = (uint32 *)_set_arena->Arealloc(data, size*sizeof(uint32), x*sizeof(uint32));
|
data = (uint32_t *)_set_arena->Arealloc(data, size*sizeof(uint32_t), x*sizeof(uint32_t));
|
||||||
memset((char *)(data + size), 0, (x - size)*sizeof(uint32));
|
memset((char *)(data + size), 0, (x - size)*sizeof(uint32_t));
|
||||||
size = x;
|
size = x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,7 +101,7 @@ void VectorSet::grow( uint newsize )
|
||||||
Set &VectorSet::operator <<= (uint elem)
|
Set &VectorSet::operator <<= (uint elem)
|
||||||
{
|
{
|
||||||
register uint word = elem >> 5; // Get the longword offset
|
register uint word = elem >> 5; // Get the longword offset
|
||||||
register uint32 mask = 1L << (elem & 31); // Get bit mask
|
register uint32_t mask = 1L << (elem & 31); // Get bit mask
|
||||||
|
|
||||||
if( word >= size ) // Need to grow set?
|
if( word >= size ) // Need to grow set?
|
||||||
grow(elem+1); // Then grow it
|
grow(elem+1); // Then grow it
|
||||||
|
@ -121,7 +116,7 @@ Set &VectorSet::operator >>= (uint elem)
|
||||||
register uint word = elem >> 5; // Get the longword offset
|
register uint word = elem >> 5; // Get the longword offset
|
||||||
if( word >= size ) // Beyond the last?
|
if( word >= size ) // Beyond the last?
|
||||||
return *this; // Then it's clear & return clear
|
return *this; // Then it's clear & return clear
|
||||||
register uint32 mask = 1L << (elem & 31); // Get bit mask
|
register uint32_t mask = 1L << (elem & 31); // Get bit mask
|
||||||
data[word] &= ~mask; // Clear bit
|
data[word] &= ~mask; // Clear bit
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -132,8 +127,8 @@ VectorSet &VectorSet::operator &= (const VectorSet &s)
|
||||||
{
|
{
|
||||||
// NOTE: The intersection is never any larger than the smallest set.
|
// NOTE: The intersection is never any larger than the smallest set.
|
||||||
if( s.size < size ) size = s.size; // Get smaller size
|
if( s.size < size ) size = s.size; // Get smaller size
|
||||||
register uint32 *u1 = data; // Pointer to the destination data
|
register uint32_t *u1 = data; // Pointer to the destination data
|
||||||
register uint32 *u2 = s.data; // Pointer to the source data
|
register uint32_t *u2 = s.data; // Pointer to the source data
|
||||||
for( uint i=0; i<size; i++) // For data in set
|
for( uint i=0; i<size; i++) // For data in set
|
||||||
*u1++ &= *u2++; // Copy and AND longwords
|
*u1++ &= *u2++; // Copy and AND longwords
|
||||||
return *this; // Return set
|
return *this; // Return set
|
||||||
|
@ -152,14 +147,14 @@ VectorSet &VectorSet::operator |= (const VectorSet &s)
|
||||||
{
|
{
|
||||||
// This many words must be unioned
|
// This many words must be unioned
|
||||||
register uint cnt = ((size<s.size)?size:s.size);
|
register uint cnt = ((size<s.size)?size:s.size);
|
||||||
register uint32 *u1 = data; // Pointer to the destination data
|
register uint32_t *u1 = data; // Pointer to the destination data
|
||||||
register uint32 *u2 = s.data; // Pointer to the source data
|
register uint32_t *u2 = s.data; // Pointer to the source data
|
||||||
for( uint i=0; i<cnt; i++) // Copy and OR the two sets
|
for( uint i=0; i<cnt; i++) // Copy and OR the two sets
|
||||||
*u1++ |= *u2++;
|
*u1++ |= *u2++;
|
||||||
if( size < s.size ) { // Is set 2 larger than set 1?
|
if( size < s.size ) { // Is set 2 larger than set 1?
|
||||||
// Extend result by larger set
|
// Extend result by larger set
|
||||||
grow(s.size*sizeof(uint32)*8);
|
grow(s.size*sizeof(uint32_t)*8);
|
||||||
memcpy(&data[cnt], u2, (s.size - cnt)*sizeof(uint32));
|
memcpy(&data[cnt], u2, (s.size - cnt)*sizeof(uint32_t));
|
||||||
}
|
}
|
||||||
return *this; // Return result set
|
return *this; // Return result set
|
||||||
}
|
}
|
||||||
|
@ -177,8 +172,8 @@ VectorSet &VectorSet::operator -= (const VectorSet &s)
|
||||||
{
|
{
|
||||||
// This many words must be unioned
|
// This many words must be unioned
|
||||||
register uint cnt = ((size<s.size)?size:s.size);
|
register uint cnt = ((size<s.size)?size:s.size);
|
||||||
register uint32 *u1 = data; // Pointer to the destination data
|
register uint32_t *u1 = data; // Pointer to the destination data
|
||||||
register uint32 *u2 = s.data; // Pointer to the source data
|
register uint32_t *u2 = s.data; // Pointer to the source data
|
||||||
for( uint i=0; i<cnt; i++ ) // For data in set
|
for( uint i=0; i<cnt; i++ ) // For data in set
|
||||||
*u1++ &= ~(*u2++); // A <-- A & ~B with longwords
|
*u1++ &= ~(*u2++); // A <-- A & ~B with longwords
|
||||||
return *this; // Return new set
|
return *this; // Return new set
|
||||||
|
@ -199,17 +194,17 @@ Set &VectorSet::operator -= (const Set &set)
|
||||||
// 1X -- B is a subset of A
|
// 1X -- B is a subset of A
|
||||||
int VectorSet::compare (const VectorSet &s) const
|
int VectorSet::compare (const VectorSet &s) const
|
||||||
{
|
{
|
||||||
register uint32 *u1 = data; // Pointer to the destination data
|
register uint32_t *u1 = data; // Pointer to the destination data
|
||||||
register uint32 *u2 = s.data; // Pointer to the source data
|
register uint32_t *u2 = s.data; // Pointer to the source data
|
||||||
register uint32 AnotB = 0, BnotA = 0;
|
register uint32_t AnotB = 0, BnotA = 0;
|
||||||
// This many words must be unioned
|
// This many words must be unioned
|
||||||
register uint cnt = ((size<s.size)?size:s.size);
|
register uint cnt = ((size<s.size)?size:s.size);
|
||||||
|
|
||||||
// Get bits for both sets
|
// Get bits for both sets
|
||||||
uint i; // Exit value of loop
|
uint i; // Exit value of loop
|
||||||
for( i=0; i<cnt; i++ ) { // For data in BOTH sets
|
for( i=0; i<cnt; i++ ) { // For data in BOTH sets
|
||||||
register uint32 A = *u1++; // Data from one guy
|
register uint32_t A = *u1++; // Data from one guy
|
||||||
register uint32 B = *u2++; // Data from other guy
|
register uint32_t B = *u2++; // Data from other guy
|
||||||
AnotB |= (A & ~B); // Compute bits in A not B
|
AnotB |= (A & ~B); // Compute bits in A not B
|
||||||
BnotA |= (B & ~A); // Compute bits in B not A
|
BnotA |= (B & ~A); // Compute bits in B not A
|
||||||
}
|
}
|
||||||
|
@ -250,8 +245,8 @@ int VectorSet::disjoint(const Set &set) const
|
||||||
|
|
||||||
// NOTE: The intersection is never any larger than the smallest set.
|
// NOTE: The intersection is never any larger than the smallest set.
|
||||||
register uint small_size = ((size<s.size)?size:s.size);
|
register uint small_size = ((size<s.size)?size:s.size);
|
||||||
register uint32 *u1 = data; // Pointer to the destination data
|
register uint32_t *u1 = data; // Pointer to the destination data
|
||||||
register uint32 *u2 = s.data; // Pointer to the source data
|
register uint32_t *u2 = s.data; // Pointer to the source data
|
||||||
for( uint i=0; i<small_size; i++) // For data in set
|
for( uint i=0; i<small_size; i++) // For data in set
|
||||||
if( *u1++ & *u2++ ) // If any elements in common
|
if( *u1++ & *u2++ ) // If any elements in common
|
||||||
return 0; // Then not disjoint
|
return 0; // Then not disjoint
|
||||||
|
@ -293,7 +288,7 @@ int VectorSet::operator[](uint elem) const
|
||||||
register uint word = elem >> 5; // Get the longword offset
|
register uint word = elem >> 5; // Get the longword offset
|
||||||
if( word >= size ) // Beyond the last?
|
if( word >= size ) // Beyond the last?
|
||||||
return 0; // Then it's clear
|
return 0; // Then it's clear
|
||||||
register uint32 mask = 1L << (elem & 31); // Get bit mask
|
register uint32_t mask = 1L << (elem & 31); // Get bit mask
|
||||||
return ((data[word] & mask))!=0; // Return the sense of the bit
|
return ((data[word] & mask))!=0; // Return the sense of the bit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -305,7 +300,7 @@ uint VectorSet::getelem(void) const
|
||||||
for( i=0; i<size; i++ )
|
for( i=0; i<size; i++ )
|
||||||
if( data[i] )
|
if( data[i] )
|
||||||
break;
|
break;
|
||||||
uint32 word = data[i];
|
uint32_t word = data[i];
|
||||||
int j; // Exit value of loop
|
int j; // Exit value of loop
|
||||||
for( j= -1; word; j++, word>>=1 );
|
for( j= -1; word; j++, word>>=1 );
|
||||||
return (i<<5)+j;
|
return (i<<5)+j;
|
||||||
|
@ -316,11 +311,11 @@ uint VectorSet::getelem(void) const
|
||||||
void VectorSet::Clear(void)
|
void VectorSet::Clear(void)
|
||||||
{
|
{
|
||||||
if( size > 100 ) { // Reclaim storage only if huge
|
if( size > 100 ) { // Reclaim storage only if huge
|
||||||
FREE_RESOURCE_ARRAY(uint32,data,size);
|
FREE_RESOURCE_ARRAY(uint32_t,data,size);
|
||||||
size = 2; // Small initial size
|
size = 2; // Small initial size
|
||||||
data = NEW_RESOURCE_ARRAY(uint32,size);
|
data = NEW_RESOURCE_ARRAY(uint32_t,size);
|
||||||
}
|
}
|
||||||
memset( data, 0, size*sizeof(uint32) );
|
memset( data, 0, size*sizeof(uint32_t) );
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------Size-------------------------------------------
|
//------------------------------Size-------------------------------------------
|
||||||
|
@ -328,8 +323,8 @@ void VectorSet::Clear(void)
|
||||||
uint VectorSet::Size(void) const
|
uint VectorSet::Size(void) const
|
||||||
{
|
{
|
||||||
uint sum = 0; // Cumulative size so far.
|
uint sum = 0; // Cumulative size so far.
|
||||||
uint8 *currByte = (uint8*)data;
|
uint8_t* currByte = (uint8_t*) data;
|
||||||
for( uint32 i = 0; i < (size<<2); i++) // While have bytes to process
|
for( uint32_t i = 0; i < (size<<2); i++) // While have bytes to process
|
||||||
sum += bitsInByte[*currByte++]; // Add bits in current byte to size.
|
sum += bitsInByte[*currByte++]; // Add bits in current byte to size.
|
||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
@ -343,7 +338,7 @@ void VectorSet::Sort(void)
|
||||||
//------------------------------hash-------------------------------------------
|
//------------------------------hash-------------------------------------------
|
||||||
int VectorSet::hash() const
|
int VectorSet::hash() const
|
||||||
{
|
{
|
||||||
uint32 _xor = 0;
|
uint32_t _xor = 0;
|
||||||
uint lim = ((size<4)?size:4);
|
uint lim = ((size<4)?size:4);
|
||||||
for( uint i = 0; i < lim; i++ )
|
for( uint i = 0; i < lim; i++ )
|
||||||
_xor ^= data[i];
|
_xor ^= data[i];
|
||||||
|
|
|
@ -47,7 +47,7 @@ class VectorSet : public Set {
|
||||||
friend class VectorSetI; // Friendly iterator class
|
friend class VectorSetI; // Friendly iterator class
|
||||||
protected:
|
protected:
|
||||||
uint size; // Size of data IN LONGWORDS (32bits)
|
uint size; // Size of data IN LONGWORDS (32bits)
|
||||||
uint32 *data; // The data, bit packed
|
uint32_t* data; // The data, bit packed
|
||||||
|
|
||||||
void slamin( const VectorSet& s ); // Initialize one set with another
|
void slamin( const VectorSet& s ); // Initialize one set with another
|
||||||
int compare(const VectorSet &s) const; // Compare set contents
|
int compare(const VectorSet &s) const; // Compare set contents
|
||||||
|
@ -99,7 +99,7 @@ public:
|
||||||
void Sort(void); // Sort before iterating
|
void Sort(void); // Sort before iterating
|
||||||
int hash() const; // Hash function
|
int hash() const; // Hash function
|
||||||
void Reset(void) { // Reset a set
|
void Reset(void) { // Reset a set
|
||||||
memset( data, 0, size*sizeof(uint32) );
|
memset( data, 0, size*sizeof(uint32_t) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Removed for MCC BUG
|
/* Removed for MCC BUG
|
||||||
|
@ -108,7 +108,7 @@ public:
|
||||||
|
|
||||||
// Expose internals for speed-critical fast iterators
|
// Expose internals for speed-critical fast iterators
|
||||||
uint word_size() const { return size; }
|
uint word_size() const { return size; }
|
||||||
uint32 *EXPOSE() const { return data; }
|
uint32_t* EXPOSE() const { return data; }
|
||||||
|
|
||||||
// Fast inlined "test and set". Replaces the idiom:
|
// Fast inlined "test and set". Replaces the idiom:
|
||||||
// if( visited[idx] ) return;
|
// if( visited[idx] ) return;
|
||||||
|
@ -120,8 +120,8 @@ public:
|
||||||
uint word = elem >> 5; // Get the longword offset
|
uint word = elem >> 5; // Get the longword offset
|
||||||
if( word >= size ) // Beyond the last?
|
if( word >= size ) // Beyond the last?
|
||||||
return test_set_grow(elem); // Then grow; set; return 0;
|
return test_set_grow(elem); // Then grow; set; return 0;
|
||||||
uint32 mask = 1L << (elem & 31); // Get bit mask
|
uint32_t mask = 1L << (elem & 31); // Get bit mask
|
||||||
uint32 datum = data[word] & mask;// Get bit
|
uint32_t datum = data[word] & mask;// Get bit
|
||||||
data[word] |= mask; // Set bit
|
data[word] |= mask; // Set bit
|
||||||
return datum; // Return bit
|
return datum; // Return bit
|
||||||
}
|
}
|
||||||
|
@ -134,7 +134,7 @@ public:
|
||||||
int test( uint elem ) const {
|
int test( uint elem ) const {
|
||||||
uint word = elem >> 5; // Get the longword offset
|
uint word = elem >> 5; // Get the longword offset
|
||||||
if( word >= size ) return 0; // Beyond the last?
|
if( word >= size ) return 0; // Beyond the last?
|
||||||
uint32 mask = 1L << (elem & 31); // Get bit mask
|
uint32_t mask = 1L << (elem & 31); // Get bit mask
|
||||||
return data[word] & mask; // Get bit
|
return data[word] & mask; // Get bit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,7 +144,7 @@ public:
|
||||||
if( word >= size ) { // Beyond the last?
|
if( word >= size ) { // Beyond the last?
|
||||||
test_set_grow(elem); // Then grow and set
|
test_set_grow(elem); // Then grow and set
|
||||||
} else {
|
} else {
|
||||||
uint32 mask = 1L << (elem & 31); // Get bit mask
|
uint32_t mask = 1L << (elem & 31); // Get bit mask
|
||||||
data[word] |= mask; // Set bit
|
data[word] |= mask; // Set bit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -164,7 +164,7 @@ class VectorSetI : public StackObj {
|
||||||
friend class VectorSet;
|
friend class VectorSet;
|
||||||
const VectorSet *s;
|
const VectorSet *s;
|
||||||
uint i, j;
|
uint i, j;
|
||||||
uint32 mask;
|
uint32_t mask;
|
||||||
uint next(void);
|
uint next(void);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -686,40 +686,57 @@ void* Arena::internal_malloc_4(size_t x) {
|
||||||
// a memory leak. Use CHeapObj as the base class of such objects to make it explicit
|
// a memory leak. Use CHeapObj as the base class of such objects to make it explicit
|
||||||
// that they're allocated on the C heap.
|
// that they're allocated on the C heap.
|
||||||
// Commented out in product version to avoid conflicts with third-party C++ native code.
|
// Commented out in product version to avoid conflicts with third-party C++ native code.
|
||||||
// On certain platforms, such as Mac OS X (Darwin), in debug version, new is being called
|
|
||||||
// from jdk source and causing data corruption. Such as
|
|
||||||
// Java_sun_security_ec_ECKeyPairGenerator_generateECKeyPair
|
|
||||||
// define ALLOW_OPERATOR_NEW_USAGE for platform on which global operator new allowed.
|
|
||||||
//
|
//
|
||||||
#ifndef ALLOW_OPERATOR_NEW_USAGE
|
// In C++98/03 the throwing new operators are defined with the following signature:
|
||||||
void* operator new(size_t size) throw() {
|
//
|
||||||
assert(false, "Should not call global operator new");
|
// void* operator new(std::size_tsize) throw(std::bad_alloc);
|
||||||
|
// void* operator new[](std::size_tsize) throw(std::bad_alloc);
|
||||||
|
//
|
||||||
|
// while all the other (non-throwing) new and delete operators are defined with an empty
|
||||||
|
// throw clause (i.e. "operator delete(void* p) throw()") which means that they do not
|
||||||
|
// throw any exceptions (see section 18.4 of the C++ standard).
|
||||||
|
//
|
||||||
|
// In the new C++11/14 standard, the signature of the throwing new operators was changed
|
||||||
|
// by completely omitting the throw clause (which effectively means they could throw any
|
||||||
|
// exception) while all the other new/delete operators where changed to have a 'nothrow'
|
||||||
|
// clause instead of an empty throw clause.
|
||||||
|
//
|
||||||
|
// Unfortunately, the support for exception specifications among C++ compilers is still
|
||||||
|
// very fragile. While some more strict compilers like AIX xlC or HP aCC reject to
|
||||||
|
// override the default throwing new operator with a user operator with an empty throw()
|
||||||
|
// clause, the MS Visual C++ compiler warns for every non-empty throw clause like
|
||||||
|
// throw(std::bad_alloc) that it will ignore the exception specification. The following
|
||||||
|
// operator definitions have been checked to correctly work with all currently supported
|
||||||
|
// compilers and they should be upwards compatible with C++11/14. Therefore
|
||||||
|
// PLEASE BE CAREFUL if you change the signature of the following operators!
|
||||||
|
|
||||||
|
void* operator new(size_t size) /* throw(std::bad_alloc) */ {
|
||||||
|
fatal("Should not call global operator new");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* operator new [](size_t size) throw() {
|
void* operator new [](size_t size) /* throw(std::bad_alloc) */ {
|
||||||
assert(false, "Should not call global operator new[]");
|
fatal("Should not call global operator new[]");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* operator new(size_t size, const std::nothrow_t& nothrow_constant) throw() {
|
void* operator new(size_t size, const std::nothrow_t& nothrow_constant) throw() {
|
||||||
assert(false, "Should not call global operator new");
|
fatal("Should not call global operator new");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* operator new [](size_t size, std::nothrow_t& nothrow_constant) throw() {
|
void* operator new [](size_t size, std::nothrow_t& nothrow_constant) throw() {
|
||||||
assert(false, "Should not call global operator new[]");
|
fatal("Should not call global operator new[]");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator delete(void* p) {
|
void operator delete(void* p) throw() {
|
||||||
assert(false, "Should not call global delete");
|
fatal("Should not call global delete");
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator delete [](void* p) {
|
void operator delete [](void* p) throw() {
|
||||||
assert(false, "Should not call global delete []");
|
fatal("Should not call global delete []");
|
||||||
}
|
}
|
||||||
#endif // ALLOW_OPERATOR_NEW_USAGE
|
|
||||||
|
|
||||||
void AllocatedObj::print() const { print_on(tty); }
|
void AllocatedObj::print() const { print_on(tty); }
|
||||||
void AllocatedObj::print_value() const { print_value_on(tty); }
|
void AllocatedObj::print_value() const { print_value_on(tty); }
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "classfile/javaClasses.hpp"
|
#include "classfile/javaClasses.hpp"
|
||||||
#include "classfile/symbolTable.hpp"
|
#include "classfile/stringTable.hpp"
|
||||||
#include "classfile/systemDictionary.hpp"
|
#include "classfile/systemDictionary.hpp"
|
||||||
#include "classfile/vmSymbols.hpp"
|
#include "classfile/vmSymbols.hpp"
|
||||||
#include "code/codeCache.hpp"
|
#include "code/codeCache.hpp"
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "classfile/symbolTable.hpp"
|
#include "classfile/stringTable.hpp"
|
||||||
#include "classfile/systemDictionary.hpp"
|
#include "classfile/systemDictionary.hpp"
|
||||||
#include "code/codeCache.hpp"
|
#include "code/codeCache.hpp"
|
||||||
#include "gc_interface/collectedHeap.inline.hpp"
|
#include "gc_interface/collectedHeap.inline.hpp"
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
#include "classfile/classLoader.hpp"
|
#include "classfile/classLoader.hpp"
|
||||||
#include "classfile/classLoaderData.hpp"
|
#include "classfile/classLoaderData.hpp"
|
||||||
#include "classfile/javaClasses.hpp"
|
#include "classfile/javaClasses.hpp"
|
||||||
#include "classfile/symbolTable.hpp"
|
#include "classfile/stringTable.hpp"
|
||||||
#include "classfile/systemDictionary.hpp"
|
#include "classfile/systemDictionary.hpp"
|
||||||
#include "classfile/vmSymbols.hpp"
|
#include "classfile/vmSymbols.hpp"
|
||||||
#include "code/codeCache.hpp"
|
#include "code/codeCache.hpp"
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
#include "classfile/classLoaderData.hpp"
|
#include "classfile/classLoaderData.hpp"
|
||||||
#include "classfile/javaClasses.hpp"
|
#include "classfile/javaClasses.hpp"
|
||||||
#include "classfile/metadataOnStackMark.hpp"
|
#include "classfile/metadataOnStackMark.hpp"
|
||||||
#include "classfile/symbolTable.hpp"
|
#include "classfile/stringTable.hpp"
|
||||||
#include "classfile/systemDictionary.hpp"
|
#include "classfile/systemDictionary.hpp"
|
||||||
#include "classfile/vmSymbols.hpp"
|
#include "classfile/vmSymbols.hpp"
|
||||||
#include "interpreter/linkResolver.hpp"
|
#include "interpreter/linkResolver.hpp"
|
||||||
|
|
|
@ -1268,7 +1268,6 @@ void UnionFind::extend( uint from_idx, uint to_idx ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnionFind::reset( uint max ) {
|
void UnionFind::reset( uint max ) {
|
||||||
assert( max <= max_uint, "Must fit within uint" );
|
|
||||||
// Force the Union-Find mapping to be at least this large
|
// Force the Union-Find mapping to be at least this large
|
||||||
extend(max,0);
|
extend(max,0);
|
||||||
// Initialize to be the ID mapping.
|
// Initialize to be the ID mapping.
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
#define SHARE_VM_OPTO_CHAITIN_HPP
|
#define SHARE_VM_OPTO_CHAITIN_HPP
|
||||||
|
|
||||||
#include "code/vmreg.hpp"
|
#include "code/vmreg.hpp"
|
||||||
#include "libadt/port.hpp"
|
|
||||||
#include "memory/resourceArea.hpp"
|
#include "memory/resourceArea.hpp"
|
||||||
#include "opto/connode.hpp"
|
#include "opto/connode.hpp"
|
||||||
#include "opto/live.hpp"
|
#include "opto/live.hpp"
|
||||||
|
@ -142,7 +141,7 @@ public:
|
||||||
|
|
||||||
// Number of registers this live range uses when it colors
|
// Number of registers this live range uses when it colors
|
||||||
private:
|
private:
|
||||||
uint8 _num_regs; // 2 for Longs and Doubles, 1 for all else
|
uint8_t _num_regs; // 2 for Longs and Doubles, 1 for all else
|
||||||
// except _num_regs is kill count for fat_proj
|
// except _num_regs is kill count for fat_proj
|
||||||
public:
|
public:
|
||||||
int num_regs() const { return _num_regs; }
|
int num_regs() const { return _num_regs; }
|
||||||
|
@ -151,7 +150,7 @@ public:
|
||||||
private:
|
private:
|
||||||
// Number of physical registers this live range uses when it colors
|
// Number of physical registers this live range uses when it colors
|
||||||
// Architecture and register-set dependent
|
// Architecture and register-set dependent
|
||||||
uint8 _reg_pressure;
|
uint8_t _reg_pressure;
|
||||||
public:
|
public:
|
||||||
void set_reg_pressure(int i) { _reg_pressure = i; }
|
void set_reg_pressure(int i) { _reg_pressure = i; }
|
||||||
int reg_pressure() const { return _reg_pressure; }
|
int reg_pressure() const { return _reg_pressure; }
|
||||||
|
|
|
@ -32,7 +32,6 @@
|
||||||
#include "compiler/compilerOracle.hpp"
|
#include "compiler/compilerOracle.hpp"
|
||||||
#include "compiler/compileBroker.hpp"
|
#include "compiler/compileBroker.hpp"
|
||||||
#include "libadt/dict.hpp"
|
#include "libadt/dict.hpp"
|
||||||
#include "libadt/port.hpp"
|
|
||||||
#include "libadt/vectset.hpp"
|
#include "libadt/vectset.hpp"
|
||||||
#include "memory/resourceArea.hpp"
|
#include "memory/resourceArea.hpp"
|
||||||
#include "opto/idealGraphPrinter.hpp"
|
#include "opto/idealGraphPrinter.hpp"
|
||||||
|
|
|
@ -514,7 +514,7 @@ const Type *DivINode::Value( PhaseTransform *phase ) const {
|
||||||
int widen = MAX2(i1->_widen, i2->_widen);
|
int widen = MAX2(i1->_widen, i2->_widen);
|
||||||
|
|
||||||
if( i2->is_con() && i2->get_con() != 0 ) {
|
if( i2->is_con() && i2->get_con() != 0 ) {
|
||||||
int32 d = i2->get_con(); // Divisor
|
int32_t d = i2->get_con(); // Divisor
|
||||||
jint lo, hi;
|
jint lo, hi;
|
||||||
if( d >= 0 ) {
|
if( d >= 0 ) {
|
||||||
lo = i1->_lo/d;
|
lo = i1->_lo/d;
|
||||||
|
@ -536,7 +536,7 @@ const Type *DivINode::Value( PhaseTransform *phase ) const {
|
||||||
|
|
||||||
// If the dividend is a constant
|
// If the dividend is a constant
|
||||||
if( i1->is_con() ) {
|
if( i1->is_con() ) {
|
||||||
int32 d = i1->get_con();
|
int32_t d = i1->get_con();
|
||||||
if( d < 0 ) {
|
if( d < 0 ) {
|
||||||
if( d == min_jint ) {
|
if( d == min_jint ) {
|
||||||
// (-min_jint) == min_jint == (min_jint / -1)
|
// (-min_jint) == min_jint == (min_jint / -1)
|
||||||
|
|
|
@ -397,8 +397,9 @@ void PhaseIdealLoop::Dominators() {
|
||||||
ntarjan[i]._control = NULL;
|
ntarjan[i]._control = NULL;
|
||||||
|
|
||||||
// Store the DFS order for the main loop
|
// Store the DFS order for the main loop
|
||||||
|
const uint fill_value = max_juint;
|
||||||
uint *dfsorder = NEW_RESOURCE_ARRAY(uint,C->unique()+1);
|
uint *dfsorder = NEW_RESOURCE_ARRAY(uint,C->unique()+1);
|
||||||
memset(dfsorder, max_uint, (C->unique()+1) * sizeof(uint));
|
memset(dfsorder, fill_value, (C->unique()+1) * sizeof(uint));
|
||||||
|
|
||||||
// Tarjan's algorithm, almost verbatim:
|
// Tarjan's algorithm, almost verbatim:
|
||||||
// Step 1:
|
// Step 1:
|
||||||
|
@ -419,7 +420,7 @@ void PhaseIdealLoop::Dominators() {
|
||||||
if( whead->in(j) == NULL || !whead->in(j)->is_CFG() )
|
if( whead->in(j) == NULL || !whead->in(j)->is_CFG() )
|
||||||
continue; // Only process control nodes
|
continue; // Only process control nodes
|
||||||
uint b = dfsorder[whead->in(j)->_idx];
|
uint b = dfsorder[whead->in(j)->_idx];
|
||||||
if(b == max_uint) continue;
|
if(b == fill_value) continue;
|
||||||
NTarjan *vx = &ntarjan[b];
|
NTarjan *vx = &ntarjan[b];
|
||||||
NTarjan *u = vx->EVAL();
|
NTarjan *u = vx->EVAL();
|
||||||
if( u->_semi < w->_semi )
|
if( u->_semi < w->_semi )
|
||||||
|
|
|
@ -51,7 +51,7 @@ int IndexSet::_serial_count = 1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// What is the first set bit in a 5 bit integer?
|
// What is the first set bit in a 5 bit integer?
|
||||||
const byte IndexSetIterator::_first_bit[32] = {
|
const uint8_t IndexSetIterator::_first_bit[32] = {
|
||||||
0, 0, 1, 0,
|
0, 0, 1, 0,
|
||||||
2, 0, 1, 0,
|
2, 0, 1, 0,
|
||||||
3, 0, 1, 0,
|
3, 0, 1, 0,
|
||||||
|
@ -63,7 +63,7 @@ const byte IndexSetIterator::_first_bit[32] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
// What is the second set bit in a 5 bit integer?
|
// What is the second set bit in a 5 bit integer?
|
||||||
const byte IndexSetIterator::_second_bit[32] = {
|
const uint8_t IndexSetIterator::_second_bit[32] = {
|
||||||
5, 5, 5, 1,
|
5, 5, 5, 1,
|
||||||
5, 2, 2, 1,
|
5, 2, 2, 1,
|
||||||
5, 3, 3, 1,
|
5, 3, 3, 1,
|
||||||
|
@ -298,7 +298,7 @@ IndexSet::IndexSet (IndexSet *set) {
|
||||||
set_block(i, &_empty_block);
|
set_block(i, &_empty_block);
|
||||||
} else {
|
} else {
|
||||||
BitBlock *new_block = alloc_block();
|
BitBlock *new_block = alloc_block();
|
||||||
memcpy(new_block->words(), block->words(), sizeof(uint32) * words_per_block);
|
memcpy(new_block->words(), block->words(), sizeof(uint32_t) * words_per_block);
|
||||||
set_block(i, new_block);
|
set_block(i, new_block);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,12 +106,12 @@ class IndexSet : public ResourceObj {
|
||||||
// is used by IndexSet to mainting this free list.
|
// is used by IndexSet to mainting this free list.
|
||||||
|
|
||||||
union {
|
union {
|
||||||
uint32 _words[words_per_block];
|
uint32_t _words[words_per_block];
|
||||||
BitBlock *_next;
|
BitBlock *_next;
|
||||||
} _data;
|
} _data;
|
||||||
|
|
||||||
// accessors
|
// accessors
|
||||||
uint32 *words() { return _data._words; }
|
uint32_t* words() { return _data._words; }
|
||||||
void set_next(BitBlock *next) { _data._next = next; }
|
void set_next(BitBlock *next) { _data._next = next; }
|
||||||
BitBlock *next() { return _data._next; }
|
BitBlock *next() { return _data._next; }
|
||||||
|
|
||||||
|
@ -120,22 +120,22 @@ class IndexSet : public ResourceObj {
|
||||||
// not assume that the block index has been masked out.
|
// not assume that the block index has been masked out.
|
||||||
|
|
||||||
void clear() {
|
void clear() {
|
||||||
memset(words(), 0, sizeof(uint32) * words_per_block);
|
memset(words(), 0, sizeof(uint32_t) * words_per_block);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool member(uint element) {
|
bool member(uint element) {
|
||||||
uint word_index = IndexSet::get_word_index(element);
|
uint word_index = IndexSet::get_word_index(element);
|
||||||
uint bit_index = IndexSet::get_bit_index(element);
|
uint bit_index = IndexSet::get_bit_index(element);
|
||||||
|
|
||||||
return ((words()[word_index] & (uint32)(0x1 << bit_index)) != 0);
|
return ((words()[word_index] & (uint32_t)(0x1 << bit_index)) != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool insert(uint element) {
|
bool insert(uint element) {
|
||||||
uint word_index = IndexSet::get_word_index(element);
|
uint word_index = IndexSet::get_word_index(element);
|
||||||
uint bit_index = IndexSet::get_bit_index(element);
|
uint bit_index = IndexSet::get_bit_index(element);
|
||||||
|
|
||||||
uint32 bit = (0x1 << bit_index);
|
uint32_t bit = (0x1 << bit_index);
|
||||||
uint32 before = words()[word_index];
|
uint32_t before = words()[word_index];
|
||||||
words()[word_index] = before | bit;
|
words()[word_index] = before | bit;
|
||||||
return ((before & bit) != 0);
|
return ((before & bit) != 0);
|
||||||
}
|
}
|
||||||
|
@ -144,8 +144,8 @@ class IndexSet : public ResourceObj {
|
||||||
uint word_index = IndexSet::get_word_index(element);
|
uint word_index = IndexSet::get_word_index(element);
|
||||||
uint bit_index = IndexSet::get_bit_index(element);
|
uint bit_index = IndexSet::get_bit_index(element);
|
||||||
|
|
||||||
uint32 bit = (0x1 << bit_index);
|
uint32_t bit = (0x1 << bit_index);
|
||||||
uint32 before = words()[word_index];
|
uint32_t before = words()[word_index];
|
||||||
words()[word_index] = before & ~bit;
|
words()[word_index] = before & ~bit;
|
||||||
return ((before & bit) != 0);
|
return ((before & bit) != 0);
|
||||||
}
|
}
|
||||||
|
@ -404,14 +404,14 @@ class IndexSetIterator VALUE_OBJ_CLASS_SPEC {
|
||||||
table_size = (1 << window_size) };
|
table_size = (1 << window_size) };
|
||||||
|
|
||||||
// For an integer of length window_size, what is the first set bit?
|
// For an integer of length window_size, what is the first set bit?
|
||||||
static const byte _first_bit[table_size];
|
static const uint8_t _first_bit[table_size];
|
||||||
|
|
||||||
// For an integer of length window_size, what is the second set bit?
|
// For an integer of length window_size, what is the second set bit?
|
||||||
static const byte _second_bit[table_size];
|
static const uint8_t _second_bit[table_size];
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// The current word we are inspecting
|
// The current word we are inspecting
|
||||||
uint32 _current;
|
uint32_t _current;
|
||||||
|
|
||||||
// What element number are we currently on?
|
// What element number are we currently on?
|
||||||
uint _value;
|
uint _value;
|
||||||
|
@ -420,7 +420,7 @@ class IndexSetIterator VALUE_OBJ_CLASS_SPEC {
|
||||||
uint _next_word;
|
uint _next_word;
|
||||||
|
|
||||||
// A pointer to the contents of the current block
|
// A pointer to the contents of the current block
|
||||||
uint32 *_words;
|
uint32_t *_words;
|
||||||
|
|
||||||
// The index of the next block we will inspect
|
// The index of the next block we will inspect
|
||||||
uint _next_block;
|
uint _next_block;
|
||||||
|
|
|
@ -25,7 +25,6 @@
|
||||||
#ifndef SHARE_VM_OPTO_LIVE_HPP
|
#ifndef SHARE_VM_OPTO_LIVE_HPP
|
||||||
#define SHARE_VM_OPTO_LIVE_HPP
|
#define SHARE_VM_OPTO_LIVE_HPP
|
||||||
|
|
||||||
#include "libadt/port.hpp"
|
|
||||||
#include "libadt/vectset.hpp"
|
#include "libadt/vectset.hpp"
|
||||||
#include "opto/block.hpp"
|
#include "opto/block.hpp"
|
||||||
#include "opto/indexSet.hpp"
|
#include "opto/indexSet.hpp"
|
||||||
|
|
|
@ -339,11 +339,11 @@ public:
|
||||||
|
|
||||||
Node_List _body; // Loop body for inner loops
|
Node_List _body; // Loop body for inner loops
|
||||||
|
|
||||||
uint8 _nest; // Nesting depth
|
uint8_t _nest; // Nesting depth
|
||||||
uint8 _irreducible:1, // True if irreducible
|
uint8_t _irreducible:1, // True if irreducible
|
||||||
_has_call:1, // True if has call safepoint
|
_has_call:1, // True if has call safepoint
|
||||||
_has_sfpt:1, // True if has non-call safepoint
|
_has_sfpt:1, // True if has non-call safepoint
|
||||||
_rce_candidate:1; // True if candidate for range check elimination
|
_rce_candidate:1; // True if candidate for range check elimination
|
||||||
|
|
||||||
Node_List* _safepts; // List of safepoints in this loop
|
Node_List* _safepts; // List of safepoints in this loop
|
||||||
Node_List* _required_safept; // A inner loop cannot delete these safepts;
|
Node_List* _required_safept; // A inner loop cannot delete these safepts;
|
||||||
|
|
|
@ -235,23 +235,23 @@ const Type *MulINode::mul_ring(const Type *t0, const Type *t1) const {
|
||||||
const TypeInt *r1 = t1->is_int();
|
const TypeInt *r1 = t1->is_int();
|
||||||
|
|
||||||
// Fetch endpoints of all ranges
|
// Fetch endpoints of all ranges
|
||||||
int32 lo0 = r0->_lo;
|
int32_t lo0 = r0->_lo;
|
||||||
double a = (double)lo0;
|
double a = (double)lo0;
|
||||||
int32 hi0 = r0->_hi;
|
int32_t hi0 = r0->_hi;
|
||||||
double b = (double)hi0;
|
double b = (double)hi0;
|
||||||
int32 lo1 = r1->_lo;
|
int32_t lo1 = r1->_lo;
|
||||||
double c = (double)lo1;
|
double c = (double)lo1;
|
||||||
int32 hi1 = r1->_hi;
|
int32_t hi1 = r1->_hi;
|
||||||
double d = (double)hi1;
|
double d = (double)hi1;
|
||||||
|
|
||||||
// Compute all endpoints & check for overflow
|
// Compute all endpoints & check for overflow
|
||||||
int32 A = lo0*lo1;
|
int32_t A = lo0*lo1;
|
||||||
if( (double)A != a*c ) return TypeInt::INT; // Overflow?
|
if( (double)A != a*c ) return TypeInt::INT; // Overflow?
|
||||||
int32 B = lo0*hi1;
|
int32_t B = lo0*hi1;
|
||||||
if( (double)B != a*d ) return TypeInt::INT; // Overflow?
|
if( (double)B != a*d ) return TypeInt::INT; // Overflow?
|
||||||
int32 C = hi0*lo1;
|
int32_t C = hi0*lo1;
|
||||||
if( (double)C != b*c ) return TypeInt::INT; // Overflow?
|
if( (double)C != b*c ) return TypeInt::INT; // Overflow?
|
||||||
int32 D = hi0*hi1;
|
int32_t D = hi0*hi1;
|
||||||
if( (double)D != b*d ) return TypeInt::INT; // Overflow?
|
if( (double)D != b*d ) return TypeInt::INT; // Overflow?
|
||||||
|
|
||||||
if( A < B ) { lo0 = A; hi0 = B; } // Sort range endpoints
|
if( A < B ) { lo0 = A; hi0 = B; } // Sort range endpoints
|
||||||
|
@ -1228,12 +1228,12 @@ const Type *URShiftINode::Value( PhaseTransform *phase ) const {
|
||||||
//
|
//
|
||||||
// const TypeInstPtr *o = t1->is_instptr();
|
// const TypeInstPtr *o = t1->is_instptr();
|
||||||
// if( t1->singleton() )
|
// if( t1->singleton() )
|
||||||
// return TypeInt::make( ((uint32)o->const_oop() + o->_offset) >> shift );
|
// return TypeInt::make( ((uint32_t)o->const_oop() + o->_offset) >> shift );
|
||||||
// }
|
// }
|
||||||
// else if( t1->base() == Type::KlassPtr ) {
|
// else if( t1->base() == Type::KlassPtr ) {
|
||||||
// const TypeKlassPtr *o = t1->is_klassptr();
|
// const TypeKlassPtr *o = t1->is_klassptr();
|
||||||
// if( t1->singleton() )
|
// if( t1->singleton() )
|
||||||
// return TypeInt::make( ((uint32)o->const_oop() + o->_offset) >> shift );
|
// return TypeInt::make( ((uint32_t)o->const_oop() + o->_offset) >> shift );
|
||||||
// }
|
// }
|
||||||
|
|
||||||
return TypeInt::INT;
|
return TypeInt::INT;
|
||||||
|
|
|
@ -25,7 +25,6 @@
|
||||||
#ifndef SHARE_VM_OPTO_NODE_HPP
|
#ifndef SHARE_VM_OPTO_NODE_HPP
|
||||||
#define SHARE_VM_OPTO_NODE_HPP
|
#define SHARE_VM_OPTO_NODE_HPP
|
||||||
|
|
||||||
#include "libadt/port.hpp"
|
|
||||||
#include "libadt/vectset.hpp"
|
#include "libadt/vectset.hpp"
|
||||||
#include "opto/compile.hpp"
|
#include "opto/compile.hpp"
|
||||||
#include "opto/type.hpp"
|
#include "opto/type.hpp"
|
||||||
|
|
|
@ -366,8 +366,8 @@ void Compile::shorten_branches(uint* blk_starts, int& code_size, int& reloc_size
|
||||||
// third inserts nops where needed.
|
// third inserts nops where needed.
|
||||||
|
|
||||||
// Step one, perform a pessimistic sizing pass.
|
// Step one, perform a pessimistic sizing pass.
|
||||||
uint last_call_adr = max_uint;
|
uint last_call_adr = max_juint;
|
||||||
uint last_avoid_back_to_back_adr = max_uint;
|
uint last_avoid_back_to_back_adr = max_juint;
|
||||||
uint nop_size = (new (this) MachNopNode())->size(_regalloc);
|
uint nop_size = (new (this) MachNopNode())->size(_regalloc);
|
||||||
for (uint i = 0; i < nblocks; i++) { // For all blocks
|
for (uint i = 0; i < nblocks; i++) { // For all blocks
|
||||||
Block* block = _cfg->get_block(i);
|
Block* block = _cfg->get_block(i);
|
||||||
|
@ -479,7 +479,7 @@ void Compile::shorten_branches(uint* blk_starts, int& code_size, int& reloc_size
|
||||||
|
|
||||||
// Step two, replace eligible long jumps.
|
// Step two, replace eligible long jumps.
|
||||||
bool progress = true;
|
bool progress = true;
|
||||||
uint last_may_be_short_branch_adr = max_uint;
|
uint last_may_be_short_branch_adr = max_juint;
|
||||||
while (has_short_branch_candidate && progress) {
|
while (has_short_branch_candidate && progress) {
|
||||||
progress = false;
|
progress = false;
|
||||||
has_short_branch_candidate = false;
|
has_short_branch_candidate = false;
|
||||||
|
|
|
@ -405,9 +405,9 @@ bool Parse::create_jump_tables(Node* key_val, SwitchRange* lo, SwitchRange* hi)
|
||||||
|
|
||||||
bool needs_guard = false;
|
bool needs_guard = false;
|
||||||
int default_dest;
|
int default_dest;
|
||||||
int64 total_outlier_size = 0;
|
int64_t total_outlier_size = 0;
|
||||||
int64 hi_size = ((int64)hi->hi()) - ((int64)hi->lo()) + 1;
|
int64_t hi_size = ((int64_t)hi->hi()) - ((int64_t)hi->lo()) + 1;
|
||||||
int64 lo_size = ((int64)lo->hi()) - ((int64)lo->lo()) + 1;
|
int64_t lo_size = ((int64_t)lo->hi()) - ((int64_t)lo->lo()) + 1;
|
||||||
|
|
||||||
if (lo->dest() == hi->dest()) {
|
if (lo->dest() == hi->dest()) {
|
||||||
total_outlier_size = hi_size + lo_size;
|
total_outlier_size = hi_size + lo_size;
|
||||||
|
@ -429,7 +429,7 @@ bool Parse::create_jump_tables(Node* key_val, SwitchRange* lo, SwitchRange* hi)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the total number of cases and ranges
|
// Find the total number of cases and ranges
|
||||||
int64 num_cases = ((int64)hi->hi()) - ((int64)lo->lo()) + 1;
|
int64_t num_cases = ((int64_t)hi->hi()) - ((int64_t)lo->lo()) + 1;
|
||||||
int num_range = hi - lo + 1;
|
int num_range = hi - lo + 1;
|
||||||
|
|
||||||
// Don't create table if: too large, too small, or too sparse.
|
// Don't create table if: too large, too small, or too sparse.
|
||||||
|
@ -473,7 +473,7 @@ bool Parse::create_jump_tables(Node* key_val, SwitchRange* lo, SwitchRange* hi)
|
||||||
// These are the switch destinations hanging off the jumpnode
|
// These are the switch destinations hanging off the jumpnode
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (SwitchRange* r = lo; r <= hi; r++) {
|
for (SwitchRange* r = lo; r <= hi; r++) {
|
||||||
for (int64 j = r->lo(); j <= r->hi(); j++, i++) {
|
for (int64_t j = r->lo(); j <= r->hi(); j++, i++) {
|
||||||
Node* input = _gvn.transform(new (C) JumpProjNode(jtn, i, r->dest(), (int)(j - lowval)));
|
Node* input = _gvn.transform(new (C) JumpProjNode(jtn, i, r->dest(), (int)(j - lowval)));
|
||||||
{
|
{
|
||||||
PreserveJVMState pjvms(this);
|
PreserveJVMState pjvms(this);
|
||||||
|
|
|
@ -25,7 +25,6 @@
|
||||||
#ifndef SHARE_VM_OPTO_PHASE_HPP
|
#ifndef SHARE_VM_OPTO_PHASE_HPP
|
||||||
#define SHARE_VM_OPTO_PHASE_HPP
|
#define SHARE_VM_OPTO_PHASE_HPP
|
||||||
|
|
||||||
#include "libadt/port.hpp"
|
|
||||||
#include "runtime/timer.hpp"
|
#include "runtime/timer.hpp"
|
||||||
|
|
||||||
class Compile;
|
class Compile;
|
||||||
|
|
|
@ -51,7 +51,7 @@
|
||||||
|
|
||||||
//-------------Non-zero bit search methods used by RegMask---------------------
|
//-------------Non-zero bit search methods used by RegMask---------------------
|
||||||
// Find lowest 1, or return 32 if empty
|
// Find lowest 1, or return 32 if empty
|
||||||
int find_lowest_bit( uint32 mask ) {
|
int find_lowest_bit( uint32_t mask ) {
|
||||||
int n = 0;
|
int n = 0;
|
||||||
if( (mask & 0xffff) == 0 ) {
|
if( (mask & 0xffff) == 0 ) {
|
||||||
mask >>= 16;
|
mask >>= 16;
|
||||||
|
@ -80,7 +80,7 @@ int find_lowest_bit( uint32 mask ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find highest 1, or return 32 if empty
|
// Find highest 1, or return 32 if empty
|
||||||
int find_hihghest_bit( uint32 mask ) {
|
int find_hihghest_bit( uint32_t mask ) {
|
||||||
int n = 0;
|
int n = 0;
|
||||||
if( mask > 0xffff ) {
|
if( mask > 0xffff ) {
|
||||||
mask >>= 16;
|
mask >>= 16;
|
||||||
|
@ -395,7 +395,7 @@ bool RegMask::is_UP() const {
|
||||||
//------------------------------Size-------------------------------------------
|
//------------------------------Size-------------------------------------------
|
||||||
// Compute size of register mask in bits
|
// Compute size of register mask in bits
|
||||||
uint RegMask::Size() const {
|
uint RegMask::Size() const {
|
||||||
extern uint8 bitsInByte[256];
|
extern uint8_t bitsInByte[256];
|
||||||
uint sum = 0;
|
uint sum = 0;
|
||||||
for( int i = 0; i < RM_SIZE; i++ )
|
for( int i = 0; i < RM_SIZE; i++ )
|
||||||
sum +=
|
sum +=
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
#define SHARE_VM_OPTO_REGMASK_HPP
|
#define SHARE_VM_OPTO_REGMASK_HPP
|
||||||
|
|
||||||
#include "code/vmreg.hpp"
|
#include "code/vmreg.hpp"
|
||||||
#include "libadt/port.hpp"
|
|
||||||
#include "opto/optoreg.hpp"
|
#include "opto/optoreg.hpp"
|
||||||
#ifdef TARGET_ARCH_MODEL_x86_32
|
#ifdef TARGET_ARCH_MODEL_x86_32
|
||||||
# include "adfiles/adGlobals_x86_32.hpp"
|
# include "adfiles/adGlobals_x86_32.hpp"
|
||||||
|
@ -68,9 +67,9 @@
|
||||||
|
|
||||||
//-------------Non-zero bit search methods used by RegMask---------------------
|
//-------------Non-zero bit search methods used by RegMask---------------------
|
||||||
// Find lowest 1, or return 32 if empty
|
// Find lowest 1, or return 32 if empty
|
||||||
int find_lowest_bit( uint32 mask );
|
int find_lowest_bit( uint32_t mask );
|
||||||
// Find highest 1, or return 32 if empty
|
// Find highest 1, or return 32 if empty
|
||||||
int find_hihghest_bit( uint32 mask );
|
int find_hihghest_bit( uint32_t mask );
|
||||||
|
|
||||||
//------------------------------RegMask----------------------------------------
|
//------------------------------RegMask----------------------------------------
|
||||||
// The ADL file describes how to print the machine-specific registers, as well
|
// The ADL file describes how to print the machine-specific registers, as well
|
||||||
|
|
|
@ -960,7 +960,7 @@ JRT_LEAF(void, OptoRuntime::profile_receiver_type_C(DataLayout* data, oopDesc* r
|
||||||
} else {
|
} else {
|
||||||
// Receiver did not match any saved receiver and there is no empty row for it.
|
// Receiver did not match any saved receiver and there is no empty row for it.
|
||||||
// Increment total counter to indicate polymorphic case.
|
// Increment total counter to indicate polymorphic case.
|
||||||
intptr_t* count_p = (intptr_t*)(((byte*)(data)) + in_bytes(CounterData::count_offset()));
|
intptr_t* count_p = (intptr_t*)(((uint8_t*)(data)) + in_bytes(CounterData::count_offset()));
|
||||||
*count_p += DataLayout::counter_increment;
|
*count_p += DataLayout::counter_increment;
|
||||||
}
|
}
|
||||||
JRT_END
|
JRT_END
|
||||||
|
|
|
@ -242,8 +242,8 @@ Node *SubINode::Ideal(PhaseGVN *phase, bool can_reshape){
|
||||||
const Type *SubINode::sub( const Type *t1, const Type *t2 ) const {
|
const Type *SubINode::sub( const Type *t1, const Type *t2 ) const {
|
||||||
const TypeInt *r0 = t1->is_int(); // Handy access
|
const TypeInt *r0 = t1->is_int(); // Handy access
|
||||||
const TypeInt *r1 = t2->is_int();
|
const TypeInt *r1 = t2->is_int();
|
||||||
int32 lo = r0->_lo - r1->_hi;
|
int32_t lo = r0->_lo - r1->_hi;
|
||||||
int32 hi = r0->_hi - r1->_lo;
|
int32_t hi = r0->_hi - r1->_lo;
|
||||||
|
|
||||||
// We next check for 32-bit overflow.
|
// We next check for 32-bit overflow.
|
||||||
// If that happens, we just assume all integers are possible.
|
// If that happens, we just assume all integers are possible.
|
||||||
|
|
|
@ -25,7 +25,6 @@
|
||||||
#ifndef SHARE_VM_OPTO_TYPE_HPP
|
#ifndef SHARE_VM_OPTO_TYPE_HPP
|
||||||
#define SHARE_VM_OPTO_TYPE_HPP
|
#define SHARE_VM_OPTO_TYPE_HPP
|
||||||
|
|
||||||
#include "libadt/port.hpp"
|
|
||||||
#include "opto/adlcVMDeps.hpp"
|
#include "opto/adlcVMDeps.hpp"
|
||||||
#include "runtime/handles.hpp"
|
#include "runtime/handles.hpp"
|
||||||
|
|
||||||
|
|
|
@ -247,7 +247,6 @@
|
||||||
# include "utilities/yieldingWorkgroup.hpp"
|
# include "utilities/yieldingWorkgroup.hpp"
|
||||||
#ifdef COMPILER2
|
#ifdef COMPILER2
|
||||||
# include "libadt/dict.hpp"
|
# include "libadt/dict.hpp"
|
||||||
# include "libadt/port.hpp"
|
|
||||||
# include "libadt/set.hpp"
|
# include "libadt/set.hpp"
|
||||||
# include "libadt/vectset.hpp"
|
# include "libadt/vectset.hpp"
|
||||||
# include "opto/addnode.hpp"
|
# include "opto/addnode.hpp"
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
#include "classfile/classLoader.hpp"
|
#include "classfile/classLoader.hpp"
|
||||||
#include "classfile/javaAssertions.hpp"
|
#include "classfile/javaAssertions.hpp"
|
||||||
#include "classfile/javaClasses.hpp"
|
#include "classfile/javaClasses.hpp"
|
||||||
#include "classfile/symbolTable.hpp"
|
#include "classfile/stringTable.hpp"
|
||||||
#include "classfile/systemDictionary.hpp"
|
#include "classfile/systemDictionary.hpp"
|
||||||
#include "classfile/vmSymbols.hpp"
|
#include "classfile/vmSymbols.hpp"
|
||||||
#include "gc_interface/collectedHeap.inline.hpp"
|
#include "gc_interface/collectedHeap.inline.hpp"
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "classfile/symbolTable.hpp"
|
#include "classfile/stringTable.hpp"
|
||||||
#include "compiler/compileBroker.hpp"
|
#include "compiler/compileBroker.hpp"
|
||||||
#include "interpreter/interpreter.hpp"
|
#include "interpreter/interpreter.hpp"
|
||||||
#include "interpreter/oopMapCache.hpp"
|
#include "interpreter/oopMapCache.hpp"
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
#include "memory/universe.hpp"
|
#include "memory/universe.hpp"
|
||||||
#include "oops/oop.inline.hpp"
|
#include "oops/oop.inline.hpp"
|
||||||
|
|
||||||
#include "classfile/symbolTable.hpp"
|
#include "classfile/stringTable.hpp"
|
||||||
#include "classfile/classLoaderData.hpp"
|
#include "classfile/classLoaderData.hpp"
|
||||||
|
|
||||||
#include "prims/whitebox.hpp"
|
#include "prims/whitebox.hpp"
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "classfile/javaAssertions.hpp"
|
#include "classfile/javaAssertions.hpp"
|
||||||
|
#include "classfile/stringTable.hpp"
|
||||||
#include "classfile/symbolTable.hpp"
|
#include "classfile/symbolTable.hpp"
|
||||||
#include "compiler/compilerOracle.hpp"
|
#include "compiler/compilerOracle.hpp"
|
||||||
#include "memory/allocation.inline.hpp"
|
#include "memory/allocation.inline.hpp"
|
||||||
|
|
|
@ -524,13 +524,6 @@ class CommandLineFlags {
|
||||||
product_pd(bool, UseMembar, \
|
product_pd(bool, UseMembar, \
|
||||||
"(Unstable) Issues membars on thread state transitions") \
|
"(Unstable) Issues membars on thread state transitions") \
|
||||||
\
|
\
|
||||||
/* Temp PPC Flag to allow disabling the use of lwsync on ppc platforms \
|
|
||||||
* that don't support it. This will be replaced by processor detection \
|
|
||||||
* logic. \
|
|
||||||
*/ \
|
|
||||||
product(bool, UsePPCLWSYNC, true, \
|
|
||||||
"Use lwsync instruction if true, else use slower sync") \
|
|
||||||
\
|
|
||||||
develop(bool, CleanChunkPoolAsync, falseInEmbedded, \
|
develop(bool, CleanChunkPoolAsync, falseInEmbedded, \
|
||||||
"Clean the chunk pool asynchronously") \
|
"Clean the chunk pool asynchronously") \
|
||||||
\
|
\
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "classfile/symbolTable.hpp"
|
#include "classfile/stringTable.hpp"
|
||||||
#include "code/icBuffer.hpp"
|
#include "code/icBuffer.hpp"
|
||||||
#include "gc_interface/collectedHeap.hpp"
|
#include "gc_interface/collectedHeap.hpp"
|
||||||
#include "interpreter/bytecodes.hpp"
|
#include "interpreter/bytecodes.hpp"
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "classfile/classLoader.hpp"
|
#include "classfile/classLoader.hpp"
|
||||||
#include "classfile/symbolTable.hpp"
|
#include "classfile/stringTable.hpp"
|
||||||
#include "classfile/systemDictionary.hpp"
|
#include "classfile/systemDictionary.hpp"
|
||||||
#include "code/codeCache.hpp"
|
#include "code/codeCache.hpp"
|
||||||
#include "compiler/compileBroker.hpp"
|
#include "compiler/compileBroker.hpp"
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "classfile/javaClasses.hpp"
|
#include "classfile/javaClasses.hpp"
|
||||||
#include "classfile/symbolTable.hpp"
|
#include "classfile/stringTable.hpp"
|
||||||
#include "classfile/systemDictionary.hpp"
|
#include "classfile/systemDictionary.hpp"
|
||||||
#include "classfile/verifier.hpp"
|
#include "classfile/verifier.hpp"
|
||||||
#include "classfile/vmSymbols.hpp"
|
#include "classfile/vmSymbols.hpp"
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "classfile/symbolTable.hpp"
|
#include "classfile/stringTable.hpp"
|
||||||
#include "classfile/systemDictionary.hpp"
|
#include "classfile/systemDictionary.hpp"
|
||||||
#include "code/codeCache.hpp"
|
#include "code/codeCache.hpp"
|
||||||
#include "code/icBuffer.hpp"
|
#include "code/icBuffer.hpp"
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include "classfile/javaClasses.hpp"
|
#include "classfile/javaClasses.hpp"
|
||||||
#include "classfile/loaderConstraints.hpp"
|
#include "classfile/loaderConstraints.hpp"
|
||||||
#include "classfile/placeholders.hpp"
|
#include "classfile/placeholders.hpp"
|
||||||
|
#include "classfile/stringTable.hpp"
|
||||||
#include "classfile/systemDictionary.hpp"
|
#include "classfile/systemDictionary.hpp"
|
||||||
#include "ci/ciField.hpp"
|
#include "ci/ciField.hpp"
|
||||||
#include "ci/ciInstance.hpp"
|
#include "ci/ciInstance.hpp"
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "classfile/altHashing.hpp"
|
#include "classfile/altHashing.hpp"
|
||||||
#include "classfile/javaClasses.hpp"
|
#include "classfile/javaClasses.hpp"
|
||||||
|
#include "classfile/stringTable.hpp"
|
||||||
#include "memory/allocation.inline.hpp"
|
#include "memory/allocation.inline.hpp"
|
||||||
#include "memory/filemap.hpp"
|
#include "memory/filemap.hpp"
|
||||||
#include "memory/resourceArea.hpp"
|
#include "memory/resourceArea.hpp"
|
||||||
|
|
|
@ -147,6 +147,11 @@ BUNDLE_UP_FAILED = ( exitCode=$$? && $(BUNDLE_UP) && exit $${exitCode} )
|
||||||
all: jtreg_tests
|
all: jtreg_tests
|
||||||
@$(ECHO) "Testing completed successfully"
|
@$(ECHO) "Testing completed successfully"
|
||||||
|
|
||||||
|
# Support "hotspot_" prefixed test make targets too
|
||||||
|
# The hotspot_% targets are for example invoked by the top level Makefile
|
||||||
|
hotspot_%:
|
||||||
|
$(MAKE) $*
|
||||||
|
|
||||||
# Prep for output
|
# Prep for output
|
||||||
prep: clean
|
prep: clean
|
||||||
@$(MKDIR) -p $(ABS_TEST_OUTPUT_DIR)
|
@$(MKDIR) -p $(ABS_TEST_OUTPUT_DIR)
|
||||||
|
|
|
@ -66,7 +66,6 @@ needs_jdk = \
|
||||||
gc/metaspace/TestMetaspacePerfCounters.java \
|
gc/metaspace/TestMetaspacePerfCounters.java \
|
||||||
gc/metaspace/TestPerfCountersAndMemoryPools.java \
|
gc/metaspace/TestPerfCountersAndMemoryPools.java \
|
||||||
runtime/6819213/TestBootNativeLibraryPath.java \
|
runtime/6819213/TestBootNativeLibraryPath.java \
|
||||||
runtime/6925573/SortMethodsTest.java \
|
|
||||||
runtime/7158988/FieldMonitor.java \
|
runtime/7158988/FieldMonitor.java \
|
||||||
runtime/7194254/Test7194254.java \
|
runtime/7194254/Test7194254.java \
|
||||||
runtime/Metaspace/FragmentMetaspace.java \
|
runtime/Metaspace/FragmentMetaspace.java \
|
||||||
|
|
1310
hotspot/test/runtime/duplAttributes/DuplAttributes.jcod
Normal file
1310
hotspot/test/runtime/duplAttributes/DuplAttributes.jcod
Normal file
File diff suppressed because it is too large
Load diff
63
hotspot/test/runtime/duplAttributes/DuplAttributesTest.java
Normal file
63
hotspot/test/runtime/duplAttributes/DuplAttributesTest.java
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test
|
||||||
|
* @bug 8040292
|
||||||
|
* @library /testlibrary
|
||||||
|
* @summary Throw exceptions when duplicate attributes are detected.
|
||||||
|
* @run main DuplAttributesTest
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import com.oracle.java.testlibrary.*;
|
||||||
|
|
||||||
|
public class DuplAttributesTest {
|
||||||
|
|
||||||
|
static final String testsrc = System.getProperty("test.src");
|
||||||
|
|
||||||
|
public static void runTest(String test, String result) throws Throwable {
|
||||||
|
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
|
||||||
|
"-cp", testsrc + File.separator + "test.jar", test);
|
||||||
|
OutputAnalyzer output = new OutputAnalyzer(pb.start());
|
||||||
|
output.shouldContain("java.lang.ClassFormatError: Multiple " + result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String args[]) throws Throwable {
|
||||||
|
System.out.println("Regression test for bug 8040292");
|
||||||
|
|
||||||
|
runTest("ClassInvisAnnotsDup", "RuntimeInvisibleAnnotations");
|
||||||
|
runTest("ClassVisAnnotsDup", "RuntimeVisibleAnnotations");
|
||||||
|
runTest("SrcDbgExtDup", "SourceDebugExtension");
|
||||||
|
|
||||||
|
runTest("FieldInvisAnnotsDup", "RuntimeInvisibleAnnotations");
|
||||||
|
runTest("FieldVisAnnotsDup", "RuntimeVisibleAnnotations");
|
||||||
|
|
||||||
|
runTest("AnnotationDefaultDup", "AnnotationDefault");
|
||||||
|
runTest("MethInvisAnnotsDup", "RuntimeInvisibleAnnotations");
|
||||||
|
runTest("MethVisAnnotsDup", "RuntimeVisibleAnnotations");
|
||||||
|
runTest("MethInvisParamAnnotsDup", "RuntimeInvisibleParameterAnnotations");
|
||||||
|
runTest("MethVisParamAnnotsDup", "RuntimeVisibleParameterAnnotations");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
BIN
hotspot/test/runtime/duplAttributes/test.jar
Normal file
BIN
hotspot/test/runtime/duplAttributes/test.jar
Normal file
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue