File: Code.cpp

package info (click to toggle)
storm-lang 0.7.5-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 52,028 kB
  • sloc: ansic: 261,471; cpp: 140,432; sh: 14,891; perl: 9,846; python: 2,525; lisp: 2,504; asm: 860; makefile: 678; pascal: 70; java: 52; xml: 37; awk: 12
file content (115 lines) | stat: -rw-r--r-- 3,104 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#include "stdafx.h"
#include "Code.h"
#include "Gc.h"
#include "Core/GcCode.h"

#include "CodeTable.h"
#include "DwarfTable.h"

#include "CodeX86.h"
#include "CodeX64.h"
#include "CodeArm64.h"

#if defined(X86)
#define ARCH x86
#elif defined(X64)
#define ARCH x64
#elif defined(ARM64)
#define ARCH arm64
#else
#error "Updating code segments is not implemented for your architecture yet!"
#endif

namespace storm {
	namespace gccode {

		// The generic cases. These are implemented the same on every platform.
		static void doWritePtr(void *code, const GcCode *refs, Nat id) {
			const GcCodeRef &ref = refs->refs[id];
			size_t ptr = size_t(ref.pointer);
			void *write = ((byte *)code) + ref.offset;

			// Note: These writes need to be visible as an atomic operation to the instruction
			// decoding unit of the CPU. Further atomicity is not required, as the GC arranges for
			// that anyway. Offsets might not be aligned as regular pointers on the system.

			switch (ref.kind) {
			case GcCodeRef::disabled:
			case GcCodeRef::ptrStorage:
			case GcCodeRef::backEdge:
				// Nothing to do...
				break;
			case GcCodeRef::rawPtr:
				unalignedAtomicWrite(*(size_t *)write, ptr);
				invalidateSingleICache(write);
				break;
			case GcCodeRef::relativePtr:
			case GcCodeRef::relative:
				unalignedAtomicWrite(*(size_t *)write, ptr - (size_t(write) + sizeof(size_t)));
				invalidateSingleICache(write);
				break;
			case GcCodeRef::inside:
				unalignedAtomicWrite(*(size_t *)write, ptr + size_t(code));
				invalidateSingleICache(write);
				break;
			case GcCodeRef::relativeHere:
				// Write a relative pointer to 'pointer' itself. Should always be the same, but the
				// offset is not really exposed conveniently anywhere else.
				ptr = size_t(&ref.pointer);
				shortUnalignedAtomicWrite(*(nat *)write, nat(ptr - (size_t(write) + sizeof(nat))));
				invalidateSingleICache(write);
				break;
			case GcCodeRef::codeInfo:
				if (ref.pointer)
					CodeTable::update(ref.pointer, code);
				break;
			case GcCodeRef::dwarfInfo:
				if (ref.pointer)
					DwarfChunk::updateFn((FDE *)ref.pointer, code);
				break;
			default:
				// Pass on to the architecture specific parts:
				ARCH::writePtr(code, refs, id);
				break;
			}
		}

		void updatePtrs(void *code, const GcCode *refs) {
			for (Nat i = 0; i < refs->refCount; i++)
				doWritePtr(code, refs, i);
		}

		void writePtr(void *code, Nat id) {
			GcCode *refs = Gc::codeRefs(code);
			doWritePtr(code, refs, id);
		}

		Bool needFinalization() {
			return ARCH::needFinalization();
		}

		void finalize(void *code) {
			GcCode *refs = Gc::codeRefs(code);
			for (size_t i = 0; i < refs->refCount; i++) {
				GcCodeRef &ref = refs->refs[i];
				if (ref.pointer) {
					if (ref.kind == GcCodeRef::codeInfo) {
						CodeTable::Handle h = ref.pointer;

						atomicWrite(ref.pointer, null);
						codeTable().remove(h);
					} else if (ref.kind == GcCodeRef::dwarfInfo) {
						FDE *ptr = (FDE *)ref.pointer;

						atomicWrite(ref.pointer, null);
						dwarfTable().free(ptr);
					}
				}
			}

			ARCH::finalize(code);
		}

	}
}