Skip to content

Commit 1284e62

Browse files
committed
rt: Support arrays in heap snapshots
1 parent 6dfb6df commit 1284e62

File tree

3 files changed

+63
-14
lines changed

3 files changed

+63
-14
lines changed

dora-runtime/src/snapshot.rs

Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::sync::Arc;
66

77
use crate::gc::root::iterate_strong_roots;
88
use crate::gc::Address;
9-
use crate::mirror::Str;
9+
use crate::mirror::{Array, Ref, Str};
1010
use crate::safepoint;
1111
use crate::shape::Shape;
1212
use crate::threads::DoraThread;
@@ -160,11 +160,12 @@ impl<'a> SnapshotGenerator<'a> {
160160

161161
edge_count += match shape.kind() {
162162
ShapeKind::Class(cls_id, type_params) => {
163-
self.process_class_object(vm, address, *cls_id, type_params, shape)
163+
self.process_class_object(address, *cls_id, type_params, shape)
164164
}
165165
ShapeKind::Array(cls_id, type_params) => {
166-
self.process_array_object(vm, address, *cls_id, type_params, shape)
166+
self.process_array_object(address, *cls_id, type_params, shape)
167167
}
168+
ShapeKind::String => 0,
168169
_ => 0,
169170
};
170171

@@ -200,6 +201,7 @@ impl<'a> SnapshotGenerator<'a> {
200201
display_ty_array(&self.vm.program, type_params)
201202
)
202203
}
204+
ShapeKind::String => "String".into(),
203205
ShapeKind::Lambda(fct_id, type_params) => {
204206
let fct = &self.vm.program.functions[fct_id.0 as usize];
205207
let params = fct
@@ -250,21 +252,20 @@ impl<'a> SnapshotGenerator<'a> {
250252

251253
fn process_class_object(
252254
&mut self,
253-
vm: &VM,
254255
address: Address,
255256
cls_id: ClassId,
256257
type_params: &BytecodeTypeArray,
257258
shape: &Shape,
258259
) -> usize {
259260
let mut edge_count = 0;
260-
let class = vm.class(cls_id);
261+
let class = self.vm.class(cls_id);
261262

262263
for (field_idx, field) in class.fields.iter().enumerate() {
263-
let ty = specialize_ty(vm, None, field.ty.clone(), type_params);
264+
let ty = specialize_ty(self.vm, None, field.ty.clone(), type_params);
264265
let field_offset = shape.fields[field_idx].offset;
265266
let field_addr = address.offset(field_offset as usize);
266267

267-
let value_node_id = self.process_value(field_addr, ty);
268+
let value_node_id = self.process_value(field_addr, &ty);
268269

269270
let field_name = if let Some(name) = field.name.as_ref() {
270271
name.clone()
@@ -284,7 +285,7 @@ impl<'a> SnapshotGenerator<'a> {
284285
edge_count
285286
}
286287

287-
fn process_value(&mut self, value_address: Address, ty: BytecodeType) -> NodeId {
288+
fn process_value(&mut self, value_address: Address, ty: &BytecodeType) -> NodeId {
288289
match ty {
289290
BytecodeType::Unit => self.ensure_value("()".into()),
290291
BytecodeType::Bool => {
@@ -342,13 +343,34 @@ impl<'a> SnapshotGenerator<'a> {
342343

343344
fn process_array_object(
344345
&mut self,
345-
_vm: &VM,
346-
_address: Address,
346+
address: Address,
347347
_cls_id: ClassId,
348-
_type_params: &BytecodeTypeArray,
349-
_shape: &Shape,
348+
type_params: &BytecodeTypeArray,
349+
shape: &Shape,
350350
) -> usize {
351-
0
351+
let mut edge_count = 0;
352+
let array: Ref<Array<u8>> = address.into();
353+
let length = array.len();
354+
355+
assert_eq!(shape.instance_size(), 0);
356+
let element_size = shape.element_size();
357+
let mut element_addr = array.data_address();
358+
359+
assert_eq!(type_params.len(), 1);
360+
let ty = type_params[0].clone();
361+
362+
for element_idx in 0..length {
363+
let element_node_id = self.process_value(element_addr, &ty);
364+
self.add_edge(Edge {
365+
name_or_idx: element_idx,
366+
to_node_index: element_node_id,
367+
kind: EdgeKind::Element,
368+
});
369+
edge_count += 1;
370+
element_addr = element_addr.offset(element_size);
371+
}
372+
373+
edge_count
352374
}
353375

354376
fn add_edge(&mut self, edge: Edge) -> EdgeId {

dora-runtime/src/vm/classes.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use dora_bytecode::{BytecodeType, BytecodeTypeArray, ClassId, EnumId, FunctionId
77
pub enum ShapeKind {
88
Array(ClassId, BytecodeTypeArray),
99
Class(ClassId, BytecodeTypeArray),
10+
String,
1011
Lambda(FunctionId, BytecodeTypeArray),
1112
TraitObject {
1213
trait_ty: BytecodeType,

dora-runtime/src/vm/specialize.rs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -297,8 +297,10 @@ pub fn create_shape_for_class(
297297

298298
debug_assert!(type_params.iter().all(|ty| ty.is_concrete_type()));
299299

300-
if vm.known.array_class_id() == cls_id || vm.known.string_class_id() == cls_id {
300+
if vm.known.array_class_id() == cls_id {
301301
create_shape_for_array_class(vm, cls_id, cls, type_params)
302+
} else if vm.known.string_class_id() == cls_id {
303+
create_shape_for_string_class(vm, cls_id, cls, type_params)
302304
} else {
303305
create_shape_for_regular_class(vm, cls_id, cls, type_params)
304306
}
@@ -436,6 +438,30 @@ fn create_shape_for_array_class(
436438
shape
437439
}
438440

441+
fn create_shape_for_string_class(
442+
vm: &VM,
443+
cls_id: ClassId,
444+
cls: &ClassData,
445+
type_params: &BytecodeTypeArray,
446+
) -> *const Shape {
447+
assert_eq!(cls_id, vm.known.string_class_id());
448+
assert!(cls.fields.is_empty());
449+
assert!(type_params.is_empty());
450+
451+
let mut specializations = vm.class_shapes.write();
452+
453+
if let Some(&shape) = specializations.get(&(cls_id, type_params.clone())) {
454+
return shape;
455+
}
456+
457+
let shape = create_shape(vm, ShapeKind::String, InstanceSize::Str, Vec::new(), 0);
458+
459+
let old = specializations.insert((cls_id, type_params.clone()), shape);
460+
assert!(old.is_none());
461+
462+
shape
463+
}
464+
439465
pub fn ensure_shape_for_lambda(
440466
vm: &VM,
441467
fct_id: FunctionId,

0 commit comments

Comments
 (0)