File: ReplaceTasks.h

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 (134 lines) | stat: -rw-r--r-- 4,853 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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#pragma once
#include "Thread.h"
#include "Value.h"
#include "ActiveFunctions.h"
#include "Gc/ObjMap.h"

namespace storm {
	STORM_PKG(core.lang);

	class Named;
	class Function;
	class VTable;
	class ReplaceContext;
	class TypeTransform;
	class ReplaceTfmWalker;

	/**
	 * An object encapsulating remaining tasks to do after replacing one or more objects, and other
	 * state that is needed while replacing objects.
	 *
	 * These tasks are things that cannot be made by the replacing objects themselves, for example
	 * since they require the GC to be paused or other similar things. Operations that are
	 * beneficial to perform in batch whenever all replacements have been performed are also queued
	 * up in this object.
	 *
	 * This encompasses:
	 * - Replacing all references of one object with another.
	 * - Modifying the layout of objects in memory.
	 *
	 * Note: If replacing object A with B, and both A and B are keys in a Map<>, future lookups and
	 * modifications of B might return inconsistent results until a full rehash is made (due to
	 * moved objects, not due to capacity). This does not seem to happen very often in the system
	 * currently, as we only allow replacing Named and Handle.
	 */
	class ReplaceTasks : public ObjectOn<Compiler> {
		STORM_CLASS;
	public:
		// Create, without information about active functions (mainly for unit-tests).
		ReplaceTasks();

		// Create, provide information about active functions.
		ReplaceTasks(PauseThreads &from);

		// Create, provide an array to store exceptions in.
		ReplaceTasks(PauseThreads &from, Array<Exception *> *exceptions);

		// Destroy.
		~ReplaceTasks();

		/**
		 * Replacing references.
		 */

		// Schedule a reference to be replaced.
		void STORM_FN replace(Named *old, Named *with);
		void STORM_FN replace(const Handle *old, const Handle *with);

		// Schedule a GcType reference to be replaced. Note: We don't touch 'myGcType' inside Type objects.
		void replace(const GcType *old, const GcType *with);

		// VTable replacement. This refers to the content of the vtable rather than the vtable itself.
		// VTables are not replaced globally, only the 'vtable' field of the type is actually modified.
		void STORM_FN replace(VTable *old, VTable *with);

		// Transform a type that has been updated. Done instead of 'replace' of VTables and GcTypes.
		void STORM_FN transform(TypeTransform *transform);

		// Check if a type is transformed.
		Bool STORM_FN hasTransformFor(Type *type);

		// Schedule an update of a potentially active function.
		void STORM_FN replaceActive(Function *newCode);

		// Apply changes requested. We don't allow doing this from Storm. It is not necessarily
		// good to do while other threads are running.
		void apply();


		/**
		 * Error reporting.
		 */

		// Report errors during the replacement process. Note that errors during the replacement
		// process must not be fatal - it is often not possible to roll back the replacement process
		// once it has been started. Note, that all involved entities have the chance to check for
		// obvious issues beforehand, so this type of errors should be comparatively rare. These
		// errors will all be replaced as one big lump at the end of the update process, so that the
		// user at least knows about them.
		void STORM_FN error(Exception *exception);

		// Throw the stored errors if there are any.
		void STORM_FN throwErrors();


		/**
		 * Inspecting/replacing active functions. Mainly used from ReplaceActive.cpp.
		 */

		// Check if a function is currently active. Returns one element for each active instance of
		// the function, each indicating the current offset of the return location into the
		// function.
		vector<ActiveOffset> findActive(const void *function) const;

		// Relace an active function by replacing the return address on the stack. Replaces all
		// instances of 'offset' inside 'function' with 'replace'. 'replace' is typically the start
		// of a newly generated thunk that migrates control flow to the new version of the function.
		// The system does, however, not make assumptions about this except that 'function' and
		// 'replace' need to be allocated code blocks on the GC heap.
		size_t replaceActive(const void *function, size_t fOffset, const void *replace, size_t rOffset) const;

	private:
		// References to replace.
		UNKNOWN(PTR_NOGC) RawObjMap *replaceMap;

		// VTables to replace.
		UNKNOWN(PTR_NOGC) RawObjMap *vtableMap;

		// Currently active functions.
		UNKNOWN(PTR_NOGC) ActiveFunctions *activeFunctions;

		// Store functions that should be updated.
		Array<Function *> *functionsToUpdate;

		// All types to transform.
		Map<Type *, TypeTransform *> *transforms;

		// All stored exceptions.
		Array<Exception *> *exceptions;

		// Helper to transform objects on the heap.
		void applyTransforms(ReplaceTfmWalker &tfm);
	};

}