2 * allocate.c - simple space-efficient blob allocator.
4 * Copyright (C) 2003 Transmeta Corp.
5 * 2003-2004 Linus Torvalds
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 * Simple allocator for data that doesn't get partially free'd.
26 * The tokenizer and parser allocate a _lot_ of small data structures
27 * (often just two-three bytes for things like small integers),
28 * and since they all depend on each other you can't free them
29 * individually _anyway_. So do something that is very space-
30 * efficient: allocate larger "blobs", and give out individual
31 * small bits and pieces of it with no maintenance overhead.
43 #include "expression.h"
44 #include "linearize.h"
46 void protect_allocations(struct allocator_struct
*desc
)
51 void drop_all_allocations(struct allocator_struct
*desc
)
53 struct allocation_blob
*blob
= desc
->blobs
;
56 desc
->allocations
= 0;
57 desc
->total_bytes
= 0;
58 desc
->useful_bytes
= 0;
59 desc
->freelist
= NULL
;
61 struct allocation_blob
*next
= blob
->next
;
62 blob_free(blob
, desc
->chunking
);
67 void free_one_entry(struct allocator_struct
*desc
, void *entry
)
74 void *allocate(struct allocator_struct
*desc
, unsigned int size
)
76 unsigned long alignment
= desc
->alignment
;
77 struct allocation_blob
*blob
= desc
->blobs
;
81 * NOTE! The freelist only works with things that are
82 * (a) sufficiently aligned
83 * (b) use a constant size
84 * Don't try to free allocators that don't follow
88 void **p
= desc
->freelist
;
94 } while ((size
-= sizeof(void *)) > 0);
99 desc
->useful_bytes
+= size
;
100 size
= (size
+ alignment
- 1) & ~(alignment
-1);
101 if (!blob
|| blob
->left
< size
) {
102 unsigned int offset
, chunking
= desc
->chunking
;
103 struct allocation_blob
*newblob
= blob_alloc(chunking
);
105 die("out of memory");
106 desc
->total_bytes
+= chunking
;
107 newblob
->next
= blob
;
109 desc
->blobs
= newblob
;
110 offset
= offsetof(struct allocation_blob
, data
);
111 offset
= (offset
+ alignment
- 1) & ~(alignment
-1);
112 blob
->left
= chunking
- offset
;
113 blob
->offset
= offset
- offsetof(struct allocation_blob
, data
);
115 retval
= blob
->data
+ blob
->offset
;
116 blob
->offset
+= size
;
121 void show_allocations(struct allocator_struct
*x
)
123 fprintf(stderr
, "%s: %d allocations, %d bytes (%d total bytes, "
124 "%6.2f%% usage, %6.2f average size)\n",
125 x
->name
, x
->allocations
, x
->useful_bytes
, x
->total_bytes
,
126 100 * (double) x
->useful_bytes
/ x
->total_bytes
,
127 (double) x
->useful_bytes
/ x
->allocations
);
130 ALLOCATOR(ident
, "identifiers");
131 ALLOCATOR(token
, "tokens");
132 ALLOCATOR(context
, "contexts");
133 ALLOCATOR(symbol
, "symbols");
134 ALLOCATOR(expression
, "expressions");
135 ALLOCATOR(statement
, "statements");
136 ALLOCATOR(string
, "strings");
137 ALLOCATOR(scope
, "scopes");
138 __DO_ALLOCATOR(void, 0, 1, "bytes", bytes
);
139 ALLOCATOR(basic_block
, "basic_block");
140 ALLOCATOR(entrypoint
, "entrypoint");
141 ALLOCATOR(instruction
, "instruction");
142 ALLOCATOR(multijmp
, "multijmp");
143 ALLOCATOR(pseudo
, "pseudo");
144 ALLOCATOR(attribute
, "attribute");