signature.cpp revision 1472:c18cbe5936b8
1/* 2 * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25# include "incls/_precompiled.incl" 26# include "incls/_signature.cpp.incl" 27 28 29// Implementation of SignatureIterator 30 31// Signature syntax: 32// 33// Signature = "(" {Parameter} ")" ReturnType. 34// Parameter = FieldType. 35// ReturnType = FieldType | "V". 36// FieldType = "B" | "C" | "D" | "F" | "I" | "J" | "S" | "Z" | "L" ClassName ";" | "[" FieldType. 37// ClassName = string. 38 39 40SignatureIterator::SignatureIterator(symbolHandle signature) { 41 assert(signature->is_symbol(), "not a symbol"); 42 _signature = signature; 43 _parameter_index = 0; 44} 45 46// Overloaded version called without handle 47SignatureIterator::SignatureIterator(symbolOop signature) { 48 symbolHandle sh(Thread::current(), signature); 49 _signature = sh; 50 _parameter_index = 0; 51} 52 53SignatureIterator::SignatureIterator(Thread *thread, symbolOop signature) { 54 symbolHandle sh(thread, signature); 55 _signature = sh; 56 _parameter_index = 0; 57} 58 59void SignatureIterator::expect(char c) { 60 if (_signature->byte_at(_index) != c) fatal(err_msg("expecting %c", c)); 61 _index++; 62} 63 64 65void SignatureIterator::skip_optional_size() { 66 symbolOop sig = _signature(); 67 char c = sig->byte_at(_index); 68 while ('0' <= c && c <= '9') c = sig->byte_at(++_index); 69} 70 71 72int SignatureIterator::parse_type() { 73 // Note: This function could be simplified by using "return T_XXX_size;" 74 // instead of the assignment and the break statements. However, it 75 // seems that the product build for win32_i486 with MS VC++ 6.0 doesn't 76 // work (stack underflow for some tests) - this seems to be a VC++ 6.0 77 // compiler bug (was problem - gri 4/27/2000). 78 int size = -1; 79 switch(_signature->byte_at(_index)) { 80 case 'B': do_byte (); if (_parameter_index < 0 ) _return_type = T_BYTE; 81 _index++; size = T_BYTE_size ; break; 82 case 'C': do_char (); if (_parameter_index < 0 ) _return_type = T_CHAR; 83 _index++; size = T_CHAR_size ; break; 84 case 'D': do_double(); if (_parameter_index < 0 ) _return_type = T_DOUBLE; 85 _index++; size = T_DOUBLE_size ; break; 86 case 'F': do_float (); if (_parameter_index < 0 ) _return_type = T_FLOAT; 87 _index++; size = T_FLOAT_size ; break; 88 case 'I': do_int (); if (_parameter_index < 0 ) _return_type = T_INT; 89 _index++; size = T_INT_size ; break; 90 case 'J': do_long (); if (_parameter_index < 0 ) _return_type = T_LONG; 91 _index++; size = T_LONG_size ; break; 92 case 'S': do_short (); if (_parameter_index < 0 ) _return_type = T_SHORT; 93 _index++; size = T_SHORT_size ; break; 94 case 'Z': do_bool (); if (_parameter_index < 0 ) _return_type = T_BOOLEAN; 95 _index++; size = T_BOOLEAN_size; break; 96 case 'V': do_void (); if (_parameter_index < 0 ) _return_type = T_VOID; 97 _index++; size = T_VOID_size; ; break; 98 case 'L': 99 { int begin = ++_index; 100 symbolOop sig = _signature(); 101 while (sig->byte_at(_index++) != ';') ; 102 do_object(begin, _index); 103 } 104 if (_parameter_index < 0 ) _return_type = T_OBJECT; 105 size = T_OBJECT_size; 106 break; 107 case '[': 108 { int begin = ++_index; 109 skip_optional_size(); 110 symbolOop sig = _signature(); 111 while (sig->byte_at(_index) == '[') { 112 _index++; 113 skip_optional_size(); 114 } 115 if (sig->byte_at(_index) == 'L') { 116 while (sig->byte_at(_index++) != ';') ; 117 } else { 118 _index++; 119 } 120 do_array(begin, _index); 121 if (_parameter_index < 0 ) _return_type = T_ARRAY; 122 } 123 size = T_ARRAY_size; 124 break; 125 default: 126 ShouldNotReachHere(); 127 break; 128 } 129 assert(size >= 0, "size must be set"); 130 return size; 131} 132 133 134void SignatureIterator::check_signature_end() { 135 if (_index < _signature->utf8_length()) { 136 tty->print_cr("too many chars in signature"); 137 _signature->print_value_on(tty); 138 tty->print_cr(" @ %d", _index); 139 } 140} 141 142 143void SignatureIterator::dispatch_field() { 144 // no '(', just one (field) type 145 _index = 0; 146 _parameter_index = 0; 147 parse_type(); 148 check_signature_end(); 149} 150 151 152void SignatureIterator::iterate_parameters() { 153 // Parse parameters 154 _index = 0; 155 _parameter_index = 0; 156 expect('('); 157 while (_signature->byte_at(_index) != ')') _parameter_index += parse_type(); 158 expect(')'); 159 _parameter_index = 0; 160} 161 162// Optimized version of iterat_parameters when fingerprint is known 163void SignatureIterator::iterate_parameters( uint64_t fingerprint ) { 164 uint64_t saved_fingerprint = fingerprint; 165 166 // Check for too many arguments 167 if ( fingerprint == UCONST64(-1) ) { 168 SignatureIterator::iterate_parameters(); 169 return; 170 } 171 172 assert(fingerprint, "Fingerprint should not be 0"); 173 174 _parameter_index = 0; 175 fingerprint = fingerprint >> (static_feature_size + result_feature_size); 176 while ( 1 ) { 177 switch ( fingerprint & parameter_feature_mask ) { 178 case bool_parm: 179 do_bool(); 180 _parameter_index += T_BOOLEAN_size; 181 break; 182 case byte_parm: 183 do_byte(); 184 _parameter_index += T_BYTE_size; 185 break; 186 case char_parm: 187 do_char(); 188 _parameter_index += T_CHAR_size; 189 break; 190 case short_parm: 191 do_short(); 192 _parameter_index += T_SHORT_size; 193 break; 194 case int_parm: 195 do_int(); 196 _parameter_index += T_INT_size; 197 break; 198 case obj_parm: 199 do_object(0, 0); 200 _parameter_index += T_OBJECT_size; 201 break; 202 case long_parm: 203 do_long(); 204 _parameter_index += T_LONG_size; 205 break; 206 case float_parm: 207 do_float(); 208 _parameter_index += T_FLOAT_size; 209 break; 210 case double_parm: 211 do_double(); 212 _parameter_index += T_DOUBLE_size; 213 break; 214 case done_parm: 215 return; 216 break; 217 default: 218 tty->print_cr("*** parameter is %d", fingerprint & parameter_feature_mask); 219 tty->print_cr("*** fingerprint is " PTR64_FORMAT, saved_fingerprint); 220 ShouldNotReachHere(); 221 break; 222 } 223 fingerprint >>= parameter_feature_size; 224 } 225 _parameter_index = 0; 226} 227 228 229void SignatureIterator::iterate_returntype() { 230 // Ignore parameters 231 _index = 0; 232 expect('('); 233 symbolOop sig = _signature(); 234 while (sig->byte_at(_index) != ')') _index++; 235 expect(')'); 236 // Parse return type 237 _parameter_index = -1; 238 parse_type(); 239 check_signature_end(); 240 _parameter_index = 0; 241} 242 243 244void SignatureIterator::iterate() { 245 // Parse parameters 246 _parameter_index = 0; 247 _index = 0; 248 expect('('); 249 while (_signature->byte_at(_index) != ')') _parameter_index += parse_type(); 250 expect(')'); 251 // Parse return type 252 _parameter_index = -1; 253 parse_type(); 254 check_signature_end(); 255 _parameter_index = 0; 256} 257 258 259// Implementation of SignatureStream 260 261bool SignatureStream::is_done() const { 262 return _end > _signature()->utf8_length(); 263} 264 265 266void SignatureStream::next_non_primitive(int t) { 267 switch (t) { 268 case 'L': { 269 _type = T_OBJECT; 270 symbolOop sig = _signature(); 271 while (sig->byte_at(_end++) != ';'); 272 break; 273 } 274 case '[': { 275 _type = T_ARRAY; 276 symbolOop sig = _signature(); 277 char c = sig->byte_at(_end); 278 while ('0' <= c && c <= '9') c = sig->byte_at(_end++); 279 while (sig->byte_at(_end) == '[') { 280 _end++; 281 c = sig->byte_at(_end); 282 while ('0' <= c && c <= '9') c = sig->byte_at(_end++); 283 } 284 switch(sig->byte_at(_end)) { 285 case 'B': 286 case 'C': 287 case 'D': 288 case 'F': 289 case 'I': 290 case 'J': 291 case 'S': 292 case 'Z':_end++; break; 293 default: { 294 while (sig->byte_at(_end++) != ';'); 295 break; 296 } 297 } 298 break; 299 } 300 case ')': _end++; next(); _at_return_type = true; break; 301 default : ShouldNotReachHere(); 302 } 303} 304 305 306bool SignatureStream::is_object() const { 307 return _type == T_OBJECT 308 || _type == T_ARRAY; 309} 310 311bool SignatureStream::is_array() const { 312 return _type == T_ARRAY; 313} 314 315symbolOop SignatureStream::as_symbol(TRAPS) { 316 // Create a symbol from for string _begin _end 317 int begin = _begin; 318 int end = _end; 319 320 if ( _signature()->byte_at(_begin) == 'L' 321 && _signature()->byte_at(_end-1) == ';') { 322 begin++; 323 end--; 324 } 325 326 symbolOop result = oopFactory::new_symbol(_signature, begin, end, CHECK_NULL); 327 return result; 328} 329 330klassOop SignatureStream::as_klass(Handle class_loader, Handle protection_domain, 331 FailureMode failure_mode, TRAPS) { 332 if (!is_object()) return NULL; 333 symbolOop name = as_symbol(CHECK_NULL); 334 if (failure_mode == ReturnNull) { 335 return SystemDictionary::resolve_or_null(name, class_loader, protection_domain, THREAD); 336 } else { 337 bool throw_error = (failure_mode == NCDFError); 338 return SystemDictionary::resolve_or_fail(name, class_loader, protection_domain, throw_error, THREAD); 339 } 340} 341 342oop SignatureStream::as_java_mirror(Handle class_loader, Handle protection_domain, 343 FailureMode failure_mode, TRAPS) { 344 if (!is_object()) 345 return Universe::java_mirror(type()); 346 klassOop klass = as_klass(class_loader, protection_domain, failure_mode, CHECK_NULL); 347 if (klass == NULL) return NULL; 348 return Klass::cast(klass)->java_mirror(); 349} 350 351symbolOop SignatureStream::as_symbol_or_null() { 352 // Create a symbol from for string _begin _end 353 ResourceMark rm; 354 355 int begin = _begin; 356 int end = _end; 357 358 if ( _signature()->byte_at(_begin) == 'L' 359 && _signature()->byte_at(_end-1) == ';') { 360 begin++; 361 end--; 362 } 363 364 char* buffer = NEW_RESOURCE_ARRAY(char, end - begin); 365 for (int index = begin; index < end; index++) { 366 buffer[index - begin] = _signature()->byte_at(index); 367 } 368 symbolOop result = SymbolTable::probe(buffer, end - begin); 369 return result; 370} 371 372bool SignatureVerifier::is_valid_signature(symbolHandle sig) { 373 const char* signature = (const char*)sig->bytes(); 374 ssize_t len = sig->utf8_length(); 375 if (signature == NULL || signature[0] == '\0' || len < 1) { 376 return false; 377 } else if (signature[0] == '(') { 378 return is_valid_method_signature(sig); 379 } else { 380 return is_valid_type_signature(sig); 381 } 382} 383 384bool SignatureVerifier::is_valid_method_signature(symbolHandle sig) { 385 const char* method_sig = (const char*)sig->bytes(); 386 ssize_t len = sig->utf8_length(); 387 ssize_t index = 0; 388 if (method_sig != NULL && len > 1 && method_sig[index] == '(') { 389 ++index; 390 while (index < len && method_sig[index] != ')') { 391 ssize_t res = is_valid_type(&method_sig[index], len - index); 392 if (res == -1) { 393 return false; 394 } else { 395 index += res; 396 } 397 } 398 if (index < len && method_sig[index] == ')') { 399 // check the return type 400 ++index; 401 return (is_valid_type(&method_sig[index], len - index) == (len - index)); 402 } 403 } 404 return false; 405} 406 407bool SignatureVerifier::is_valid_type_signature(symbolHandle sig) { 408 const char* type_sig = (const char*)sig->bytes(); 409 ssize_t len = sig->utf8_length(); 410 return (type_sig != NULL && len >= 1 && 411 (is_valid_type(type_sig, len) == len)); 412} 413 414// Checks to see if the type (not to go beyond 'limit') refers to a valid type. 415// Returns -1 if it is not, or the index of the next character that is not part 416// of the type. The type encoding may end before 'limit' and that's ok. 417ssize_t SignatureVerifier::is_valid_type(const char* type, ssize_t limit) { 418 ssize_t index = 0; 419 420 // Iterate over any number of array dimensions 421 while (index < limit && type[index] == '[') ++index; 422 if (index >= limit) { 423 return -1; 424 } 425 switch (type[index]) { 426 case 'B': case 'C': case 'D': case 'F': case 'I': 427 case 'J': case 'S': case 'Z': case 'V': 428 return index + 1; 429 case 'L': 430 for (index = index + 1; index < limit; ++index) { 431 char c = type[index]; 432 if (c == ';') { 433 return index + 1; 434 } 435 if (invalid_name_char(c)) { 436 return -1; 437 } 438 } 439 // fall through 440 default: ; // fall through 441 } 442 return -1; 443} 444 445bool SignatureVerifier::invalid_name_char(char c) { 446 switch (c) { 447 case '\0': case '.': case ';': case '[': 448 return true; 449 default: 450 return false; 451 } 452} 453