Mercurial > hg > truffle
diff src/share/vm/runtime/signature.cpp @ 0:a61af66fc99e jdk7-b24
Initial load
author | duke |
---|---|
date | Sat, 01 Dec 2007 00:00:00 +0000 |
parents | |
children | f03d0a26bf83 2ffde6cfe049 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/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; + } +}