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