annotate src/share/vm/runtime/signature.cpp @ 3979:4dfb2df418f2

6484982: G1: process references during evacuation pauses Summary: G1 now uses two reference processors - one is used by concurrent marking and the other is used by STW GCs (both full and incremental evacuation pauses). In an evacuation pause, the reference processor is embedded into the closures used to scan objects. Doing so causes causes reference objects to be 'discovered' by the reference processor. At the end of the evacuation pause, these discovered reference objects are processed - preserving (and copying) referent objects (and their reachable graphs) as appropriate. Reviewed-by: ysr, jwilhelm, brutisso, stefank, tonyp
author johnc
date Thu, 22 Sep 2011 10:57:37 -0700
parents 1d1603768966
children da91efe96a93
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1 /*
2426
1d1603768966 7010070: Update all 2010 Oracle-changed OpenJDK files to have the proper copyright dates - second pass
trims
parents: 2177
diff changeset
2 * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
a61af66fc99e Initial load
duke
parents:
diff changeset
4 *
a61af66fc99e Initial load
duke
parents:
diff changeset
5 * This code is free software; you can redistribute it and/or modify it
a61af66fc99e Initial load
duke
parents:
diff changeset
6 * under the terms of the GNU General Public License version 2 only, as
a61af66fc99e Initial load
duke
parents:
diff changeset
7 * published by the Free Software Foundation.
a61af66fc99e Initial load
duke
parents:
diff changeset
8 *
a61af66fc99e Initial load
duke
parents:
diff changeset
9 * This code is distributed in the hope that it will be useful, but WITHOUT
a61af66fc99e Initial load
duke
parents:
diff changeset
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
a61af66fc99e Initial load
duke
parents:
diff changeset
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
a61af66fc99e Initial load
duke
parents:
diff changeset
12 * version 2 for more details (a copy is included in the LICENSE file that
a61af66fc99e Initial load
duke
parents:
diff changeset
13 * accompanied this code).
a61af66fc99e Initial load
duke
parents:
diff changeset
14 *
a61af66fc99e Initial load
duke
parents:
diff changeset
15 * You should have received a copy of the GNU General Public License version
a61af66fc99e Initial load
duke
parents:
diff changeset
16 * 2 along with this work; if not, write to the Free Software Foundation,
a61af66fc99e Initial load
duke
parents:
diff changeset
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
a61af66fc99e Initial load
duke
parents:
diff changeset
18 *
1552
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 1513
diff changeset
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 1513
diff changeset
20 * or visit www.oracle.com if you need additional information or have any
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 1513
diff changeset
21 * questions.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
22 *
a61af66fc99e Initial load
duke
parents:
diff changeset
23 */
a61af66fc99e Initial load
duke
parents:
diff changeset
24
1972
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
25 #include "precompiled.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
26 #include "classfile/symbolTable.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
27 #include "classfile/systemDictionary.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
28 #include "memory/oopFactory.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
29 #include "oops/instanceKlass.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
30 #include "oops/oop.inline.hpp"
2177
3582bf76420e 6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents: 1972
diff changeset
31 #include "oops/symbol.hpp"
1972
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
32 #include "oops/typeArrayKlass.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
33 #include "runtime/signature.hpp"
0
a61af66fc99e Initial load
duke
parents:
diff changeset
34
a61af66fc99e Initial load
duke
parents:
diff changeset
35
a61af66fc99e Initial load
duke
parents:
diff changeset
36 // Implementation of SignatureIterator
a61af66fc99e Initial load
duke
parents:
diff changeset
37
a61af66fc99e Initial load
duke
parents:
diff changeset
38 // Signature syntax:
a61af66fc99e Initial load
duke
parents:
diff changeset
39 //
a61af66fc99e Initial load
duke
parents:
diff changeset
40 // Signature = "(" {Parameter} ")" ReturnType.
a61af66fc99e Initial load
duke
parents:
diff changeset
41 // Parameter = FieldType.
a61af66fc99e Initial load
duke
parents:
diff changeset
42 // ReturnType = FieldType | "V".
a61af66fc99e Initial load
duke
parents:
diff changeset
43 // FieldType = "B" | "C" | "D" | "F" | "I" | "J" | "S" | "Z" | "L" ClassName ";" | "[" FieldType.
a61af66fc99e Initial load
duke
parents:
diff changeset
44 // ClassName = string.
a61af66fc99e Initial load
duke
parents:
diff changeset
45
a61af66fc99e Initial load
duke
parents:
diff changeset
46
2177
3582bf76420e 6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents: 1972
diff changeset
47 SignatureIterator::SignatureIterator(Symbol* signature) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
48 _signature = signature;
a61af66fc99e Initial load
duke
parents:
diff changeset
49 _parameter_index = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
50 }
a61af66fc99e Initial load
duke
parents:
diff changeset
51
a61af66fc99e Initial load
duke
parents:
diff changeset
52 void SignatureIterator::expect(char c) {
1490
f03d0a26bf83 6888954: argument formatting for assert() and friends
jcoomes
parents: 0
diff changeset
53 if (_signature->byte_at(_index) != c) fatal(err_msg("expecting %c", c));
0
a61af66fc99e Initial load
duke
parents:
diff changeset
54 _index++;
a61af66fc99e Initial load
duke
parents:
diff changeset
55 }
a61af66fc99e Initial load
duke
parents:
diff changeset
56
a61af66fc99e Initial load
duke
parents:
diff changeset
57
a61af66fc99e Initial load
duke
parents:
diff changeset
58 void SignatureIterator::skip_optional_size() {
2177
3582bf76420e 6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents: 1972
diff changeset
59 Symbol* sig = _signature;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
60 char c = sig->byte_at(_index);
a61af66fc99e Initial load
duke
parents:
diff changeset
61 while ('0' <= c && c <= '9') c = sig->byte_at(++_index);
a61af66fc99e Initial load
duke
parents:
diff changeset
62 }
a61af66fc99e Initial load
duke
parents:
diff changeset
63
a61af66fc99e Initial load
duke
parents:
diff changeset
64
a61af66fc99e Initial load
duke
parents:
diff changeset
65 int SignatureIterator::parse_type() {
a61af66fc99e Initial load
duke
parents:
diff changeset
66 // Note: This function could be simplified by using "return T_XXX_size;"
a61af66fc99e Initial load
duke
parents:
diff changeset
67 // instead of the assignment and the break statements. However, it
a61af66fc99e Initial load
duke
parents:
diff changeset
68 // seems that the product build for win32_i486 with MS VC++ 6.0 doesn't
a61af66fc99e Initial load
duke
parents:
diff changeset
69 // work (stack underflow for some tests) - this seems to be a VC++ 6.0
a61af66fc99e Initial load
duke
parents:
diff changeset
70 // compiler bug (was problem - gri 4/27/2000).
a61af66fc99e Initial load
duke
parents:
diff changeset
71 int size = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
72 switch(_signature->byte_at(_index)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
73 case 'B': do_byte (); if (_parameter_index < 0 ) _return_type = T_BYTE;
a61af66fc99e Initial load
duke
parents:
diff changeset
74 _index++; size = T_BYTE_size ; break;
a61af66fc99e Initial load
duke
parents:
diff changeset
75 case 'C': do_char (); if (_parameter_index < 0 ) _return_type = T_CHAR;
a61af66fc99e Initial load
duke
parents:
diff changeset
76 _index++; size = T_CHAR_size ; break;
a61af66fc99e Initial load
duke
parents:
diff changeset
77 case 'D': do_double(); if (_parameter_index < 0 ) _return_type = T_DOUBLE;
a61af66fc99e Initial load
duke
parents:
diff changeset
78 _index++; size = T_DOUBLE_size ; break;
a61af66fc99e Initial load
duke
parents:
diff changeset
79 case 'F': do_float (); if (_parameter_index < 0 ) _return_type = T_FLOAT;
a61af66fc99e Initial load
duke
parents:
diff changeset
80 _index++; size = T_FLOAT_size ; break;
a61af66fc99e Initial load
duke
parents:
diff changeset
81 case 'I': do_int (); if (_parameter_index < 0 ) _return_type = T_INT;
a61af66fc99e Initial load
duke
parents:
diff changeset
82 _index++; size = T_INT_size ; break;
a61af66fc99e Initial load
duke
parents:
diff changeset
83 case 'J': do_long (); if (_parameter_index < 0 ) _return_type = T_LONG;
a61af66fc99e Initial load
duke
parents:
diff changeset
84 _index++; size = T_LONG_size ; break;
a61af66fc99e Initial load
duke
parents:
diff changeset
85 case 'S': do_short (); if (_parameter_index < 0 ) _return_type = T_SHORT;
a61af66fc99e Initial load
duke
parents:
diff changeset
86 _index++; size = T_SHORT_size ; break;
a61af66fc99e Initial load
duke
parents:
diff changeset
87 case 'Z': do_bool (); if (_parameter_index < 0 ) _return_type = T_BOOLEAN;
a61af66fc99e Initial load
duke
parents:
diff changeset
88 _index++; size = T_BOOLEAN_size; break;
a61af66fc99e Initial load
duke
parents:
diff changeset
89 case 'V': do_void (); if (_parameter_index < 0 ) _return_type = T_VOID;
a61af66fc99e Initial load
duke
parents:
diff changeset
90 _index++; size = T_VOID_size; ; break;
a61af66fc99e Initial load
duke
parents:
diff changeset
91 case 'L':
a61af66fc99e Initial load
duke
parents:
diff changeset
92 { int begin = ++_index;
2177
3582bf76420e 6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents: 1972
diff changeset
93 Symbol* sig = _signature;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
94 while (sig->byte_at(_index++) != ';') ;
a61af66fc99e Initial load
duke
parents:
diff changeset
95 do_object(begin, _index);
a61af66fc99e Initial load
duke
parents:
diff changeset
96 }
a61af66fc99e Initial load
duke
parents:
diff changeset
97 if (_parameter_index < 0 ) _return_type = T_OBJECT;
a61af66fc99e Initial load
duke
parents:
diff changeset
98 size = T_OBJECT_size;
a61af66fc99e Initial load
duke
parents:
diff changeset
99 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
100 case '[':
a61af66fc99e Initial load
duke
parents:
diff changeset
101 { int begin = ++_index;
a61af66fc99e Initial load
duke
parents:
diff changeset
102 skip_optional_size();
2177
3582bf76420e 6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents: 1972
diff changeset
103 Symbol* sig = _signature;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
104 while (sig->byte_at(_index) == '[') {
a61af66fc99e Initial load
duke
parents:
diff changeset
105 _index++;
a61af66fc99e Initial load
duke
parents:
diff changeset
106 skip_optional_size();
a61af66fc99e Initial load
duke
parents:
diff changeset
107 }
a61af66fc99e Initial load
duke
parents:
diff changeset
108 if (sig->byte_at(_index) == 'L') {
a61af66fc99e Initial load
duke
parents:
diff changeset
109 while (sig->byte_at(_index++) != ';') ;
a61af66fc99e Initial load
duke
parents:
diff changeset
110 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
111 _index++;
a61af66fc99e Initial load
duke
parents:
diff changeset
112 }
a61af66fc99e Initial load
duke
parents:
diff changeset
113 do_array(begin, _index);
a61af66fc99e Initial load
duke
parents:
diff changeset
114 if (_parameter_index < 0 ) _return_type = T_ARRAY;
a61af66fc99e Initial load
duke
parents:
diff changeset
115 }
a61af66fc99e Initial load
duke
parents:
diff changeset
116 size = T_ARRAY_size;
a61af66fc99e Initial load
duke
parents:
diff changeset
117 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
118 default:
a61af66fc99e Initial load
duke
parents:
diff changeset
119 ShouldNotReachHere();
a61af66fc99e Initial load
duke
parents:
diff changeset
120 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
121 }
a61af66fc99e Initial load
duke
parents:
diff changeset
122 assert(size >= 0, "size must be set");
a61af66fc99e Initial load
duke
parents:
diff changeset
123 return size;
a61af66fc99e Initial load
duke
parents:
diff changeset
124 }
a61af66fc99e Initial load
duke
parents:
diff changeset
125
a61af66fc99e Initial load
duke
parents:
diff changeset
126
a61af66fc99e Initial load
duke
parents:
diff changeset
127 void SignatureIterator::check_signature_end() {
a61af66fc99e Initial load
duke
parents:
diff changeset
128 if (_index < _signature->utf8_length()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
129 tty->print_cr("too many chars in signature");
a61af66fc99e Initial load
duke
parents:
diff changeset
130 _signature->print_value_on(tty);
a61af66fc99e Initial load
duke
parents:
diff changeset
131 tty->print_cr(" @ %d", _index);
a61af66fc99e Initial load
duke
parents:
diff changeset
132 }
a61af66fc99e Initial load
duke
parents:
diff changeset
133 }
a61af66fc99e Initial load
duke
parents:
diff changeset
134
a61af66fc99e Initial load
duke
parents:
diff changeset
135
a61af66fc99e Initial load
duke
parents:
diff changeset
136 void SignatureIterator::dispatch_field() {
a61af66fc99e Initial load
duke
parents:
diff changeset
137 // no '(', just one (field) type
a61af66fc99e Initial load
duke
parents:
diff changeset
138 _index = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
139 _parameter_index = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
140 parse_type();
a61af66fc99e Initial load
duke
parents:
diff changeset
141 check_signature_end();
a61af66fc99e Initial load
duke
parents:
diff changeset
142 }
a61af66fc99e Initial load
duke
parents:
diff changeset
143
a61af66fc99e Initial load
duke
parents:
diff changeset
144
a61af66fc99e Initial load
duke
parents:
diff changeset
145 void SignatureIterator::iterate_parameters() {
a61af66fc99e Initial load
duke
parents:
diff changeset
146 // Parse parameters
a61af66fc99e Initial load
duke
parents:
diff changeset
147 _index = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
148 _parameter_index = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
149 expect('(');
a61af66fc99e Initial load
duke
parents:
diff changeset
150 while (_signature->byte_at(_index) != ')') _parameter_index += parse_type();
a61af66fc99e Initial load
duke
parents:
diff changeset
151 expect(')');
a61af66fc99e Initial load
duke
parents:
diff changeset
152 _parameter_index = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
153 }
a61af66fc99e Initial load
duke
parents:
diff changeset
154
a61af66fc99e Initial load
duke
parents:
diff changeset
155 // Optimized version of iterat_parameters when fingerprint is known
a61af66fc99e Initial load
duke
parents:
diff changeset
156 void SignatureIterator::iterate_parameters( uint64_t fingerprint ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
157 uint64_t saved_fingerprint = fingerprint;
a61af66fc99e Initial load
duke
parents:
diff changeset
158
a61af66fc99e Initial load
duke
parents:
diff changeset
159 // Check for too many arguments
a61af66fc99e Initial load
duke
parents:
diff changeset
160 if ( fingerprint == UCONST64(-1) ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
161 SignatureIterator::iterate_parameters();
a61af66fc99e Initial load
duke
parents:
diff changeset
162 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
163 }
a61af66fc99e Initial load
duke
parents:
diff changeset
164
a61af66fc99e Initial load
duke
parents:
diff changeset
165 assert(fingerprint, "Fingerprint should not be 0");
a61af66fc99e Initial load
duke
parents:
diff changeset
166
a61af66fc99e Initial load
duke
parents:
diff changeset
167 _parameter_index = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
168 fingerprint = fingerprint >> (static_feature_size + result_feature_size);
a61af66fc99e Initial load
duke
parents:
diff changeset
169 while ( 1 ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
170 switch ( fingerprint & parameter_feature_mask ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
171 case bool_parm:
a61af66fc99e Initial load
duke
parents:
diff changeset
172 do_bool();
a61af66fc99e Initial load
duke
parents:
diff changeset
173 _parameter_index += T_BOOLEAN_size;
a61af66fc99e Initial load
duke
parents:
diff changeset
174 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
175 case byte_parm:
a61af66fc99e Initial load
duke
parents:
diff changeset
176 do_byte();
a61af66fc99e Initial load
duke
parents:
diff changeset
177 _parameter_index += T_BYTE_size;
a61af66fc99e Initial load
duke
parents:
diff changeset
178 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
179 case char_parm:
a61af66fc99e Initial load
duke
parents:
diff changeset
180 do_char();
a61af66fc99e Initial load
duke
parents:
diff changeset
181 _parameter_index += T_CHAR_size;
a61af66fc99e Initial load
duke
parents:
diff changeset
182 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
183 case short_parm:
a61af66fc99e Initial load
duke
parents:
diff changeset
184 do_short();
a61af66fc99e Initial load
duke
parents:
diff changeset
185 _parameter_index += T_SHORT_size;
a61af66fc99e Initial load
duke
parents:
diff changeset
186 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
187 case int_parm:
a61af66fc99e Initial load
duke
parents:
diff changeset
188 do_int();
a61af66fc99e Initial load
duke
parents:
diff changeset
189 _parameter_index += T_INT_size;
a61af66fc99e Initial load
duke
parents:
diff changeset
190 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
191 case obj_parm:
a61af66fc99e Initial load
duke
parents:
diff changeset
192 do_object(0, 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
193 _parameter_index += T_OBJECT_size;
a61af66fc99e Initial load
duke
parents:
diff changeset
194 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
195 case long_parm:
a61af66fc99e Initial load
duke
parents:
diff changeset
196 do_long();
a61af66fc99e Initial load
duke
parents:
diff changeset
197 _parameter_index += T_LONG_size;
a61af66fc99e Initial load
duke
parents:
diff changeset
198 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
199 case float_parm:
a61af66fc99e Initial load
duke
parents:
diff changeset
200 do_float();
a61af66fc99e Initial load
duke
parents:
diff changeset
201 _parameter_index += T_FLOAT_size;
a61af66fc99e Initial load
duke
parents:
diff changeset
202 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
203 case double_parm:
a61af66fc99e Initial load
duke
parents:
diff changeset
204 do_double();
a61af66fc99e Initial load
duke
parents:
diff changeset
205 _parameter_index += T_DOUBLE_size;
a61af66fc99e Initial load
duke
parents:
diff changeset
206 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
207 case done_parm:
a61af66fc99e Initial load
duke
parents:
diff changeset
208 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
209 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
210 default:
a61af66fc99e Initial load
duke
parents:
diff changeset
211 tty->print_cr("*** parameter is %d", fingerprint & parameter_feature_mask);
a61af66fc99e Initial load
duke
parents:
diff changeset
212 tty->print_cr("*** fingerprint is " PTR64_FORMAT, saved_fingerprint);
a61af66fc99e Initial load
duke
parents:
diff changeset
213 ShouldNotReachHere();
a61af66fc99e Initial load
duke
parents:
diff changeset
214 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
215 }
a61af66fc99e Initial load
duke
parents:
diff changeset
216 fingerprint >>= parameter_feature_size;
a61af66fc99e Initial load
duke
parents:
diff changeset
217 }
a61af66fc99e Initial load
duke
parents:
diff changeset
218 _parameter_index = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
219 }
a61af66fc99e Initial load
duke
parents:
diff changeset
220
a61af66fc99e Initial load
duke
parents:
diff changeset
221
a61af66fc99e Initial load
duke
parents:
diff changeset
222 void SignatureIterator::iterate_returntype() {
a61af66fc99e Initial load
duke
parents:
diff changeset
223 // Ignore parameters
a61af66fc99e Initial load
duke
parents:
diff changeset
224 _index = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
225 expect('(');
2177
3582bf76420e 6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents: 1972
diff changeset
226 Symbol* sig = _signature;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
227 while (sig->byte_at(_index) != ')') _index++;
a61af66fc99e Initial load
duke
parents:
diff changeset
228 expect(')');
a61af66fc99e Initial load
duke
parents:
diff changeset
229 // Parse return type
a61af66fc99e Initial load
duke
parents:
diff changeset
230 _parameter_index = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
231 parse_type();
a61af66fc99e Initial load
duke
parents:
diff changeset
232 check_signature_end();
a61af66fc99e Initial load
duke
parents:
diff changeset
233 _parameter_index = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
234 }
a61af66fc99e Initial load
duke
parents:
diff changeset
235
a61af66fc99e Initial load
duke
parents:
diff changeset
236
a61af66fc99e Initial load
duke
parents:
diff changeset
237 void SignatureIterator::iterate() {
a61af66fc99e Initial load
duke
parents:
diff changeset
238 // Parse parameters
a61af66fc99e Initial load
duke
parents:
diff changeset
239 _parameter_index = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
240 _index = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
241 expect('(');
a61af66fc99e Initial load
duke
parents:
diff changeset
242 while (_signature->byte_at(_index) != ')') _parameter_index += parse_type();
a61af66fc99e Initial load
duke
parents:
diff changeset
243 expect(')');
a61af66fc99e Initial load
duke
parents:
diff changeset
244 // Parse return type
a61af66fc99e Initial load
duke
parents:
diff changeset
245 _parameter_index = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
246 parse_type();
a61af66fc99e Initial load
duke
parents:
diff changeset
247 check_signature_end();
a61af66fc99e Initial load
duke
parents:
diff changeset
248 _parameter_index = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
249 }
a61af66fc99e Initial load
duke
parents:
diff changeset
250
a61af66fc99e Initial load
duke
parents:
diff changeset
251
a61af66fc99e Initial load
duke
parents:
diff changeset
252 // Implementation of SignatureStream
2177
3582bf76420e 6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents: 1972
diff changeset
253 SignatureStream::SignatureStream(Symbol* signature, bool is_method) :
3582bf76420e 6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents: 1972
diff changeset
254 _signature(signature), _at_return_type(false) {
3582bf76420e 6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents: 1972
diff changeset
255 _begin = _end = (is_method ? 1 : 0); // skip first '(' in method signatures
3582bf76420e 6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents: 1972
diff changeset
256 _names = new GrowableArray<Symbol*>(10);
3582bf76420e 6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents: 1972
diff changeset
257 next();
3582bf76420e 6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents: 1972
diff changeset
258 }
3582bf76420e 6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents: 1972
diff changeset
259
3582bf76420e 6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents: 1972
diff changeset
260 SignatureStream::~SignatureStream() {
3582bf76420e 6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents: 1972
diff changeset
261 // decrement refcount for names created during signature parsing
3582bf76420e 6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents: 1972
diff changeset
262 for (int i = 0; i < _names->length(); i++) {
3582bf76420e 6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents: 1972
diff changeset
263 _names->at(i)->decrement_refcount();
3582bf76420e 6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents: 1972
diff changeset
264 }
3582bf76420e 6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents: 1972
diff changeset
265 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
266
a61af66fc99e Initial load
duke
parents:
diff changeset
267 bool SignatureStream::is_done() const {
2177
3582bf76420e 6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents: 1972
diff changeset
268 return _end > _signature->utf8_length();
0
a61af66fc99e Initial load
duke
parents:
diff changeset
269 }
a61af66fc99e Initial load
duke
parents:
diff changeset
270
a61af66fc99e Initial load
duke
parents:
diff changeset
271
a61af66fc99e Initial load
duke
parents:
diff changeset
272 void SignatureStream::next_non_primitive(int t) {
a61af66fc99e Initial load
duke
parents:
diff changeset
273 switch (t) {
a61af66fc99e Initial load
duke
parents:
diff changeset
274 case 'L': {
a61af66fc99e Initial load
duke
parents:
diff changeset
275 _type = T_OBJECT;
2177
3582bf76420e 6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents: 1972
diff changeset
276 Symbol* sig = _signature;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
277 while (sig->byte_at(_end++) != ';');
a61af66fc99e Initial load
duke
parents:
diff changeset
278 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
279 }
a61af66fc99e Initial load
duke
parents:
diff changeset
280 case '[': {
a61af66fc99e Initial load
duke
parents:
diff changeset
281 _type = T_ARRAY;
2177
3582bf76420e 6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents: 1972
diff changeset
282 Symbol* sig = _signature;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
283 char c = sig->byte_at(_end);
a61af66fc99e Initial load
duke
parents:
diff changeset
284 while ('0' <= c && c <= '9') c = sig->byte_at(_end++);
a61af66fc99e Initial load
duke
parents:
diff changeset
285 while (sig->byte_at(_end) == '[') {
a61af66fc99e Initial load
duke
parents:
diff changeset
286 _end++;
a61af66fc99e Initial load
duke
parents:
diff changeset
287 c = sig->byte_at(_end);
a61af66fc99e Initial load
duke
parents:
diff changeset
288 while ('0' <= c && c <= '9') c = sig->byte_at(_end++);
a61af66fc99e Initial load
duke
parents:
diff changeset
289 }
a61af66fc99e Initial load
duke
parents:
diff changeset
290 switch(sig->byte_at(_end)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
291 case 'B':
a61af66fc99e Initial load
duke
parents:
diff changeset
292 case 'C':
a61af66fc99e Initial load
duke
parents:
diff changeset
293 case 'D':
a61af66fc99e Initial load
duke
parents:
diff changeset
294 case 'F':
a61af66fc99e Initial load
duke
parents:
diff changeset
295 case 'I':
a61af66fc99e Initial load
duke
parents:
diff changeset
296 case 'J':
a61af66fc99e Initial load
duke
parents:
diff changeset
297 case 'S':
a61af66fc99e Initial load
duke
parents:
diff changeset
298 case 'Z':_end++; break;
a61af66fc99e Initial load
duke
parents:
diff changeset
299 default: {
a61af66fc99e Initial load
duke
parents:
diff changeset
300 while (sig->byte_at(_end++) != ';');
a61af66fc99e Initial load
duke
parents:
diff changeset
301 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
302 }
a61af66fc99e Initial load
duke
parents:
diff changeset
303 }
a61af66fc99e Initial load
duke
parents:
diff changeset
304 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
305 }
a61af66fc99e Initial load
duke
parents:
diff changeset
306 case ')': _end++; next(); _at_return_type = true; break;
a61af66fc99e Initial load
duke
parents:
diff changeset
307 default : ShouldNotReachHere();
a61af66fc99e Initial load
duke
parents:
diff changeset
308 }
a61af66fc99e Initial load
duke
parents:
diff changeset
309 }
a61af66fc99e Initial load
duke
parents:
diff changeset
310
a61af66fc99e Initial load
duke
parents:
diff changeset
311
a61af66fc99e Initial load
duke
parents:
diff changeset
312 bool SignatureStream::is_object() const {
a61af66fc99e Initial load
duke
parents:
diff changeset
313 return _type == T_OBJECT
a61af66fc99e Initial load
duke
parents:
diff changeset
314 || _type == T_ARRAY;
a61af66fc99e Initial load
duke
parents:
diff changeset
315 }
a61af66fc99e Initial load
duke
parents:
diff changeset
316
a61af66fc99e Initial load
duke
parents:
diff changeset
317 bool SignatureStream::is_array() const {
a61af66fc99e Initial load
duke
parents:
diff changeset
318 return _type == T_ARRAY;
a61af66fc99e Initial load
duke
parents:
diff changeset
319 }
a61af66fc99e Initial load
duke
parents:
diff changeset
320
2177
3582bf76420e 6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents: 1972
diff changeset
321 Symbol* SignatureStream::as_symbol(TRAPS) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
322 // Create a symbol from for string _begin _end
a61af66fc99e Initial load
duke
parents:
diff changeset
323 int begin = _begin;
a61af66fc99e Initial load
duke
parents:
diff changeset
324 int end = _end;
a61af66fc99e Initial load
duke
parents:
diff changeset
325
2177
3582bf76420e 6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents: 1972
diff changeset
326 if ( _signature->byte_at(_begin) == 'L'
3582bf76420e 6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents: 1972
diff changeset
327 && _signature->byte_at(_end-1) == ';') {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
328 begin++;
a61af66fc99e Initial load
duke
parents:
diff changeset
329 end--;
a61af66fc99e Initial load
duke
parents:
diff changeset
330 }
a61af66fc99e Initial load
duke
parents:
diff changeset
331
2177
3582bf76420e 6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents: 1972
diff changeset
332 // Save names for cleaning up reference count at the end of
3582bf76420e 6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents: 1972
diff changeset
333 // SignatureStream scope.
3582bf76420e 6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents: 1972
diff changeset
334 Symbol* name = SymbolTable::new_symbol(_signature, begin, end, CHECK_NULL);
3582bf76420e 6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents: 1972
diff changeset
335 _names->push(name); // save new symbol for decrementing later
3582bf76420e 6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents: 1972
diff changeset
336 return name;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
337 }
a61af66fc99e Initial load
duke
parents:
diff changeset
338
1508
2ffde6cfe049 6939196: method handle signatures off the boot class path get linkage errors
jrose
parents: 0
diff changeset
339 klassOop SignatureStream::as_klass(Handle class_loader, Handle protection_domain,
2ffde6cfe049 6939196: method handle signatures off the boot class path get linkage errors
jrose
parents: 0
diff changeset
340 FailureMode failure_mode, TRAPS) {
2ffde6cfe049 6939196: method handle signatures off the boot class path get linkage errors
jrose
parents: 0
diff changeset
341 if (!is_object()) return NULL;
2177
3582bf76420e 6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents: 1972
diff changeset
342 Symbol* name = as_symbol(CHECK_NULL);
1508
2ffde6cfe049 6939196: method handle signatures off the boot class path get linkage errors
jrose
parents: 0
diff changeset
343 if (failure_mode == ReturnNull) {
2ffde6cfe049 6939196: method handle signatures off the boot class path get linkage errors
jrose
parents: 0
diff changeset
344 return SystemDictionary::resolve_or_null(name, class_loader, protection_domain, THREAD);
2ffde6cfe049 6939196: method handle signatures off the boot class path get linkage errors
jrose
parents: 0
diff changeset
345 } else {
2ffde6cfe049 6939196: method handle signatures off the boot class path get linkage errors
jrose
parents: 0
diff changeset
346 bool throw_error = (failure_mode == NCDFError);
2ffde6cfe049 6939196: method handle signatures off the boot class path get linkage errors
jrose
parents: 0
diff changeset
347 return SystemDictionary::resolve_or_fail(name, class_loader, protection_domain, throw_error, THREAD);
2ffde6cfe049 6939196: method handle signatures off the boot class path get linkage errors
jrose
parents: 0
diff changeset
348 }
2ffde6cfe049 6939196: method handle signatures off the boot class path get linkage errors
jrose
parents: 0
diff changeset
349 }
2ffde6cfe049 6939196: method handle signatures off the boot class path get linkage errors
jrose
parents: 0
diff changeset
350
2ffde6cfe049 6939196: method handle signatures off the boot class path get linkage errors
jrose
parents: 0
diff changeset
351 oop SignatureStream::as_java_mirror(Handle class_loader, Handle protection_domain,
2ffde6cfe049 6939196: method handle signatures off the boot class path get linkage errors
jrose
parents: 0
diff changeset
352 FailureMode failure_mode, TRAPS) {
2ffde6cfe049 6939196: method handle signatures off the boot class path get linkage errors
jrose
parents: 0
diff changeset
353 if (!is_object())
2ffde6cfe049 6939196: method handle signatures off the boot class path get linkage errors
jrose
parents: 0
diff changeset
354 return Universe::java_mirror(type());
2ffde6cfe049 6939196: method handle signatures off the boot class path get linkage errors
jrose
parents: 0
diff changeset
355 klassOop klass = as_klass(class_loader, protection_domain, failure_mode, CHECK_NULL);
2ffde6cfe049 6939196: method handle signatures off the boot class path get linkage errors
jrose
parents: 0
diff changeset
356 if (klass == NULL) return NULL;
2ffde6cfe049 6939196: method handle signatures off the boot class path get linkage errors
jrose
parents: 0
diff changeset
357 return Klass::cast(klass)->java_mirror();
2ffde6cfe049 6939196: method handle signatures off the boot class path get linkage errors
jrose
parents: 0
diff changeset
358 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
359
2177
3582bf76420e 6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents: 1972
diff changeset
360 Symbol* SignatureStream::as_symbol_or_null() {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
361 // Create a symbol from for string _begin _end
a61af66fc99e Initial load
duke
parents:
diff changeset
362 ResourceMark rm;
a61af66fc99e Initial load
duke
parents:
diff changeset
363
a61af66fc99e Initial load
duke
parents:
diff changeset
364 int begin = _begin;
a61af66fc99e Initial load
duke
parents:
diff changeset
365 int end = _end;
a61af66fc99e Initial load
duke
parents:
diff changeset
366
2177
3582bf76420e 6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents: 1972
diff changeset
367 if ( _signature->byte_at(_begin) == 'L'
3582bf76420e 6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents: 1972
diff changeset
368 && _signature->byte_at(_end-1) == ';') {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
369 begin++;
a61af66fc99e Initial load
duke
parents:
diff changeset
370 end--;
a61af66fc99e Initial load
duke
parents:
diff changeset
371 }
a61af66fc99e Initial load
duke
parents:
diff changeset
372
a61af66fc99e Initial load
duke
parents:
diff changeset
373 char* buffer = NEW_RESOURCE_ARRAY(char, end - begin);
a61af66fc99e Initial load
duke
parents:
diff changeset
374 for (int index = begin; index < end; index++) {
2177
3582bf76420e 6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents: 1972
diff changeset
375 buffer[index - begin] = _signature->byte_at(index);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
376 }
2177
3582bf76420e 6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents: 1972
diff changeset
377 Symbol* result = SymbolTable::probe(buffer, end - begin);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
378 return result;
a61af66fc99e Initial load
duke
parents:
diff changeset
379 }
a61af66fc99e Initial load
duke
parents:
diff changeset
380
2177
3582bf76420e 6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents: 1972
diff changeset
381 bool SignatureVerifier::is_valid_signature(Symbol* sig) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
382 const char* signature = (const char*)sig->bytes();
a61af66fc99e Initial load
duke
parents:
diff changeset
383 ssize_t len = sig->utf8_length();
a61af66fc99e Initial load
duke
parents:
diff changeset
384 if (signature == NULL || signature[0] == '\0' || len < 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
385 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
386 } else if (signature[0] == '(') {
a61af66fc99e Initial load
duke
parents:
diff changeset
387 return is_valid_method_signature(sig);
a61af66fc99e Initial load
duke
parents:
diff changeset
388 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
389 return is_valid_type_signature(sig);
a61af66fc99e Initial load
duke
parents:
diff changeset
390 }
a61af66fc99e Initial load
duke
parents:
diff changeset
391 }
a61af66fc99e Initial load
duke
parents:
diff changeset
392
2177
3582bf76420e 6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents: 1972
diff changeset
393 bool SignatureVerifier::is_valid_method_signature(Symbol* sig) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
394 const char* method_sig = (const char*)sig->bytes();
a61af66fc99e Initial load
duke
parents:
diff changeset
395 ssize_t len = sig->utf8_length();
a61af66fc99e Initial load
duke
parents:
diff changeset
396 ssize_t index = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
397 if (method_sig != NULL && len > 1 && method_sig[index] == '(') {
a61af66fc99e Initial load
duke
parents:
diff changeset
398 ++index;
a61af66fc99e Initial load
duke
parents:
diff changeset
399 while (index < len && method_sig[index] != ')') {
a61af66fc99e Initial load
duke
parents:
diff changeset
400 ssize_t res = is_valid_type(&method_sig[index], len - index);
a61af66fc99e Initial load
duke
parents:
diff changeset
401 if (res == -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
402 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
403 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
404 index += res;
a61af66fc99e Initial load
duke
parents:
diff changeset
405 }
a61af66fc99e Initial load
duke
parents:
diff changeset
406 }
a61af66fc99e Initial load
duke
parents:
diff changeset
407 if (index < len && method_sig[index] == ')') {
a61af66fc99e Initial load
duke
parents:
diff changeset
408 // check the return type
a61af66fc99e Initial load
duke
parents:
diff changeset
409 ++index;
a61af66fc99e Initial load
duke
parents:
diff changeset
410 return (is_valid_type(&method_sig[index], len - index) == (len - index));
a61af66fc99e Initial load
duke
parents:
diff changeset
411 }
a61af66fc99e Initial load
duke
parents:
diff changeset
412 }
a61af66fc99e Initial load
duke
parents:
diff changeset
413 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
414 }
a61af66fc99e Initial load
duke
parents:
diff changeset
415
2177
3582bf76420e 6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents: 1972
diff changeset
416 bool SignatureVerifier::is_valid_type_signature(Symbol* sig) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
417 const char* type_sig = (const char*)sig->bytes();
a61af66fc99e Initial load
duke
parents:
diff changeset
418 ssize_t len = sig->utf8_length();
a61af66fc99e Initial load
duke
parents:
diff changeset
419 return (type_sig != NULL && len >= 1 &&
a61af66fc99e Initial load
duke
parents:
diff changeset
420 (is_valid_type(type_sig, len) == len));
a61af66fc99e Initial load
duke
parents:
diff changeset
421 }
a61af66fc99e Initial load
duke
parents:
diff changeset
422
a61af66fc99e Initial load
duke
parents:
diff changeset
423 // Checks to see if the type (not to go beyond 'limit') refers to a valid type.
a61af66fc99e Initial load
duke
parents:
diff changeset
424 // Returns -1 if it is not, or the index of the next character that is not part
a61af66fc99e Initial load
duke
parents:
diff changeset
425 // of the type. The type encoding may end before 'limit' and that's ok.
a61af66fc99e Initial load
duke
parents:
diff changeset
426 ssize_t SignatureVerifier::is_valid_type(const char* type, ssize_t limit) {
a61af66fc99e Initial load
duke
parents:
diff changeset
427 ssize_t index = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
428
a61af66fc99e Initial load
duke
parents:
diff changeset
429 // Iterate over any number of array dimensions
a61af66fc99e Initial load
duke
parents:
diff changeset
430 while (index < limit && type[index] == '[') ++index;
a61af66fc99e Initial load
duke
parents:
diff changeset
431 if (index >= limit) {
a61af66fc99e Initial load
duke
parents:
diff changeset
432 return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
433 }
a61af66fc99e Initial load
duke
parents:
diff changeset
434 switch (type[index]) {
a61af66fc99e Initial load
duke
parents:
diff changeset
435 case 'B': case 'C': case 'D': case 'F': case 'I':
a61af66fc99e Initial load
duke
parents:
diff changeset
436 case 'J': case 'S': case 'Z': case 'V':
a61af66fc99e Initial load
duke
parents:
diff changeset
437 return index + 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
438 case 'L':
a61af66fc99e Initial load
duke
parents:
diff changeset
439 for (index = index + 1; index < limit; ++index) {
a61af66fc99e Initial load
duke
parents:
diff changeset
440 char c = type[index];
a61af66fc99e Initial load
duke
parents:
diff changeset
441 if (c == ';') {
a61af66fc99e Initial load
duke
parents:
diff changeset
442 return index + 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
443 }
a61af66fc99e Initial load
duke
parents:
diff changeset
444 if (invalid_name_char(c)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
445 return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
446 }
a61af66fc99e Initial load
duke
parents:
diff changeset
447 }
a61af66fc99e Initial load
duke
parents:
diff changeset
448 // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
449 default: ; // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
450 }
a61af66fc99e Initial load
duke
parents:
diff changeset
451 return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
452 }
a61af66fc99e Initial load
duke
parents:
diff changeset
453
a61af66fc99e Initial load
duke
parents:
diff changeset
454 bool SignatureVerifier::invalid_name_char(char c) {
a61af66fc99e Initial load
duke
parents:
diff changeset
455 switch (c) {
a61af66fc99e Initial load
duke
parents:
diff changeset
456 case '\0': case '.': case ';': case '[':
a61af66fc99e Initial load
duke
parents:
diff changeset
457 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
458 default:
a61af66fc99e Initial load
duke
parents:
diff changeset
459 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
460 }
a61af66fc99e Initial load
duke
parents:
diff changeset
461 }