To protect your data, the CISO officer has suggested users to enable 2FA as soon as possible.
Currently 2.7% of users enabled 2FA.

mm_mu.rs 7.93 KB
Newer Older
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
1
// Copyright 2017 The Australian National University
qinsoon's avatar
qinsoon committed
2
//
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
3
4
5
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
qinsoon's avatar
qinsoon committed
6
//
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
7
//     http://www.apache.org/licenses/LICENSE-2.0
qinsoon's avatar
qinsoon committed
8
//
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
9
10
11
12
13
14
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

qinsoon's avatar
qinsoon committed
15
/// the garbage collection crate as in src/gc
16
17
18
19
/// we design the GC crate to be separate from other parts of the VM, and to be
/// self-contained as much as possible. We only expose limited interface
/// (functions, data structures, constants) from the GC crate, and those get
/// re-exported in this module.
qinsoon's avatar
qinsoon committed
20
extern crate mu_gc as gc;
21
pub use self::gc::*;
22
use super::*;
23

24
25
/// we do not allocate hybrid into tiny object space (hybrid should be at least
/// 32 bytes)
26
27
28
29
30
31
32
33
pub fn check_hybrid_size(size: ByteSize) -> ByteSize {
    if size < 32 {
        32
    } else {
        math::align_up(size, POINTER_SIZE)
    }
}

34
35
36
37
38
pub fn gen_object_encode(
    backend_ty: &BackendType,
    size: ByteSize,
    vm: &VM
) -> ObjectEncode {
39
40
41
42
43
44
45
46
    let is_hybrid = backend_ty.ty.is_hybrid();
    let gc_tyid = {
        let ty_encode = backend_ty.gc_type.as_ref().unwrap();
        vm.get_gc_type_id(ty_encode)
    };
    let full_tyid = {
        match backend_ty.gc_type_hybrid_full {
            Some(ref enc) => vm.get_gc_type_id(enc),
47
            None => 0
48
49
50
        }
    };

51
52
    debug_if!(
        log_settings::MM_MU_DEBUG,
qinsoon's avatar
fix    
qinsoon committed
53
        "ENCODE: gen_object_encode: {:?}, size: {}",
54
55
56
57
58
59
60
61
        backend_ty,
        size
    );
    debug_if!(
        log_settings::MM_MU_DEBUG,
        "ENCODE: gc_ty: {}, full_gc_ty: {}",
        gc_tyid,
        full_tyid
qinsoon's avatar
fix    
qinsoon committed
62
63
    );

64
65
66
67
68
69
70
71
    gen_object_encode_internal(is_hybrid, gc_tyid, full_tyid, size, vm)
}

pub fn gen_object_encode_internal(
    is_hybrid: bool,
    gc_tyid: TypeID,
    full_tyid: TypeID,
    size: ByteSize,
72
    vm: &VM
73
74
75
76
) -> ObjectEncode {
    let size = math::align_up(size, POINTER_SIZE);
    if size <= MAX_TINY_OBJECT {
        if !is_hybrid {
qinsoon's avatar
fix    
qinsoon committed
77
            let size = if size <= 16 {
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
                16
            } else {
                assert!(size <= 24);
                24
            };
            let gc_type = vm.get_gc_type(gc_tyid);
            let enc = gc_type.as_short();
            let field0 = if enc.fix_len() > 0 {
                enc.fix_ty(0)
            } else {
                WordType::NonRef
            };
            let field1 = if enc.fix_len() > 1 {
                enc.fix_ty(1)
            } else {
                WordType::NonRef
            };
            let field2 = if enc.fix_len() > 2 {
                enc.fix_ty(2)
            } else {
                WordType::NonRef
            };
100
101
102
            ObjectEncode::Tiny(TinyObjectEncode::create(
                size, field0, field1, field2
            ))
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
        } else {
            unreachable!()
        }
    } else if size <= MAX_SMALL_OBJECT {
        ObjectEncode::Small(SmallObjectEncode::create(size, gc_tyid))
    } else if size <= MAX_MEDIUM_OBJECT {
        ObjectEncode::Medium(MediumObjectEncode::create(size, gc_tyid))
    } else {
        if !is_hybrid {
            ObjectEncode::Large(LargeObjectEncode::new(size, gc_tyid))
        } else {
            ObjectEncode::Large(LargeObjectEncode::new(size, full_tyid))
        }
    }
}

qinsoon's avatar
fix    
qinsoon committed
119
#[no_mangle]
120
121
122
123
124
125
pub extern "C" fn muentry_alloc_var_size(
    fix_size: ByteSize,
    var_size: ByteSize,
    var_len: usize,
    align: ByteSize,
    tyid: TypeID,
126
    full_tyid: TypeID
127
128
) -> ObjectReference {
    debug_assert!(MuThread::has_current());
qinsoon's avatar
qinsoon committed
129
    let cur_thread = MuThread::current_mut();
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
    let mutator: *mut Mutator = &mut cur_thread.allocator as *mut Mutator;
    let size = check_hybrid_size(fix_size + var_size * var_len);

    // alloc
    let res = if size <= MAX_TINY_OBJECT {
        muentry_alloc_tiny(mutator, size, align)
    } else if size <= MAX_MEDIUM_OBJECT {
        muentry_alloc_normal(mutator, size, align)
    } else {
        muentry_alloc_large(mutator, size, align)
    };

    // get encoding
    let ref vm = cur_thread.vm;
    let encode = gen_object_encode_internal(true, tyid, full_tyid, size, vm);

    match encode {
qinsoon's avatar
qinsoon committed
147
        ObjectEncode::Tiny(_) => unreachable!(),
148
149
150
151
152
153
154
        ObjectEncode::Small(enc) => {
            muentry_init_small_object(mutator, res, enc)
        }
        ObjectEncode::Medium(enc) => {
            muentry_init_medium_object(mutator, res, enc)
        }
        ObjectEncode::Large(enc) => muentry_init_large_object(mutator, res, enc)
155
156
157
158
    }

    res
}
159

160
161
// the following functions are used by VM to allocate for the client (through
// API)
qinsoon's avatar
qinsoon committed
162
163

/// finds an allocator and allocates memory
164
165
166
167
168
169
170
/// if current thread has an allocator, use the allocator. Otherwise creates a
/// new allocator, allocates objects and drops the allocator
fn check_allocator(
    size: ByteSize,
    align: ByteSize,
    encode: ObjectEncode
) -> ObjectReference {
qinsoon's avatar
qinsoon committed
171
172
    if MuThread::has_current() {
        // we have an allocator
173
174
        let allocator =
            (&mut MuThread::current_mut().allocator) as *mut Mutator;
175
        allocate(allocator, size, align, encode)
qinsoon's avatar
qinsoon committed
176
    } else {
177
178
179
        let allocator = new_mutator_ptr();
        let ret = allocate(allocator, size, align, encode);
        drop_mutator(allocator);
qinsoon's avatar
qinsoon committed
180
181
182
183

        ret
    }
}
184

qinsoon's avatar
qinsoon committed
185
/// allocates and initiates an object (hybrid or other types, large or small)
qinsoon's avatar
qinsoon committed
186
#[inline(always)]
qinsoon's avatar
qinsoon committed
187
188
189
190
fn allocate(
    allocator: *mut Mutator,
    size: ByteSize,
    align: ByteSize,
191
    encode: ObjectEncode
qinsoon's avatar
qinsoon committed
192
) -> ObjectReference {
193
    let size = math::align_up(size, POINTER_SIZE);
qinsoon's avatar
qinsoon committed
194
    // allocate
195
196
197
198
199
200
201
202
203
204
205
206
    if size <= MAX_TINY_OBJECT {
        let res = muentry_alloc_tiny(allocator, size, align);
        muentry_init_tiny_object(allocator, res, encode.tiny());
        res
    } else if size <= MAX_SMALL_OBJECT {
        let res = muentry_alloc_normal(allocator, size, align);
        muentry_init_small_object(allocator, res, encode.small());
        res
    } else if size <= MAX_MEDIUM_OBJECT {
        let res = muentry_alloc_normal(allocator, size, align);
        muentry_init_medium_object(allocator, res, encode.medium());
        res
qinsoon's avatar
qinsoon committed
207
    } else {
208
209
210
        let res = muentry_alloc_large(allocator, size, align);
        muentry_init_large_object(allocator, res, encode.large());
        res
qinsoon's avatar
qinsoon committed
211
    }
212
213
}

qinsoon's avatar
qinsoon committed
214
/// allocates an object of fixed types
215
216
217
218
219
pub fn allocate_fixed(
    ty: P<MuType>,
    backendtype: Box<BackendType>,
    vm: &VM
) -> Address {
220
    let encode = gen_object_encode(&backendtype, backendtype.size, vm);
qinsoon's avatar
qinsoon committed
221

222
    trace_if!(log_settings::MM_MU_TRACE, "API: allocate fixed ty: {}", ty);
223
224
    check_allocator(backendtype.size, backendtype.alignment, encode)
        .to_address()
qinsoon's avatar
qinsoon committed
225
226
}

qinsoon's avatar
qinsoon committed
227
/// allocates an object of hybrid types
228
229
230
231
pub fn allocate_hybrid(
    ty: P<MuType>,
    len: usize,
    backendtype: Box<BackendType>,
232
    vm: &VM
233
) -> Address {
234
235
236
    let size = check_hybrid_size(
        backendtype.size + backendtype.elem_size.unwrap() * len
    );
237
    let encode = gen_object_encode(&backendtype, size, vm);
238

239
    trace_if!(log_settings::MM_MU_TRACE, "API: allocate hybrd ty: {}", ty);
240
    check_allocator(size, backendtype.alignment, encode).to_address()
qinsoon's avatar
qinsoon committed
241
}
242

qinsoon's avatar
qinsoon committed
243
/// allocates a global cell
244
245
246
pub fn allocate_global(
    iref_global: P<Value>,
    backendtype: Box<BackendType>,
247
    vm: &VM
248
) -> ValueLocation {
249
    let referenced_type = match iref_global.ty.get_referent_ty() {
qinsoon's avatar
qinsoon committed
250
        Some(ty) => ty,
251
252
253
        None => panic!(
            "expected global to be an iref type, found {}",
            iref_global.ty
254
        )
qinsoon's avatar
qinsoon committed
255
    };
256

qinsoon's avatar
qinsoon committed
257
258
259
260
    assert!(
        !referenced_type.is_hybrid(),
        "global cell cannot be hybrid type"
    );
qinsoon's avatar
qinsoon committed
261

262
263
264
265
266
    trace_if!(
        log_settings::MM_MU_TRACE,
        "API: allocate hybrd ty: {}",
        referenced_type
    );
267

268
    let addr = allocate_fixed(referenced_type, backendtype, vm);
269
    ValueLocation::Direct(RegGroup::GPR, addr)
270
}