runtime (gc): correct scan bounds
This fixes 2 bugs in the GC scan bounds: 1. On AVR, the GC could sometimes read one byte past the end of a block due to the difference between pointer size and alignment. 2. On WASM, the linker does not properly align the marker for the end of the globals section. A manual alignment operation has been added to markGlobals to work around this.
Этот коммит содержится в:
		
							родитель
							
								
									62bda8e129
								
							
						
					
					
						коммит
						e6fbad13c6
					
				
					 2 изменённых файлов: 23 добавлений и 1 удалений
				
			
		|  | @ -430,8 +430,18 @@ func markRoots(start, end uintptr) { | ||||||
| 		if start >= end { | 		if start >= end { | ||||||
| 			runtimePanic("gc: unexpected range to mark") | 			runtimePanic("gc: unexpected range to mark") | ||||||
| 		} | 		} | ||||||
|  | 		if start%unsafe.Alignof(start) != 0 { | ||||||
|  | 			runtimePanic("gc: unaligned start pointer") | ||||||
|  | 		} | ||||||
|  | 		if end%unsafe.Alignof(end) != 0 { | ||||||
|  | 			runtimePanic("gc: unaligned end pointer") | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	// Reduce the end bound to avoid reading too far on platforms where pointer alignment is smaller than pointer size. | ||||||
|  | 	// If the size of the range is 0, then end will be slightly below start after this. | ||||||
|  | 	end -= unsafe.Sizeof(end) - unsafe.Alignof(end) | ||||||
|  | 
 | ||||||
| 	for addr := start; addr < end; addr += unsafe.Alignof(addr) { | 	for addr := start; addr < end; addr += unsafe.Alignof(addr) { | ||||||
| 		root := *(*uintptr)(unsafe.Pointer(addr)) | 		root := *(*uintptr)(unsafe.Pointer(addr)) | ||||||
| 		markRoot(addr, root) | 		markRoot(addr, root) | ||||||
|  |  | ||||||
|  | @ -1,12 +1,24 @@ | ||||||
|  | //go:build (gc.conservative || gc.extalloc) && (baremetal || tinygo.wasm) | ||||||
| // +build gc.conservative gc.extalloc | // +build gc.conservative gc.extalloc | ||||||
| // +build baremetal tinygo.wasm | // +build baremetal tinygo.wasm | ||||||
| 
 | 
 | ||||||
| package runtime | package runtime | ||||||
| 
 | 
 | ||||||
|  | import "unsafe" | ||||||
|  | 
 | ||||||
| // markGlobals marks all globals, which are reachable by definition. | // markGlobals marks all globals, which are reachable by definition. | ||||||
| // | // | ||||||
| // This implementation marks all globals conservatively and assumes it can use | // This implementation marks all globals conservatively and assumes it can use | ||||||
| // linker-defined symbols for the start and end of the .data section. | // linker-defined symbols for the start and end of the .data section. | ||||||
| func markGlobals() { | func markGlobals() { | ||||||
| 	markRoots(globalsStart, globalsEnd) | 	end := globalsEnd | ||||||
|  | 	if GOARCH == "wasm" { | ||||||
|  | 		// This is a workaround for a bug in wasm-ld: wasm-ld doesn't always | ||||||
|  | 		// align __heap_base and when this memory is shared through an API, it | ||||||
|  | 		// might result in unaligned memory. For details, see: | ||||||
|  | 		// https://reviews.llvm.org/D106499 | ||||||
|  | 		// It should be removed once we switch to LLVM 13, where this is fixed. | ||||||
|  | 		end = end &^ (unsafe.Alignof(end) - 1) | ||||||
|  | 	} | ||||||
|  | 	markRoots(globalsStart, end) | ||||||
| } | } | ||||||
|  |  | ||||||
		Загрузка…
	
	Создание таблицы
		
		Сослаться в новой задаче
	
	 Nia Waldvogel
						Nia Waldvogel