1 /*
2  * Copyright (c) 2001, 2010, 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 package sun.jvm.hotspot.runtime;
26 
27 import sun.jvm.hotspot.oops.*;
28 
29 /** <P> SignatureIterators iterate over a Java signature (or parts of it).
30     (Syntax according to: "The Java Virtual Machine Specification" by
31     Tim Lindholm & Frank Yellin; section 4.3 Descriptors; p. 89ff.) </P>
32 
33     <P> Example: Iterating over
34 <PRE>
35 ([Lfoo;D)I
36 0123456789
37 </PRE>
38 
39     using </P>
40 
41 <PRE>
42 iterateParameters() calls: do_array(2, 7); do_double();
43 iterateReturntype() calls:                              do_int();
44 iterate()           calls: do_array(2, 7); do_double(); do_int();
45 
46 is_returnType()        is: false         ; false      ; true
47 </PRE>
48 */
49 
50 public abstract class SignatureIterator {
51   protected Symbol _signature;       // the signature to iterate over
52   protected int    _index;           // the current character index (only valid during iteration)
53   protected int    _parameter_index; // the current parameter index (0 outside iteration phase)
54 
expect(char c)55   protected void expect(char c) {
56     if (_signature.getByteAt(_index) != (byte) c) {
57       throw new RuntimeException("expecting '" + c + "'");
58     }
59     _index++;
60   }
skipOptionalSize()61   protected void skipOptionalSize() {
62     byte c = _signature.getByteAt(_index);
63     while ('0' <= c && c <= '9') {
64       c = _signature.getByteAt(++_index);
65     }
66   }
67   // returns the parameter size in words (0 for void)
parseType()68   protected int parseType() {
69     switch(_signature.getByteAt(_index)) {
70     case 'B': doByte  (); _index++; return BasicTypeSize.getTByteSize();
71     case 'C': doChar  (); _index++; return BasicTypeSize.getTCharSize();
72     case 'D': doDouble(); _index++; return BasicTypeSize.getTDoubleSize();
73     case 'F': doFloat (); _index++; return BasicTypeSize.getTFloatSize();
74     case 'I': doInt   (); _index++; return BasicTypeSize.getTIntSize();
75     case 'J': doLong  (); _index++; return BasicTypeSize.getTLongSize();
76     case 'S': doShort (); _index++; return BasicTypeSize.getTShortSize();
77     case 'Z': doBool  (); _index++; return BasicTypeSize.getTBooleanSize();
78     case 'V':
79       {
80         if (!isReturnType()) {
81           throw new RuntimeException("illegal parameter type V (void)");
82         }
83 
84         doVoid(); _index++;
85         return BasicTypeSize.getTVoidSize();
86       }
87     case 'L':
88       {
89         int begin = ++_index;
90         while (_signature.getByteAt(_index++) != ';') ;
91         doObject(begin, _index);
92         return BasicTypeSize.getTObjectSize();
93       }
94     case '[':
95       {
96         int begin = ++_index;
97         skipOptionalSize();
98         while (_signature.getByteAt(_index) == '[') {
99           _index++;
100           skipOptionalSize();
101         }
102         if (_signature.getByteAt(_index) == 'L') {
103           while (_signature.getByteAt(_index++) != ';') ;
104         } else {
105           _index++;
106         }
107         doArray(begin, _index);
108         return BasicTypeSize.getTArraySize();
109       }
110     }
111     throw new RuntimeException("Should not reach here: char " + (char)_signature.getByteAt(_index) + " @ " + _index + " in " + _signature.asString());
112   }
checkSignatureEnd()113   protected void checkSignatureEnd() {
114     if (_index < _signature.getLength()) {
115       System.err.println("too many chars in signature");
116       _signature.printValueOn(System.err);
117       System.err.println(" @ " + _index);
118     }
119   }
120 
SignatureIterator(Symbol signature)121   public SignatureIterator(Symbol signature) {
122     _signature       = signature;
123     _parameter_index = 0;
124   }
125 
126   //
127   // Iteration
128   //
129 
130   // dispatches once for field signatures
dispatchField()131   public void dispatchField() {
132     // no '(', just one (field) type
133     _index = 0;
134     _parameter_index = 0;
135     parseType();
136     checkSignatureEnd();
137   }
138 
139   // iterates over parameters only
iterateParameters()140   public void iterateParameters() {
141     // Parse parameters
142     _index = 0;
143     _parameter_index = 0;
144     expect('(');
145     while (_signature.getByteAt(_index) != ')') {
146       _parameter_index += parseType();
147     }
148     expect(')');
149     _parameter_index = 0; // so isReturnType() is false outside iteration
150   }
151 
152   // iterates over returntype only
iterateReturntype()153   public void iterateReturntype() {
154     // Ignore parameters
155     _index = 0;
156     expect('(');
157     while (_signature.getByteAt(_index) != ')') {
158       _index++;
159     }
160     expect(')');
161     // Parse return type
162     _parameter_index = -1;
163     parseType();
164     checkSignatureEnd();
165     _parameter_index = 0; // so isReturnType() is false outside iteration
166   }
167 
168   // iterates over whole signature
iterate()169   public void iterate() {
170     // Parse parameters
171     _index = 0;
172     _parameter_index = 0;
173     expect('(');
174     while (_signature.getByteAt(_index) != ')') {
175       _parameter_index += parseType();
176     }
177     expect(')');
178     // Parse return type
179     _parameter_index = -1;
180     parseType();
181     checkSignatureEnd();
182     _parameter_index = 0; // so isReturnType() is false outside iteration
183   }
184 
185   // Returns the word index of the current parameter; returns a negative value at the return type
parameterIndex()186   public int  parameterIndex()               { return _parameter_index; }
isReturnType()187   public boolean isReturnType()              { return (parameterIndex() < 0); }
188 
189   // Basic types
doBool()190   public abstract void doBool  ();
doChar()191   public abstract void doChar  ();
doFloat()192   public abstract void doFloat ();
doDouble()193   public abstract void doDouble();
doByte()194   public abstract void doByte  ();
doShort()195   public abstract void doShort ();
doInt()196   public abstract void doInt   ();
doLong()197   public abstract void doLong  ();
doVoid()198   public abstract void doVoid  ();
199 
200   // Object types (begin indexes the first character of the entry, end
201   // indexes the first character after the entry)
doObject(int begin, int end)202   public abstract void doObject(int begin, int end);
doArray(int begin, int end)203   public abstract void doArray (int begin, int end);
204 }
205