Skip to main content

luaur_vm/records/
size_class_config.rs

1//! Node: `cxx:Record:Luau.VM:VM/src/lmem.cpp:127:size_class_config`
2//! Source: `VM/src/lmem.cpp:127-176` (hand-fixed: the constexpr constructor
3//! was ported as an instance method nobody called, the `kSizeClassConfig`
4//! static referenced by `sizeclass!` never existed, and kSizeClasses said 32
5//! where the C++ says LUA_SIZECLASSES = 40 — the table is now built at
6//! compile time by a const fn, faithful to the C++ constructor)
7
8#[allow(non_upper_case_globals)]
9pub(crate) const kSizeClasses: usize = 40; // LUA_SIZECLASSES
10#[allow(non_upper_case_globals)]
11pub(crate) const kMaxSmallSize: usize = 1024;
12
13#[allow(non_camel_case_types)]
14#[repr(C)]
15#[derive(Debug)]
16pub struct SizeClassConfig {
17    pub sizeOfClass: [core::ffi::c_int; kSizeClasses],
18    pub classForSize: [core::ffi::c_char; kMaxSmallSize + 1],
19    pub classCount: core::ffi::c_int,
20}
21
22const fn build_size_class_config() -> SizeClassConfig {
23    let mut size_of_class = [0i32; kSizeClasses];
24    let mut class_for_size = [-1i8 as core::ffi::c_char; kMaxSmallSize + 1];
25    let mut class_count = 0usize;
26
27    // we use a progressive size class scheme:
28    // - all size classes are aligned by 8b to satisfy pointer alignment requirements
29    // - we first allocate sizes classes in multiples of 8
30    // - after the first cutoff we allocate size classes in multiples of 16
31    // - after the second cutoff we allocate size classes in multiples of 32
32    // - after the third cutoff we allocate size classes in multiples of 64
33    // this balances internal fragmentation vs external fragmentation
34    let mut size = 8;
35    while size < 64 {
36        size_of_class[class_count] = size;
37        class_count += 1;
38        size += 8;
39    }
40    let mut size = 64;
41    while size < 256 {
42        size_of_class[class_count] = size;
43        class_count += 1;
44        size += 16;
45    }
46    let mut size = 256;
47    while size < 512 {
48        size_of_class[class_count] = size;
49        class_count += 1;
50        size += 32;
51    }
52    let mut size = 512;
53    while size <= 1024 {
54        size_of_class[class_count] = size;
55        class_count += 1;
56        size += 64;
57    }
58
59    assert!(class_count <= kSizeClasses);
60
61    // fill the lookup table for all classes
62    let mut klass = 0usize;
63    while klass < class_count {
64        class_for_size[size_of_class[klass] as usize] = klass as core::ffi::c_char;
65        klass += 1;
66    }
67
68    // fill the gaps in lookup table
69    let mut size = kMaxSmallSize as i32 - 1;
70    while size >= 0 {
71        if (class_for_size[size as usize] as i8) < 0 {
72            class_for_size[size as usize] = class_for_size[size as usize + 1];
73        }
74        size -= 1;
75    }
76
77    SizeClassConfig {
78        sizeOfClass: size_of_class,
79        classForSize: class_for_size,
80        classCount: class_count as core::ffi::c_int,
81    }
82}
83
84#[allow(non_upper_case_globals)]
85pub static kSizeClassConfig: SizeClassConfig = build_size_class_config();