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