comparison src/share/vm/jvmci/jvmciRuntime.cpp @ 21562:47bebae7454f

Merge.
author Doug Simon <doug.simon@oracle.com>
date Thu, 28 May 2015 21:58:33 +0200
parents src/share/vm/graal/graalRuntime.cpp@cecb4e39521c src/share/vm/graal/graalRuntime.cpp@be896a1983c0
children 4f63449b4422
comparison
equal deleted inserted replaced
21561:ce2113326bc8 21562:47bebae7454f
35 #include "runtime/biasedLocking.hpp" 35 #include "runtime/biasedLocking.hpp"
36 #include "runtime/interfaceSupport.hpp" 36 #include "runtime/interfaceSupport.hpp"
37 #include "runtime/arguments.hpp" 37 #include "runtime/arguments.hpp"
38 #include "runtime/reflection.hpp" 38 #include "runtime/reflection.hpp"
39 #include "utilities/debug.hpp" 39 #include "utilities/debug.hpp"
40 #include "utilities/defaultStream.hpp"
40 41
41 jobject JVMCIRuntime::_HotSpotJVMCIRuntime_instance = NULL; 42 jobject JVMCIRuntime::_HotSpotJVMCIRuntime_instance = NULL;
42 bool JVMCIRuntime::_HotSpotJVMCIRuntime_initialized = false; 43 bool JVMCIRuntime::_HotSpotJVMCIRuntime_initialized = false;
43 bool JVMCIRuntime::_shutdown_called = false; 44 bool JVMCIRuntime::_shutdown_called = false;
44 45
623 SystemDictionary::init_jvmci_loader(JNIHandles::resolve(loader_handle)); 624 SystemDictionary::init_jvmci_loader(JNIHandles::resolve(loader_handle));
624 SystemDictionary::WKID scan = SystemDictionary::FIRST_JVMCI_WKID; 625 SystemDictionary::WKID scan = SystemDictionary::FIRST_JVMCI_WKID;
625 SystemDictionary::initialize_wk_klasses_through(SystemDictionary::LAST_JVMCI_WKID, scan, CHECK); 626 SystemDictionary::initialize_wk_klasses_through(SystemDictionary::LAST_JVMCI_WKID, scan, CHECK);
626 JVM_END 627 JVM_END
627 628
629 // boolean com.oracle.jvmci.hotspot.HotSpotOptions.isCITimingEnabled()
630 JVM_ENTRY(jboolean, JVM_IsCITimingEnabled(JNIEnv *env, jclass c))
631 return CITime || CITimeEach;
632 JVM_END
633
628 // private static JVMCIRuntime JVMCI.initializeRuntime() 634 // private static JVMCIRuntime JVMCI.initializeRuntime()
629 JVM_ENTRY(jobject, JVM_GetJVMCIRuntime(JNIEnv *env, jclass c)) 635 JVM_ENTRY(jobject, JVM_GetJVMCIRuntime(JNIEnv *env, jclass c))
630 JVMCIRuntime::initialize_HotSpotJVMCIRuntime(); 636 JVMCIRuntime::initialize_HotSpotJVMCIRuntime();
631 return JVMCIRuntime::get_HotSpotJVMCIRuntime_jobject(); 637 return JVMCIRuntime::get_HotSpotJVMCIRuntime_jobject();
632 JVM_END 638 JVM_END
663 JavaValue result(T_OBJECT); 669 JavaValue result(T_OBJECT);
664 JavaCalls::call_static(&result, klass, makeInstance, sig, CHECK_NULL); 670 JavaCalls::call_static(&result, klass, makeInstance, sig, CHECK_NULL);
665 return JNIHandles::make_local(THREAD, (oop) result.get_jobject()); 671 return JNIHandles::make_local(THREAD, (oop) result.get_jobject());
666 JVM_END 672 JVM_END
667 673
668 void JVMCIRuntime::check_generated_sources_sha1(TRAPS) {
669 TempNewSymbol name = SymbolTable::new_symbol("com/oracle/jvmci/hotspot/sourcegen/GeneratedSourcesSha1", CHECK_ABORT);
670 KlassHandle klass = load_required_class(name);
671 fieldDescriptor fd;
672 if (!InstanceKlass::cast(klass())->find_field(vmSymbols::value_name(), vmSymbols::string_signature(), true, &fd)) {
673 THROW_MSG(vmSymbols::java_lang_NoSuchFieldError(), "GeneratedSourcesSha1.value");
674 }
675
676 Symbol* value = java_lang_String::as_symbol(klass->java_mirror()->obj_field(fd.offset()), CHECK);
677 if (!value->equals(_generated_sources_sha1)) {
678 char buf[200];
679 jio_snprintf(buf, sizeof(buf), "Generated sources SHA1 check failed (%s != %s) - need to rebuild the VM", value->as_C_string(), _generated_sources_sha1);
680 THROW_MSG(vmSymbols::java_lang_InternalError(), buf);
681 }
682 }
683
684 Handle JVMCIRuntime::callInitializer(const char* className, const char* methodName, const char* returnType) { 674 Handle JVMCIRuntime::callInitializer(const char* className, const char* methodName, const char* returnType) {
685 guarantee(!_HotSpotJVMCIRuntime_initialized, "cannot reinitialize HotSpotJVMCIRuntime"); 675 guarantee(!_HotSpotJVMCIRuntime_initialized, "cannot reinitialize HotSpotJVMCIRuntime");
686 Thread* THREAD = Thread::current(); 676 Thread* THREAD = Thread::current();
687 check_generated_sources_sha1(CHECK_ABORT_(Handle()));
688 677
689 TempNewSymbol name = SymbolTable::new_symbol(className, CHECK_ABORT_(Handle())); 678 TempNewSymbol name = SymbolTable::new_symbol(className, CHECK_ABORT_(Handle()));
690 KlassHandle klass = load_required_class(name); 679 KlassHandle klass = load_required_class(name);
691 TempNewSymbol runtime = SymbolTable::new_symbol(methodName, CHECK_ABORT_(Handle())); 680 TempNewSymbol runtime = SymbolTable::new_symbol(methodName, CHECK_ABORT_(Handle()));
692 TempNewSymbol sig = SymbolTable::new_symbol(returnType, CHECK_ABORT_(Handle())); 681 TempNewSymbol sig = SymbolTable::new_symbol(returnType, CHECK_ABORT_(Handle()));
722 711
723 // private static void CompilerToVMImpl.init() 712 // private static void CompilerToVMImpl.init()
724 JVM_ENTRY(void, JVM_InitializeJVMCINatives(JNIEnv *env, jclass c2vmClass)) 713 JVM_ENTRY(void, JVM_InitializeJVMCINatives(JNIEnv *env, jclass c2vmClass))
725 JVMCIRuntime::initialize_natives(env, c2vmClass); 714 JVMCIRuntime::initialize_natives(env, c2vmClass);
726 JVM_END 715 JVM_END
727
728 // private static OptionsParsed[] HotSpotOptions.parseVMOptions(Class)
729 JVM_ENTRY(jobject, JVM_ParseJVMCIOptions(JNIEnv *env, jclass c, jobject optionsParsedClass_obj))
730 HandleMark hm;
731 KlassHandle hotSpotOptionsClass(THREAD, java_lang_Class::as_Klass(JNIHandles::resolve_non_null(c)));
732 JVMCIRuntime::parse_arguments(hotSpotOptionsClass, CHECK_NULL);
733 KlassHandle optionsParsedClass(THREAD, java_lang_Class::as_Klass(JNIHandles::resolve_non_null(optionsParsedClass_obj)));
734 return JNIHandles::make_local(THREAD, JVMCIRuntime::get_service_impls(optionsParsedClass, THREAD)());
735 JVM_END
736
737 716
738 void JVMCIRuntime::ensure_jvmci_class_loader_is_initialized() { 717 void JVMCIRuntime::ensure_jvmci_class_loader_is_initialized() {
739 // This initialization code is guarded by a static pointer to the Factory class. 718 // This initialization code is guarded by a static pointer to the Factory class.
740 // Once it is non-null, the JVMCI class loader and well known JVMCI classes are 719 // Once it is non-null, the JVMCI class loader and well known JVMCI classes are
741 // guaranteed to have been initialized. By going through the static 720 // guaranteed to have been initialized. By going through the static
771 InstanceKlass* ik = InstanceKlass::cast(klass()); 750 InstanceKlass* ik = InstanceKlass::cast(klass());
772 address addr = ik->static_field_addr(field_desc.offset() - InstanceMirrorKlass::offset_of_static_fields()); 751 address addr = ik->static_field_addr(field_desc.offset() - InstanceMirrorKlass::offset_of_static_fields());
773 *((jboolean *) addr) = (jboolean) UseJVMCIClassLoader; 752 *((jboolean *) addr) = (jboolean) UseJVMCIClassLoader;
774 klass->initialize(CHECK_ABORT); 753 klass->initialize(CHECK_ABORT);
775 _FactoryKlass = klass(); 754 _FactoryKlass = klass();
776 } 755 assert(!UseJVMCIClassLoader || SystemDictionary::jvmci_loader() != NULL, "JVMCI classloader should have been initialized");
777 } 756 }
778 757 }
779 jint JVMCIRuntime::check_arguments(TRAPS) { 758
780 KlassHandle nullHandle; 759 OptionsValueTable* JVMCIRuntime::parse_arguments() {
781 parse_arguments(nullHandle, THREAD); 760 OptionsTable* table = OptionsTable::load_options();
782 if (HAS_PENDING_EXCEPTION) { 761 if (table == NULL) {
783 // Errors in parsing JVMCI arguments cause exceptions. 762 return NULL;
784 // We now load and initialize HotSpotOptions which in turn 763 }
785 // causes argument parsing to be redone with better error messages. 764
786 CLEAR_PENDING_EXCEPTION; 765 OptionsValueTable* options = new OptionsValueTable(table);
787 TempNewSymbol name = SymbolTable::new_symbol("Lcom/oracle/jvmci/hotspot/HotSpotOptions;", CHECK_ABORT_(JNI_ERR));
788 instanceKlassHandle hotSpotOptionsClass = resolve_or_fail(name, CHECK_ABORT_(JNI_ERR));
789
790 parse_arguments(hotSpotOptionsClass, THREAD);
791 assert(HAS_PENDING_EXCEPTION, "must be");
792
793 ResourceMark rm;
794 Handle exception = PENDING_EXCEPTION;
795 CLEAR_PENDING_EXCEPTION;
796 oop message = java_lang_Throwable::message(exception);
797 if (message != NULL) {
798 tty->print_cr("Error parsing JVMCI options: %s", java_lang_String::as_utf8_string(message));
799 } else {
800 call_printStackTrace(exception, THREAD);
801 }
802 return JNI_ERR;
803 }
804 return JNI_OK;
805 }
806
807 void JVMCIRuntime::parse_arguments(KlassHandle hotSpotOptionsClass, TRAPS) {
808 ResourceMark rm(THREAD);
809 766
810 // Process option overrides from jvmci.options first 767 // Process option overrides from jvmci.options first
811 parse_jvmci_options_file(hotSpotOptionsClass, CHECK); 768 parse_jvmci_options_file(options);
812 769
813 // Now process options on the command line 770 // Now process options on the command line
814 int numOptions = Arguments::num_jvmci_args(); 771 int numOptions = Arguments::num_jvmci_args();
815 for (int i = 0; i < numOptions; i++) { 772 for (int i = 0; i < numOptions; i++) {
816 char* arg = Arguments::jvmci_args_array()[i]; 773 char* arg = Arguments::jvmci_args_array()[i];
817 parse_argument(hotSpotOptionsClass, arg, CHECK); 774 if (!parse_argument(options, arg)) {
818 } 775 delete options;
819 } 776 return NULL;
820 777 }
821 void JVMCIRuntime::check_required_value(const char* name, size_t name_len, const char* value, TRAPS) { 778 }
822 if (value == NULL) { 779 return options;
823 char buf[200]; 780 }
824 jio_snprintf(buf, sizeof(buf), "Must use '-G:%.*s=<value>' format for %.*s option", name_len, name, name_len, name); 781
825 THROW_MSG(vmSymbols::java_lang_InternalError(), buf); 782 void not_found(OptionsTable* table, const char* argname, size_t namelen) {
826 } 783 jio_fprintf(defaultStream::error_stream(),"Unrecognized VM option '%.*s'\n", namelen, argname);
827 } 784 OptionDesc* fuzzy_matched = table->fuzzy_match(argname, strlen(argname));
828 785 if (fuzzy_matched != NULL) {
829 void JVMCIRuntime::parse_argument(KlassHandle hotSpotOptionsClass, char* arg, TRAPS) { 786 jio_fprintf(defaultStream::error_stream(),
830 ensure_jvmci_class_loader_is_initialized(); 787 "Did you mean '%s%s%s'?\n",
788 (fuzzy_matched->type == _boolean) ? "(+/-)" : "",
789 fuzzy_matched->name,
790 (fuzzy_matched->type == _boolean) ? "" : "=<value>");
791 }
792 }
793
794 bool JVMCIRuntime::parse_argument(OptionsValueTable* options, const char* arg) {
795 OptionsTable* table = options->options_table();
831 char first = arg[0]; 796 char first = arg[0];
832 char* name; 797 const char* name;
833 size_t name_len; 798 size_t name_len;
834 bool recognized = true;
835 if (first == '+' || first == '-') { 799 if (first == '+' || first == '-') {
836 name = arg + 1; 800 name = arg + 1;
837 name_len = strlen(name); 801 OptionDesc* optionDesc = table->get(name);
838 recognized = set_option_bool(hotSpotOptionsClass, name, name_len, first, CHECK); 802 if (optionDesc == NULL) {
803 not_found(table, name, strlen(name));
804 return false;
805 }
806 if (optionDesc->type != _boolean) {
807 jio_fprintf(defaultStream::error_stream(), "Unexpected +/- setting in VM option '%s'\n", name);
808 return false;
809 }
810 OptionValue value;
811 value.desc = *optionDesc;
812 value.boolean_value = first == '+';
813 options->put(value);
814 return true;
839 } else { 815 } else {
840 char* sep = strchr(arg, '='); 816 const char* sep = strchr(arg, '=');
841 name = arg; 817 name = arg;
842 char* value = NULL; 818 const char* value = NULL;
843 if (sep != NULL) { 819 if (sep != NULL) {
844 name_len = sep - name; 820 name_len = sep - name;
845 value = sep + 1; 821 value = sep + 1;
846 } else { 822 } else {
847 name_len = strlen(name); 823 name_len = strlen(name);
848 } 824 }
849 recognized = set_option(hotSpotOptionsClass, name, name_len, value, CHECK); 825 OptionDesc* optionDesc = table->get(name, name_len);
850 } 826 if (optionDesc == NULL) {
851 827 not_found(table, name, name_len);
852 if (!recognized) { 828 return false;
853 bool throw_err = hotSpotOptionsClass.is_null(); 829 }
854 if (!hotSpotOptionsClass.is_null()) { 830 if (optionDesc->type == _boolean) {
855 set_option_helper(hotSpotOptionsClass, name, name_len, Handle(), ' ', Handle(), 0L); 831 jio_fprintf(defaultStream::error_stream(), "Missing +/- setting for VM option '%s'\n", name);
856 if (!HAS_PENDING_EXCEPTION) { 832 return false;
857 throw_err = true; 833 }
834 if (value == NULL) {
835 jio_fprintf(defaultStream::error_stream(), "Must use '-G:%.*s=<value>' format for %.*s option", name_len, name, name_len, name);
836 return false;
837 }
838 OptionValue optionValue;
839 optionValue.desc = *optionDesc;
840 char* check;
841 errno = 0;
842 switch(optionDesc->type) {
843 case _int: {
844 long int int_value = ::strtol(value, &check, 10);
845 if (*check != '\0' || errno == ERANGE || int_value > max_jint || int_value < min_jint) {
846 jio_fprintf(defaultStream::error_stream(), "Expected int value for VM option '%s'\n", name);
847 return false;
848 }
849 optionValue.int_value = int_value;
850 break;
858 } 851 }
859 } 852 case _long: {
860 853 long long int long_value = ::strtoll(value, &check, 10);
861 if (throw_err) { 854 if (*check != '\0' || errno == ERANGE || long_value > max_jlong || long_value < min_jlong) {
862 char buf[200]; 855 jio_fprintf(defaultStream::error_stream(), "Expected long value for VM option '%s'\n", name);
863 jio_snprintf(buf, sizeof(buf), "Unrecognized JVMCI option %.*s", name_len, name); 856 return false;
864 THROW_MSG(vmSymbols::java_lang_InternalError(), buf); 857 }
865 } 858 optionValue.long_value = long_value;
866 } 859 break;
867 } 860 }
868 861 case _float: {
869 void JVMCIRuntime::parse_jvmci_options_file(KlassHandle hotSpotOptionsClass, TRAPS) { 862 optionValue.float_value = ::strtof(value, &check);
863 if (*check != '\0' || errno == ERANGE) {
864 jio_fprintf(defaultStream::error_stream(), "Expected float value for VM option '%s'\n", name);
865 return false;
866 }
867 break;
868 }
869 case _double: {
870 optionValue.double_value = ::strtod(value, &check);
871 if (*check != '\0' || errno == ERANGE) {
872 jio_fprintf(defaultStream::error_stream(), "Expected double value for VM option '%s'\n", name);
873 return false;
874 }
875 break;
876 }
877 case _string: {
878 char* copy = NEW_C_HEAP_ARRAY(char, strlen(value) + 1, mtCompiler);
879 strcpy(copy, value);
880 optionValue.string_value = copy;
881 break;
882 }
883 default:
884 ShouldNotReachHere();
885 }
886 options->put(optionValue);
887 return true;
888 }
889 }
890
891 class JVMCIOptionParseClosure : public ParseClosure {
892 OptionsValueTable* _options;
893 public:
894 JVMCIOptionParseClosure(OptionsValueTable* options) : _options(options) {}
895 void do_line(char* line) {
896 if (!JVMCIRuntime::parse_argument(_options, line)) {
897 warn("There was an error parsing an argument. Skipping it.");
898 }
899 }
900 };
901
902 void JVMCIRuntime::parse_jvmci_options_file(OptionsValueTable* options) {
870 const char* home = Arguments::get_java_home(); 903 const char* home = Arguments::get_java_home();
871 size_t path_len = strlen(home) + strlen("/lib/jvmci.options") + 1; 904 size_t path_len = strlen(home) + strlen("/lib/jvmci.options") + 1;
872 char* path = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, path_len); 905 char path[JVM_MAXPATHLEN];
873 char sep = os::file_separator()[0]; 906 char sep = os::file_separator()[0];
874 sprintf(path, "%s%clib%cjvmci.options", home, sep, sep); 907 jio_snprintf(path, JVM_MAXPATHLEN, "%s%clib%cjvmci.options", home, sep, sep);
875 908 JVMCIOptionParseClosure closure(options);
876 struct stat st; 909 parse_lines(path, &closure, false);
877 if (os::stat(path, &st) == 0) { 910 }
878 int file_handle = os::open(path, 0, 0); 911
879 if (file_handle != -1) { 912 #define CHECK_WARN_ABORT_(message) THREAD); \
880 char* buffer = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, st.st_size); 913 if (HAS_PENDING_EXCEPTION) { \
881 int num_read = (int) os::read(file_handle, (char*) buffer, st.st_size); 914 warning(message); \
882 if (num_read == -1) { 915 char buf[512]; \
883 warning("Error reading file %s due to %s", path, strerror(errno)); 916 jio_snprintf(buf, 512, "Uncaught exception at %s:%d", __FILE__, __LINE__); \
884 } else if (num_read != st.st_size) { 917 JVMCIRuntime::abort_on_pending_exception(PENDING_EXCEPTION, buf); \
885 warning("Only read %d of " SIZE_FORMAT " bytes from %s", num_read, (size_t) st.st_size, path); 918 return; \
919 } \
920 (void)(0
921
922 class SetOptionClosure : public ValueClosure<OptionValue> {
923 Thread* _thread;
924 public:
925 SetOptionClosure(TRAPS) : _thread(THREAD) {}
926 void do_value(OptionValue* optionValue) {
927 TRAPS = _thread;
928 const char* declaringClass = optionValue->desc.declaringClass;
929 if (declaringClass == NULL) {
930 // skip PrintFlags pseudo-option
931 return;
932 }
933 const char* fieldName = optionValue->desc.name;
934 const char* fieldClass = optionValue->desc.fieldClass;
935
936 size_t fieldSigLen = 2 + strlen(fieldClass);
937 char* fieldSig = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, fieldSigLen + 1);
938 jio_snprintf(fieldSig, fieldSigLen + 1, "L%s;", fieldClass);
939 for (size_t i = 0; i < fieldSigLen; ++i) {
940 if (fieldSig[i] == '.') {
941 fieldSig[i] = '/';
886 } 942 }
887 os::close(file_handle); 943 }
888 if (num_read == st.st_size) { 944 fieldSig[fieldSigLen] = '\0';
889 char* line = buffer; 945 size_t declaringClassLen = strlen(declaringClass);
890 int lineNo = 1; 946 char* declaringClassBinary = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, declaringClassLen + 1);
891 while (line - buffer < num_read) { 947 for (size_t i = 0; i < declaringClassLen; ++i) {
892 char* nl = strchr(line, '\n'); 948 if (declaringClass[i] == '.') {
893 if (nl != NULL) { 949 declaringClassBinary[i] = '/';
894 *nl = '\0'; 950 } else {
895 } 951 declaringClassBinary[i] = declaringClass[i];
896 parse_argument(hotSpotOptionsClass, line, THREAD);
897 if (HAS_PENDING_EXCEPTION) {
898 warning("Error in %s:%d", path, lineNo);
899 return;
900 }
901 if (nl != NULL) {
902 line = nl + 1;
903 lineNo++;
904 } else {
905 // File without newline at the end
906 break;
907 }
908 }
909 } 952 }
910 } else { 953 }
911 warning("Error opening file %s due to %s", path, strerror(errno)); 954 declaringClassBinary[declaringClassLen] = '\0';
912 } 955
913 } 956 TempNewSymbol name = SymbolTable::new_symbol(declaringClassBinary, CHECK_WARN_ABORT_("Declaring class could not be found"));
914 } 957 Klass* klass = JVMCIRuntime::resolve_or_null(name, CHECK_WARN_ABORT_("Declaring class could not be resolved"));
915 958
916 jlong JVMCIRuntime::parse_primitive_option_value(char spec, const char* name, size_t name_len, const char* value, TRAPS) { 959 if (klass == NULL) {
917 check_required_value(name, name_len, value, CHECK_(0L)); 960 warning("Declaring class for option %s could not be resolved", declaringClass);
918 union { 961 abort();
919 jint i; 962 return;
920 jlong l; 963 }
921 double d; 964
922 } uu; 965 // The class has been loaded so the field and signature should already be in the symbol
923 uu.l = 0L; 966 // table. If they're not there, the field doesn't exist.
924 char dummy; 967 TempNewSymbol fieldname = SymbolTable::probe(fieldName, (int)strlen(fieldName));
925 switch (spec) { 968 TempNewSymbol signame = SymbolTable::probe(fieldSig, (int)fieldSigLen);
926 case 'd': 969 if (fieldname == NULL || signame == NULL) {
927 case 'f': { 970 warning("Symbols for field for option %s not found (in %s)", fieldName, declaringClass);
928 if (sscanf(value, "%lf%c", &uu.d, &dummy) == 1) { 971 abort();
929 return uu.l; 972 return;
930 } 973 }
974 // Make sure class is initialized before handing id's out to fields
975 klass->initialize(CHECK_WARN_ABORT_("Error while initializing declaring class for option"));
976
977 fieldDescriptor fd;
978 if (!InstanceKlass::cast(klass)->find_field(fieldname, signame, true, &fd)) {
979 warning("Field for option %s not found (in %s)", fieldName, declaringClass);
980 abort();
981 return;
982 }
983 oop value;
984 switch(optionValue->desc.type) {
985 case _boolean: {
986 jvalue jv;
987 jv.z = optionValue->boolean_value;
988 value = java_lang_boxing_object::create(T_BOOLEAN, &jv, THREAD);
931 break; 989 break;
932 } 990 }
933 case 'i': { 991 case _int: {
934 if (sscanf(value, "%d%c", &uu.i, &dummy) == 1) { 992 jvalue jv;
935 return (jlong)uu.i; 993 jv.i = optionValue->int_value;
936 } 994 value = java_lang_boxing_object::create(T_INT, &jv, THREAD);
937 break; 995 break;
938 } 996 }
997 case _long: {
998 jvalue jv;
999 jv.j = optionValue->long_value;
1000 value = java_lang_boxing_object::create(T_LONG, &jv, THREAD);
1001 break;
1002 }
1003 case _float: {
1004 jvalue jv;
1005 jv.f = optionValue->float_value;
1006 value = java_lang_boxing_object::create(T_FLOAT, &jv, THREAD);
1007 break;
1008 }
1009 case _double: {
1010 jvalue jv;
1011 jv.d = optionValue->double_value;
1012 value = java_lang_boxing_object::create(T_DOUBLE, &jv, THREAD);
1013 break;
1014 }
1015 case _string:
1016 value = java_lang_String::create_from_str(optionValue->string_value, THREAD)();
1017 break;
939 default: 1018 default:
940 ShouldNotReachHere(); 1019 ShouldNotReachHere();
941 } 1020 }
942 ResourceMark rm(THREAD); 1021
943 char buf[200]; 1022 oop optionValueOop = klass->java_mirror()->obj_field(fd.offset());
944 bool missing = strlen(value) == 0; 1023
945 if (missing) { 1024 if (optionValueOop == NULL) {
946 jio_snprintf(buf, sizeof(buf), "Missing %s value for JVMCI option %.*s", (spec == 'i' ? "numeric" : "float/double"), name_len, name); 1025 warning("Option field was null, can not set %s", fieldName);
947 } else { 1026 abort();
948 jio_snprintf(buf, sizeof(buf), "Invalid %s value for JVMCI option %.*s: %s", (spec == 'i' ? "numeric" : "float/double"), name_len, name, value); 1027 return;
949 } 1028 }
950 THROW_MSG_(vmSymbols::java_lang_InternalError(), buf, 0L); 1029
951 } 1030 if (!InstanceKlass::cast(optionValueOop->klass())->find_field(vmSymbols::value_name(), vmSymbols::object_signature(), false, &fd)) {
952 1031 warning("'Object value' field not found in option class %s, can not set option %s", fieldClass, fieldName);
953 void JVMCIRuntime::set_option_helper(KlassHandle hotSpotOptionsClass, char* name, size_t name_len, Handle option, jchar spec, Handle stringValue, jlong primitiveValue) { 1032 abort();
954 Thread* THREAD = Thread::current(); 1033 return;
955 Handle name_handle; 1034 }
956 if (name != NULL) { 1035
957 if (strlen(name) > name_len) { 1036 optionValueOop->obj_field_put(fd.offset(), value);
958 // Temporarily replace '=' with NULL to create the Java string for the option name 1037 }
959 char save = name[name_len]; 1038 };
960 name[name_len] = '\0'; 1039
961 name_handle = java_lang_String::create_from_str(name, THREAD); 1040 void JVMCIRuntime::set_options(OptionsValueTable* options, TRAPS) {
962 name[name_len] = '='; 1041 ensure_jvmci_class_loader_is_initialized();
963 if (HAS_PENDING_EXCEPTION) { 1042 {
964 return; 1043 ResourceMark rm;
965 } 1044 SetOptionClosure closure(THREAD);
966 } else { 1045 options->for_each(&closure);
967 assert(strlen(name) == name_len, "must be"); 1046 if (closure.is_aborted()) {
968 name_handle = java_lang_String::create_from_str(name, CHECK); 1047 vm_abort(false);
969 } 1048 }
970 } 1049 }
971 1050 OptionValue* printFlags = options->get(PRINT_FLAGS_ARG);
972 TempNewSymbol setOption = SymbolTable::new_symbol("setOption", CHECK); 1051 if (printFlags != NULL && printFlags->boolean_value) {
973 TempNewSymbol sig = SymbolTable::new_symbol("(Ljava/lang/String;Lcom/oracle/jvmci/options/OptionValue;CLjava/lang/String;J)V", CHECK); 1052 print_flags_helper(CHECK_ABORT);
1053 }
1054 }
1055
1056 void JVMCIRuntime::print_flags_helper(TRAPS) {
1057 // TODO(gd) write this in C++?
1058 HandleMark hm(THREAD);
1059 TempNewSymbol name = SymbolTable::new_symbol("com/oracle/jvmci/hotspot/HotSpotOptions", CHECK_ABORT);
1060 KlassHandle hotSpotOptionsClass = load_required_class(name);
1061 TempNewSymbol setOption = SymbolTable::new_symbol("printFlags", CHECK);
974 JavaValue result(T_VOID); 1062 JavaValue result(T_VOID);
975 JavaCallArguments args; 1063 JavaCallArguments args;
976 args.push_oop(name_handle()); 1064 JavaCalls::call_static(&result, hotSpotOptionsClass, setOption, vmSymbols::void_method_signature(), &args, CHECK);
977 args.push_oop(option());
978 args.push_int(spec);
979 args.push_oop(stringValue());
980 args.push_long(primitiveValue);
981 JavaCalls::call_static(&result, hotSpotOptionsClass, setOption, sig, &args, CHECK);
982 }
983
984 Handle JVMCIRuntime::get_OptionValue(const char* declaringClass, const char* fieldName, const char* fieldSig, TRAPS) {
985 TempNewSymbol name = SymbolTable::new_symbol(declaringClass, CHECK_NH);
986 Klass* klass = resolve_or_fail(name, CHECK_NH);
987
988 // The class has been loaded so the field and signature should already be in the symbol
989 // table. If they're not there, the field doesn't exist.
990 TempNewSymbol fieldname = SymbolTable::probe(fieldName, (int)strlen(fieldName));
991 TempNewSymbol signame = SymbolTable::probe(fieldSig, (int)strlen(fieldSig));
992 if (fieldname == NULL || signame == NULL) {
993 THROW_MSG_(vmSymbols::java_lang_NoSuchFieldError(), (char*) fieldName, Handle());
994 }
995 // Make sure class is initialized before handing id's out to fields
996 klass->initialize(CHECK_NH);
997
998 fieldDescriptor fd;
999 if (!InstanceKlass::cast(klass)->find_field(fieldname, signame, true, &fd)) {
1000 THROW_MSG_(vmSymbols::java_lang_NoSuchFieldError(), (char*) fieldName, Handle());
1001 }
1002
1003 Handle ret = klass->java_mirror()->obj_field(fd.offset());
1004 return ret;
1005 } 1065 }
1006 1066
1007 Handle JVMCIRuntime::create_Service(const char* name, TRAPS) { 1067 Handle JVMCIRuntime::create_Service(const char* name, TRAPS) {
1008 TempNewSymbol kname = SymbolTable::new_symbol(name, CHECK_NH); 1068 TempNewSymbol kname = SymbolTable::new_symbol(name, CHECK_NH);
1009 Klass* k = resolve_or_fail(kname, CHECK_NH); 1069 Klass* k = resolve_or_fail(kname, CHECK_NH);
1074 vm_abort(false); 1134 vm_abort(false);
1075 } 1135 }
1076 return klass; 1136 return klass;
1077 } 1137 }
1078 1138
1079 Handle JVMCIRuntime::get_service_impls(KlassHandle serviceKlass, TRAPS) { 1139 void JVMCIRuntime::parse_lines(char* path, ParseClosure* closure, bool warnStatFailure) {
1080 const char* home = Arguments::get_java_home();
1081 const char* serviceName = serviceKlass->external_name();
1082
1083 size_t path_len = strlen(home) + strlen("/lib/jvmci/services/") + strlen(serviceName) + 1;
1084 char* path = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, path_len);
1085 char sep = os::file_separator()[0];
1086 sprintf(path, "%s%clib%cjvmci%cservices%c%s", home, sep, sep, sep, sep, serviceName);
1087 struct stat st; 1140 struct stat st;
1088 if (os::stat(path, &st) == 0) { 1141 if (os::stat(path, &st) == 0 && (st.st_mode & S_IFREG) == S_IFREG) { // exists & is regular file
1089 int file_handle = os::open(path, 0, 0); 1142 int file_handle = os::open(path, 0, 0);
1090 if (file_handle != -1) { 1143 if (file_handle != -1) {
1091 char* buffer = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, st.st_size + 1); 1144 char* buffer = NEW_C_HEAP_ARRAY(char, st.st_size + 1, mtInternal);
1092 int num_read = (int) os::read(file_handle, (char*) buffer, st.st_size); 1145 int num_read = (int) os::read(file_handle, (char*) buffer, st.st_size);
1093 if (num_read == -1) { 1146 if (num_read == -1) {
1094 warning("Error reading file %s due to %s", path, strerror(errno)); 1147 warning("Error reading file %s due to %s", path, strerror(errno));
1095 } else if (num_read != st.st_size) { 1148 } else if (num_read != st.st_size) {
1096 warning("Only read %d of " SIZE_FORMAT " bytes from %s", num_read, (size_t) st.st_size, path); 1149 warning("Only read %d of " SIZE_FORMAT " bytes from %s", num_read, (size_t) st.st_size, path);
1097 } 1150 }
1098 os::close(file_handle); 1151 os::close(file_handle);
1152 closure->set_filename(path);
1099 if (num_read == st.st_size) { 1153 if (num_read == st.st_size) {
1100 buffer[num_read] = '\0'; 1154 buffer[num_read] = '\0';
1101 GrowableArray<char*>* implNames = new GrowableArray<char*>(); 1155
1102 char* line = buffer; 1156 char* line = buffer;
1103 while (line - buffer < num_read) { 1157 while (line - buffer < num_read && !closure->is_aborted()) {
1104 // find line end (\r, \n or \r\n) 1158 // find line end (\r, \n or \r\n)
1105 char* nextline = NULL; 1159 char* nextline = NULL;
1106 char* cr = strchr(line, '\r'); 1160 char* cr = strchr(line, '\r');
1107 char* lf = strchr(line, '\n'); 1161 char* lf = strchr(line, '\n');
1108 if (cr != NULL && lf != NULL) { 1162 if (cr != NULL && lf != NULL) {
1126 // trim right 1180 // trim right
1127 while (end > line && (*(end -1) == ' ' || *(end -1) == '\t')) end--; 1181 while (end > line && (*(end -1) == ' ' || *(end -1) == '\t')) end--;
1128 *end = '\0'; 1182 *end = '\0';
1129 // skip comments and empty lines 1183 // skip comments and empty lines
1130 if (*line != '#' && strlen(line) > 0) { 1184 if (*line != '#' && strlen(line) > 0) {
1131 // Turn all '.'s into '/'s 1185 closure->parse_line(line);
1132 for (size_t index = 0; line[index] != '\0'; index++) {
1133 if (line[index] == '.') {
1134 line[index] = '/';
1135 }
1136 }
1137 implNames->append(line);
1138 } 1186 }
1139 if (nextline != NULL) { 1187 if (nextline != NULL) {
1140 line = nextline; 1188 line = nextline;
1141 } else { 1189 } else {
1142 // File without newline at the end 1190 // File without newline at the end
1143 break; 1191 break;
1144 } 1192 }
1145 } 1193 }
1146
1147 objArrayOop servicesOop = oopFactory::new_objArray(serviceKlass(), implNames->length(), CHECK_NH);
1148 objArrayHandle services(THREAD, servicesOop);
1149 for (int i = 0; i < implNames->length(); ++i) {
1150 char* implName = implNames->at(i);
1151 Handle service = create_Service(implName, CHECK_NH);
1152 services->obj_at_put(i, service());
1153 }
1154 return services;
1155 } 1194 }
1195 FREE_C_HEAP_ARRAY(char, buffer, mtInternal);
1156 } else { 1196 } else {
1157 warning("Error opening file %s due to %s", path, strerror(errno)); 1197 warning("Error opening file %s due to %s", path, strerror(errno));
1158 } 1198 }
1159 } else { 1199 } else if (warnStatFailure) {
1160 warning("Error opening file %s due to %s", path, strerror(errno)); 1200 warning("Could not stat file %s due to %s", path, strerror(errno));
1161 } 1201 }
1162 return Handle(); 1202 }
1163 } 1203
1164 1204 class ServiceParseClosure : public ParseClosure {
1165 #include "graalRuntime.inline.hpp" 1205 GrowableArray<char*> _implNames;
1206 public:
1207 ServiceParseClosure() : _implNames() {}
1208 void do_line(char* line) {
1209 size_t lineLen = strlen(line);
1210 char* implName = NEW_C_HEAP_ARRAY(char, lineLen + 1, mtCompiler); // TODO (gd) i'm leaking
1211 // Turn all '.'s into '/'s
1212 for (size_t index = 0; index < lineLen; ++index) {
1213 if (line[index] == '.') {
1214 implName[index] = '/';
1215 } else {
1216 implName[index] = line[index];
1217 }
1218 }
1219 implName[lineLen] = '\0';
1220 _implNames.append(implName);
1221 }
1222 GrowableArray<char*>* implNames() {return &_implNames;}
1223 };
1224
1225
1226 Handle JVMCIRuntime::get_service_impls(KlassHandle serviceKlass, TRAPS) {
1227 const char* home = Arguments::get_java_home();
1228 const char* serviceName = serviceKlass->external_name();
1229 size_t path_len = strlen(home) + strlen("/lib/jvmci/services/") + strlen(serviceName) + 1;
1230 char* path = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, path_len);
1231 char sep = os::file_separator()[0];
1232 sprintf(path, "%s%clib%cjvmci%cservices%c%s", home, sep, sep, sep, sep, serviceName);
1233 ServiceParseClosure closure;
1234 parse_lines(path, &closure, true); // TODO(gd) cache parsing results?
1235
1236 GrowableArray<char*>* implNames = closure.implNames();
1237 objArrayOop servicesOop = oopFactory::new_objArray(serviceKlass(), implNames->length(), CHECK_NH);
1238 objArrayHandle services(THREAD, servicesOop);
1239 for (int i = 0; i < implNames->length(); ++i) {
1240 char* implName = implNames->at(i);
1241 Handle service = create_Service(implName, CHECK_NH);
1242 services->obj_at_put(i, service());
1243 }
1244 return services;
1245 }