神奇的PERL-深入篇-perl源码解析(2)_C/C++_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > C/C++ > 神奇的PERL-深入篇-perl源码解析(2)

神奇的PERL-深入篇-perl源码解析(2)

 2010/11/19 9:18:40  deepfuture  http://deepfuture.javaeye.com  我要评论(0)
  • 摘要:本神奇的Perl系列为刘兴(http://deepfuture.javaeye.com/)原创,未经笔者授权,任何人和机构不能转载1、1)Perl本身有三种主要的数据类型:①标量(scalar)②数组(array)③散列(hash)这三种类型在perlapi中对应有三种:①SV(ScalarVariables)②AV(ArrayVariables)③HV(HashVariables)2)指令标志IA64处理器I-tanium(安腾)X6464位的处理器.X3232位的处理器
  • 标签:PERL perl源码解析

本神奇的Perl系列为刘兴(http://deepfuture.javaeye.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,必须以下一个指令指针位置,返回给函数调用者

?

?

?

}

?

?

?


?

发表评论
用户名: 匿名