⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 copy.c

📁 OTP是开放电信平台的简称
💻 C
📖 第 1 页 / 共 2 页
字号:
        (hp) = erts_inc_alloc(n);                                       \    } else {                                                            \        (hp) = IncAlloc((p),n,&dest,1);                                 \        if (ma_gc_flags & GC_CYCLE_START) {                             \            alloc_old = 1;                                              \            global_htop = global_heap;                                  \            (hp) = erts_inc_alloc(n);                                   \        }                                                               \    }                                                                   \    CLEARMEM((hp),(n));                                                 \    BM_SWAP_TIMER(system,copy);                                         \} while(0)#else /* no INCREMELNTAL */#define GlobalAlloc(p, need, hp)                                        \do {                                                                    \    Uint n = (need);                                                    \    total_need += n;                                                    \    if (total_need >= global_heap_sz)                                   \        erl_exit(ERTS_ABORT_EXIT, "Copying a message (%d words) larger than the nursery simply won't work...\n", total_need); \    if (global_hend - n < global_htop) {                                \        BM_SWAP_TIMER(copy,system);                                     \        erts_global_garbage_collect((p),total_need,NULL,0);             \        BM_SWAP_TIMER(system,copy);                                     \        total_need = 0;                                                 \        ma_src_top = 0;                                                 \        ma_dst_top = 0;                                                 \        ma_offset_top = 0;                                              \        goto copy_start;                                                \    }                                                                   \    (hp) = global_htop;                                                 \    global_htop += n;                                                   \    BM_ADD(words_copied,n);                                             \} while(0)#endif /* INCREMENTAL *//* Copy a message to the message area. */Eterm copy_struct_lazy(Process *from, Eterm orig, Uint offs){    Eterm obj;    Eterm dest;#ifdef INCREMENTAL    int alloc_old = 0;#else    int total_need = 0;#endif    VERBOSE(DEBUG_MESSAGES,            ("COPY START; %T is sending a message @ 0x%016x\n%T\n",             from->id, orig, orig));#ifndef INCREMENTAL copy_start:#endif    MA_STACK_PUSH(src,orig);    MA_STACK_PUSH(dst,&dest);    MA_STACK_PUSH(offset,offs);    while (ma_src_top > 0) {        obj = MA_STACK_POP(src);        /* copy_struct_lazy should never be called with something that         * do not need to be copied. Within the loop, nothing that do         * not need copying should be placed in the src-stack.         */        ASSERT(!NO_COPY(obj));        switch (primary_tag(obj)) {        case TAG_PRIMARY_LIST: {            Eterm *hp;            Eterm *objp;            GlobalAlloc(from,2,hp);            objp = list_val(obj);            MA_STACK_UPDATE(dst,MA_STACK_POP(offset),make_list(hp));            MA_STACK_POP(dst);            /* TODO: Byt ordningen nedan så att CDR pushas först. */            if (NO_COPY(*objp)) {                hp[0] = *objp;#ifdef INCREMENTAL                if (ptr_within(ptr_val(*objp),inc_fromspc,inc_fromend))                    INC_STORE(gray,hp,2);#endif            } else {                MA_STACK_PUSH(src,*objp);                MA_STACK_PUSH(dst,hp);                MA_STACK_PUSH(offset,0);            }            objp++;            if (NO_COPY(*objp)) {                hp[1] = *objp;#ifdef INCREMENTAL                if (ptr_within(ptr_val(*objp),inc_fromspc,inc_fromend))                    INC_STORE(gray,hp,2);#endif            }            else {                MA_STACK_PUSH(src,*objp);                MA_STACK_PUSH(dst,hp);                MA_STACK_PUSH(offset,1);            }            continue;        }        case TAG_PRIMARY_BOXED: {            Eterm *objp = boxed_val(obj);            switch (*objp & _TAG_HEADER_MASK) {            case ARITYVAL_SUBTAG: {                Uint ari = arityval(*objp);                Uint i;                Eterm *hp;                GlobalAlloc(from,ari + 1,hp);                /* A GC above might invalidate the value of objp */                objp = boxed_val(obj);                MA_STACK_UPDATE(dst,MA_STACK_POP(offset),make_tuple(hp));                MA_STACK_POP(dst);                *hp = *objp++;                for (i = 1; i <= ari; i++) {                    switch (primary_tag(*objp)) {                    case TAG_PRIMARY_LIST:                    case TAG_PRIMARY_BOXED:                        if (NO_COPY(*objp)) {                            hp[i] = *objp;#ifdef INCREMENTAL                            if (ptr_within(ptr_val(*objp),                                           inc_fromspc,inc_fromend))                                INC_STORE(gray,hp,BOXED_NEED(hp,*hp));#endif                            objp++;                        } else {                            MA_STACK_PUSH(src,*objp++);                            MA_STACK_PUSH(dst,hp);                            MA_STACK_PUSH(offset,i);                        }                        break;                    default:                        hp[i] = *objp++;                    }                }                continue;            }            case REFC_BINARY_SUBTAG: {                ProcBin *pb;                Uint i = thing_arityval(*objp) + 1;                Eterm *hp;                GlobalAlloc(from,i,hp);                /* A GC above might invalidate the value of objp */                objp = boxed_val(obj);                MA_STACK_UPDATE(dst,MA_STACK_POP(offset),make_binary(hp));                MA_STACK_POP(dst);                pb = (ProcBin*) hp;                while (i--) {                    *hp++ = *objp++;                }                erts_refc_inc(&pb->val->refc, 2);                pb->next = erts_global_offheap.mso;                erts_global_offheap.mso = pb;                erts_global_offheap.overhead += pb->size /                    BINARY_OVERHEAD_FACTOR / sizeof(Eterm);                continue;            }            case FUN_SUBTAG: {                ErlFunThing *funp = (ErlFunThing*) objp;                Uint i = thing_arityval(*objp) + 1;                Uint j = i + 1 + funp->num_free;                Uint k = i;                Eterm *hp, *hp_start;                GlobalAlloc(from,j,hp);                /* A GC above might invalidate the value of objp */                objp = boxed_val(obj);                hp_start = hp;                MA_STACK_UPDATE(dst,MA_STACK_POP(offset),make_fun(hp));                MA_STACK_POP(dst);                funp = (ErlFunThing*) hp;                while (i--) {                    *hp++ = *objp++;                }#ifndef HYBRID // FIND ME!                funp->next = erts_global_offheap.funs;                erts_global_offheap.funs = funp;                erts_refc_inc(&funp->fe->refc, 2);#endif                for (i = k; i < j; i++) {                    switch (primary_tag(*objp)) {                    case TAG_PRIMARY_LIST:                    case TAG_PRIMARY_BOXED:                        if (NO_COPY(*objp)) {#ifdef INCREMENTAL                            if (ptr_within(ptr_val(*objp),                                           inc_fromspc,inc_fromend))                                INC_STORE(gray,hp,BOXED_NEED(hp,*hp));#endif                            *hp++ = *objp++;                        } else {                            MA_STACK_PUSH(src,*objp++);                            MA_STACK_PUSH(dst,hp_start);                            MA_STACK_PUSH(offset,i);                            hp++;                        }                        break;                    default:                        *hp++ = *objp++;                    }                }                continue;            }            case EXTERNAL_PID_SUBTAG:            case EXTERNAL_PORT_SUBTAG:            case EXTERNAL_REF_SUBTAG: {                ExternalThing *etp;                Uint i =  thing_arityval(*objp) + 1;                Eterm *hp;                GlobalAlloc(from,i,hp);                /* A GC above might invalidate the value of objp */                objp = boxed_val(obj);                MA_STACK_UPDATE(dst,MA_STACK_POP(offset),make_external(hp));                MA_STACK_POP(dst);                etp = (ExternalThing*) hp;                while (i--)  {                    *hp++ = *objp++;                }                etp->next = erts_global_offheap.externals;                erts_global_offheap.externals = etp;		erts_refc_inc(&etp->node->refc, 2);                continue;            }            case SUB_BINARY_SUBTAG: {                ErlSubBin *sb = (ErlSubBin *) objp;		Eterm *hp;		Eterm res_binary;                Eterm real_bin = sb->orig;                Uint bit_offset = sb->bitoffs;		Uint bit_size = sb -> bitsize;		Uint sub_offset = sb->offs;                size_t size = sb->size;		Uint extra_bytes;		Uint real_size;		Uint sub_binary_heapneed;		if ((bit_size + bit_offset) > 8) {		    extra_bytes = 2;		    sub_binary_heapneed = ERL_SUB_BIN_SIZE;		}  		else if ((bit_size + bit_offset) > 0) {		    extra_bytes = 1;		    sub_binary_heapneed = ERL_SUB_BIN_SIZE;		}		else {		    extra_bytes = 0;		    sub_binary_heapneed = 0;		}				real_size = size+extra_bytes;                objp = binary_val(real_bin);                if (thing_subtag(*objp) == HEAP_BINARY_SUBTAG) {                    ErlHeapBin *from_bin;                    ErlHeapBin *to_bin;                    Uint i = heap_bin_size(real_size);                    GlobalAlloc(from,i+sub_binary_heapneed,hp);                    from_bin = (ErlHeapBin *) objp;                    to_bin = (ErlHeapBin *) hp;                    to_bin->thing_word = header_heap_bin(real_size);                    to_bin->size = real_size;                    sys_memcpy(to_bin->data, ((byte *)from_bin->data) +                               sub_offset, real_size);		    res_binary=make_binary(to_bin);		    hp += i;                } else {                    ProcBin *from_bin;                    ProcBin *to_bin;                                        ASSERT(thing_subtag(*objp) == REFC_BINARY_SUBTAG);		    from_bin = (ProcBin *) objp;		    erts_refc_inc(&from_bin->val->refc, 2);                    GlobalAlloc(from,PROC_BIN_SIZE+sub_binary_heapneed,hp);                    to_bin = (ProcBin *) hp;                    to_bin->thing_word = HEADER_PROC_BIN;                    to_bin->size = real_size;                    to_bin->val = from_bin->val;                    to_bin->bytes = from_bin->bytes + sub_offset;                    to_bin->next = erts_global_offheap.mso;                    erts_global_offheap.mso = to_bin;                    erts_global_offheap.overhead += to_bin->size /                        BINARY_OVERHEAD_FACTOR / sizeof(Eterm);		    res_binary=make_binary(to_bin);		    hp += PROC_BIN_SIZE;                }		if (extra_bytes != 0) {		      ErlSubBin* res;		      res = (ErlSubBin *) hp;		      res->thing_word = HEADER_SUB_BIN;		      res->size = size;		      res->bitsize = bit_size;		      res->bitoffs = bit_offset;		      res->offs = 0;		      res->orig = res_binary;		      res_binary = make_binary(hp);		    }		MA_STACK_UPDATE(dst,MA_STACK_POP(offset),res_binary);		MA_STACK_POP(dst);                continue;            }	    case BIN_MATCHSTATE_SUBTAG:		erl_exit(ERTS_ABORT_EXIT,			 "copy_struct_lazy: matchstate term not allowed");            default: {                Uint size = thing_arityval(*objp) + 1;                Eterm *hp;                GlobalAlloc(from,size,hp);                /* A GC above might invalidate the value of objp */                objp = boxed_val(obj);                MA_STACK_UPDATE(dst,MA_STACK_POP(offset),make_boxed(hp));                MA_STACK_POP(dst);                while (size--) {                    *hp++ = *objp++;                }                continue;            }            }            continue;        }        case TAG_PRIMARY_HEADER:        ASSERT((obj & _TAG_HEADER_MASK) == ARITYVAL_SUBTAG);        {            Eterm *objp = &obj;            Uint ari = arityval(obj);            Uint i;            Eterm *hp;            GlobalAlloc(from,ari + 1,hp);            MA_STACK_UPDATE(dst,MA_STACK_POP(offset),make_tuple(hp));            MA_STACK_POP(dst);            *hp = *objp++;            for (i = 1; i <= ari; i++) {                switch (primary_tag(*objp)) {                case TAG_PRIMARY_LIST:                case TAG_PRIMARY_BOXED:                    if (NO_COPY(*objp)) {#ifdef INCREMENTAL                        if (ptr_within(ptr_val(*objp),inc_fromspc,inc_fromend))                            INC_STORE(gray,hp,ari + 1);#endif                        hp[i] = *objp++;                    } else {                        MA_STACK_PUSH(src,*objp++);                        MA_STACK_PUSH(dst,hp);                        MA_STACK_PUSH(offset,i);                    }                    break;                default:                    hp[i] = *objp++;                }            }            continue;        }        default:            erl_exit(ERTS_ABORT_EXIT,		     "%s, line %d: Internal error in copy_struct_lazy: 0x%08x\n",                     __FILE__, __LINE__,obj);        }    }    VERBOSE(DEBUG_MESSAGES,            ("Copy allocated @ 0x%08lx:\n%T\n",             (unsigned long)ptr_val(dest),dest));    ma_gc_flags &= ~GC_CYCLE_START;    ASSERT(eq(orig, dest));    ASSERT(ma_src_top == 0);    ASSERT(ma_dst_top == 0);    ASSERT(ma_offset_top == 0);    return dest;}#undef NO_COPY#endif /* HYBRID *//* * Copy a term that is guaranteed to be contained in a single * heap block. The heap block is copied word by word, and any * pointers are offsetted to point correctly in the new location. * * Typically used to copy a term from an ets table. * * NOTE: Assumes that term is a tuple (ptr is an untagged tuple ptr). */Etermcopy_shallow(Eterm* ptr, Uint sz, Eterm** hpp, ErlOffHeap* off_heap){    Eterm* tp = ptr;    Eterm* hp = *hpp;    Sint offs = hp - tp;    while (sz--) {	Eterm val = *tp++;	switch (primary_tag(val)) {	case TAG_PRIMARY_IMMED1:	    *hp++ = val;	    break;	case TAG_PRIMARY_LIST:	case TAG_PRIMARY_BOXED:	    *hp++ = offset_ptr(val, offs);	    break;	case TAG_PRIMARY_HEADER:	    *hp++ = val;	    switch (val & _HEADER_SUBTAG_MASK) {	    case ARITYVAL_SUBTAG:		break;	    case REFC_BINARY_SUBTAG:		{		    ProcBin* pb = (ProcBin *) (hp-1);		    int tari = thing_arityval(val);		    sz -= tari;		    while (tari--) {			*hp++ = *tp++;		    }		    erts_refc_inc(&pb->val->refc, 2);		    pb->next = off_heap->mso;		    off_heap->mso = pb;		}		break;	    case FUN_SUBTAG:		{#ifndef HYBRID /* FIND ME! */		    ErlFunThing* funp = (ErlFunThing *) (hp-1);#endif		    int tari = thing_arityval(val);		    sz -= tari;		    while (tari--) {			*hp++ = *tp++;		    }#ifndef HYBRID /* FIND ME! */		    funp->next = off_heap->funs;		    off_heap->funs = funp;		    erts_refc_inc(&funp->fe->refc, 2);#endif		}		break;	    case EXTERNAL_PID_SUBTAG:	    case EXTERNAL_PORT_SUBTAG:	    case EXTERNAL_REF_SUBTAG:		{		    ExternalThing* etp = (ExternalThing *) (hp-1);		    int tari = thing_arityval(val);		    sz -= tari;		    while (tari--) {			*hp++ = *tp++;		    }		    etp->next = off_heap->externals;		    off_heap->externals = etp;		    erts_refc_inc(&etp->node->refc, 2);		}		break;	    default:		{		    int tari = header_arity(val);		    sz -= tari;		    while (tari--) {			*hp++ = *tp++;		    }		}		break;	    }	    break;	}    }    *hpp = hp;    return make_tuple(ptr + offs); }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -