blob: ddc755c16333b88c56a1f4fbcaea7f1b8e7b7b82 (
plain)
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
|
In-place construction
=====================
For example:
a = get_a
...
# if `a` is always the last reference, then this could
# allocate the result "over" the previous allocation.
# (note that this is tricky to do if the function also takes
# the return value as a parameter, but in some cases it can be
# done anyway).
a = get_a
ABI
---
How should this work on the ABI level?
Maybe add a new parameter?
From this (source):
func get_a
returns
Thing ret
code
...
end
To this (ABI pseudo code):
func get_a
?Thing placement
returns
Thing ret
code
...
end
And with the edge case where the function takes the return value
as a parameter:
func get_a
aliased ?Thing placement
aliased Thing existing
return
Thing ret
code
if placement == existing
# implies placement<>none
placement.a += 10
elif placement <> none
placement.a = existing.a + 10
else
ret = new
ret.a = existing.a + 10
return ret
end
end
Opaque and non-opaque types
---------------------------
This always works for non-opaque types. Those can even be allocated on the
stack (if small enough that there's no risk for eventual stack overflow).
For opaque types, it only works if there's an object that can be recycled.
Usages of in-place construction
-------------------------------
If objects are allowed to have variable length, then in-place construction
could be used for sub-arena allocation into an embedded slot type:
TreeNode:
typeparam T
?TreeNode T left = none
?TreeNode T right = none
embed T data
constructor
embed T data
code
end
# TODO nicer getters?
func get_data
returns
T data
code
return data
end
# maybe this:
func get_data = data
TreeExample:
func f
code
TreeNode Thing tree = new new
end
Implementation idea:
* Have an internal function TreeNode__prealloc
* Take a allocation placement parameter in constructors
* Optionally take a size parameter (necessary for e.g. embedded arrays),
- This would prevent variable-sized data structures though.
Pseudo-code:
TreeNode<Thing> tree = TreeNode__prealloc()
Thing_new(tree.data)
TreeNode_new(tree)
|