本本系列为刘兴(http://deepfuture.iteye.com/)原创,未经笔者授权,任何人和机构不能转载
1、
1)Perl本身有三种主要的数据类型:
①标量(scalar)
②数组(array)
③散列(hash)
这三种类型在perlapi中对应有三种:
①SV(Scalar Variables)
②AV(Array Variables)
③HV(Hash Variables)
2)指令标志
IA64处理器I-tanium(安腾)
X64 64位的处理器.
X32 32位的处理器.
i32 32位的操作系统
3)perlapi.h
#undef PL_OpPtr
#define PL_OpPtr (*Perl_IOpPtr_ptr(aTHX))
#undef PL_OpSlab
#define PL_OpSlab (*Perl_IOpSlab_ptr(aTHX))
2、分配perl片区内存
片区大小PERL_SLAB_SIZE*sizeof(I32*),PERL_SLAB_SIZE在READONLY调试模式,默认为4096,否则为2048
#ifdef PERL_DEBUG_READONLY_OPS
# define PERL_SLAB_SIZE 4096
# include <sys/mman.h>
#endif
#ifndef PERL_SLAB_SIZE
#define PERL_SLAB_SIZE 2048
#endif
void *
Perl_Slab_Alloc(pTHX_ size_t sz)
{
//传入的sz参数是指分配的片区大小(字节为单位)
dVAR;//ifdef PERL_GLOBAL_STRUCT,则完成 my_vars赋值
//my_vars赋值:struct perl_vars*my_vars= (struct perl_vars*)PERL_GET_VARS()
/*
PL_OpPtr指向指令集合池中的某条I32指令的地址PL_OpSlab
PL_OpSlab保存了具体该条I32指令地址
PL_OpPtr和PL_OpSlab都是指针,PL_OpSlab指向某条最终指令的地址
I32指令是一个结构变量,含有该指令的信息
当增加某条指令时,从指令集合池中分配一个指针大小的空间存放该条指令的指针PL_OpSlab
* To make incrementing use count easy PL_OpSlab is an I32 *
* To make inserting the link to slab PL_OpPtr is I32 **
* So compute size in units of sizeof(I32 *) as that is how Pl_OpPtr increments
* Add an overhead for pointer to slab and round up as a number of pointers
*/
//将函数参数sz改为I32指令数量,在函数参数基础上加了2条指令
sz = (sz + 2*sizeof(I32 *) -1)/sizeof(I32 *);
if ((PL_OpSpace -= sz) < 0) {//PL_OpSpace空间太小,分配新片区(即指令指针池),片区内仅存放指令指针
//如果PL_OpSpace空间不能容纳本次分配的片区,则分配新的片区
//PERL_SLAB_SIZE为新片区指令总数量
#ifdef PERL_DEBUG_READONLY_OPS//如果是调试模式
/* We need to allocate chunk by chunk so that we can control the VM
mapping */
//定义了只读调试,则将PERL_SLAB_SIZE*sizeof(I32*)的大小的片区映射到内存,地址返回给PL_OpPtr(I32 **类型)
PL_OpPtr = (I32**) mmap(0, PERL_SLAB_SIZE*sizeof(I32*), PROT_READ|PROT_WRITE,
MAP_ANON|MAP_PRIVATE, -1, 0);
//打印OP调试信息,其中包括片区大小和片区起始地址
DEBUG_m(PerlIO_printf(Perl_debug_log, "mapped %lu at %p\n",
(unsigned long) PERL_SLAB_SIZE*sizeof(I32*),
PL_OpPtr));
if(PL_OpPtr == MAP_FAILED) {
perror("mmap failed");
abort();
}
#else
如果不是调试模式,直接分配PERL_SLAB_SIZE*sizeof(I32*)大小空间
该空间容纳PERL_SLAB_SIZE 条指令(不是指令结构变量本身,而是指令结构变量的指针)
PL_OpPtr = (I32 **) PerlMemShared_calloc(PERL_SLAB_SIZE,sizeof(I32*));
//iperlsys.h找到PerlMemShared_calloc相关定义
#define PerlMemShared_calloc(num, size) \
(*PL_MemShared->pCalloc)(PL_MemShared, (num), (size))
#endif
if (!PL_OpPtr) {//PL_OpPtr分配错误,返回NULL
return NULL;
}
//接着处理分配的PERL_SLAB_SIZE*sizeof(I32*)大小空间
/* We reserve the 0'th I32 sized chunk as a use count */
//PL_OpSlab从PL_OpPtr获得指令地址
PL_OpSlab = (I32 *) PL_OpPtr;
/* Reduce size by the use count word, and by the size we need.
* Latter is to mimic the '-=' in the if() above
*/
//PL_OpSpace 为余下的空间,重新计算
PL_OpSpace = PERL_SLAB_SIZE - (sizeof(I32)+sizeof(I32 **)-1)/sizeof(I32 **) - sz;
/* Allocation pointer starts at the top.
Theory: because we build leaves before trunk allocating at end
means that at run time access is cache friendly upward
*/
//PL_OpPtr指向片区空间(即指令指针池)的未尾,因为空间容纳了PERL_SLAB_SIZE个I32指令结构地址(I32*)
PL_OpPtr += PERL_SLAB_SIZE;
//处理在只读调试的情况下,新增片区,需要放置相关片区地址在PL_slabs数组中(仅用于调试),该数组存放了所有曾经分配过的OP片区,注意不是PL_OpSlab
#ifdef PERL_DEBUG_READONLY_OPS
/* We remember this slab. */
/* This implementation isn't efficient, but it is simple. */
PL_slabs = (I32**) realloc(PL_slabs, sizeof(I32**) * (PL_slab_count + 1));
PL_slabs[PL_slab_count++] = PL_OpSlab;
DEBUG_m(PerlIO_printf(Perl_debug_log, "Allocate %p\n", PL_OpSlab));
#endif
}
assert( PL_OpSpace >= 0 );//确保PL_OpSpace还有空间容纳I32指令
//新分配空间或原有空间已经足够容纳,处理返回值(void *)(PL_OpPtr + 1)
/* Move the allocation pointer down */
PL_OpPtr -= sz;//分配片区空间的使用是从未尾开始向前推进,即从后向前使用空间,PL_OpPtr指向本次从片区空间中分配的指令集合所使用的空间的起始地址
assert( PL_OpPtr > (I32 **) PL_OpSlab );//确保本次分配的指令集合空间够用,
//没有超过片区的起始地址(I32 **) PL_OpSlab
//本次分配的空间起始地址放置片区空间首指令( I32*)PL_OpSlab
*PL_OpPtr = PL_OpSlab; /* Note which slab it belongs to */
//PL_OpSlab是(I32*)
(*PL_OpSlab)++; /* Increment use count of slab */
assert( PL_OpPtr+sz <= ((I32 **) PL_OpSlab + PERL_SLAB_SIZE) );
assert( *PL_OpSlab > 0 );
return (void *)(PL_OpPtr + 1);//因为*PL_OpPtr处放置了片区空间首指令PL_OpSlab,必须以下一个指令指针位置,返回给函数调用者
}
- 大小: 9.5 KB
- 大小: 11.7 KB
- 大小: 14.1 KB
- 大小: 15.6 KB
分享到:
相关推荐
### GNU编译器家族源码解析 #### 一、引言与背景介绍 GNU Compiler Collection (GCC) 是一套由自由软件基金会(Free Software Foundation, FSF)开发的编译器集合,它支持多种编程语言,如 C、C++、Objective-C、...
AMD K6-2 CPU 编号探密 AMD K6-2 CPU 编号探密是指 AMD 公司推出的 K6-2 系列 CPU 的编号系统,用于标识和区分不同型号的 K6-2 处理器。本文将深入探讨 AMD K6-2 CPU 编号的组成部分、编号规则、性能特点和实际应用...
任天堂游戏编程探密 任天堂主机由6502处理器和一个特制的图形处理器组成。 CPU是6502,而不是传言中的65C02(CMOS)。 PPU的显存是和CPU的内存是分离的,可以通过对特殊端口的读/写来操作。 卡带可能包含的...
探密电动汽车的无线充电技术
DDR探密.pdf
### MP3歌词显示探密——Delphi实现 #### 一、引言 随着数字音频技术的发展,MP3格式因其高质量的音质和较小的文件体积而受到广泛欢迎。对于喜欢边听音乐边看歌词的用户来说,能够实现在播放MP3的同时同步显示歌词...
入门级的百科全书,系统地介绍了常用的计算机词汇
**Ajax.Hacks探密书籍**是一本专注于Ajax技术的深入解析和实践指南,它揭示了Ajax(Asynchronous JavaScript and XML)技术的核心原理及其在Web开发中的广泛应用。Ajax是一种用于创建快速、动态网页的技术,通过在...
【幼儿园政治:其他教案-大鲨鱼探密】 在幼儿教育阶段,政治教案并不局限于传统的政治概念,而是更广泛地涵盖了社会认知、道德情感、生态环保等多方面内容。这篇《大鲨鱼探密》教案就是一个很好的例证,旨在通过...
GNURadio探密.pdf
在《任天堂游戏编程探密2.pdf》中,我们可以期待学习到以下几点: 1. **CPU架构与指令集**:书中可能会详细介绍6502或ARM7TDMI等任天堂游戏机CPU的架构,以及它们的指令集,包括数据处理、分支、跳转等指令的使用。...
本文将深入探讨“任天堂游戏编程探密”这一主题,解析相关知识点,旨在为那些对任天堂游戏开发感兴趣的程序员提供指导。 首先,我们要了解任天堂游戏机的基本架构。任天堂游戏平台如Switch、3DS等,都有其独特的...
2. 完善阶段:Intel公司完善了早期产品MCS-48系列,推出了具有代表性的MCS-51系列单片机,采用通用总线技术,形成了通用总线型单片机体系结构。 3. 转型阶段:随着测控系统要求的提高,MCS-51系列中的8051单片机...
《任天堂游戏编程探密》是一本专注于探讨任天堂游戏开发技术的专业书籍,它主要侧重于硬件层面的解析,为读者揭示了游戏开发背后的神秘世界。任天堂作为全球知名的电子游戏公司,其游戏平台如GBA(Game Boy Advance...
一汽大众工厂探密报告.doc
2. **JSON与XML**:Ajax最初与XML关联,但现在更常见的是使用JSON(JavaScript Object Notation),因为它更轻量、易于解析和生成。 3. **动态内容加载**:通过Ajax,可以动态地向页面添加或修改内容,如实时聊天、...