Mercurial > hg > truffle
annotate src/share/vm/adlc/forms.cpp @ 452:00b023ae2d78
6722113: CMS: Incorrect overflow handling during precleaning of Reference lists
Summary: When we encounter marking stack overflow during precleaning of Reference lists, we were using the overflow list mechanism, which can cause problems on account of mutating the mark word of the header because of conflicts with mutator accesses and updates of that field. Instead we should use the usual mechanism for overflow handling in concurrent phases, namely dirtying of the card on which the overflowed object lies. Since precleaning effectively does a form of discovered list processing, albeit with discovery enabled, we needed to adjust some code to be correct in the face of interleaved processing and discovery.
Reviewed-by: apetrusenko, jcoomes
author | ysr |
---|---|
date | Thu, 20 Nov 2008 12:27:41 -0800 |
parents | 4d9884b01ba6 |
children | 3b5ac9e7e6ea |
rev | line source |
---|---|
0 | 1 /* |
196 | 2 * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. |
0 | 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, | |
20 * CA 95054 USA or visit www.sun.com if you need additional information or | |
21 * have any questions. | |
22 * | |
23 */ | |
24 | |
25 // FORMS.CPP - Definitions for ADL Parser Generic & Utility Forms Classes | |
26 #include "adlc.hpp" | |
27 | |
28 //------------------------------Static Initializers---------------------------- | |
29 // allocate arena used by forms | |
30 Arena *Form::arena = Form::generate_arena(); // = Form::generate_arena(); | |
31 Arena *Form::generate_arena() { | |
32 return (new Arena); | |
33 } | |
34 | |
35 //------------------------------NameList--------------------------------------- | |
36 // reserved user-defined string | |
37 const char *NameList::_signal = "$$SIGNAL$$"; | |
415
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
196
diff
changeset
|
38 const char *NameList::_signal2 = "$$SIGNAL2$$"; |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
196
diff
changeset
|
39 const char *NameList::_signal3 = "$$SIGNAL3$$"; |
0 | 40 |
41 // Constructor and Destructor | |
42 NameList::NameList() : _cur(0), _max(4), _iter(0), _justReset(true) { | |
43 _names = (const char**)malloc(_max*sizeof(char*)); | |
44 } | |
45 NameList::~NameList() { | |
46 // The following free is a double-free, and crashes the program: | |
47 //free(_names); // not owner of strings | |
48 } | |
49 | |
50 void NameList::addName(const char *name) { | |
51 if (_cur == _max) _names =(const char**)realloc(_names,(_max *=2)*sizeof(char*)); | |
52 _names[_cur++] = name; | |
53 } | |
54 | |
55 void NameList::add_signal() { | |
56 addName( _signal ); | |
57 } | |
58 void NameList::clear() { | |
59 _cur = 0; | |
60 _iter = 0; | |
61 _justReset = true; | |
62 // _max = 4; Already allocated | |
63 } | |
64 | |
65 int NameList::count() const { return _cur; } | |
66 | |
67 void NameList::reset() { _iter = 0; _justReset = true;} | |
68 const char *NameList::iter() { | |
69 if (_justReset) {_justReset=false; return (_iter < _cur ? _names[_iter] : NULL);} | |
70 else return (_iter <_cur-1 ? _names[++_iter] : NULL); | |
71 } | |
72 const char *NameList::current() { return (_iter < _cur ? _names[_iter] : NULL); } | |
73 | |
74 // Return 'true' if current entry is signal | |
75 bool NameList::current_is_signal() { | |
76 const char *entry = current(); | |
77 return is_signal(entry); | |
78 } | |
79 | |
80 // Return true if entry is a signal | |
81 bool NameList::is_signal(const char *entry) { | |
82 return ( (strcmp(entry,NameList::_signal) == 0) ? true : false); | |
83 } | |
84 | |
85 // Search for a name in the list | |
86 bool NameList::search(const char *name) { | |
87 const char *entry; | |
88 for(reset(); (entry = iter()) != NULL; ) { | |
89 if(!strcmp(entry,name)) return true; | |
90 } | |
91 return false; | |
92 } | |
93 | |
94 // Return index of name in list | |
95 int NameList::index(const char *name) { | |
96 int cnt = 0; | |
97 const char *entry; | |
98 for(reset(); (entry = iter()) != NULL; ) { | |
99 if(!strcmp(entry,name)) return cnt; | |
100 cnt++; | |
101 } | |
102 return Not_in_list; | |
103 } | |
104 | |
105 // Return name at index in list | |
106 const char *NameList::name(intptr_t index) { | |
107 return ( index < _cur ? _names[index] : NULL); | |
108 } | |
109 | |
110 void NameList::dump() { output(stderr); } | |
111 | |
112 void NameList::output(FILE *fp) { | |
113 fprintf(fp, "\n"); | |
114 | |
115 // Run iteration over all entries, independent of position of iterator. | |
116 const char *name = NULL; | |
117 int iter = 0; | |
118 bool justReset = true; | |
119 | |
120 while( ( name = (justReset ? | |
121 (justReset=false, (iter < _cur ? _names[iter] : NULL)) : | |
122 (iter < _cur-1 ? _names[++iter] : NULL)) ) | |
123 != NULL ) { | |
124 fprintf( fp, " %s,\n", name); | |
125 } | |
126 fprintf(fp, "\n"); | |
127 } | |
128 | |
129 //------------------------------NameAndList------------------------------------ | |
130 // Storage for a name and an associated list of names | |
131 NameAndList::NameAndList(char *name) : _name(name) { | |
132 } | |
133 NameAndList::~NameAndList() { | |
134 } | |
135 | |
136 // Add to entries in list | |
137 void NameAndList::add_entry(const char *entry) { | |
138 _list.addName(entry); | |
139 } | |
140 | |
141 // Access the name and its associated list. | |
142 const char *NameAndList::name() const { return _name; } | |
143 void NameAndList::reset() { _list.reset(); } | |
144 const char *NameAndList::iter() { return _list.iter(); } | |
145 | |
146 // Return the "index" entry in the list, zero-based | |
147 const char *NameAndList::operator[](int index) { | |
148 assert( index >= 0, "Internal Error(): index less than 0."); | |
149 | |
150 _list.reset(); | |
151 const char *entry = _list.iter(); | |
152 // Iterate further if it isn't at index 0. | |
153 for ( int position = 0; position != index; ++position ) { | |
154 entry = _list.iter(); | |
155 } | |
156 | |
157 return entry; | |
158 } | |
159 | |
160 | |
161 void NameAndList::dump() { output(stderr); } | |
162 void NameAndList::output(FILE *fp) { | |
163 fprintf(fp, "\n"); | |
164 | |
165 // Output the Name | |
166 fprintf(fp, "Name == %s", (_name ? _name : "") ); | |
167 | |
168 // Output the associated list of names | |
169 const char *name; | |
170 fprintf(fp, " ("); | |
171 for (reset(); (name = iter()) != NULL;) { | |
172 fprintf(fp, " %s,\n", name); | |
173 } | |
174 fprintf(fp, ")"); | |
175 fprintf(fp, "\n"); | |
176 } | |
177 | |
178 //------------------------------Form------------------------------------------- | |
179 OpClassForm *Form::is_opclass() const { | |
180 return NULL; | |
181 } | |
182 | |
183 OperandForm *Form::is_operand() const { | |
184 return NULL; | |
185 } | |
186 | |
187 InstructForm *Form::is_instruction() const { | |
188 return NULL; | |
189 } | |
190 | |
191 MachNodeForm *Form::is_machnode() const { | |
192 return NULL; | |
193 } | |
194 | |
195 AttributeForm *Form::is_attribute() const { | |
196 return NULL; | |
197 } | |
198 | |
199 Effect *Form::is_effect() const { | |
200 return NULL; | |
201 } | |
202 | |
203 ResourceForm *Form::is_resource() const { | |
204 return NULL; | |
205 } | |
206 | |
207 PipeClassForm *Form::is_pipeclass() const { | |
208 return NULL; | |
209 } | |
210 | |
211 Form::DataType Form::ideal_to_const_type(const char *name) const { | |
212 if( name == NULL ) { return Form::none; } | |
213 | |
214 if (strcmp(name,"ConI")==0) return Form::idealI; | |
215 if (strcmp(name,"ConP")==0) return Form::idealP; | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
216 if (strcmp(name,"ConN")==0) return Form::idealN; |
0 | 217 if (strcmp(name,"ConL")==0) return Form::idealL; |
218 if (strcmp(name,"ConF")==0) return Form::idealF; | |
219 if (strcmp(name,"ConD")==0) return Form::idealD; | |
220 if (strcmp(name,"Bool")==0) return Form::idealI; | |
221 | |
222 return Form::none; | |
223 } | |
224 | |
225 Form::DataType Form::ideal_to_sReg_type(const char *name) const { | |
226 if( name == NULL ) { return Form::none; } | |
227 | |
228 if (strcmp(name,"sRegI")==0) return Form::idealI; | |
229 if (strcmp(name,"sRegP")==0) return Form::idealP; | |
230 if (strcmp(name,"sRegF")==0) return Form::idealF; | |
231 if (strcmp(name,"sRegD")==0) return Form::idealD; | |
232 if (strcmp(name,"sRegL")==0) return Form::idealL; | |
233 return Form::none; | |
234 } | |
235 | |
236 Form::DataType Form::ideal_to_Reg_type(const char *name) const { | |
237 if( name == NULL ) { return Form::none; } | |
238 | |
239 if (strcmp(name,"RegI")==0) return Form::idealI; | |
240 if (strcmp(name,"RegP")==0) return Form::idealP; | |
241 if (strcmp(name,"RegF")==0) return Form::idealF; | |
242 if (strcmp(name,"RegD")==0) return Form::idealD; | |
243 if (strcmp(name,"RegL")==0) return Form::idealL; | |
244 | |
245 return Form::none; | |
246 } | |
247 | |
248 // True if 'opType', an ideal name, loads or stores. | |
249 Form::DataType Form::is_load_from_memory(const char *opType) const { | |
250 if( strcmp(opType,"LoadB")==0 ) return Form::idealB; | |
251 if( strcmp(opType,"LoadC")==0 ) return Form::idealC; | |
252 if( strcmp(opType,"LoadD")==0 ) return Form::idealD; | |
253 if( strcmp(opType,"LoadD_unaligned")==0 ) return Form::idealD; | |
254 if( strcmp(opType,"LoadF")==0 ) return Form::idealF; | |
255 if( strcmp(opType,"LoadI")==0 ) return Form::idealI; | |
256 if( strcmp(opType,"LoadKlass")==0 ) return Form::idealP; | |
164
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
113
diff
changeset
|
257 if( strcmp(opType,"LoadNKlass")==0 ) return Form::idealN; |
0 | 258 if( strcmp(opType,"LoadL")==0 ) return Form::idealL; |
259 if( strcmp(opType,"LoadL_unaligned")==0 ) return Form::idealL; | |
260 if( strcmp(opType,"LoadPLocked")==0 ) return Form::idealP; | |
261 if( strcmp(opType,"LoadLLocked")==0 ) return Form::idealL; | |
262 if( strcmp(opType,"LoadP")==0 ) return Form::idealP; | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
263 if( strcmp(opType,"LoadN")==0 ) return Form::idealN; |
0 | 264 if( strcmp(opType,"LoadRange")==0 ) return Form::idealI; |
265 if( strcmp(opType,"LoadS")==0 ) return Form::idealS; | |
266 if( strcmp(opType,"Load16B")==0 ) return Form::idealB; | |
267 if( strcmp(opType,"Load8B")==0 ) return Form::idealB; | |
268 if( strcmp(opType,"Load4B")==0 ) return Form::idealB; | |
269 if( strcmp(opType,"Load8C")==0 ) return Form::idealC; | |
270 if( strcmp(opType,"Load4C")==0 ) return Form::idealC; | |
271 if( strcmp(opType,"Load2C")==0 ) return Form::idealC; | |
272 if( strcmp(opType,"Load8S")==0 ) return Form::idealS; | |
273 if( strcmp(opType,"Load4S")==0 ) return Form::idealS; | |
274 if( strcmp(opType,"Load2S")==0 ) return Form::idealS; | |
275 if( strcmp(opType,"Load2D")==0 ) return Form::idealD; | |
276 if( strcmp(opType,"Load4F")==0 ) return Form::idealF; | |
277 if( strcmp(opType,"Load2F")==0 ) return Form::idealF; | |
278 if( strcmp(opType,"Load4I")==0 ) return Form::idealI; | |
279 if( strcmp(opType,"Load2I")==0 ) return Form::idealI; | |
280 if( strcmp(opType,"Load2L")==0 ) return Form::idealL; | |
281 assert( strcmp(opType,"Load") != 0, "Must type Loads" ); | |
282 return Form::none; | |
283 } | |
284 | |
285 Form::DataType Form::is_store_to_memory(const char *opType) const { | |
286 if( strcmp(opType,"StoreB")==0) return Form::idealB; | |
287 if( strcmp(opType,"StoreCM")==0) return Form::idealB; | |
288 if( strcmp(opType,"StoreC")==0) return Form::idealC; | |
289 if( strcmp(opType,"StoreD")==0) return Form::idealD; | |
290 if( strcmp(opType,"StoreF")==0) return Form::idealF; | |
291 if( strcmp(opType,"StoreI")==0) return Form::idealI; | |
292 if( strcmp(opType,"StoreL")==0) return Form::idealL; | |
293 if( strcmp(opType,"StoreP")==0) return Form::idealP; | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
294 if( strcmp(opType,"StoreN")==0) return Form::idealN; |
0 | 295 if( strcmp(opType,"Store16B")==0) return Form::idealB; |
296 if( strcmp(opType,"Store8B")==0) return Form::idealB; | |
297 if( strcmp(opType,"Store4B")==0) return Form::idealB; | |
298 if( strcmp(opType,"Store8C")==0) return Form::idealC; | |
299 if( strcmp(opType,"Store4C")==0) return Form::idealC; | |
300 if( strcmp(opType,"Store2C")==0) return Form::idealC; | |
301 if( strcmp(opType,"Store2D")==0) return Form::idealD; | |
302 if( strcmp(opType,"Store4F")==0) return Form::idealF; | |
303 if( strcmp(opType,"Store2F")==0) return Form::idealF; | |
304 if( strcmp(opType,"Store4I")==0) return Form::idealI; | |
305 if( strcmp(opType,"Store2I")==0) return Form::idealI; | |
306 if( strcmp(opType,"Store2L")==0) return Form::idealL; | |
307 assert( strcmp(opType,"Store") != 0, "Must type Stores" ); | |
308 return Form::none; | |
309 } | |
310 | |
311 Form::InterfaceType Form::interface_type(FormDict &globals) const { | |
312 return Form::no_interface; | |
313 } | |
314 | |
315 //------------------------------FormList--------------------------------------- | |
316 // Destructor | |
317 FormList::~FormList() { | |
318 // // This list may not own its elements | |
319 // Form *cur = _root; | |
320 // Form *next = NULL; | |
321 // for( ; (cur = next) != NULL; ) { | |
322 // next = (Form *)cur->_next; | |
323 // delete cur; | |
324 // } | |
325 }; | |
326 | |
327 //------------------------------FormDict--------------------------------------- | |
328 // Constructor | |
329 FormDict::FormDict( CmpKey cmp, Hash hash, Arena *arena ) | |
330 : _form(cmp, hash, arena) { | |
331 } | |
332 FormDict::~FormDict() { | |
333 } | |
334 | |
335 // Return # of name-Form pairs in dict | |
336 int FormDict::Size(void) const { | |
337 return _form.Size(); | |
338 } | |
339 | |
340 // Insert inserts the given key-value pair into the dictionary. The prior | |
341 // value of the key is returned; NULL if the key was not previously defined. | |
342 const Form *FormDict::Insert(const char *name, Form *form) { | |
343 return (Form*)_form.Insert((void*)name, (void*)form); | |
344 } | |
345 | |
346 // Finds the value of a given key; or NULL if not found. | |
347 // The dictionary is NOT changed. | |
348 const Form *FormDict::operator [](const char *name) const { | |
349 return (Form*)_form[name]; | |
350 } | |
351 | |
352 //------------------------------FormDict::private------------------------------ | |
353 // Disable public use of constructor, copy-ctor, operator =, operator == | |
354 FormDict::FormDict( ) : _form(cmpkey,hashkey) { | |
355 assert( false, "NotImplemented"); | |
356 } | |
357 FormDict::FormDict( const FormDict & fd) : _form(fd._form) { | |
358 } | |
359 FormDict &FormDict::operator =( const FormDict &rhs) { | |
360 assert( false, "NotImplemented"); | |
361 _form = rhs._form; | |
362 return *this; | |
363 } | |
364 // == compares two dictionaries; they must have the same keys (their keys | |
365 // must match using CmpKey) and they must have the same values (pointer | |
366 // comparison). If so 1 is returned, if not 0 is returned. | |
367 bool FormDict::operator ==(const FormDict &d) const { | |
368 assert( false, "NotImplemented"); | |
369 return false; | |
370 } | |
371 | |
372 // Print out the dictionary contents as key-value pairs | |
373 static void dumpkey (const void* key) { fprintf(stdout, "%s", key); } | |
374 static void dumpform(const void* form) { fflush(stdout); ((Form*)form)->dump(); } | |
375 | |
376 void FormDict::dump() { | |
377 _form.print(dumpkey, dumpform); | |
378 } | |
379 | |
380 //------------------------------SourceForm------------------------------------- | |
381 SourceForm::SourceForm(char* code) : _code(code) { }; // Constructor | |
382 SourceForm::~SourceForm() { | |
383 } | |
384 | |
385 void SourceForm::dump() { // Debug printer | |
386 output(stderr); | |
387 } | |
388 | |
389 void SourceForm::output(FILE *fp) { | |
390 fprintf(fp,"\n//%s\n%s\n",classname(),(_code?_code:"")); | |
391 } |