signature.cpp revision 10762:ea81fe138932
1316485Sdavidcs/*
2316485Sdavidcs * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
3316485Sdavidcs * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4316485Sdavidcs *
5316485Sdavidcs * This code is free software; you can redistribute it and/or modify it
6316485Sdavidcs * under the terms of the GNU General Public License version 2 only, as
7316485Sdavidcs * published by the Free Software Foundation.
8316485Sdavidcs *
9316485Sdavidcs * This code is distributed in the hope that it will be useful, but WITHOUT
10316485Sdavidcs * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11316485Sdavidcs * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12316485Sdavidcs * version 2 for more details (a copy is included in the LICENSE file that
13316485Sdavidcs * accompanied this code).
14316485Sdavidcs *
15316485Sdavidcs * You should have received a copy of the GNU General Public License version
16316485Sdavidcs * 2 along with this work; if not, write to the Free Software Foundation,
17316485Sdavidcs * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18316485Sdavidcs *
19316485Sdavidcs * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20316485Sdavidcs * or visit www.oracle.com if you need additional information or have any
21316485Sdavidcs * questions.
22316485Sdavidcs *
23316485Sdavidcs */
24316485Sdavidcs
25316485Sdavidcs#include "precompiled.hpp"
26316485Sdavidcs#include "classfile/symbolTable.hpp"
27316485Sdavidcs#include "classfile/systemDictionary.hpp"
28316485Sdavidcs#include "memory/oopFactory.hpp"
29316485Sdavidcs#include "memory/resourceArea.hpp"
30316485Sdavidcs#include "oops/instanceKlass.hpp"
31316485Sdavidcs#include "oops/oop.inline.hpp"
32316485Sdavidcs#include "oops/symbol.hpp"
33316485Sdavidcs#include "oops/typeArrayKlass.hpp"
34316485Sdavidcs#include "runtime/signature.hpp"
35316485Sdavidcs
36316485Sdavidcs// Implementation of SignatureIterator
37316485Sdavidcs
38316485Sdavidcs// Signature syntax:
39316485Sdavidcs//
40316485Sdavidcs// Signature  = "(" {Parameter} ")" ReturnType.
41316485Sdavidcs// Parameter  = FieldType.
42316485Sdavidcs// ReturnType = FieldType | "V".
43316485Sdavidcs// FieldType  = "B" | "C" | "D" | "F" | "I" | "J" | "S" | "Z" | "L" ClassName ";" | "[" FieldType.
44316485Sdavidcs// ClassName  = string.
45316485Sdavidcs
46316485Sdavidcs
47316485SdavidcsSignatureIterator::SignatureIterator(Symbol* signature) {
48316485Sdavidcs  _signature       = signature;
49316485Sdavidcs  _parameter_index = 0;
50316485Sdavidcs}
51316485Sdavidcs
52316485Sdavidcsvoid SignatureIterator::expect(char c) {
53316485Sdavidcs  if (_signature->byte_at(_index) != c) fatal("expecting %c", c);
54316485Sdavidcs  _index++;
55316485Sdavidcs}
56316485Sdavidcs
57316485Sdavidcs
58316485Sdavidcsvoid SignatureIterator::skip_optional_size() {
59316485Sdavidcs  Symbol* sig = _signature;
60316485Sdavidcs  char c = sig->byte_at(_index);
61316485Sdavidcs  while ('0' <= c && c <= '9') c = sig->byte_at(++_index);
62316485Sdavidcs}
63316485Sdavidcs
64316485Sdavidcs
65316485Sdavidcsint SignatureIterator::parse_type() {
66316485Sdavidcs  // Note: This function could be simplified by using "return T_XXX_size;"
67316485Sdavidcs  //       instead of the assignment and the break statements. However, it
68316485Sdavidcs  //       seems that the product build for win32_i486 with MS VC++ 6.0 doesn't
69316485Sdavidcs  //       work (stack underflow for some tests) - this seems to be a VC++ 6.0
70316485Sdavidcs  //       compiler bug (was problem - gri 4/27/2000).
71316485Sdavidcs  int size = -1;
72316485Sdavidcs  switch(_signature->byte_at(_index)) {
73316485Sdavidcs    case 'B': do_byte  (); if (_parameter_index < 0 ) _return_type = T_BYTE;
74316485Sdavidcs              _index++; size = T_BYTE_size   ; break;
75316485Sdavidcs    case 'C': do_char  (); if (_parameter_index < 0 ) _return_type = T_CHAR;
76316485Sdavidcs              _index++; size = T_CHAR_size   ; break;
77316485Sdavidcs    case 'D': do_double(); if (_parameter_index < 0 ) _return_type = T_DOUBLE;
78316485Sdavidcs              _index++; size = T_DOUBLE_size ; break;
79316485Sdavidcs    case 'F': do_float (); if (_parameter_index < 0 ) _return_type = T_FLOAT;
80316485Sdavidcs              _index++; size = T_FLOAT_size  ; break;
81316485Sdavidcs    case 'I': do_int   (); if (_parameter_index < 0 ) _return_type = T_INT;
82316485Sdavidcs              _index++; size = T_INT_size    ; break;
83316485Sdavidcs    case 'J': do_long  (); if (_parameter_index < 0 ) _return_type = T_LONG;
84316485Sdavidcs              _index++; size = T_LONG_size   ; break;
85316485Sdavidcs    case 'S': do_short (); if (_parameter_index < 0 ) _return_type = T_SHORT;
86316485Sdavidcs              _index++; size = T_SHORT_size  ; break;
87316485Sdavidcs    case 'Z': do_bool  (); if (_parameter_index < 0 ) _return_type = T_BOOLEAN;
88316485Sdavidcs              _index++; size = T_BOOLEAN_size; break;
89316485Sdavidcs    case 'V': do_void  (); if (_parameter_index < 0 ) _return_type = T_VOID;
90316485Sdavidcs              _index++; size = T_VOID_size;  ; break;
91316485Sdavidcs    case 'L':
92316485Sdavidcs      { int begin = ++_index;
93316485Sdavidcs        Symbol* sig = _signature;
94316485Sdavidcs        while (sig->byte_at(_index++) != ';') ;
95316485Sdavidcs        do_object(begin, _index);
96316485Sdavidcs      }
97316485Sdavidcs      if (_parameter_index < 0 ) _return_type = T_OBJECT;
98316485Sdavidcs      size = T_OBJECT_size;
99316485Sdavidcs      break;
100316485Sdavidcs    case '[':
101316485Sdavidcs      { int begin = ++_index;
102316485Sdavidcs        skip_optional_size();
103316485Sdavidcs        Symbol* sig = _signature;
104316485Sdavidcs        while (sig->byte_at(_index) == '[') {
105316485Sdavidcs          _index++;
106316485Sdavidcs          skip_optional_size();
107316485Sdavidcs        }
108316485Sdavidcs        if (sig->byte_at(_index) == 'L') {
109316485Sdavidcs          while (sig->byte_at(_index++) != ';') ;
110316485Sdavidcs        } else {
111316485Sdavidcs          _index++;
112316485Sdavidcs        }
113316485Sdavidcs        do_array(begin, _index);
114316485Sdavidcs       if (_parameter_index < 0 ) _return_type = T_ARRAY;
115316485Sdavidcs      }
116316485Sdavidcs      size = T_ARRAY_size;
117316485Sdavidcs      break;
118316485Sdavidcs    default:
119316485Sdavidcs      ShouldNotReachHere();
120316485Sdavidcs      break;
121316485Sdavidcs  }
122316485Sdavidcs  assert(size >= 0, "size must be set");
123316485Sdavidcs  return size;
124316485Sdavidcs}
125316485Sdavidcs
126316485Sdavidcs
127316485Sdavidcsvoid SignatureIterator::check_signature_end() {
128316485Sdavidcs  if (_index < _signature->utf8_length()) {
129316485Sdavidcs    tty->print_cr("too many chars in signature");
130316485Sdavidcs    _signature->print_value_on(tty);
131316485Sdavidcs    tty->print_cr(" @ %d", _index);
132316485Sdavidcs  }
133316485Sdavidcs}
134316485Sdavidcs
135316485Sdavidcs
136316485Sdavidcsvoid SignatureIterator::dispatch_field() {
137316485Sdavidcs  // no '(', just one (field) type
138316485Sdavidcs  _index = 0;
139316485Sdavidcs  _parameter_index = 0;
140316485Sdavidcs  parse_type();
141316485Sdavidcs  check_signature_end();
142316485Sdavidcs}
143316485Sdavidcs
144316485Sdavidcs
145316485Sdavidcsvoid SignatureIterator::iterate_parameters() {
146316485Sdavidcs  // Parse parameters
147316485Sdavidcs  _index = 0;
148316485Sdavidcs  _parameter_index = 0;
149316485Sdavidcs  expect('(');
150316485Sdavidcs  while (_signature->byte_at(_index) != ')') _parameter_index += parse_type();
151316485Sdavidcs  expect(')');
152316485Sdavidcs  _parameter_index = 0;
153316485Sdavidcs}
154316485Sdavidcs
155316485Sdavidcs// Optimized version of iterate_parameters when fingerprint is known
156316485Sdavidcsvoid SignatureIterator::iterate_parameters( uint64_t fingerprint ) {
157316485Sdavidcs  uint64_t saved_fingerprint = fingerprint;
158316485Sdavidcs
159316485Sdavidcs  // Check for too many arguments
160316485Sdavidcs  if (fingerprint == (uint64_t)CONST64(-1)) {
161316485Sdavidcs    SignatureIterator::iterate_parameters();
162337519Sdavidcs    return;
163337519Sdavidcs  }
164337519Sdavidcs
165337519Sdavidcs  assert(fingerprint, "Fingerprint should not be 0");
166316485Sdavidcs
167316485Sdavidcs  _parameter_index = 0;
168316485Sdavidcs  fingerprint = fingerprint >> (static_feature_size + result_feature_size);
169316485Sdavidcs  while ( 1 ) {
170316485Sdavidcs    switch ( fingerprint & parameter_feature_mask ) {
171316485Sdavidcs      case bool_parm:
172316485Sdavidcs        do_bool();
173316485Sdavidcs        _parameter_index += T_BOOLEAN_size;
174316485Sdavidcs        break;
175316485Sdavidcs      case byte_parm:
176316485Sdavidcs        do_byte();
177316485Sdavidcs        _parameter_index += T_BYTE_size;
178316485Sdavidcs        break;
179316485Sdavidcs      case char_parm:
180316485Sdavidcs        do_char();
181316485Sdavidcs        _parameter_index += T_CHAR_size;
182316485Sdavidcs        break;
183316485Sdavidcs      case short_parm:
184316485Sdavidcs        do_short();
185316485Sdavidcs        _parameter_index += T_SHORT_size;
186316485Sdavidcs        break;
187316485Sdavidcs      case int_parm:
188316485Sdavidcs        do_int();
189316485Sdavidcs        _parameter_index += T_INT_size;
190316485Sdavidcs        break;
191316485Sdavidcs      case obj_parm:
192316485Sdavidcs        do_object(0, 0);
193316485Sdavidcs        _parameter_index += T_OBJECT_size;
194316485Sdavidcs        break;
195316485Sdavidcs      case long_parm:
196316485Sdavidcs        do_long();
197316485Sdavidcs        _parameter_index += T_LONG_size;
198316485Sdavidcs        break;
199316485Sdavidcs      case float_parm:
200316485Sdavidcs        do_float();
201316485Sdavidcs        _parameter_index += T_FLOAT_size;
202316485Sdavidcs        break;
203316485Sdavidcs      case double_parm:
204316485Sdavidcs        do_double();
205316485Sdavidcs        _parameter_index += T_DOUBLE_size;
206316485Sdavidcs        break;
207316485Sdavidcs      case done_parm:
208316485Sdavidcs        return;
209316485Sdavidcs        break;
210316485Sdavidcs      default:
211316485Sdavidcs        tty->print_cr("*** parameter is " UINT64_FORMAT, fingerprint & parameter_feature_mask);
212316485Sdavidcs        tty->print_cr("*** fingerprint is " PTR64_FORMAT, saved_fingerprint);
213316485Sdavidcs        ShouldNotReachHere();
214316485Sdavidcs        break;
215316485Sdavidcs    }
216316485Sdavidcs    fingerprint >>= parameter_feature_size;
217316485Sdavidcs  }
218316485Sdavidcs  _parameter_index = 0;
219316485Sdavidcs}
220316485Sdavidcs
221316485Sdavidcs
222316485Sdavidcsvoid SignatureIterator::iterate_returntype() {
223316485Sdavidcs  // Ignore parameters
224316485Sdavidcs  _index = 0;
225316485Sdavidcs  expect('(');
226316485Sdavidcs  Symbol* sig = _signature;
227316485Sdavidcs  while (sig->byte_at(_index) != ')') _index++;
228316485Sdavidcs  expect(')');
229316485Sdavidcs  // Parse return type
230316485Sdavidcs  _parameter_index = -1;
231316485Sdavidcs  parse_type();
232316485Sdavidcs  check_signature_end();
233316485Sdavidcs  _parameter_index = 0;
234316485Sdavidcs}
235316485Sdavidcs
236316485Sdavidcs
237316485Sdavidcsvoid SignatureIterator::iterate() {
238316485Sdavidcs  // Parse parameters
239316485Sdavidcs  _parameter_index = 0;
240316485Sdavidcs  _index = 0;
241316485Sdavidcs  expect('(');
242316485Sdavidcs  while (_signature->byte_at(_index) != ')') _parameter_index += parse_type();
243316485Sdavidcs  expect(')');
244337519Sdavidcs  // Parse return type
245316485Sdavidcs  _parameter_index = -1;
246316485Sdavidcs  parse_type();
247316485Sdavidcs  check_signature_end();
248316485Sdavidcs  _parameter_index = 0;
249316485Sdavidcs}
250316485Sdavidcs
251316485Sdavidcs
252316485Sdavidcs// Implementation of SignatureStream
253316485SdavidcsSignatureStream::SignatureStream(Symbol* signature, bool is_method) :
254316485Sdavidcs                   _signature(signature), _at_return_type(false) {
255316485Sdavidcs  _begin = _end = (is_method ? 1 : 0);  // skip first '(' in method signatures
256316485Sdavidcs  _names = new GrowableArray<Symbol*>(10);
257316485Sdavidcs  next();
258316485Sdavidcs}
259316485Sdavidcs
260316485SdavidcsSignatureStream::~SignatureStream() {
261316485Sdavidcs  // decrement refcount for names created during signature parsing
262316485Sdavidcs  for (int i = 0; i < _names->length(); i++) {
263316485Sdavidcs    _names->at(i)->decrement_refcount();
264316485Sdavidcs  }
265316485Sdavidcs}
266316485Sdavidcs
267316485Sdavidcsbool SignatureStream::is_done() const {
268316485Sdavidcs  return _end > _signature->utf8_length();
269316485Sdavidcs}
270316485Sdavidcs
271316485Sdavidcs
272316485Sdavidcsvoid SignatureStream::next_non_primitive(int t) {
273316485Sdavidcs  switch (t) {
274316485Sdavidcs    case 'L': {
275316485Sdavidcs      _type = T_OBJECT;
276316485Sdavidcs      Symbol* sig = _signature;
277316485Sdavidcs      while (sig->byte_at(_end++) != ';');
278316485Sdavidcs      break;
279316485Sdavidcs    }
280316485Sdavidcs    case '[': {
281316485Sdavidcs      _type = T_ARRAY;
282316485Sdavidcs      Symbol* sig = _signature;
283316485Sdavidcs      char c = sig->byte_at(_end);
284316485Sdavidcs      while ('0' <= c && c <= '9') c = sig->byte_at(_end++);
285316485Sdavidcs      while (sig->byte_at(_end) == '[') {
286316485Sdavidcs        _end++;
287316485Sdavidcs        c = sig->byte_at(_end);
288316485Sdavidcs        while ('0' <= c && c <= '9') c = sig->byte_at(_end++);
289316485Sdavidcs      }
290316485Sdavidcs      switch(sig->byte_at(_end)) {
291316485Sdavidcs        case 'B':
292316485Sdavidcs        case 'C':
293316485Sdavidcs        case 'D':
294316485Sdavidcs        case 'F':
295316485Sdavidcs        case 'I':
296316485Sdavidcs        case 'J':
297316485Sdavidcs        case 'S':
298316485Sdavidcs        case 'Z':_end++; break;
299316485Sdavidcs        default: {
300316485Sdavidcs          while (sig->byte_at(_end++) != ';');
301316485Sdavidcs          break;
302316485Sdavidcs        }
303316485Sdavidcs      }
304316485Sdavidcs      break;
305316485Sdavidcs    }
306316485Sdavidcs    case ')': _end++; next(); _at_return_type = true; break;
307316485Sdavidcs    default : ShouldNotReachHere();
308316485Sdavidcs  }
309316485Sdavidcs}
310316485Sdavidcs
311316485Sdavidcs
312316485Sdavidcsbool SignatureStream::is_object() const {
313316485Sdavidcs  return _type == T_OBJECT
314316485Sdavidcs      || _type == T_ARRAY;
315316485Sdavidcs}
316316485Sdavidcs
317316485Sdavidcsbool SignatureStream::is_array() const {
318316485Sdavidcs  return _type == T_ARRAY;
319316485Sdavidcs}
320316485Sdavidcs
321316485SdavidcsSymbol* SignatureStream::as_symbol(TRAPS) {
322316485Sdavidcs  // Create a symbol from for string _begin _end
323316485Sdavidcs  int begin = _begin;
324316485Sdavidcs  int end   = _end;
325316485Sdavidcs
326316485Sdavidcs  if (   _signature->byte_at(_begin) == 'L'
327316485Sdavidcs      && _signature->byte_at(_end-1) == ';') {
328316485Sdavidcs    begin++;
329316485Sdavidcs    end--;
330316485Sdavidcs  }
331316485Sdavidcs
332316485Sdavidcs  // Save names for cleaning up reference count at the end of
333316485Sdavidcs  // SignatureStream scope.
334316485Sdavidcs  Symbol* name = SymbolTable::new_symbol(_signature, begin, end, CHECK_NULL);
335316485Sdavidcs  _names->push(name);  // save new symbol for decrementing later
336316485Sdavidcs  return name;
337316485Sdavidcs}
338316485Sdavidcs
339316485SdavidcsKlass* SignatureStream::as_klass(Handle class_loader, Handle protection_domain,
340316485Sdavidcs                                   FailureMode failure_mode, TRAPS) {
341316485Sdavidcs  if (!is_object())  return NULL;
342316485Sdavidcs  Symbol* name = as_symbol(CHECK_NULL);
343316485Sdavidcs  if (failure_mode == ReturnNull) {
344316485Sdavidcs    return SystemDictionary::resolve_or_null(name, class_loader, protection_domain, THREAD);
345316485Sdavidcs  } else {
346316485Sdavidcs    bool throw_error = (failure_mode == NCDFError);
347316485Sdavidcs    return SystemDictionary::resolve_or_fail(name, class_loader, protection_domain, throw_error, THREAD);
348316485Sdavidcs  }
349316485Sdavidcs}
350316485Sdavidcs
351316485Sdavidcsoop SignatureStream::as_java_mirror(Handle class_loader, Handle protection_domain,
352316485Sdavidcs                                    FailureMode failure_mode, TRAPS) {
353316485Sdavidcs  if (!is_object())
354316485Sdavidcs    return Universe::java_mirror(type());
355316485Sdavidcs  Klass* klass = as_klass(class_loader, protection_domain, failure_mode, CHECK_NULL);
356316485Sdavidcs  if (klass == NULL)  return NULL;
357316485Sdavidcs  return klass->java_mirror();
358316485Sdavidcs}
359316485Sdavidcs
360316485SdavidcsSymbol* SignatureStream::as_symbol_or_null() {
361316485Sdavidcs  // Create a symbol from for string _begin _end
362316485Sdavidcs  ResourceMark rm;
363316485Sdavidcs
364316485Sdavidcs  int begin = _begin;
365316485Sdavidcs  int end   = _end;
366316485Sdavidcs
367316485Sdavidcs  if (   _signature->byte_at(_begin) == 'L'
368316485Sdavidcs      && _signature->byte_at(_end-1) == ';') {
369316485Sdavidcs    begin++;
370316485Sdavidcs    end--;
371316485Sdavidcs  }
372316485Sdavidcs
373316485Sdavidcs  char* buffer = NEW_RESOURCE_ARRAY(char, end - begin);
374316485Sdavidcs  for (int index = begin; index < end; index++) {
375316485Sdavidcs    buffer[index - begin] = _signature->byte_at(index);
376316485Sdavidcs  }
377316485Sdavidcs  Symbol* result = SymbolTable::probe(buffer, end - begin);
378316485Sdavidcs  return result;
379316485Sdavidcs}
380316485Sdavidcs
381316485Sdavidcsint SignatureStream::reference_parameter_count() {
382316485Sdavidcs  int args_count = 0;
383316485Sdavidcs  for ( ; !at_return_type(); next()) {
384316485Sdavidcs    if (is_object()) {
385316485Sdavidcs      args_count++;
386316485Sdavidcs    }
387316485Sdavidcs  }
388316485Sdavidcs  return args_count;
389316485Sdavidcs}
390316485Sdavidcs
391316485Sdavidcsbool SignatureVerifier::is_valid_signature(Symbol* sig) {
392316485Sdavidcs  const char* signature = (const char*)sig->bytes();
393316485Sdavidcs  ssize_t len = sig->utf8_length();
394316485Sdavidcs  if (signature == NULL || signature[0] == '\0' || len < 1) {
395316485Sdavidcs    return false;
396316485Sdavidcs  } else if (signature[0] == '(') {
397316485Sdavidcs    return is_valid_method_signature(sig);
398316485Sdavidcs  } else {
399316485Sdavidcs    return is_valid_type_signature(sig);
400316485Sdavidcs  }
401316485Sdavidcs}
402316485Sdavidcs
403316485Sdavidcsbool SignatureVerifier::is_valid_method_signature(Symbol* sig) {
404316485Sdavidcs  const char* method_sig = (const char*)sig->bytes();
405316485Sdavidcs  ssize_t len = sig->utf8_length();
406316485Sdavidcs  ssize_t index = 0;
407316485Sdavidcs  if (method_sig != NULL && len > 1 && method_sig[index] == '(') {
408316485Sdavidcs    ++index;
409316485Sdavidcs    while (index < len && method_sig[index] != ')') {
410316485Sdavidcs      ssize_t res = is_valid_type(&method_sig[index], len - index);
411316485Sdavidcs      if (res == -1) {
412316485Sdavidcs        return false;
413316485Sdavidcs      } else {
414316485Sdavidcs        index += res;
415316485Sdavidcs      }
416316485Sdavidcs    }
417316485Sdavidcs    if (index < len && method_sig[index] == ')') {
418316485Sdavidcs      // check the return type
419316485Sdavidcs      ++index;
420316485Sdavidcs      return (is_valid_type(&method_sig[index], len - index) == (len - index));
421316485Sdavidcs    }
422316485Sdavidcs  }
423316485Sdavidcs  return false;
424316485Sdavidcs}
425316485Sdavidcs
426316485Sdavidcsbool SignatureVerifier::is_valid_type_signature(Symbol* sig) {
427316485Sdavidcs  const char* type_sig = (const char*)sig->bytes();
428316485Sdavidcs  ssize_t len = sig->utf8_length();
429316485Sdavidcs  return (type_sig != NULL && len >= 1 &&
430316485Sdavidcs          (is_valid_type(type_sig, len) == len));
431316485Sdavidcs}
432316485Sdavidcs
433316485Sdavidcs// Checks to see if the type (not to go beyond 'limit') refers to a valid type.
434316485Sdavidcs// Returns -1 if it is not, or the index of the next character that is not part
435316485Sdavidcs// of the type.  The type encoding may end before 'limit' and that's ok.
436316485Sdavidcsssize_t SignatureVerifier::is_valid_type(const char* type, ssize_t limit) {
437316485Sdavidcs  ssize_t index = 0;
438316485Sdavidcs
439316485Sdavidcs  // Iterate over any number of array dimensions
440316485Sdavidcs  while (index < limit && type[index] == '[') ++index;
441316485Sdavidcs  if (index >= limit) {
442316485Sdavidcs    return -1;
443316485Sdavidcs  }
444316485Sdavidcs  switch (type[index]) {
445316485Sdavidcs    case 'B': case 'C': case 'D': case 'F': case 'I':
446316485Sdavidcs    case 'J': case 'S': case 'Z': case 'V':
447316485Sdavidcs      return index + 1;
448316485Sdavidcs    case 'L':
449316485Sdavidcs      for (index = index + 1; index < limit; ++index) {
450316485Sdavidcs        char c = type[index];
451316485Sdavidcs        if (c == ';') {
452316485Sdavidcs          return index + 1;
453316485Sdavidcs        }
454316485Sdavidcs        if (invalid_name_char(c)) {
455316485Sdavidcs          return -1;
456316485Sdavidcs        }
457316485Sdavidcs      }
458316485Sdavidcs      // fall through
459316485Sdavidcs    default: ; // fall through
460316485Sdavidcs  }
461316485Sdavidcs  return -1;
462316485Sdavidcs}
463316485Sdavidcs
464316485Sdavidcsbool SignatureVerifier::invalid_name_char(char c) {
465316485Sdavidcs  switch (c) {
466316485Sdavidcs    case '\0': case '.': case ';': case '[':
467316485Sdavidcs      return true;
468316485Sdavidcs    default:
469316485Sdavidcs      return false;
470316485Sdavidcs  }
471316485Sdavidcs}
472316485Sdavidcs