js引擎SemiSpace怎么实现
发表于:2026-11-02 作者:千家信息网编辑
千家信息网最后更新 2026年11月02日,这篇文章主要讲解了"js引擎SemiSpace怎么实现",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"js引擎SemiSpace怎么实现"吧!1 Sem
千家信息网最后更新 2026年11月02日js引擎SemiSpace怎么实现
这篇文章主要讲解了"js引擎SemiSpace怎么实现",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"js引擎SemiSpace怎么实现"吧!
1 SemiSpace
SemiSpace是管理新生代内存的类。
// SemiSpace in young generation
//
// A semispace is a contiguous chunk of memory. The mark-compact collector
// uses the memory in the from space as a marking stack when tracing live
// objects.
class SemiSpace BASE_EMBEDDED {
public:
// Creates a space in the young generation. The constructor does not
// allocate memory from the OS. A SemiSpace is given a contiguous chunk of
// memory of size 'capacity' when set up, and does not grow or shrink
// otherwise. In the mark-compact collector, the memory region of the from
// space is used as the marking stack. It requires contiguous memory
// addresses.
SemiSpace(int initial_capacity, int maximum_capacity);
// Sets up the semispace using the given chunk.
bool Setup(Address start, int size);
// Tear down the space. Heap memory was not allocated by the space, so it
// is not deallocated here.
void TearDown();
// True if the space has been set up but not torn down.
bool HasBeenSetup() { return start_ != NULL; }
bool Double();
// Returns the start address of the space.
Address low() { return start_; }
// Returns one past the end address of the space.
Address high() { return low() + capacity_; }
// Age mark accessors.
Address age_mark() { return ag偏移_mark_; }
void set_age_mark(Address mark) { age_mark_ = mark; }
// True if the address is in the address range of this semispace (not
// necessarily below the allocation pointer).
// 判断地址a是否在该对象管理的内存中,&address_mask即让a减去size-1的大小。如果等于start说明在管理范围内
bool Contains(Address a) {
return (reinterpret_cast(a) & address_mask_)
== reinterpret_cast(start_);
}
// True if the object is a heap object in the address range of this
// semispace (not necessarily below the allocation pointer).
// 类似上面的逻辑,但是堆对象低位是标记,判断时候需要处理一下,加SetUp
bool Contains(Object* o) {
return (reinterpret_cast(o) & object_mask_) == object_expected_;
}
// The offset of an address from the begining of the space.
// 距离开始地址的p
int SpaceOffsetForAddress(Address addr) { return addr - low(); }
private:
// The current and maximum capacity of the space.
int capacity_;
int maximum_capacity_;
// The start address of the space.
Address start_;
// Used to govern object promotion during mark-compact collection.
Address age_mark_;
// Masks and comparison values to test for containment in this semispace.
// 见SetUp函数
uint32_t address_ma函数
uint32_t object_mask_;
uint32_t object_expected_;
public:
TRACK_MEMORY("SemiSpace")
};
下面是实现
SemiSpace::SemiSpace(int initial_capacity, int maximum_capacity)
: capacity_(initial_capacity), maximum_capacity_(maximum_capacity),
start_(NULL), age_mark_(NULL) {
}
// 设置管理的地址范围
bool SemiSpace::Setup(Address start, int size) {
ASSERT(size == maximum_capacity_);
// 判断地址的有效性
if (!MemoryAllocator::CommitBlock(start, capacity_)) return false;
// 管理地址空间的首地址
start_ = start;
// 低于有效范围的掩码,即保证相与后的值小于等于管理的地址范围
address_mask_ = ~(size - 1);
// 计算对象地址掩码,低位是标记位,判断的时候需要保留
object_mask_ = address_mask_ | kHeapObjectTag;
// 见contains函数,对象地址里低位是标记位,判断的时候需要带上
object_expected_ = reinterpret_cast(start) | kHeapObjectTag;
// gc相关
age_mark_ = start_;
return true;
}
ja
void SemiSpace::TearDown() {
start_ = NULL;
capacity_ = 0;
}
// 扩容
bool SemiSpace::Double() {
if (!MemoryAllocator::CommitBlock(high(), capacity_)) return false;
capacity_ *= 2;
return true;
}
SemiSpace他自己不申请内存。他是负责管理某块内存的,内存申请在其他地方处理。
2 NewSpace
NewSpace也是管理新生代内存的类。新生代内存分为两半,一个是from区,一个是to区。具体的作用在分析gc的时候再探讨。
// The young generation space.
//
// The new space consists of a contiguous pair of semispaces. It simply
// forwards most functions to the appropriate semispace.
class NewSpace : public Malloced {
public:
NewSpace(int initial_semispace_capacity, int maximum_semispace_capacity);
bool Setup(Address start, int size);
void TearDown();
// True if the space has been set up but not torn down.
bool HasBeenSetup() {
return to_space_->HasBeenSetup() && from_space_->HasBeenSetup();
}
// Flip the pair of spaces.
void Flip();
bool Double();
bool Contains(Address a) {
return (reinterpret_cast(a) & address_mask_)
== reinterpret_cast(start_);
}
bool Contains(Object* o) {
return (reinterpret_cast(o) & object_mask_) == object_expected_;
}
// Return the allocated bytes in the active semispace.
// to区已分配的内存大小
int Size() { return top() - bottom(); }
// Return the current capacity of a semispace.
int Capacity() { return capacity_; }
// Return the available bytes without growing in the active semispace.
// to区还有多少内存可用
int Available() { return Capacity() - Size(); }
// Return the maximum capacity of a semispace.
int MaximumCapacity() { return maximum_capacity_; }
// Return the address of the allocation pointer in the active semispace.
// 当前已经分配出去的内存的末地址
Address top() { return allocation_info_.top; }
// Return the address of the first object in thkeyoctive semispace.
// to_space的管理的内存的首地址
Address bottom() { return to_space_->low(); }
// Get the age mark of the inactive semispace.
Address age_mark() { return from_space_->age_mark(); }
// Set the age mark in the active semispace.
void set_age_mark(Address mark) { to_space_->set_age_mark(mark); }
// The start address of the space and a bit mask. Anding an address in the
// new space with the mask will result in the start address.
Address start() { return start_; }
uint32_t mask() { return address_mask_; }
// The allocation top and limit addresses.
// 当前已分配的内存的末地址
Address* allocation_top_address() { return &allocation_info_.top; }
// 最大能分配的内存末地址
Address* allocation_limit_address() { return &allocation_info_.limit; }
Object* AllocateRaw(int size_in_bytes) {
return AllocateRawInternal(size_in_bytes, &allocation_info_);
}
Object* MCAllocateRaw(int size_in_bytes) {
return AllocateRawInternal(size_in_bytes, &mc_forwarding_info_);
}
void ResetAllocationInfo();
void MCResetRelocationInfo();
void MCCommitRelocationInfo();
// Get the extent of the inactive semispace (for use as a marking stack).
Address FromSpaceLow() { return from_space_->low(); }
Address FromSpaceHigh() { return from_space_->high(); }
// Get the extent of the active semispace (to sweep newly copied objects
// during a scavenge collection).
Address ToSpaceLow() { return to_space_->low(); }
Address ToSpaceHigh() { return to_space_->high(); }
// Offsets from the beginning of the semispaces.
int ToSpaceOffsetForAddress(Address a) {
return to_space_->SpaceOffsetForAddress(a);
}
int FromSpaceOffsetForAddress(Address a) {
return from_space_->SpaceOffsetForAddress(a);
}
bool ToSpaceContains(Object* o) { return to_space_->Contains(o); }
bool FromSpaceContains(Object* o) { return from_space_->Contains(o); }
bool ToSpaceContains(Address a) { return to_space_->Contains(a); }
bool FromSpaceContains(Address a) { return from_space_->Contains(a); }
void RecordAllocation(HeapObject* obj);
void RecordPromotion(HeapObject* obj);
#endif
private:
// The current and maximum capacities of a semispace.
int capacity_;
int maximum_capacity_;
// The semispaces.
SemiSpace* to_space_;
SemiSpace* from_space_;
// Start address and bit mask for containment testing.
Address start_;
uint32_t address_mask_;
uint32_t object_mask_;
uint32_t object_expected_;
// Allocation pointer and limit for normal allocation and allocation during
// mark-compact collection.
AllocationInfo allocation_info_;
AllocationInfo mc_forwarding_info_;
// Implementation of AllocateRaw and MCAllocateRaw.
inline Object* AllocateRawInternal(int size_in_bytes,
AllocationInfo* alloc_info);
friend class SemiSpaceIterator;
public:
TRACK_MEMORY("NewSpace")
};
newSpace的很多功能但是靠semiSpace来实现的。他负责内存的具体分配。但不负责内存的申请。还有些是和gc相关的功能,后续再分析。
// 分为两个space
NewSpace::NewSpace(int initial_semispace_capacity,
int maximum_semispace_capacity) {
ASSERT(initial_semispace_capacity <= maximum_semispace_capacity);
ASSERT(IsPowerOf2(maximum_semispace_capacity));
maximum_capacity_ = maximum_semispace_capacity;
capacity_ = initial_semispace_capacity;
to_space_ = new SemiSpace(capacity_, maximum_capacity_);
from_space_ = new SemiSpace(capacity_, maximum_capacity_);
}
// 设置需要管理的地址空间,start是首地址,size是大小
bool NewSpace::Setup(Address start, int size) {
ASSERT(size == 2 * maximum_capacity_);
ASSERT(IsAddressAligned(start, size, 0));
// to区
if (to_space_ == NULL
|| !to_space_->Setup(start, maximum_capacity_)) {
return false;
}
// from区,和to区一人一半
if (from_space_ == NULL
|| !from_space_->Setup(start + maximum_capacity_, maximum_capacity_)) {
return false;
}
// 开始地址
start_ = start;
/*
address_mask的高位是地址的有效位,
size是只有一位为一,减一后一变成0,一右边
的全部0位变成1,然后取反,高位的0变成1,再加上size中本来的1,
即从左往右的1位地址有效位
*/
address_mask_ = ~(size - 1);
// 参考semiSpace的分析
object_mask_ = address_mask_ | kHeapObjectTag;
object_expected_ = reinterpret_cast(start) | kHeapObjectTag;
// 初始化管理的地址的信息
allocation_info_.top = to_space_->low();
allocation_info_.limit = to_space_->high();
mc_forwarding_info_.top = NULL;
mc_forwarding_info_.limit = NULL;
ASSERT_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_);
return true;
}
// 重置属性,不负责内存的释放
void NewSpace::TearDown() {
start_ = NULL;
capacity_ = 0;
allocation_info_.top = NULL;
allocation_info_.limit = NULL;
mc_forwarding_info_.top = NULL;
mc_forwarding_info_.limit = NULL;
if (to_space_ != NULL) {
to_space_->TearDown();
delete to_space_;
to_space_ = NULL;
}
if (from_space_ != NULL) {
from_space_->TearDown();
delete from_space_;
from_space_ = NULL;
}
}
// 翻转,在gc中调用
void NewSpace::Flip() {
SemiSpace* tmp = from_space_;
from_space_ = to_space_;
to_space_ = tmp;
}
// 扩容
bool NewSpace::Double() {
ASSERT(capacity_ <= maximum_capacity_ / 2);
// TODO(1240712): Failure to double the from space can result in
// semispaces of different sizes. In the event of that failure, the
// to space doubling should be rolled back before returning false.
if (!to_space_->Double() || !from_space_->Double()) return false;
capacity_ *= 2;
// 从新扩容的地址开始分配内存,即老内存的末端。
allocation_info_.limit = to_space_->high();
ASSERT_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_);
return true;
}
// 重置管理内存分配的指针
void NewSpace::ResetAllocationInfo() {
allocation_info_.top = to_space_->low();
allocation_info_.limit = to_space_->high();
ASSERT_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_);
}
void NewSpace::MCResetRelocationInfo() {
mc_forwarding_info_.top = from_space_->low();
mc_forwarding_info_.limit = from_space_->high();
ASSERT_SEMISPACE_ALLOCATION_INFO(mc_forwarding_info_, from_space_);
}
void NewSpace::MCCommitRelocationInfo() {
// Assumes that the spaces have been flipped so that mc_forwarding_info_ is
// valid allocation info for the to space.
allocation_info_.top = mc_forwarding_info_.top;
allocation_info_.limit = to_space_->high();
ASSERT_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_);
}
我们看到实现里没有很多具体的逻辑,只是对属性进行操作,或者把操作下发到semiSpace。下面看一下内存分配的函数。
// 分配内存
Object* NewSpace::AllocateRawInternal(int size_in_bytes,
AllocationInfo* alloc_info) {
Address new_top = alloc_info->top + size_in_bytes;
// 内存不够了
if (new_top > alloc_info->limit) {
return Failure::RetryAfterGC(size_in_bytes, NEW_SPACE);
}
// 地址+低一位的标记
Object* obj = HeapObject::FromAddress(alloc_info->top);
// 更新指针,指向下一块可分配的内存
alloc_info->top = new_top;
#ifdef DEBUG
SemiSpace* space =
(alloc_info == &allocation_info_) ? to_space_ : from_space_;
ASSERT(space->low() <= alloc_info->top
&& alloc_info->top <= space->high()
&& alloc_info->limit == space->high());
#endif
return obj;
}
}
内存管理,主要是通过开始指针、结束指针、指向当前可分配的内存的指针来进行管理。每次分配内存都会修改当前指针的值。
感谢各位的阅读,以上就是"js引擎SemiSpace怎么实现"的内容了,经过本文的学习后,相信大家对js引擎SemiSpace怎么实现这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是,小编将为大家推送更多相关知识点的文章,欢迎关注!
内存
地址
管理
分配
指针
引擎
有效
函数
对象
时候
标记
范围
低位
大小
新生
新生代
分析
学习
内容
功能
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
科技制造互联网公司
科技服务与互联网
期待互联网科技
唐信互联网科技
互联网科技排名
亿策互联网科技
科技互联网创业计划书
互联网养老 桔豆科技
厦门千工互联网科技有限公司
互联网保险科技创业
996高科技互联网公司
广东工业互联网大赛深圳学泰科技
黑云互联网科技有限公司
宇信科技在杭州互联网排第几
珠海东科互联网科技有限公司
江苏互联网智能科技产品出厂价
求路客互联网科技电话
广州三三互联网科技有限公司
高科技和互联网的现代国家
互联网 科技节活动 微视频大赛
奇士达互联网科技
福建科技产业互联网发展
互联网软件和科技
互联网科技革命什么开始
互联网与医疗科技
宜昌元轩互联网科技有限公司
搜狐科技互联网
半导体行业属于互联网高科技类吗
银川新华互联网科技学校原画
科技互联网公司两年变化