hare

[hare] The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

traces.ha (1404B)


      1 // SPDX-License-Identifier: MPL-2.0
      2 // (c) Hare authors <https://harelang.org>
      3 
      4 use hash;
      5 use hash::fnv;
      6 use rt;
      7 
      8 def TRACE_BUCKETS = 65535;
      9 
     10 let traces: [TRACE_BUCKETS][]trace = [[]...];
     11 
     12 export type trace = struct {
     13 	id: u64,
     14 	frames: *stackframe,
     15 };
     16 
     17 // Retrives a stack trace by its ID.
     18 export fn trace_by_id(id: u64) (stackframe | void) = {
     19 	let bucket = &traces[id % TRACE_BUCKETS];
     20 	for (let trace &.. bucket) {
     21 		if (trace.id == id) {
     22 			return *trace.frames;
     23 		};
     24 	};
     25 };
     26 
     27 // Stores a stack trace and returns its ID. Stored stack traces are hashed and
     28 // de-duplicated in a global stack list.
     29 export fn trace_store(frame: stackframe) u64 = {
     30 	static let pc: []uintptr = [];
     31 	pc = pc[..0];
     32 
     33 	const prev_heap = begin_altheap();
     34 	defer end_altheap(prev_heap);
     35 
     36 	const hash = fnv::fnv64a();
     37 	for (true) {
     38 		hash::write(&hash, &frame_pc(frame): *[size(uintptr)]u8);
     39 		append(pc, frame_pc(frame))!;
     40 
     41 		match (next(frame)) {
     42 		case let next: stackframe =>
     43 			frame = next;
     44 		case done => break;
     45 		};
     46 	};
     47 
     48 	const id = fnv::sum64(&hash);
     49 	let bucket = &traces[id % TRACE_BUCKETS];
     50 	for (let trace &.. bucket) {
     51 		if (trace.id == id) {
     52 			return id;
     53 		};
     54 	};
     55 
     56 	let frames: []stackframe = alloc([stackframe { ... }...], len(pc) + 1)!;
     57 	for (let i = 0z; i < len(pc); i += 1) {
     58 		frames[i] = mkframe(&frames[i + 1], pc[i]);
     59 	};
     60 
     61 	append(bucket, trace {
     62 		id = id,
     63 		frames = &frames[0],
     64 	})!;
     65 
     66 	return id;
     67 };