Mercurial > hg > graal-compiler
annotate src/share/vm/memory/filemap.cpp @ 1716:be3f9c242c9d
6948538: CMS: BOT walkers can fall into object allocation and initialization cracks
Summary: GC workers now recognize an intermediate transient state of blocks which are allocated but have not yet completed initialization. blk_start() calls do not attempt to determine the size of a block in the transient state, rather waiting for the block to become initialized so that it is safe to query its size. Audited and ensured the order of initialization of object fields (klass, free bit and size) to respect block state transition protocol. Also included some new assertion checking code enabled in debug mode.
Reviewed-by: chrisphi, johnc, poonam
author | ysr |
---|---|
date | Mon, 16 Aug 2010 15:58:42 -0700 |
parents | c18cbe5936b8 |
children | f95d63e2154a |
rev | line source |
---|---|
0 | 1 /* |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
605
diff
changeset
|
2 * Copyright (c) 2003, 2006, Oracle and/or its affiliates. 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 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
605
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
605
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:
605
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
25 # include "incls/_precompiled.incl" | |
26 # include "incls/_filemap.cpp.incl" | |
27 # include <sys/stat.h> | |
28 # include <errno.h> | |
29 | |
30 #ifndef O_BINARY // if defined (Win32) use binary files. | |
31 #define O_BINARY 0 // otherwise do nothing. | |
32 #endif | |
33 | |
34 | |
35 extern address JVM_FunctionAtStart(); | |
36 extern address JVM_FunctionAtEnd(); | |
37 | |
605 | 38 // Complain and stop. All error conditions occurring during the writing of |
0 | 39 // an archive file should stop the process. Unrecoverable errors during |
40 // the reading of the archive file should stop the process. | |
41 | |
42 static void fail(const char *msg, va_list ap) { | |
43 // This occurs very early during initialization: tty is not initialized. | |
44 jio_fprintf(defaultStream::error_stream(), | |
605 | 45 "An error has occurred while processing the" |
0 | 46 " shared archive file.\n"); |
47 jio_vfprintf(defaultStream::error_stream(), msg, ap); | |
48 jio_fprintf(defaultStream::error_stream(), "\n"); | |
49 vm_exit_during_initialization("Unable to use shared archive.", NULL); | |
50 } | |
51 | |
52 | |
53 void FileMapInfo::fail_stop(const char *msg, ...) { | |
54 va_list ap; | |
55 va_start(ap, msg); | |
56 fail(msg, ap); // Never returns. | |
57 va_end(ap); // for completeness. | |
58 } | |
59 | |
60 | |
61 // Complain and continue. Recoverable errors during the reading of the | |
62 // archive file may continue (with sharing disabled). | |
63 // | |
64 // If we continue, then disable shared spaces and close the file. | |
65 | |
66 void FileMapInfo::fail_continue(const char *msg, ...) { | |
67 va_list ap; | |
68 va_start(ap, msg); | |
69 if (RequireSharedSpaces) { | |
70 fail(msg, ap); | |
71 } | |
72 va_end(ap); | |
73 UseSharedSpaces = false; | |
74 close(); | |
75 } | |
76 | |
77 | |
78 // Fill in the fileMapInfo structure with data about this VM instance. | |
79 | |
80 void FileMapInfo::populate_header(size_t alignment) { | |
81 _header._magic = 0xf00baba2; | |
82 _header._version = _current_version; | |
83 _header._alignment = alignment; | |
84 | |
85 // The following fields are for sanity checks for whether this archive | |
86 // will function correctly with this JVM and the bootclasspath it's | |
87 // invoked with. | |
88 | |
89 // JVM version string ... changes on each build. | |
90 const char *vm_version = VM_Version::internal_vm_info_string(); | |
91 if (strlen(vm_version) < (JVM_IDENT_MAX-1)) { | |
92 strcpy(_header._jvm_ident, vm_version); | |
93 } else { | |
94 fail_stop("JVM Ident field for shared archive is too long" | |
95 " - truncated to <%s>", _header._jvm_ident); | |
96 } | |
97 | |
98 // Build checks on classpath and jar files | |
99 _header._num_jars = 0; | |
100 ClassPathEntry *cpe = ClassLoader::classpath_entry(0); | |
101 for ( ; cpe != NULL; cpe = cpe->next()) { | |
102 | |
103 if (cpe->is_jar_file()) { | |
104 if (_header._num_jars >= JVM_SHARED_JARS_MAX) { | |
105 fail_stop("Too many jar files to share.", NULL); | |
106 } | |
107 | |
108 // Jar file - record timestamp and file size. | |
109 struct stat st; | |
110 const char *path = cpe->name(); | |
111 if (os::stat(path, &st) != 0) { | |
112 // If we can't access a jar file in the boot path, then we can't | |
113 // make assumptions about where classes get loaded from. | |
114 fail_stop("Unable to open jar file %s.", path); | |
115 } | |
116 _header._jar[_header._num_jars]._timestamp = st.st_mtime; | |
117 _header._jar[_header._num_jars]._filesize = st.st_size; | |
118 _header._num_jars++; | |
119 } else { | |
120 | |
121 // If directories appear in boot classpath, they must be empty to | |
122 // avoid having to verify each individual class file. | |
123 const char* name = ((ClassPathDirEntry*)cpe)->name(); | |
124 if (!os::dir_is_empty(name)) { | |
125 fail_stop("Boot classpath directory %s is not empty.", name); | |
126 } | |
127 } | |
128 } | |
129 } | |
130 | |
131 | |
132 // Read the FileMapInfo information from the file. | |
133 | |
134 bool FileMapInfo::init_from_file(int fd) { | |
135 | |
136 size_t n = read(fd, &_header, sizeof(struct FileMapHeader)); | |
137 if (n != sizeof(struct FileMapHeader)) { | |
138 fail_continue("Unable to read the file header."); | |
139 return false; | |
140 } | |
141 if (_header._version != current_version()) { | |
142 fail_continue("The shared archive file has the wrong version."); | |
143 return false; | |
144 } | |
145 _file_offset = (long)n; | |
146 return true; | |
147 } | |
148 | |
149 | |
150 // Read the FileMapInfo information from the file. | |
151 bool FileMapInfo::open_for_read() { | |
152 _full_path = Arguments::GetSharedArchivePath(); | |
153 int fd = open(_full_path, O_RDONLY | O_BINARY, 0); | |
154 if (fd < 0) { | |
155 if (errno == ENOENT) { | |
156 // Not locating the shared archive is ok. | |
157 fail_continue("Specified shared archive not found."); | |
158 } else { | |
159 fail_continue("Failed to open shared archive file (%s).", | |
160 strerror(errno)); | |
161 } | |
162 return false; | |
163 } | |
164 | |
165 _fd = fd; | |
166 _file_open = true; | |
167 return true; | |
168 } | |
169 | |
170 | |
171 // Write the FileMapInfo information to the file. | |
172 | |
173 void FileMapInfo::open_for_write() { | |
174 _full_path = Arguments::GetSharedArchivePath(); | |
175 if (PrintSharedSpaces) { | |
176 tty->print_cr("Dumping shared data to file: "); | |
177 tty->print_cr(" %s", _full_path); | |
178 } | |
179 | |
180 // Remove the existing file in case another process has it open. | |
181 remove(_full_path); | |
182 int fd = open(_full_path, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0444); | |
183 if (fd < 0) { | |
184 fail_stop("Unable to create shared archive file %s.", _full_path); | |
185 } | |
186 _fd = fd; | |
187 _file_offset = 0; | |
188 _file_open = true; | |
189 } | |
190 | |
191 | |
192 // Write the header to the file, seek to the next allocation boundary. | |
193 | |
194 void FileMapInfo::write_header() { | |
195 write_bytes_aligned(&_header, sizeof(FileMapHeader)); | |
196 } | |
197 | |
198 | |
199 // Dump shared spaces to file. | |
200 | |
201 void FileMapInfo::write_space(int i, CompactibleSpace* space, bool read_only) { | |
202 align_file_position(); | |
203 struct FileMapInfo::FileMapHeader::space_info* si = &_header._space[i]; | |
204 write_region(i, (char*)space->bottom(), space->used(), | |
205 space->capacity(), read_only, false); | |
206 } | |
207 | |
208 | |
209 // Dump region to file. | |
210 | |
211 void FileMapInfo::write_region(int region, char* base, size_t size, | |
212 size_t capacity, bool read_only, | |
213 bool allow_exec) { | |
214 struct FileMapInfo::FileMapHeader::space_info* si = &_header._space[region]; | |
215 | |
216 if (_file_open) { | |
217 guarantee(si->_file_offset == _file_offset, "file offset mismatch."); | |
218 if (PrintSharedSpaces) { | |
219 tty->print_cr("Shared file region %d: 0x%x bytes, addr 0x%x," | |
220 " file offset 0x%x", region, size, base, _file_offset); | |
221 } | |
222 } else { | |
223 si->_file_offset = _file_offset; | |
224 } | |
225 si->_base = base; | |
226 si->_used = size; | |
227 si->_capacity = capacity; | |
228 si->_read_only = read_only; | |
229 si->_allow_exec = allow_exec; | |
230 write_bytes_aligned(base, (int)size); | |
231 } | |
232 | |
233 | |
234 // Dump bytes to file -- at the current file position. | |
235 | |
236 void FileMapInfo::write_bytes(const void* buffer, int nbytes) { | |
237 if (_file_open) { | |
238 int n = ::write(_fd, buffer, nbytes); | |
239 if (n != nbytes) { | |
240 // It is dangerous to leave the corrupted shared archive file around, | |
241 // close and remove the file. See bug 6372906. | |
242 close(); | |
243 remove(_full_path); | |
244 fail_stop("Unable to write to shared archive file.", NULL); | |
245 } | |
246 } | |
247 _file_offset += nbytes; | |
248 } | |
249 | |
250 | |
251 // Align file position to an allocation unit boundary. | |
252 | |
253 void FileMapInfo::align_file_position() { | |
254 long new_file_offset = align_size_up(_file_offset, os::vm_allocation_granularity()); | |
255 if (new_file_offset != _file_offset) { | |
256 _file_offset = new_file_offset; | |
257 if (_file_open) { | |
258 // Seek one byte back from the target and write a byte to insure | |
259 // that the written file is the correct length. | |
260 _file_offset -= 1; | |
261 if (lseek(_fd, _file_offset, SEEK_SET) < 0) { | |
262 fail_stop("Unable to seek.", NULL); | |
263 } | |
264 char zero = 0; | |
265 write_bytes(&zero, 1); | |
266 } | |
267 } | |
268 } | |
269 | |
270 | |
271 // Dump bytes to file -- at the current file position. | |
272 | |
273 void FileMapInfo::write_bytes_aligned(const void* buffer, int nbytes) { | |
274 align_file_position(); | |
275 write_bytes(buffer, nbytes); | |
276 align_file_position(); | |
277 } | |
278 | |
279 | |
280 // Close the shared archive file. This does NOT unmap mapped regions. | |
281 | |
282 void FileMapInfo::close() { | |
283 if (_file_open) { | |
284 if (::close(_fd) < 0) { | |
285 fail_stop("Unable to close the shared archive file."); | |
286 } | |
287 _file_open = false; | |
288 _fd = -1; | |
289 } | |
290 } | |
291 | |
292 | |
293 // Memory map a shared space from the archive file. | |
294 | |
295 bool FileMapInfo::map_space(int i, ReservedSpace rs, ContiguousSpace* space) { | |
296 struct FileMapInfo::FileMapHeader::space_info* si = &_header._space[i]; | |
297 if (space != NULL) { | |
298 if (si->_base != (char*)space->bottom() || | |
299 si->_capacity != space->capacity()) { | |
300 fail_continue("Shared space base address does not match."); | |
301 return false; | |
302 } | |
303 } | |
304 bool result = (map_region(i, rs) != NULL); | |
305 if (space != NULL && result) { | |
306 space->set_top((HeapWord*)(si->_base + si->_used)); | |
307 space->set_saved_mark(); | |
308 } | |
309 return result; | |
310 } | |
311 | |
312 | |
313 // JVM/TI RedefineClasses() support: | |
314 // Remap the shared readonly space to shared readwrite, private. | |
315 bool FileMapInfo::remap_shared_readonly_as_readwrite() { | |
316 struct FileMapInfo::FileMapHeader::space_info* si = &_header._space[0]; | |
317 if (!si->_read_only) { | |
318 // the space is already readwrite so we are done | |
319 return true; | |
320 } | |
321 size_t used = si->_used; | |
322 size_t size = align_size_up(used, os::vm_allocation_granularity()); | |
323 if (!open_for_read()) { | |
324 return false; | |
325 } | |
326 char *base = os::remap_memory(_fd, _full_path, si->_file_offset, | |
327 si->_base, size, false /* !read_only */, | |
328 si->_allow_exec); | |
329 close(); | |
330 if (base == NULL) { | |
331 fail_continue("Unable to remap shared readonly space (errno=%d).", errno); | |
332 return false; | |
333 } | |
334 if (base != si->_base) { | |
335 fail_continue("Unable to remap shared readonly space at required address."); | |
336 return false; | |
337 } | |
338 si->_read_only = false; | |
339 return true; | |
340 } | |
341 | |
342 | |
343 // Memory map a region in the address space. | |
344 | |
345 char* FileMapInfo::map_region(int i, ReservedSpace rs) { | |
346 struct FileMapInfo::FileMapHeader::space_info* si = &_header._space[i]; | |
347 size_t used = si->_used; | |
348 size_t size = align_size_up(used, os::vm_allocation_granularity()); | |
349 | |
350 ReservedSpace mapped_rs = rs.first_part(size, true, true); | |
351 ReservedSpace unmapped_rs = rs.last_part(size); | |
352 mapped_rs.release(); | |
353 | |
354 return map_region(i, true); | |
355 } | |
356 | |
357 | |
358 // Memory map a region in the address space. | |
359 | |
360 char* FileMapInfo::map_region(int i, bool address_must_match) { | |
361 struct FileMapInfo::FileMapHeader::space_info* si = &_header._space[i]; | |
362 size_t used = si->_used; | |
363 size_t size = align_size_up(used, os::vm_allocation_granularity()); | |
364 char *requested_addr = 0; | |
365 if (address_must_match) { | |
366 requested_addr = si->_base; | |
367 } | |
368 char *base = os::map_memory(_fd, _full_path, si->_file_offset, | |
369 requested_addr, size, si->_read_only, | |
370 si->_allow_exec); | |
371 if (base == NULL) { | |
372 fail_continue("Unable to map shared space."); | |
373 return NULL; | |
374 } | |
375 if (address_must_match) { | |
376 if (base != si->_base) { | |
377 fail_continue("Unable to map shared space at required address."); | |
378 return NULL; | |
379 } | |
380 } else { | |
381 si->_base = base; // save mapped address for unmapping. | |
382 } | |
383 return base; | |
384 } | |
385 | |
386 | |
387 // Unmap a memory region in the address space. | |
388 | |
389 void FileMapInfo::unmap_region(int i) { | |
390 struct FileMapInfo::FileMapHeader::space_info* si = &_header._space[i]; | |
391 size_t used = si->_used; | |
392 size_t size = align_size_up(used, os::vm_allocation_granularity()); | |
393 if (!os::unmap_memory(si->_base, size)) { | |
394 fail_stop("Unable to unmap shared space."); | |
395 } | |
396 } | |
397 | |
398 | |
399 void FileMapInfo::assert_mark(bool check) { | |
400 if (!check) { | |
401 fail_stop("Mark mismatch while restoring from shared file.", NULL); | |
402 } | |
403 } | |
404 | |
405 | |
406 FileMapInfo* FileMapInfo::_current_info = NULL; | |
407 | |
408 | |
409 // Open the shared archive file, read and validate the header | |
410 // information (version, boot classpath, etc.). If initialization | |
411 // fails, shared spaces are disabled and the file is closed. [See | |
412 // fail_continue.] | |
413 | |
414 | |
415 bool FileMapInfo::initialize() { | |
416 assert(UseSharedSpaces, "UseSharedSpaces expected."); | |
417 | |
418 if (JvmtiExport::can_modify_any_class() || JvmtiExport::can_walk_any_space()) { | |
419 fail_continue("Tool agent requires sharing to be disabled."); | |
420 return false; | |
421 } | |
422 | |
423 if (!open_for_read()) { | |
424 return false; | |
425 } | |
426 | |
427 init_from_file(_fd); | |
428 if (!validate()) { | |
429 return false; | |
430 } | |
431 | |
432 SharedReadOnlySize = _header._space[0]._capacity; | |
433 SharedReadWriteSize = _header._space[1]._capacity; | |
434 SharedMiscDataSize = _header._space[2]._capacity; | |
435 SharedMiscCodeSize = _header._space[3]._capacity; | |
436 return true; | |
437 } | |
438 | |
439 | |
440 bool FileMapInfo::validate() { | |
441 if (_header._version != current_version()) { | |
442 fail_continue("The shared archive file is the wrong version."); | |
443 return false; | |
444 } | |
445 if (_header._magic != (int)0xf00baba2) { | |
446 fail_continue("The shared archive file has a bad magic number."); | |
447 return false; | |
448 } | |
449 if (strncmp(_header._jvm_ident, VM_Version::internal_vm_info_string(), | |
450 JVM_IDENT_MAX-1) != 0) { | |
451 fail_continue("The shared archive file was created by a different" | |
452 " version or build of HotSpot."); | |
453 return false; | |
454 } | |
455 | |
456 // Cannot verify interpreter yet, as it can only be created after the GC | |
457 // heap has been initialized. | |
458 | |
459 if (_header._num_jars >= JVM_SHARED_JARS_MAX) { | |
460 fail_continue("Too many jar files to share."); | |
461 return false; | |
462 } | |
463 | |
464 // Build checks on classpath and jar files | |
465 int num_jars_now = 0; | |
466 ClassPathEntry *cpe = ClassLoader::classpath_entry(0); | |
467 for ( ; cpe != NULL; cpe = cpe->next()) { | |
468 | |
469 if (cpe->is_jar_file()) { | |
470 if (num_jars_now < _header._num_jars) { | |
471 | |
472 // Jar file - verify timestamp and file size. | |
473 struct stat st; | |
474 const char *path = cpe->name(); | |
475 if (os::stat(path, &st) != 0) { | |
476 fail_continue("Unable to open jar file %s.", path); | |
477 return false; | |
478 } | |
479 if (_header._jar[num_jars_now]._timestamp != st.st_mtime || | |
480 _header._jar[num_jars_now]._filesize != st.st_size) { | |
481 fail_continue("A jar file is not the one used while building" | |
482 " the shared archive file."); | |
483 return false; | |
484 } | |
485 } | |
486 ++num_jars_now; | |
487 } else { | |
488 | |
489 // If directories appear in boot classpath, they must be empty to | |
490 // avoid having to verify each individual class file. | |
491 const char* name = ((ClassPathDirEntry*)cpe)->name(); | |
492 if (!os::dir_is_empty(name)) { | |
493 fail_continue("Boot classpath directory %s is not empty.", name); | |
494 return false; | |
495 } | |
496 } | |
497 } | |
498 if (num_jars_now < _header._num_jars) { | |
499 fail_continue("The number of jar files in the boot classpath is" | |
500 " less than the number the shared archive was created with."); | |
501 return false; | |
502 } | |
503 | |
504 return true; | |
505 } | |
506 | |
507 // The following method is provided to see whether a given pointer | |
508 // falls in the mapped shared space. | |
509 // Param: | |
510 // p, The given pointer | |
511 // Return: | |
512 // True if the p is within the mapped shared space, otherwise, false. | |
513 bool FileMapInfo::is_in_shared_space(const void* p) { | |
514 for (int i = 0; i < CompactingPermGenGen::n_regions; i++) { | |
515 if (p >= _header._space[i]._base && | |
516 p < _header._space[i]._base + _header._space[i]._used) { | |
517 return true; | |
518 } | |
519 } | |
520 | |
521 return false; | |
522 } |