signature.cpp revision 0:a61af66fc99e
1230557Sjimharris/* 2230557Sjimharris * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. 3230557Sjimharris * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4230557Sjimharris * 5230557Sjimharris * This code is free software; you can redistribute it and/or modify it 6230557Sjimharris * under the terms of the GNU General Public License version 2 only, as 7230557Sjimharris * published by the Free Software Foundation. 8230557Sjimharris * 9230557Sjimharris * This code is distributed in the hope that it will be useful, but WITHOUT 10230557Sjimharris * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11230557Sjimharris * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12230557Sjimharris * version 2 for more details (a copy is included in the LICENSE file that 13230557Sjimharris * accompanied this code). 14230557Sjimharris * 15230557Sjimharris * You should have received a copy of the GNU General Public License version 16230557Sjimharris * 2 along with this work; if not, write to the Free Software Foundation, 17230557Sjimharris * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18230557Sjimharris * 19230557Sjimharris * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 20230557Sjimharris * CA 95054 USA or visit www.sun.com if you need additional information or 21230557Sjimharris * have any questions. 22230557Sjimharris * 23230557Sjimharris */ 24230557Sjimharris 25230557Sjimharris# include "incls/_precompiled.incl" 26230557Sjimharris# include "incls/_signature.cpp.incl" 27230557Sjimharris 28230557Sjimharris 29230557Sjimharris// Implementation of SignatureIterator 30230557Sjimharris 31230557Sjimharris// Signature syntax: 32230557Sjimharris// 33230557Sjimharris// Signature = "(" {Parameter} ")" ReturnType. 34230557Sjimharris// Parameter = FieldType. 35230557Sjimharris// ReturnType = FieldType | "V". 36230557Sjimharris// FieldType = "B" | "C" | "D" | "F" | "I" | "J" | "S" | "Z" | "L" ClassName ";" | "[" FieldType. 37230557Sjimharris// ClassName = string. 38230557Sjimharris 39230557Sjimharris 40230557SjimharrisSignatureIterator::SignatureIterator(symbolHandle signature) { 41230557Sjimharris assert(signature->is_symbol(), "not a symbol"); 42230557Sjimharris _signature = signature; 43230557Sjimharris _parameter_index = 0; 44230557Sjimharris} 45230557Sjimharris 46230557Sjimharris// Overloaded version called without handle 47230557SjimharrisSignatureIterator::SignatureIterator(symbolOop signature) { 48230557Sjimharris symbolHandle sh(Thread::current(), signature); 49230557Sjimharris _signature = sh; 50230557Sjimharris _parameter_index = 0; 51230557Sjimharris} 52230557Sjimharris 53230557SjimharrisSignatureIterator::SignatureIterator(Thread *thread, symbolOop signature) { 54230557Sjimharris symbolHandle sh(thread, signature); 55230557Sjimharris _signature = sh; 56230557Sjimharris _parameter_index = 0; 57230557Sjimharris} 58230557Sjimharris 59230557Sjimharrisvoid SignatureIterator::expect(char c) { 60230557Sjimharris if (_signature->byte_at(_index) != c) fatal1("expecting %c", c); 61230557Sjimharris _index++; 62230557Sjimharris} 63230557Sjimharris 64230557Sjimharris 65230557Sjimharrisvoid SignatureIterator::skip_optional_size() { 66230557Sjimharris symbolOop sig = _signature(); 67230557Sjimharris char c = sig->byte_at(_index); 68230557Sjimharris while ('0' <= c && c <= '9') c = sig->byte_at(++_index); 69230557Sjimharris} 70230557Sjimharris 71230557Sjimharris 72230557Sjimharrisint SignatureIterator::parse_type() { 73230557Sjimharris // Note: This function could be simplified by using "return T_XXX_size;" 74230557Sjimharris // instead of the assignment and the break statements. However, it 75230557Sjimharris // seems that the product build for win32_i486 with MS VC++ 6.0 doesn't 76230557Sjimharris // work (stack underflow for some tests) - this seems to be a VC++ 6.0 77230557Sjimharris // compiler bug (was problem - gri 4/27/2000). 78230557Sjimharris int size = -1; 79230557Sjimharris switch(_signature->byte_at(_index)) { 80230557Sjimharris case 'B': do_byte (); if (_parameter_index < 0 ) _return_type = T_BYTE; 81230557Sjimharris _index++; size = T_BYTE_size ; break; 82230557Sjimharris case 'C': do_char (); if (_parameter_index < 0 ) _return_type = T_CHAR; 83230557Sjimharris _index++; size = T_CHAR_size ; break; 84230557Sjimharris case 'D': do_double(); if (_parameter_index < 0 ) _return_type = T_DOUBLE; 85230557Sjimharris _index++; size = T_DOUBLE_size ; break; 86230557Sjimharris case 'F': do_float (); if (_parameter_index < 0 ) _return_type = T_FLOAT; 87230557Sjimharris _index++; size = T_FLOAT_size ; break; 88230557Sjimharris case 'I': do_int (); if (_parameter_index < 0 ) _return_type = T_INT; 89230557Sjimharris _index++; size = T_INT_size ; break; 90230557Sjimharris case 'J': do_long (); if (_parameter_index < 0 ) _return_type = T_LONG; 91230557Sjimharris _index++; size = T_LONG_size ; break; 92230557Sjimharris case 'S': do_short (); if (_parameter_index < 0 ) _return_type = T_SHORT; 93230557Sjimharris _index++; size = T_SHORT_size ; break; 94230557Sjimharris case 'Z': do_bool (); if (_parameter_index < 0 ) _return_type = T_BOOLEAN; 95230557Sjimharris _index++; size = T_BOOLEAN_size; break; 96230557Sjimharris case 'V': do_void (); if (_parameter_index < 0 ) _return_type = T_VOID; 97230557Sjimharris _index++; size = T_VOID_size; ; break; 98230557Sjimharris case 'L': 99230557Sjimharris { int begin = ++_index; 100230557Sjimharris symbolOop sig = _signature(); 101230557Sjimharris while (sig->byte_at(_index++) != ';') ; 102230557Sjimharris do_object(begin, _index); 103230557Sjimharris } 104230557Sjimharris if (_parameter_index < 0 ) _return_type = T_OBJECT; 105230557Sjimharris size = T_OBJECT_size; 106230557Sjimharris break; 107230557Sjimharris case '[': 108230557Sjimharris { int begin = ++_index; 109230557Sjimharris skip_optional_size(); 110230557Sjimharris symbolOop sig = _signature(); 111230557Sjimharris while (sig->byte_at(_index) == '[') { 112230557Sjimharris _index++; 113230557Sjimharris skip_optional_size(); 114230557Sjimharris } 115230557Sjimharris if (sig->byte_at(_index) == 'L') { 116230557Sjimharris while (sig->byte_at(_index++) != ';') ; 117230557Sjimharris } else { 118230557Sjimharris _index++; 119230557Sjimharris } 120230557Sjimharris do_array(begin, _index); 121230557Sjimharris if (_parameter_index < 0 ) _return_type = T_ARRAY; 122230557Sjimharris } 123230557Sjimharris size = T_ARRAY_size; 124230557Sjimharris break; 125230557Sjimharris default: 126230557Sjimharris ShouldNotReachHere(); 127230557Sjimharris break; 128230557Sjimharris } 129230557Sjimharris assert(size >= 0, "size must be set"); 130230557Sjimharris return size; 131230557Sjimharris} 132230557Sjimharris 133230557Sjimharris 134230557Sjimharrisvoid SignatureIterator::check_signature_end() { 135230557Sjimharris if (_index < _signature->utf8_length()) { 136230557Sjimharris tty->print_cr("too many chars in signature"); 137230557Sjimharris _signature->print_value_on(tty); 138230557Sjimharris tty->print_cr(" @ %d", _index); 139230557Sjimharris } 140230557Sjimharris} 141230557Sjimharris 142230557Sjimharris 143230557Sjimharrisvoid SignatureIterator::dispatch_field() { 144230557Sjimharris // no '(', just one (field) type 145230557Sjimharris _index = 0; 146230557Sjimharris _parameter_index = 0; 147230557Sjimharris parse_type(); 148230557Sjimharris check_signature_end(); 149230557Sjimharris} 150230557Sjimharris 151230557Sjimharris 152230557Sjimharrisvoid SignatureIterator::iterate_parameters() { 153230557Sjimharris // Parse parameters 154230557Sjimharris _index = 0; 155230557Sjimharris _parameter_index = 0; 156230557Sjimharris expect('('); 157230557Sjimharris while (_signature->byte_at(_index) != ')') _parameter_index += parse_type(); 158230557Sjimharris expect(')'); 159230557Sjimharris _parameter_index = 0; 160230557Sjimharris} 161230557Sjimharris 162230557Sjimharris// Optimized version of iterat_parameters when fingerprint is known 163230557Sjimharrisvoid SignatureIterator::iterate_parameters( uint64_t fingerprint ) { 164230557Sjimharris uint64_t saved_fingerprint = fingerprint; 165230557Sjimharris 166230557Sjimharris // Check for too many arguments 167230557Sjimharris if ( fingerprint == UCONST64(-1) ) { 168230557Sjimharris SignatureIterator::iterate_parameters(); 169230557Sjimharris return; 170230557Sjimharris } 171230557Sjimharris 172230557Sjimharris assert(fingerprint, "Fingerprint should not be 0"); 173230557Sjimharris 174230557Sjimharris _parameter_index = 0; 175230557Sjimharris fingerprint = fingerprint >> (static_feature_size + result_feature_size); 176230557Sjimharris while ( 1 ) { 177230557Sjimharris switch ( fingerprint & parameter_feature_mask ) { 178230557Sjimharris case bool_parm: 179230557Sjimharris do_bool(); 180230557Sjimharris _parameter_index += T_BOOLEAN_size; 181230557Sjimharris break; 182230557Sjimharris case byte_parm: 183230557Sjimharris do_byte(); 184230557Sjimharris _parameter_index += T_BYTE_size; 185230557Sjimharris break; 186230557Sjimharris case char_parm: 187230557Sjimharris do_char(); 188230557Sjimharris _parameter_index += T_CHAR_size; 189230557Sjimharris break; 190230557Sjimharris case short_parm: 191230557Sjimharris do_short(); 192230557Sjimharris _parameter_index += T_SHORT_size; 193230557Sjimharris break; 194230557Sjimharris case int_parm: 195230557Sjimharris do_int(); 196230557Sjimharris _parameter_index += T_INT_size; 197230557Sjimharris break; 198230557Sjimharris case obj_parm: 199230557Sjimharris do_object(0, 0); 200230557Sjimharris _parameter_index += T_OBJECT_size; 201230557Sjimharris break; 202230557Sjimharris case long_parm: 203230557Sjimharris do_long(); 204230557Sjimharris _parameter_index += T_LONG_size; 205230557Sjimharris break; 206230557Sjimharris case float_parm: 207230557Sjimharris do_float(); 208230557Sjimharris _parameter_index += T_FLOAT_size; 209230557Sjimharris break; 210230557Sjimharris case double_parm: 211230557Sjimharris do_double(); 212230557Sjimharris _parameter_index += T_DOUBLE_size; 213230557Sjimharris break; 214230557Sjimharris case done_parm: 215230557Sjimharris return; 216230557Sjimharris break; 217230557Sjimharris default: 218230557Sjimharris tty->print_cr("*** parameter is %d", fingerprint & parameter_feature_mask); 219230557Sjimharris tty->print_cr("*** fingerprint is " PTR64_FORMAT, saved_fingerprint); 220230557Sjimharris ShouldNotReachHere(); 221230557Sjimharris break; 222230557Sjimharris } 223230557Sjimharris fingerprint >>= parameter_feature_size; 224230557Sjimharris } 225230557Sjimharris _parameter_index = 0; 226230557Sjimharris} 227230557Sjimharris 228230557Sjimharris 229230557Sjimharrisvoid SignatureIterator::iterate_returntype() { 230230557Sjimharris // Ignore parameters 231230557Sjimharris _index = 0; 232230557Sjimharris expect('('); 233230557Sjimharris symbolOop sig = _signature(); 234230557Sjimharris while (sig->byte_at(_index) != ')') _index++; 235230557Sjimharris expect(')'); 236230557Sjimharris // Parse return type 237230557Sjimharris _parameter_index = -1; 238230557Sjimharris parse_type(); 239230557Sjimharris check_signature_end(); 240230557Sjimharris _parameter_index = 0; 241230557Sjimharris} 242230557Sjimharris 243230557Sjimharris 244230557Sjimharrisvoid SignatureIterator::iterate() { 245230557Sjimharris // Parse parameters 246230557Sjimharris _parameter_index = 0; 247230557Sjimharris _index = 0; 248230557Sjimharris expect('('); 249230557Sjimharris while (_signature->byte_at(_index) != ')') _parameter_index += parse_type(); 250230557Sjimharris expect(')'); 251230557Sjimharris // Parse return type 252230557Sjimharris _parameter_index = -1; 253230557Sjimharris parse_type(); 254230557Sjimharris check_signature_end(); 255230557Sjimharris _parameter_index = 0; 256230557Sjimharris} 257230557Sjimharris 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 330 331symbolOop SignatureStream::as_symbol_or_null() { 332 // Create a symbol from for string _begin _end 333 ResourceMark rm; 334 335 int begin = _begin; 336 int end = _end; 337 338 if ( _signature()->byte_at(_begin) == 'L' 339 && _signature()->byte_at(_end-1) == ';') { 340 begin++; 341 end--; 342 } 343 344 char* buffer = NEW_RESOURCE_ARRAY(char, end - begin); 345 for (int index = begin; index < end; index++) { 346 buffer[index - begin] = _signature()->byte_at(index); 347 } 348 symbolOop result = SymbolTable::probe(buffer, end - begin); 349 return result; 350} 351 352bool SignatureVerifier::is_valid_signature(symbolHandle sig) { 353 const char* signature = (const char*)sig->bytes(); 354 ssize_t len = sig->utf8_length(); 355 if (signature == NULL || signature[0] == '\0' || len < 1) { 356 return false; 357 } else if (signature[0] == '(') { 358 return is_valid_method_signature(sig); 359 } else { 360 return is_valid_type_signature(sig); 361 } 362} 363 364bool SignatureVerifier::is_valid_method_signature(symbolHandle sig) { 365 const char* method_sig = (const char*)sig->bytes(); 366 ssize_t len = sig->utf8_length(); 367 ssize_t index = 0; 368 if (method_sig != NULL && len > 1 && method_sig[index] == '(') { 369 ++index; 370 while (index < len && method_sig[index] != ')') { 371 ssize_t res = is_valid_type(&method_sig[index], len - index); 372 if (res == -1) { 373 return false; 374 } else { 375 index += res; 376 } 377 } 378 if (index < len && method_sig[index] == ')') { 379 // check the return type 380 ++index; 381 return (is_valid_type(&method_sig[index], len - index) == (len - index)); 382 } 383 } 384 return false; 385} 386 387bool SignatureVerifier::is_valid_type_signature(symbolHandle sig) { 388 const char* type_sig = (const char*)sig->bytes(); 389 ssize_t len = sig->utf8_length(); 390 return (type_sig != NULL && len >= 1 && 391 (is_valid_type(type_sig, len) == len)); 392} 393 394// Checks to see if the type (not to go beyond 'limit') refers to a valid type. 395// Returns -1 if it is not, or the index of the next character that is not part 396// of the type. The type encoding may end before 'limit' and that's ok. 397ssize_t SignatureVerifier::is_valid_type(const char* type, ssize_t limit) { 398 ssize_t index = 0; 399 400 // Iterate over any number of array dimensions 401 while (index < limit && type[index] == '[') ++index; 402 if (index >= limit) { 403 return -1; 404 } 405 switch (type[index]) { 406 case 'B': case 'C': case 'D': case 'F': case 'I': 407 case 'J': case 'S': case 'Z': case 'V': 408 return index + 1; 409 case 'L': 410 for (index = index + 1; index < limit; ++index) { 411 char c = type[index]; 412 if (c == ';') { 413 return index + 1; 414 } 415 if (invalid_name_char(c)) { 416 return -1; 417 } 418 } 419 // fall through 420 default: ; // fall through 421 } 422 return -1; 423} 424 425bool SignatureVerifier::invalid_name_char(char c) { 426 switch (c) { 427 case '\0': case '.': case ';': case '[': 428 return true; 429 default: 430 return false; 431 } 432} 433