js引擎SemiSpace怎么实现
发表于:2025-01-31 作者:千家信息网编辑
千家信息网最后更新 2025年01月31日,这篇文章主要讲解了"js引擎SemiSpace怎么实现",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"js引擎SemiSpace怎么实现"吧!1 Sem
千家信息网最后更新 2025年01月31日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安全错误
数据库的锁怎样保障安全
河北企业软件开发制作
asp 删除数据库记录
数据库设计教学管理数据库
编写数据库目的
王牌战争社区服务器建造
江西质量软件开发服务推广
登陆税控盘显示连接服务器失败
国家网络安全宣传周工作协调会
idc回收服务器安全教程
服务器 mc 链接
镇江海航软件开发常见问题
查询数据库中数据表的位置
捷顺数据库处理异常
上市公司网络安全计划
软件开发年度述职ppt
金蝶eas数据库类型
hp服务器如何进入救援模式
有关网络安全主题视频
网络安全知识竞赛高中部
路云天网络安全研究院海淀
mysql查找每天的数据库
计算机网络技术学编程语言吗
租用云服务器
宝山区品牌网络技术服务代理商
2. 如何维护网络安全
网络技术培训师证书
计算机网络技术的专业去向
远程怎么查看服务器操作系统
序列构建数据库比对软件
数据库db的范围