1 /*
2  * %CopyrightBegin%
3  *
4  * Copyright Ericsson AB 2000-2017. All Rights Reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * %CopyrightEnd%
19  */
20 
21 #if HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24 #include "sys.h"
25 #include "erl_vm.h"
26 #include "global.h"
27 #include "erl_map.h"
28 #include <stdlib.h>
29 #include <stdio.h>
30 
31 void
erts_set_literal_tag(Eterm * term,Eterm * hp_start,Eterm hsz)32 erts_set_literal_tag(Eterm *term, Eterm *hp_start, Eterm hsz)
33 {
34 #ifdef TAG_LITERAL_PTR
35     Eterm *hp_end, *hp;
36 
37     hp_end = hp_start + hsz;
38     hp = hp_start;
39 
40     while (hp < hp_end) {
41 	switch (primary_tag(*hp)) {
42 	case TAG_PRIMARY_BOXED:
43 	case TAG_PRIMARY_LIST:
44 	    *hp |= TAG_LITERAL_PTR;
45 	    break;
46 	case TAG_PRIMARY_HEADER:
47 	    if (header_is_thing(*hp)) {
48 		hp += thing_arityval(*hp);
49 	    }
50 	    break;
51 	default:
52 	    break;
53 	}
54 
55 	hp++;
56     }
57     if (is_boxed(*term) || is_list(*term))
58 	*term |= TAG_LITERAL_PTR;
59 #endif
60 }
61 
62 void
erts_term_init(void)63 erts_term_init(void)
64 {
65 #ifdef ERTS_ORDINARY_REF_MARKER
66     /* Ordinary and magic references of same size... */
67 
68     ErtsRefThing ref_thing;
69 
70     ERTS_CT_ASSERT(ERTS_ORDINARY_REF_MARKER == ~((Uint32)0));
71     ref_thing.m.header = ERTS_REF_THING_HEADER;
72     ref_thing.m.mb = (ErtsMagicBinary *) ~((UWord) 3);
73     ref_thing.m.next = (struct erl_off_heap_header *) ~((UWord) 3);
74     if (ref_thing.o.marker == ERTS_ORDINARY_REF_MARKER)
75         ERTS_INTERNAL_ERROR("Cannot differentiate between magic and ordinary references");
76 
77     ERTS_CT_ASSERT(offsetof(ErtsORefThing,marker) != 0);
78     ERTS_CT_ASSERT(sizeof(ErtsORefThing) == sizeof(ErtsMRefThing));
79 #  ifdef ERTS_MAGIC_REF_THING_HEADER
80 #    error Magic ref thing header should not have been defined...
81 #  endif
82 
83 #else
84     /* Ordinary and magic references of different sizes... */
85 
86 #  ifndef ERTS_MAGIC_REF_THING_HEADER
87 #    error Magic ref thing header should have been defined...
88 #  endif
89     ERTS_CT_ASSERT(sizeof(ErtsORefThing) != sizeof(ErtsMRefThing));
90 
91 #endif
92 
93     ERTS_CT_ASSERT(ERTS_REF_THING_SIZE*sizeof(Eterm) == sizeof(ErtsORefThing));
94     ERTS_CT_ASSERT(ERTS_MAGIC_REF_THING_SIZE*sizeof(Eterm) == sizeof(ErtsMRefThing));
95 
96 }
97 
98 /*
99  * XXX: define NUMBER_CODE() here when new representation is used
100  */
101 
102 #if ET_DEBUG
103 #define ET_DEFINE_CHECKED(FUNTY,FUN,ARGTY,PRECOND) \
104 FUNTY checked_##FUN(ARGTY x, const char *file, unsigned line) \
105 { \
106     ET_ASSERT(PRECOND(x),file,line); \
107     return _unchecked_##FUN(x); \
108 }
109 
110 ET_DEFINE_CHECKED(Eterm,make_boxed,const Eterm*,_is_taggable_pointer);
111 ET_DEFINE_CHECKED(int,is_boxed,Eterm,!is_header);
112 ET_DEFINE_CHECKED(Eterm*,boxed_val,Wterm,_boxed_precond);
113 ET_DEFINE_CHECKED(Eterm,make_list,const Eterm*,_is_taggable_pointer);
114 ET_DEFINE_CHECKED(int,is_not_list,Eterm,!is_header);
115 ET_DEFINE_CHECKED(Eterm*,list_val,Wterm,_list_precond);
116 ET_DEFINE_CHECKED(Uint,unsigned_val,Eterm,is_small);
117 ET_DEFINE_CHECKED(Sint,signed_val,Eterm,is_small);
118 ET_DEFINE_CHECKED(Uint,atom_val,Eterm,is_atom);
119 ET_DEFINE_CHECKED(Uint,header_arity,Eterm,is_header);
120 ET_DEFINE_CHECKED(Uint,arityval,Eterm,is_sane_arity_value);
121 ET_DEFINE_CHECKED(Uint,thing_arityval,Eterm,is_thing);
122 ET_DEFINE_CHECKED(Uint,thing_subtag,Eterm,is_thing);
123 ET_DEFINE_CHECKED(Eterm*,binary_val,Wterm,is_binary);
124 ET_DEFINE_CHECKED(Eterm*,fun_val,Wterm,is_fun);
125 ET_DEFINE_CHECKED(int,bignum_header_is_neg,Eterm,_is_bignum_header);
126 ET_DEFINE_CHECKED(Eterm,bignum_header_neg,Eterm,_is_bignum_header);
127 ET_DEFINE_CHECKED(Uint,bignum_header_arity,Eterm,_is_bignum_header);
128 ET_DEFINE_CHECKED(Eterm*,big_val,Wterm,is_big);
129 ET_DEFINE_CHECKED(Eterm*,float_val,Wterm,is_float);
130 ET_DEFINE_CHECKED(Eterm*,tuple_val,Wterm,is_tuple);
131 ET_DEFINE_CHECKED(struct erl_node_*,internal_pid_node,Eterm,is_internal_pid);
132 ET_DEFINE_CHECKED(struct erl_node_*,internal_port_node,Eterm,is_internal_port);
133 ET_DEFINE_CHECKED(Eterm*,internal_ref_val,Wterm,is_internal_ref);
134 ET_DEFINE_CHECKED(Uint32*,internal_magic_ref_numbers,Wterm,is_internal_magic_ref);
135 ET_DEFINE_CHECKED(Uint32*,internal_ordinary_ref_numbers,Wterm,is_internal_ordinary_ref);
136 ET_DEFINE_CHECKED(struct erl_node_*,internal_ref_node,Eterm,is_internal_ref);
137 ET_DEFINE_CHECKED(Eterm*,external_val,Wterm,is_external);
138 ET_DEFINE_CHECKED(Uint,external_data_words,Wterm,is_external);
139 ET_DEFINE_CHECKED(Uint,external_pid_data_words,Wterm,is_external_pid);
140 ET_DEFINE_CHECKED(Uint,external_pid_data,Wterm,is_external_pid);
141 ET_DEFINE_CHECKED(struct erl_node_*,external_pid_node,Wterm,is_external_pid);
142 ET_DEFINE_CHECKED(Uint,external_port_data_words,Wterm,is_external_port);
143 ET_DEFINE_CHECKED(Uint,external_port_data,Wterm,is_external_port);
144 ET_DEFINE_CHECKED(struct erl_node_*,external_port_node,Wterm,is_external_port);
145 ET_DEFINE_CHECKED(Uint,external_ref_data_words,Wterm,is_external_ref);
146 ET_DEFINE_CHECKED(Uint32*,external_ref_data,Wterm,is_external_ref);
147 ET_DEFINE_CHECKED(struct erl_node_*,external_ref_node,Eterm,is_external_ref);
148 ET_DEFINE_CHECKED(Eterm*,export_val,Wterm,is_export);
149 ET_DEFINE_CHECKED(Uint,external_thing_data_words,ExternalThing*,is_thing_ptr);
150 
151 ET_DEFINE_CHECKED(Eterm,make_cp,UWord *,_is_taggable_pointer);
152 ET_DEFINE_CHECKED(UWord *,cp_val,Eterm,is_CP);
153 ET_DEFINE_CHECKED(Uint,catch_val,Eterm,is_catch);
154 ET_DEFINE_CHECKED(Uint,loader_x_reg_index,Uint,_is_loader_x_reg);
155 ET_DEFINE_CHECKED(Uint,loader_y_reg_index,Uint,_is_loader_y_reg);
156 
157 #endif	/* ET_DEBUG */
158