cvm

Форк
0
/
virtual_v1.c 
404 строки · 11.0 Кб
1
/*-*-coding:utf-8 -*-
2
 * Auto updated?
3
 *   Yes
4
 * Created:
5
 *   11 December 2023 at 9:06:14 GMT+3
6
 * Modified:
7
 *   January 30, 2024 at 4:57:55 PM GMT+3
8
 *
9
 */
10
/*
11
    Copyright (C) 2022-2047 Artur Mustafin (artur.mustafin@gmail.com)
12

13
    This program is free software: you can redistribute it and/or modify
14
    it under the terms of the GNU General Public License as published by
15
    the Free Software Foundation, either version 3 of the License, or
16
    (at your option) any later version.
17

18
    This program is distributed in the hope that it will be useful,
19
    but WITHOUT ANY WARRANTY; without even the implied warranty of
20
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
    GNU General Public License for more details.
22

23
    You should have received a copy of the GNU General Public License
24
    along with this program.  If not, see <https://www.gnu.org/licenses/>.
25
*/
26

27
#include "generic/memory_v1.h"
28

29
#include "list/list_v1.h"
30

31
#include "vm/v1/pointer/pointer_v1.h"
32
#include "vm/v1/virtual/virtual_v1.h"
33
#include "vm/v1/vm_v1.h"
34

35
/* macros */
36
#define DEFAULT_SIZE 0x8 /* 8 */
37
#define PTR_SIZE sizeof(void*) /* size of a pointer */
38
#define VM_DATA_SIZE sizeof(struct vm_data)
39
#define ALLOC_SIZE(size) (size * PTR_SIZE)
40

41
#ifndef USE_GC
42
#define VM_POINTER_SIZE sizeof(struct vm_pointer)
43
/* pointer definition */
44
struct vm_pointer {
45
    struct pointer** ptr;
46
    struct vm_data* vm;
47
};
48
#endif
49

50
/* private */
51
struct vm {
52
    struct vm_data* head;
53
    struct vm_data* tail;
54
};
55

56
#ifndef USE_GC
57
static struct list_data** cache;
58
#endif
59

60
static struct vm vm_definition_v1;
61

62
static struct vm* vm = &vm_definition_v1;
63

64
struct vm_data {
65
    struct pointer** sp; /* stack pointer */
66
    struct pointer** bp; /* base pointer */
67
    struct vm_data* prev;
68
    struct vm_data* next;
69
    u64 offset;
70
    u64 size;
71
};
72

73
struct vm_state {
74
    struct vm_data* vm;
75
    struct pointer** ptr;
76
};
77

78
struct vm_data_enumerator {
79
    struct pointer* (*next)(void);
80
};
81

82
static struct vm_state vm_state;
83
static struct vm_state* state = &vm_state;
84

85
/* api */
86

87
static void vm_init(struct vm**, u64 size);
88
static void vm_destroy(struct vm**);
89
#if defined(VM_MEMORY_DEBUG_INFO)
90
static void vm_dump(void);
91
static void vm_dump_ref(void);
92
#endif
93
static u64 vm_alloc(struct pointer* ptr);
94
static void vm_free(const struct pointer* ptr);
95
static struct pointer* vm_read(u64 address);
96
static struct pointer* vm_read_type(u64 address, u64 id);
97
static u64 virtual_enumerator_next(void);
98

99
/* internal */
100

101
static struct vm_data* vm_init_internal(u64 size, u64 offset);
102
static struct pointer** vm_read_internal(u64 address);
103
static struct pointer** vm_alloc_internal(u64* address, struct vm_data** target);
104
static void virtual_enumerator_init(void);
105
static void virtual_enumerator_destroy(void);
106
static void virtual_enumerator_init_internal(struct vm* ptr);
107
#if defined(VM_MEMORY_DEBUG_INFO)
108
static void virtual_enumerator_destroy_internal(void);
109
#endif
110
static void** virtual_enumerator_next_internal(void);
111
#if defined(VM_ALLOC_DEBUG_INFO)
112
static struct pointer* virtual_enumerator_pointer_next_internal(void);
113
#endif
114

115
static struct vm_data* vm_init_internal(u64 size, u64 offset) {
116
    struct vm_data* vm_data_ptr = generic_memory_v1->alloc(VM_DATA_SIZE);
117
    vm_data_ptr->bp = generic_memory_v1->alloc(ALLOC_SIZE(size));
118
    vm_data_ptr->sp = vm_data_ptr->bp;
119
    vm_data_ptr->offset = offset;
120
    vm_data_ptr->size = size;
121
    return vm_data_ptr;
122
}
123

124
static struct pointer** vm_read_internal(u64 address) {
125
    struct pointer** ptr = 0;
126
    const struct vm_data* vm_data_ptr = vm->head;
127
    do {
128
        if (address > vm_data_ptr->offset && address <= vm_data_ptr->offset + vm_data_ptr->size) {
129
            ptr = vm_data_ptr->bp + address - vm_data_ptr->offset - 1;
130
            break;
131
        }
132
        vm_data_ptr = vm_data_ptr->next;
133
    } while (vm_data_ptr != 0);
134
    return ptr;
135
}
136

137
static struct pointer** vm_alloc_internal(u64* address, struct vm_data** target) {
138
    struct vm_data* vm_data_ptr = vm->tail;
139
    struct pointer** ptr = 0;
140
#ifndef USE_GC
141
    struct vm_pointer* list_ptr = list_v1->pop(cache);
142
    if (list_ptr != 0) {
143
        ptr = list_ptr->ptr;
144
        vm_data_ptr = list_ptr->vm;
145
        generic_memory_v1->free(list_ptr, VM_POINTER_SIZE);
146
    }
147
    if (ptr == 0) {
148
#endif
149
        if ((u64)(vm_data_ptr->sp - vm_data_ptr->bp) == vm_data_ptr->size) {
150
            struct vm_data* prev = vm_data_ptr;
151
            vm_data_ptr = vm_init_internal(vm_data_ptr->size, vm_data_ptr->offset + vm_data_ptr->size);
152
            vm_data_ptr->prev = prev;
153
            prev->next = vm_data_ptr;
154
            vm->tail = vm_data_ptr;
155
        }
156
        ptr = vm_data_ptr->sp;
157
        ++vm_data_ptr->sp;
158
#ifndef USE_GC
159
    }
160
#endif
161
    *target = vm_data_ptr;
162
    *address = (u64)(ptr - vm_data_ptr->bp) + vm_data_ptr->offset + 1;
163
    return ptr;
164
}
165

166
static void virtual_enumerator_init(void) {
167
    virtual_enumerator_init_internal(vm);
168
}
169

170
static void virtual_enumerator_destroy(void) {
171
    virtual_enumerator_init_internal(vm);
172
}
173

174
static void virtual_enumerator_init_internal(struct vm* ptr) {
175
    struct vm_data* vm_data_ptr = ptr->head;
176
    state->vm = vm_data_ptr;
177
    state->ptr = vm_data_ptr->bp;
178
}
179

180
#if defined(VM_MEMORY_DEBUG_INFO)
181
static void virtual_enumerator_destroy_internal(void) {
182
    state->vm = 0;
183
    state->ptr = 0;
184
}
185
#endif
186

187
/* implementation */
188

189
static void vm_init(struct vm** ptr, u64 size) {
190
#ifndef USE_GC
191
    cache = generic_memory_v1->alloc(PTR_SIZE);
192
    list_v1->init(cache);
193
#endif
194
    struct vm_data* vm_data_ptr = vm_init_internal(size == 0 ? DEFAULT_SIZE : size, 0);
195
    vm->head = vm_data_ptr;
196
    vm->tail = vm_data_ptr;
197
    struct vm* vm_ptr = generic_memory_v1->alloc(sizeof(struct vm));
198
    vm_ptr->head = vm_data_ptr;
199
    vm_ptr->tail = vm_data_ptr;
200
    *ptr = vm_ptr;
201
}
202

203
static void vm_destroy(struct vm** ptr) {
204
    if (ptr == 0 || *ptr == 0) {
205
        return;
206
    }
207
    struct vm* current = *ptr;
208
    vm->head = current->head;
209
    vm->tail = current->tail;
210
    generic_memory_v1->free(current, sizeof(struct vm));
211
    *ptr = 0;
212
#ifndef USE_GC
213
    struct vm_pointer* vm_pointer_ptr = 0;
214
    while ((vm_pointer_ptr = list_v1->pop(cache)) != 0) {
215
        generic_memory_v1->free(vm_pointer_ptr, VM_POINTER_SIZE);
216
    }
217
    list_v1->destroy(cache);
218
    generic_memory_v1->free(cache, PTR_SIZE);
219
#ifdef USE_MEMORY_CLEANUP
220
    cache = 0;
221
#endif
222
#endif
223
    struct vm_data* vm_data_ptr = vm->head;
224
    while (vm_data_ptr != 0) {
225
        struct vm_data* next = vm_data_ptr->next;
226
        generic_memory_v1->free(vm_data_ptr->bp, ALLOC_SIZE(vm_data_ptr->size));
227
        generic_memory_v1->free(vm_data_ptr, VM_DATA_SIZE);
228
        vm_data_ptr = next;
229
    }
230
    vm->head = 0;
231
    vm->tail = 0;
232
}
233

234
#if defined(VM_MEMORY_DEBUG_INFO)
235
static void vm_dump(void) {
236
    virtual_enumerator_init_internal(vm);
237
    struct pointer* ptr = 0;
238
    while ((ptr = virtual_enumerator_pointer_next_internal()) != 0) {
239
        pointer_v1->dump(ptr);
240
    }
241
    virtual_enumerator_destroy_internal();
242
}
243

244
static void vm_dump_ref(void) {
245
    virtual_enumerator_init_internal(vm);
246
    void** ptr = 0;
247
    while ((ptr = virtual_enumerator_next_internal()) != 0) {
248
        pointer_v1->dump_ref(ptr);
249
    }
250
    virtual_enumerator_destroy_internal();
251
}
252
#endif
253

254
static void vm_free(const struct pointer* ptr) {
255
    if (!ptr) {
256
        return;
257
    }
258
    const struct vm_data* vm_data_ptr = pointer_v1->vm(ptr);
259
    struct pointer** data = vm_data_ptr->bp - vm_data_ptr->offset - 1 + pointer_v1->address(ptr);
260
    if (data != 0) {
261
#ifndef USE_GC
262
        struct vm_pointer* vm_pointer_ptr = generic_memory_v1->alloc(VM_POINTER_SIZE);
263
        vm_pointer_ptr->ptr = data;
264
        vm_pointer_ptr->vm = pointer_v1->vm(ptr);
265
        list_v1->push(cache, vm_pointer_ptr);
266
#endif
267
#ifdef USE_VM_DEBUG_INFO
268
#if defined(VM_ALLOC_DEBUG_INFO)
269
        printf("  >-: %016llx ! %016llx > %016llx\n", pointer_v1->address(ptr), (u64)ptr, (u64)data);
270
#endif
271
#endif
272
        *data = 0;
273
    }
274
}
275

276
static struct pointer* vm_read_type(u64 address, u64 id) {
277
    if (!address) {
278
        return 0;
279
    }
280
    struct pointer** data = vm_read_internal(address);
281
    struct pointer* ptr = 0;
282
    if (data == 0) {
283
        return 0;
284
    }
285
    ptr = *data;
286
    if (ptr == 0) {
287
        return 0;
288
    }
289
    if (!pointer_v1->read_type(ptr, id)) {
290
        return 0;
291
    }
292
#ifdef USE_VM_DEBUG_INFO
293
#if defined(VM_ACCESS_DEBUG_INFO)
294
    printf("  <v: %016llx ! %016llx > %016llx\n", address, (u64)ptr, (u64)data);
295
#endif
296
#endif
297
    return ptr;
298
}
299

300
static struct pointer* vm_read(u64 address) {
301
    if (!address) {
302
        return 0;
303
    }
304
    struct pointer** data = vm_read_internal(address);
305
    struct pointer* ptr = 0;
306
    if (data == 0) {
307
        return 0;
308
    }
309
    ptr = *data;
310
    if (ptr == 0) {
311
        return 0;
312
    }
313
#ifdef USE_VM_DEBUG_INFO
314
#if defined(VM_ACCESS_DEBUG_INFO)
315
    printf("  <v: %016llx ! %016llx > %016llx\n", address, (u64)ptr, (u64)data);
316
#endif
317
#endif
318
    return ptr;
319
}
320

321
static u64 vm_alloc(struct pointer* ptr) {
322
    if (!ptr) {
323
        return 0;
324
    }
325
    u64 address = 0;
326
    struct vm_data* target = 0;
327
    struct pointer** data = vm_alloc_internal(&address, &target);
328
    *data = ptr;
329
    pointer_v1->write(ptr, target, address);
330
#ifdef USE_VM_DEBUG_INFO
331
#if defined(VM_ALLOC_DEBUG_INFO)
332
    printf("  >+: %016llx ! %016llx > %016llx\n", address, (u64)ptr, (u64)data);
333
#endif
334
#endif
335
    return address;
336
}
337

338
#if defined(VM_ALLOC_DEBUG_INFO)
339
static struct pointer* virtual_enumerator_pointer_next_internal(void) {
340
    struct pointer* data = 0;
341
    struct vm_data* vm_data_ptr = state->vm;
342
    while (data == 0) {
343
        if (state->ptr == vm_data_ptr->sp) {
344
            if (vm_data_ptr->next == 0) {
345
                break;
346
            }
347
            vm_data_ptr = vm_data_ptr->next;
348
            state->vm = vm_data_ptr;
349
            state->ptr = vm_data_ptr->bp;
350
        }
351
        data = *state->ptr++;
352
    }
353
    return data;
354
}
355
#endif
356

357
static u64 virtual_enumerator_next(void) {
358
    u64 address = 0;
359
    void** ptr;
360
    while ((ptr = virtual_enumerator_next_internal()) != 0) {
361
        if (*ptr != 0) {
362
            const struct pointer* data_ptr = *ptr;
363
            if (data_ptr != 0) {
364
                address = pointer_v1->address(data_ptr);
365
                break;
366
            }
367
        }
368
    }
369
    return address;
370
}
371

372
static void** virtual_enumerator_next_internal(void) {
373
    void** data = 0;
374
    struct vm_data* vm_data_ptr = state->vm;
375
    while (data == 0) {
376
        if (state->ptr == vm_data_ptr->sp) {
377
            if (vm_data_ptr->next == 0) {
378
                break;
379
            }
380
            vm_data_ptr = vm_data_ptr->next;
381
            state->vm = vm_data_ptr;
382
            state->ptr = vm_data_ptr->bp;
383
        }
384
        data = (void**)state->ptr++;
385
    }
386
    return data;
387
}
388

389
/* public */
390
const struct virtual_methods_v1 virtual_methods_definition_v1 = {
391
    .init = vm_init,
392
    .destroy = vm_destroy,
393
    .alloc = vm_alloc,
394
    .free = vm_free,
395
    .read = vm_read,
396
    .read_type = vm_read_type,
397
    .enumerator_init = virtual_enumerator_init,
398
    .enumerator_destroy = virtual_enumerator_destroy,
399
    .enumerator_next = virtual_enumerator_next,
400
#if defined(VM_MEMORY_DEBUG_INFO)
401
    .dump = vm_dump,
402
    .dump_ref = vm_dump_ref
403
#endif
404
};
405

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.