Mercurial > hg > truffle
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 } |