Skip to content

Commit

Permalink
WIP: 完善新版 malloc 测试
Browse files Browse the repository at this point in the history
  • Loading branch information
chai2010 committed Jan 15, 2025
1 parent e05560c commit 570175e
Show file tree
Hide file tree
Showing 3 changed files with 138 additions and 16 deletions.
68 changes: 65 additions & 3 deletions internal/waroot/malloc/malloc.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ var malloc_wat string

// 默认值
const (
KPageBytes = 64 << 10 // 一个内存页大小

DefaultMemoryPages int32 = 1 // 内存页数
DefaultMemoryPagesMax int32 = 10 // 内存最大页数

Expand All @@ -30,8 +32,8 @@ const (

// 内部常量
const (
kFreeListHeadSize = 5 * 8 // 全部空闲链表头大小
kBlockHeadSize = 2 * 8 // 块头大小
kBlockHeadSize = 8 // 块头大小
kFreeListHeadSize = 5 * kBlockHeadSize // 全部空闲链表头大小
)

// Heap配置
Expand Down Expand Up @@ -126,8 +128,68 @@ func (p *Heap) init() {
}
}

// 获取全局变量
func (p *Heap) Global__stack_ptr() int32 {
return p.xGlobal("__stack_ptr")
}
func (p *Heap) Global__heap_base() int32 {
return p.xGlobal("__heap_base")
}
func (p *Heap) Global__heap_ptr() int32 {
return p.xGlobal("__heap_ptr")
}
func (p *Heap) Global__heap_top() int32 {
return p.xGlobal("__heap_top")
}
func (p *Heap) Global__heap_l128_freep() int32 {
return p.xGlobal("__heap_l128_freep")
}
func (p *Heap) Global__heap_lfixed_cap() int32 {
return p.xGlobal("__heap_lfixed_cap")
}

func (p *Heap) xGlobal(name string) int32 {
v := p.wazeroModule.ExportedGlobal(name).Get(context.Background())
return int32(uint32(v))
}

// 去读内存
func (p *Heap) ReadMemoryI32(offset int32) int32 {
v, _ := p.wazeroModule.Memory().ReadUint32Le(context.Background(), uint32(offset))
return int32(v)
}

// 读取空闲链表头
func (p *Heap) ReadL24Header() HeapBlock {
offset := p.Global__heap_base() + 8*0
return p.ReadBlock(offset)
}
func (p *Heap) ReadL32Header() HeapBlock {
offset := p.Global__heap_base() + 8*1
return p.ReadBlock(offset)
}
func (p *Heap) ReadL46Header() HeapBlock {
offset := p.Global__heap_base() + 8*2
return p.ReadBlock(offset)
}
func (p *Heap) ReadL80Header() HeapBlock {
offset := p.Global__heap_base() + 8*3
return p.ReadBlock(offset)
}
func (p *Heap) ReadL128Header() HeapBlock {
offset := p.Global__heap_base() + 8*4
return p.ReadBlock(offset)
}

// 读取 HeapBlock 数据
func (p *Heap) ReadBlock(offset int32) HeapBlock {
size := p.ReadMemoryI32(offset + 0)
next := p.ReadMemoryI32(offset + 4)
return HeapBlock{Size: size, Next: next}
}

// 初始化获取空闲链表
func (p *Heap) FreeList(size int32) HeapBlock {
func (p *Heap) ReadFreeListHeader(z int32) HeapBlock {
return HeapBlock{}
}

Expand Down
22 changes: 15 additions & 7 deletions internal/waroot/malloc/malloc.wat
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

(export "memory" (memory $memory))

(export "__stack_ptr" (global $__stack_ptr))
(export "__heap_base" (global $__heap_base))
(export "__heap_ptr" (global $__heap_ptr))
(export "__heap_top" (global $__heap_top))
(export "__heap_l128_freep" (global $__heap_l128_freep))
(export "__heap_lfixed_cap" (global $__heap_lfixed_cap))

(memory $memory {{.MemoryPages}} {{.MemoryPagesMax}})

;; 栈/静态数据/堆的内存布局
Expand Down Expand Up @@ -230,16 +237,10 @@
global.get $__heap_base
call $heap_assert_align8

;; $__heap_l128_freep = $__heap_base + 5*sizeof(heap_block_t)
;; $__heap_ptr = $__heap_base + 5*sizeof(heap_block_t)
global.get $__heap_base
i32.const 40 ;; 5*sizeof(heap_block_t)
i32.add
global.set $__heap_l128_freep

;; $__heap_ptr = $__heap_l128_freep + 8
global.get $__heap_l128_freep
i32.const 8
i32.add
global.set $__heap_ptr

;; $__heap_top = memory.size * page_size
Expand Down Expand Up @@ -293,6 +294,13 @@
i32.add
i64.const 0 ;; size+next
i64.store offset=0

;; $__heap_l128_freep = $__heap_base + 4*sizeof(heap_block_t)
;; 该字段改用 global 表示, 不占用内存空间
global.get $__heap_base
i32.const 32 ;; 4*sizeof(heap_block_t)
i32.add
global.set $__heap_l128_freep
)

;; func wa_malloc(size: i32) => i32
Expand Down
64 changes: 58 additions & 6 deletions internal/waroot/malloc/malloc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,64 @@ package malloc

import "testing"

func TestHeap(t *testing.T) {
func TestHeap_init(t *testing.T) {
h := NewHeap(nil)
got := h.Malloc(1)
defer h.Free(got)
expect := DefaultHeapBase + kFreeListHeadSize + kBlockHeadSize
if got != expect {
t.Fatalf("invalid ptr: expect = %d, got = %d", expect, got)

// 全局变量状态
tAssertEQ(t, h.Global__stack_ptr(), DefaultStackPtr)
tAssertEQ(t, h.Global__heap_base(), DefaultHeapBase)
tAssertEQ(t, h.Global__heap_ptr(), DefaultHeapBase+kFreeListHeadSize)
tAssertEQ(t, h.Global__heap_top(), DefaultMemoryPages*KPageBytes)
tAssertEQ(t, h.Global__heap_l128_freep(), h.Global__heap_ptr()-8)
tAssertEQ(t, h.Global__heap_lfixed_cap(), DefaultHeapLFixedCap)

// 空闲链表头状态
tAssertEQ(t, h.ReadL24Header(), HeapBlock{0, 0})
tAssertEQ(t, h.ReadL32Header(), HeapBlock{0, 0})
tAssertEQ(t, h.ReadL46Header(), HeapBlock{0, 0})
tAssertEQ(t, h.ReadL80Header(), HeapBlock{0, 0})
tAssertEQ(t, h.ReadL128Header(), HeapBlock{0, 0})
}

func TestHeap_fixedSize1(t *testing.T) {
h := NewHeap(nil)
got1 := h.Malloc(1)
expect1 := DefaultHeapBase + kFreeListHeadSize + kBlockHeadSize
tAssertEQ(t, got1, expect1)
h.Free(got1)

got2 := h.Malloc(1)
expect2 := expect1
tAssertEQ(t, got2, expect2)

got3 := h.Malloc(1)
_ = got3
//h.Free(got3) // TODO: 死循环
//if got := h.Malloc(1); got != got3 {
// t.Fatalf("invalid ptr: expect = %d, got = %d", got3, got3)
//}
}

func tAssert(tb testing.TB, ok bool) {
if !ok {
tb.Helper()
tb.Fatalf("tAssert failed")
}
}

func tAssertEQ(tb testing.TB, a, b interface{}) {
switch a.(type) {
case int32:
if a.(int32) != b.(int32) {
tb.Helper()
tb.Fatalf("tAssertEQ failed: %d != %d", a, b)
}
case HeapBlock:
if a.(HeapBlock) != b.(HeapBlock) {
tb.Helper()
tb.Fatalf("tAssertEQ failed: %v != %v", a, b)
}
default:
panic("unreachable")
}
}

0 comments on commit 570175e

Please sign in to comment.