--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/runtime/signature.cpp Sat Dec 01 00:00:00 2007 +0000
@@ -0,0 +1,432 @@
+/*
+ * Copyright 1997-2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ */
+
+# include "incls/_precompiled.incl"
+# include "incls/_signature.cpp.incl"
+
+
+// Implementation of SignatureIterator
+
+// Signature syntax:
+//
+// Signature = "(" {Parameter} ")" ReturnType.
+// Parameter = FieldType.
+// ReturnType = FieldType | "V".
+// FieldType = "B" | "C" | "D" | "F" | "I" | "J" | "S" | "Z" | "L" ClassName ";" | "[" FieldType.
+// ClassName = string.
+
+
+SignatureIterator::SignatureIterator(symbolHandle signature) {
+ assert(signature->is_symbol(), "not a symbol");
+ _signature = signature;
+ _parameter_index = 0;
+}
+
+// Overloaded version called without handle
+SignatureIterator::SignatureIterator(symbolOop signature) {
+ symbolHandle sh(Thread::current(), signature);
+ _signature = sh;
+ _parameter_index = 0;
+}
+
+SignatureIterator::SignatureIterator(Thread *thread, symbolOop signature) {
+ symbolHandle sh(thread, signature);
+ _signature = sh;
+ _parameter_index = 0;
+}
+
+void SignatureIterator::expect(char c) {
+ if (_signature->byte_at(_index) != c) fatal1("expecting %c", c);
+ _index++;
+}
+
+
+void SignatureIterator::skip_optional_size() {
+ symbolOop sig = _signature();
+ char c = sig->byte_at(_index);
+ while ('0' <= c && c <= '9') c = sig->byte_at(++_index);
+}
+
+
+int SignatureIterator::parse_type() {
+ // Note: This function could be simplified by using "return T_XXX_size;"
+ // instead of the assignment and the break statements. However, it
+ // seems that the product build for win32_i486 with MS VC++ 6.0 doesn't
+ // work (stack underflow for some tests) - this seems to be a VC++ 6.0
+ // compiler bug (was problem - gri 4/27/2000).
+ int size = -1;
+ switch(_signature->byte_at(_index)) {
+ case 'B': do_byte (); if (_parameter_index < 0 ) _return_type = T_BYTE;
+ _index++; size = T_BYTE_size ; break;
+ case 'C': do_char (); if (_parameter_index < 0 ) _return_type = T_CHAR;
+ _index++; size = T_CHAR_size ; break;
+ case 'D': do_double(); if (_parameter_index < 0 ) _return_type = T_DOUBLE;
+ _index++; size = T_DOUBLE_size ; break;
+ case 'F': do_float (); if (_parameter_index < 0 ) _return_type = T_FLOAT;
+ _index++; size = T_FLOAT_size ; break;
+ case 'I': do_int (); if (_parameter_index < 0 ) _return_type = T_INT;
+ _index++; size = T_INT_size ; break;
+ case 'J': do_long (); if (_parameter_index < 0 ) _return_type = T_LONG;
+ _index++; size = T_LONG_size ; break;
+ case 'S': do_short (); if (_parameter_index < 0 ) _return_type = T_SHORT;
+ _index++; size = T_SHORT_size ; break;
+ case 'Z': do_bool (); if (_parameter_index < 0 ) _return_type = T_BOOLEAN;
+ _index++; size = T_BOOLEAN_size; break;
+ case 'V': do_void (); if (_parameter_index < 0 ) _return_type = T_VOID;
+ _index++; size = T_VOID_size; ; break;
+ case 'L':
+ { int begin = ++_index;
+ symbolOop sig = _signature();
+ while (sig->byte_at(_index++) != ';') ;
+ do_object(begin, _index);
+ }
+ if (_parameter_index < 0 ) _return_type = T_OBJECT;
+ size = T_OBJECT_size;
+ break;
+ case '[':
+ { int begin = ++_index;
+ skip_optional_size();
+ symbolOop sig = _signature();
+ while (sig->byte_at(_index) == '[') {
+ _index++;
+ skip_optional_size();
+ }
+ if (sig->byte_at(_index) == 'L') {
+ while (sig->byte_at(_index++) != ';') ;
+ } else {
+ _index++;
+ }
+ do_array(begin, _index);
+ if (_parameter_index < 0 ) _return_type = T_ARRAY;
+ }
+ size = T_ARRAY_size;
+ break;
+ default:
+ ShouldNotReachHere();
+ break;
+ }
+ assert(size >= 0, "size must be set");
+ return size;
+}
+
+
+void SignatureIterator::check_signature_end() {
+ if (_index < _signature->utf8_length()) {
+ tty->print_cr("too many chars in signature");
+ _signature->print_value_on(tty);
+ tty->print_cr(" @ %d", _index);
+ }
+}
+
+
+void SignatureIterator::dispatch_field() {
+ // no '(', just one (field) type
+ _index = 0;
+ _parameter_index = 0;
+ parse_type();
+ check_signature_end();
+}
+
+
+void SignatureIterator::iterate_parameters() {
+ // Parse parameters
+ _index = 0;
+ _parameter_index = 0;
+ expect('(');
+ while (_signature->byte_at(_index) != ')') _parameter_index += parse_type();
+ expect(')');
+ _parameter_index = 0;
+}
+
+// Optimized version of iterat_parameters when fingerprint is known
+void SignatureIterator::iterate_parameters( uint64_t fingerprint ) {
+ uint64_t saved_fingerprint = fingerprint;
+
+ // Check for too many arguments
+ if ( fingerprint == UCONST64(-1) ) {
+ SignatureIterator::iterate_parameters();
+ return;
+ }
+
+ assert(fingerprint, "Fingerprint should not be 0");
+
+ _parameter_index = 0;
+ fingerprint = fingerprint >> (static_feature_size + result_feature_size);
+ while ( 1 ) {
+ switch ( fingerprint & parameter_feature_mask ) {
+ case bool_parm:
+ do_bool();
+ _parameter_index += T_BOOLEAN_size;
+ break;
+ case byte_parm:
+ do_byte();
+ _parameter_index += T_BYTE_size;
+ break;
+ case char_parm:
+ do_char();
+ _parameter_index += T_CHAR_size;
+ break;
+ case short_parm:
+ do_short();
+ _parameter_index += T_SHORT_size;
+ break;
+ case int_parm:
+ do_int();
+ _parameter_index += T_INT_size;
+ break;
+ case obj_parm:
+ do_object(0, 0);
+ _parameter_index += T_OBJECT_size;
+ break;
+ case long_parm:
+ do_long();
+ _parameter_index += T_LONG_size;
+ break;
+ case float_parm:
+ do_float();
+ _parameter_index += T_FLOAT_size;
+ break;
+ case double_parm:
+ do_double();
+ _parameter_index += T_DOUBLE_size;
+ break;
+ case done_parm:
+ return;
+ break;
+ default:
+ tty->print_cr("*** parameter is %d", fingerprint & parameter_feature_mask);
+ tty->print_cr("*** fingerprint is " PTR64_FORMAT, saved_fingerprint);
+ ShouldNotReachHere();
+ break;
+ }
+ fingerprint >>= parameter_feature_size;
+ }
+ _parameter_index = 0;
+}
+
+
+void SignatureIterator::iterate_returntype() {
+ // Ignore parameters
+ _index = 0;
+ expect('(');
+ symbolOop sig = _signature();
+ while (sig->byte_at(_index) != ')') _index++;
+ expect(')');
+ // Parse return type
+ _parameter_index = -1;
+ parse_type();
+ check_signature_end();
+ _parameter_index = 0;
+}
+
+
+void SignatureIterator::iterate() {
+ // Parse parameters
+ _parameter_index = 0;
+ _index = 0;
+ expect('(');
+ while (_signature->byte_at(_index) != ')') _parameter_index += parse_type();
+ expect(')');
+ // Parse return type
+ _parameter_index = -1;
+ parse_type();
+ check_signature_end();
+ _parameter_index = 0;
+}
+
+
+// Implementation of SignatureStream
+
+bool SignatureStream::is_done() const {
+ return _end > _signature()->utf8_length();
+}
+
+
+void SignatureStream::next_non_primitive(int t) {
+ switch (t) {
+ case 'L': {
+ _type = T_OBJECT;
+ symbolOop sig = _signature();
+ while (sig->byte_at(_end++) != ';');
+ break;
+ }
+ case '[': {
+ _type = T_ARRAY;
+ symbolOop sig = _signature();
+ char c = sig->byte_at(_end);
+ while ('0' <= c && c <= '9') c = sig->byte_at(_end++);
+ while (sig->byte_at(_end) == '[') {
+ _end++;
+ c = sig->byte_at(_end);
+ while ('0' <= c && c <= '9') c = sig->byte_at(_end++);
+ }
+ switch(sig->byte_at(_end)) {
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'F':
+ case 'I':
+ case 'J':
+ case 'S':
+ case 'Z':_end++; break;
+ default: {
+ while (sig->byte_at(_end++) != ';');
+ break;
+ }
+ }
+ break;
+ }
+ case ')': _end++; next(); _at_return_type = true; break;
+ default : ShouldNotReachHere();
+ }
+}
+
+
+bool SignatureStream::is_object() const {
+ return _type == T_OBJECT
+ || _type == T_ARRAY;
+}
+
+bool SignatureStream::is_array() const {
+ return _type == T_ARRAY;
+}
+
+symbolOop SignatureStream::as_symbol(TRAPS) {
+ // Create a symbol from for string _begin _end
+ int begin = _begin;
+ int end = _end;
+
+ if ( _signature()->byte_at(_begin) == 'L'
+ && _signature()->byte_at(_end-1) == ';') {
+ begin++;
+ end--;
+ }
+
+ symbolOop result = oopFactory::new_symbol(_signature, begin, end, CHECK_NULL);
+ return result;
+}
+
+
+symbolOop SignatureStream::as_symbol_or_null() {
+ // Create a symbol from for string _begin _end
+ ResourceMark rm;
+
+ int begin = _begin;
+ int end = _end;
+
+ if ( _signature()->byte_at(_begin) == 'L'
+ && _signature()->byte_at(_end-1) == ';') {
+ begin++;
+ end--;
+ }
+
+ char* buffer = NEW_RESOURCE_ARRAY(char, end - begin);
+ for (int index = begin; index < end; index++) {
+ buffer[index - begin] = _signature()->byte_at(index);
+ }
+ symbolOop result = SymbolTable::probe(buffer, end - begin);
+ return result;
+}
+
+bool SignatureVerifier::is_valid_signature(symbolHandle sig) {
+ const char* signature = (const char*)sig->bytes();
+ ssize_t len = sig->utf8_length();
+ if (signature == NULL || signature[0] == '\0' || len < 1) {
+ return false;
+ } else if (signature[0] == '(') {
+ return is_valid_method_signature(sig);
+ } else {
+ return is_valid_type_signature(sig);
+ }
+}
+
+bool SignatureVerifier::is_valid_method_signature(symbolHandle sig) {
+ const char* method_sig = (const char*)sig->bytes();
+ ssize_t len = sig->utf8_length();
+ ssize_t index = 0;
+ if (method_sig != NULL && len > 1 && method_sig[index] == '(') {
+ ++index;
+ while (index < len && method_sig[index] != ')') {
+ ssize_t res = is_valid_type(&method_sig[index], len - index);
+ if (res == -1) {
+ return false;
+ } else {
+ index += res;
+ }
+ }
+ if (index < len && method_sig[index] == ')') {
+ // check the return type
+ ++index;
+ return (is_valid_type(&method_sig[index], len - index) == (len - index));
+ }
+ }
+ return false;
+}
+
+bool SignatureVerifier::is_valid_type_signature(symbolHandle sig) {
+ const char* type_sig = (const char*)sig->bytes();
+ ssize_t len = sig->utf8_length();
+ return (type_sig != NULL && len >= 1 &&
+ (is_valid_type(type_sig, len) == len));
+}
+
+// Checks to see if the type (not to go beyond 'limit') refers to a valid type.
+// Returns -1 if it is not, or the index of the next character that is not part
+// of the type. The type encoding may end before 'limit' and that's ok.
+ssize_t SignatureVerifier::is_valid_type(const char* type, ssize_t limit) {
+ ssize_t index = 0;
+
+ // Iterate over any number of array dimensions
+ while (index < limit && type[index] == '[') ++index;
+ if (index >= limit) {
+ return -1;
+ }
+ switch (type[index]) {
+ case 'B': case 'C': case 'D': case 'F': case 'I':
+ case 'J': case 'S': case 'Z': case 'V':
+ return index + 1;
+ case 'L':
+ for (index = index + 1; index < limit; ++index) {
+ char c = type[index];
+ if (c == ';') {
+ return index + 1;
+ }
+ if (invalid_name_char(c)) {
+ return -1;
+ }
+ }
+ // fall through
+ default: ; // fall through
+ }
+ return -1;
+}
+
+bool SignatureVerifier::invalid_name_char(char c) {
+ switch (c) {
+ case '\0': case '.': case ';': case '[':
+ return true;
+ default:
+ return false;
+ }
+}