1
1
use super :: UPCALLS ;
2
2
use mmtk:: util:: constants:: * ;
3
3
use mmtk:: util:: conversions;
4
+ use mmtk:: util:: ObjectReference ;
4
5
use mmtk:: util:: { Address , OpaquePointer } ;
5
6
use std:: ffi:: CStr ;
6
7
use std:: fmt;
@@ -64,9 +65,31 @@ pub struct Klass {
64
65
}
65
66
66
67
impl Klass {
68
+ pub const LH_NEUTRAL_VALUE : i32 = 0 ;
69
+ pub const LH_INSTANCE_SLOW_PATH_BIT : i32 = 0x01 ;
70
+ #[ allow( clippy:: erasing_op) ]
71
+ pub const LH_LOG2_ELEMENT_SIZE_SHIFT : i32 = BITS_IN_BYTE as i32 * 0 ;
72
+ pub const LH_LOG2_ELEMENT_SIZE_MASK : i32 = BITS_IN_LONG as i32 - 1 ;
73
+ pub const LH_HEADER_SIZE_SHIFT : i32 = BITS_IN_BYTE as i32 * 2 ;
74
+ pub const LH_HEADER_SIZE_MASK : i32 = ( 1 << BITS_IN_BYTE ) - 1 ;
67
75
pub unsafe fn cast < ' a , T > ( & self ) -> & ' a T {
68
76
& * ( self as * const _ as usize as * const T )
69
77
}
78
+ /// Force slow-path for instance size calculation?
79
+ #[ inline( always) ]
80
+ const fn layout_helper_needs_slow_path ( lh : i32 ) -> bool {
81
+ ( lh & Self :: LH_INSTANCE_SLOW_PATH_BIT ) != 0
82
+ }
83
+ /// Get log2 array element size
84
+ #[ inline( always) ]
85
+ const fn layout_helper_log2_element_size ( lh : i32 ) -> i32 {
86
+ ( lh >> Self :: LH_LOG2_ELEMENT_SIZE_SHIFT ) & Self :: LH_LOG2_ELEMENT_SIZE_MASK
87
+ }
88
+ /// Get array header size
89
+ #[ inline( always) ]
90
+ const fn layout_helper_header_size ( lh : i32 ) -> i32 {
91
+ ( lh >> Self :: LH_HEADER_SIZE_SHIFT ) & Self :: LH_HEADER_SIZE_MASK
92
+ }
70
93
}
71
94
72
95
#[ repr( C ) ]
@@ -238,6 +261,13 @@ pub struct OopDesc {
238
261
pub klass : & ' static Klass ,
239
262
}
240
263
264
+ impl OopDesc {
265
+ #[ inline( always) ]
266
+ pub fn start ( & self ) -> Address {
267
+ unsafe { mem:: transmute ( self ) }
268
+ }
269
+ }
270
+
241
271
impl fmt:: Debug for OopDesc {
242
272
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
243
273
let c_string = unsafe { ( ( * UPCALLS ) . dump_object_string ) ( mem:: transmute ( self ) ) } ;
@@ -249,6 +279,22 @@ impl fmt::Debug for OopDesc {
249
279
250
280
pub type Oop = & ' static OopDesc ;
251
281
282
+ /// Convert ObjectReference to Oop
283
+ impl From < ObjectReference > for & OopDesc {
284
+ #[ inline( always) ]
285
+ fn from ( o : ObjectReference ) -> Self {
286
+ unsafe { mem:: transmute ( o) }
287
+ }
288
+ }
289
+
290
+ /// Convert Oop to ObjectReference
291
+ impl From < & OopDesc > for ObjectReference {
292
+ #[ inline( always) ]
293
+ fn from ( o : & OopDesc ) -> Self {
294
+ unsafe { mem:: transmute ( o) }
295
+ }
296
+ }
297
+
252
298
impl OopDesc {
253
299
pub unsafe fn as_array_oop < T > ( & self ) -> ArrayOop < T > {
254
300
& * ( self as * const OopDesc as * const ArrayOopDesc < T > )
@@ -257,6 +303,40 @@ impl OopDesc {
257
303
pub fn get_field_address ( & self , offset : i32 ) -> Address {
258
304
Address :: from_ref ( self ) + offset as isize
259
305
}
306
+
307
+ /// Slow-path for calculating object instance size
308
+ #[ inline( always) ]
309
+ unsafe fn size_slow ( & self ) -> usize {
310
+ ( ( * UPCALLS ) . get_object_size ) ( self . into ( ) )
311
+ }
312
+
313
+ /// Calculate object instance size
314
+ #[ inline( always) ]
315
+ pub unsafe fn size ( & self ) -> usize {
316
+ let klass = self . klass ;
317
+ let lh = klass. layout_helper ;
318
+ // The (scalar) instance size is pre-recorded in the TIB?
319
+ if lh > Klass :: LH_NEUTRAL_VALUE {
320
+ if !Klass :: layout_helper_needs_slow_path ( lh) {
321
+ lh as _
322
+ } else {
323
+ self . size_slow ( )
324
+ }
325
+ } else if lh <= Klass :: LH_NEUTRAL_VALUE {
326
+ if lh < Klass :: LH_NEUTRAL_VALUE {
327
+ // Calculate array size
328
+ let array_length = self . as_array_oop :: < ( ) > ( ) . length ( ) ;
329
+ let mut size_in_bytes: usize =
330
+ ( array_length as usize ) << Klass :: layout_helper_log2_element_size ( lh) ;
331
+ size_in_bytes += Klass :: layout_helper_header_size ( lh) as usize ;
332
+ ( size_in_bytes + 0b111 ) & !0b111
333
+ } else {
334
+ self . size_slow ( )
335
+ }
336
+ } else {
337
+ unreachable ! ( )
338
+ }
339
+ }
260
340
}
261
341
262
342
#[ repr( C ) ]
0 commit comments