1 /*
2  *  Heap object representation.
3  *
4  *  Heap objects are used for Ecmascript objects, arrays, and functions,
5  *  but also for internal control like declarative and object environment
6  *  records.  Compiled functions, native functions, and threads are also
7  *  objects but with an extended C struct.
8  *
9  *  Objects provide the required Ecmascript semantics and exotic behaviors
10  *  especially for property access.
11  *
12  *  Properties are stored in three conceptual parts:
13  *
14  *    1. A linear 'entry part' contains ordered key-value-attributes triples
15  *       and is the main method of string properties.
16  *
17  *    2. An optional linear 'array part' is used for array objects to store a
18  *       (dense) range of [0,N[ array indexed entries with default attributes
19  *       (writable, enumerable, configurable).  If the array part would become
20  *       sparse or non-default attributes are required, the array part is
21  *       abandoned and moved to the 'entry part'.
22  *
23  *    3. An optional 'hash part' is used to optimize lookups of the entry
24  *       part; it is used only for objects with sufficiently many properties
25  *       and can be abandoned without loss of information.
26  *
27  *  These three conceptual parts are stored in a single memory allocated area.
28  *  This minimizes memory allocation overhead but also means that all three
29  *  parts are resized together, and makes property access a bit complicated.
30  */
31 
32 #ifndef DUK_HOBJECT_H_INCLUDED
33 #define DUK_HOBJECT_H_INCLUDED
34 
35 /* Object flag.  There are currently 26 flag bits available.  Make sure
36  * this stays in sync with debugger object inspection code.
37  */
38 #define DUK_HOBJECT_FLAG_EXTENSIBLE            DUK_HEAPHDR_USER_FLAG(0)   /* object is extensible */
39 #define DUK_HOBJECT_FLAG_CONSTRUCTABLE         DUK_HEAPHDR_USER_FLAG(1)   /* object is constructable */
40 #define DUK_HOBJECT_FLAG_BOUND                 DUK_HEAPHDR_USER_FLAG(2)   /* object established using Function.prototype.bind() */
41 #define DUK_HOBJECT_FLAG_COMPILEDFUNCTION      DUK_HEAPHDR_USER_FLAG(4)   /* object is a compiled function (duk_hcompiledfunction) */
42 #define DUK_HOBJECT_FLAG_NATIVEFUNCTION        DUK_HEAPHDR_USER_FLAG(5)   /* object is a native function (duk_hnativefunction) */
43 #define DUK_HOBJECT_FLAG_BUFFEROBJECT          DUK_HEAPHDR_USER_FLAG(6)   /* object is a buffer object (duk_hbufferobject) (always exotic) */
44 #define DUK_HOBJECT_FLAG_THREAD                DUK_HEAPHDR_USER_FLAG(7)   /* object is a thread (duk_hthread) */
45 #define DUK_HOBJECT_FLAG_ARRAY_PART            DUK_HEAPHDR_USER_FLAG(8)   /* object has an array part (a_size may still be 0) */
46 #define DUK_HOBJECT_FLAG_STRICT                DUK_HEAPHDR_USER_FLAG(9)   /* function: function object is strict */
47 #define DUK_HOBJECT_FLAG_NOTAIL                DUK_HEAPHDR_USER_FLAG(10)  /* function: function must not be tail called */
48 #define DUK_HOBJECT_FLAG_NEWENV                DUK_HEAPHDR_USER_FLAG(11)  /* function: create new environment when called (see duk_hcompiledfunction) */
49 #define DUK_HOBJECT_FLAG_NAMEBINDING           DUK_HEAPHDR_USER_FLAG(12)  /* function: create binding for func name (function templates only, used for named function expressions) */
50 #define DUK_HOBJECT_FLAG_CREATEARGS            DUK_HEAPHDR_USER_FLAG(13)  /* function: create an arguments object on function call */
51 #define DUK_HOBJECT_FLAG_ENVRECCLOSED          DUK_HEAPHDR_USER_FLAG(14)  /* envrec: (declarative) record is closed */
52 #define DUK_HOBJECT_FLAG_EXOTIC_ARRAY          DUK_HEAPHDR_USER_FLAG(15)  /* 'Array' object, array length and index exotic behavior */
53 #define DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ      DUK_HEAPHDR_USER_FLAG(16)  /* 'String' object, array index exotic behavior */
54 #define DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS      DUK_HEAPHDR_USER_FLAG(17)  /* 'Arguments' object and has arguments exotic behavior (non-strict callee) */
55 #define DUK_HOBJECT_FLAG_EXOTIC_DUKFUNC        DUK_HEAPHDR_USER_FLAG(18)  /* Duktape/C (nativefunction) object, exotic 'length' */
56 #define DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ       DUK_HEAPHDR_USER_FLAG(19)  /* 'Proxy' object */
57 
58 #define DUK_HOBJECT_FLAG_CLASS_BASE            DUK_HEAPHDR_USER_FLAG_NUMBER(20)
59 #define DUK_HOBJECT_FLAG_CLASS_BITS            5
60 
61 #define DUK_HOBJECT_GET_CLASS_NUMBER(h)        \
62 	DUK_HEAPHDR_GET_FLAG_RANGE(&(h)->hdr, DUK_HOBJECT_FLAG_CLASS_BASE, DUK_HOBJECT_FLAG_CLASS_BITS)
63 #define DUK_HOBJECT_SET_CLASS_NUMBER(h,v)      \
64 	DUK_HEAPHDR_SET_FLAG_RANGE(&(h)->hdr, DUK_HOBJECT_FLAG_CLASS_BASE, DUK_HOBJECT_FLAG_CLASS_BITS, (v))
65 
66 #define DUK_HOBJECT_GET_CLASS_MASK(h)          \
67 	(1UL << DUK_HEAPHDR_GET_FLAG_RANGE(&(h)->hdr, DUK_HOBJECT_FLAG_CLASS_BASE, DUK_HOBJECT_FLAG_CLASS_BITS))
68 
69 /* Macro for creating flag initializer from a class number.
70  * Unsigned type cast is needed to avoid warnings about coercing
71  * a signed integer to an unsigned one; the largest class values
72  * have the highest bit (bit 31) set which causes this.
73  */
74 #define DUK_HOBJECT_CLASS_AS_FLAGS(v)          (((duk_uint_t) (v)) << DUK_HOBJECT_FLAG_CLASS_BASE)
75 
76 /* E5 Section 8.6.2 + custom classes */
77 #define DUK_HOBJECT_CLASS_UNUSED               0
78 #define DUK_HOBJECT_CLASS_ARGUMENTS            1
79 #define DUK_HOBJECT_CLASS_ARRAY                2
80 #define DUK_HOBJECT_CLASS_BOOLEAN              3
81 #define DUK_HOBJECT_CLASS_DATE                 4
82 #define DUK_HOBJECT_CLASS_ERROR                5
83 #define DUK_HOBJECT_CLASS_FUNCTION             6
84 #define DUK_HOBJECT_CLASS_JSON                 7
85 #define DUK_HOBJECT_CLASS_MATH                 8
86 #define DUK_HOBJECT_CLASS_NUMBER               9
87 #define DUK_HOBJECT_CLASS_OBJECT               10
88 #define DUK_HOBJECT_CLASS_REGEXP               11
89 #define DUK_HOBJECT_CLASS_STRING               12
90 #define DUK_HOBJECT_CLASS_GLOBAL               13
91 #define DUK_HOBJECT_CLASS_OBJENV               14  /* custom */
92 #define DUK_HOBJECT_CLASS_DECENV               15  /* custom */
93 #define DUK_HOBJECT_CLASS_BUFFER               16  /* custom; implies DUK_HOBJECT_IS_BUFFEROBJECT */
94 #define DUK_HOBJECT_CLASS_POINTER              17  /* custom */
95 #define DUK_HOBJECT_CLASS_THREAD               18  /* custom; implies DUK_HOBJECT_IS_THREAD */
96 #define DUK_HOBJECT_CLASS_ARRAYBUFFER          19  /* implies DUK_HOBJECT_IS_BUFFEROBJECT */
97 #define DUK_HOBJECT_CLASS_DATAVIEW             20
98 #define DUK_HOBJECT_CLASS_INT8ARRAY            21
99 #define DUK_HOBJECT_CLASS_UINT8ARRAY           22
100 #define DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY    23
101 #define DUK_HOBJECT_CLASS_INT16ARRAY           24
102 #define DUK_HOBJECT_CLASS_UINT16ARRAY          25
103 #define DUK_HOBJECT_CLASS_INT32ARRAY           26
104 #define DUK_HOBJECT_CLASS_UINT32ARRAY          27
105 #define DUK_HOBJECT_CLASS_FLOAT32ARRAY         28
106 #define DUK_HOBJECT_CLASS_FLOAT64ARRAY         29
107 #define DUK_HOBJECT_CLASS_MAX                  29
108 
109 /* class masks */
110 #define DUK_HOBJECT_CMASK_ALL                  ((1UL << (DUK_HOBJECT_CLASS_MAX + 1)) - 1UL)
111 #define DUK_HOBJECT_CMASK_UNUSED               (1UL << DUK_HOBJECT_CLASS_UNUSED)
112 #define DUK_HOBJECT_CMASK_ARGUMENTS            (1UL << DUK_HOBJECT_CLASS_ARGUMENTS)
113 #define DUK_HOBJECT_CMASK_ARRAY                (1UL << DUK_HOBJECT_CLASS_ARRAY)
114 #define DUK_HOBJECT_CMASK_BOOLEAN              (1UL << DUK_HOBJECT_CLASS_BOOLEAN)
115 #define DUK_HOBJECT_CMASK_DATE                 (1UL << DUK_HOBJECT_CLASS_DATE)
116 #define DUK_HOBJECT_CMASK_ERROR                (1UL << DUK_HOBJECT_CLASS_ERROR)
117 #define DUK_HOBJECT_CMASK_FUNCTION             (1UL << DUK_HOBJECT_CLASS_FUNCTION)
118 #define DUK_HOBJECT_CMASK_JSON                 (1UL << DUK_HOBJECT_CLASS_JSON)
119 #define DUK_HOBJECT_CMASK_MATH                 (1UL << DUK_HOBJECT_CLASS_MATH)
120 #define DUK_HOBJECT_CMASK_NUMBER               (1UL << DUK_HOBJECT_CLASS_NUMBER)
121 #define DUK_HOBJECT_CMASK_OBJECT               (1UL << DUK_HOBJECT_CLASS_OBJECT)
122 #define DUK_HOBJECT_CMASK_REGEXP               (1UL << DUK_HOBJECT_CLASS_REGEXP)
123 #define DUK_HOBJECT_CMASK_STRING               (1UL << DUK_HOBJECT_CLASS_STRING)
124 #define DUK_HOBJECT_CMASK_GLOBAL               (1UL << DUK_HOBJECT_CLASS_GLOBAL)
125 #define DUK_HOBJECT_CMASK_OBJENV               (1UL << DUK_HOBJECT_CLASS_OBJENV)
126 #define DUK_HOBJECT_CMASK_DECENV               (1UL << DUK_HOBJECT_CLASS_DECENV)
127 #define DUK_HOBJECT_CMASK_BUFFER               (1UL << DUK_HOBJECT_CLASS_BUFFER)
128 #define DUK_HOBJECT_CMASK_POINTER              (1UL << DUK_HOBJECT_CLASS_POINTER)
129 #define DUK_HOBJECT_CMASK_THREAD               (1UL << DUK_HOBJECT_CLASS_THREAD)
130 #define DUK_HOBJECT_CMASK_ARRAYBUFFER          (1UL << DUK_HOBJECT_CLASS_ARRAYBUFFER)
131 #define DUK_HOBJECT_CMASK_DATAVIEW             (1UL << DUK_HOBJECT_CLASS_DATAVIEW)
132 #define DUK_HOBJECT_CMASK_INT8ARRAY            (1UL << DUK_HOBJECT_CLASS_INT8ARRAY)
133 #define DUK_HOBJECT_CMASK_UINT8ARRAY           (1UL << DUK_HOBJECT_CLASS_UINT8ARRAY)
134 #define DUK_HOBJECT_CMASK_UINT8CLAMPEDARRAY    (1UL << DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY)
135 #define DUK_HOBJECT_CMASK_INT16ARRAY           (1UL << DUK_HOBJECT_CLASS_INT16ARRAY)
136 #define DUK_HOBJECT_CMASK_UINT16ARRAY          (1UL << DUK_HOBJECT_CLASS_UINT16ARRAY)
137 #define DUK_HOBJECT_CMASK_INT32ARRAY           (1UL << DUK_HOBJECT_CLASS_INT32ARRAY)
138 #define DUK_HOBJECT_CMASK_UINT32ARRAY          (1UL << DUK_HOBJECT_CLASS_UINT32ARRAY)
139 #define DUK_HOBJECT_CMASK_FLOAT32ARRAY         (1UL << DUK_HOBJECT_CLASS_FLOAT32ARRAY)
140 #define DUK_HOBJECT_CMASK_FLOAT64ARRAY         (1UL << DUK_HOBJECT_CLASS_FLOAT64ARRAY)
141 
142 #define DUK_HOBJECT_CMASK_ALL_BUFFEROBJECTS \
143 	(DUK_HOBJECT_CMASK_BUFFER | \
144 	 DUK_HOBJECT_CMASK_ARRAYBUFFER | \
145 	 DUK_HOBJECT_CMASK_DATAVIEW | \
146 	 DUK_HOBJECT_CMASK_INT8ARRAY | \
147 	 DUK_HOBJECT_CMASK_UINT8ARRAY | \
148 	 DUK_HOBJECT_CMASK_UINT8CLAMPEDARRAY | \
149 	 DUK_HOBJECT_CMASK_INT16ARRAY | \
150 	 DUK_HOBJECT_CMASK_UINT16ARRAY | \
151 	 DUK_HOBJECT_CMASK_INT32ARRAY | \
152 	 DUK_HOBJECT_CMASK_UINT32ARRAY | \
153 	 DUK_HOBJECT_CMASK_FLOAT32ARRAY | \
154 	 DUK_HOBJECT_CMASK_FLOAT64ARRAY)
155 
156 #define DUK_HOBJECT_IS_OBJENV(h)               (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_OBJENV)
157 #define DUK_HOBJECT_IS_DECENV(h)               (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_DECENV)
158 #define DUK_HOBJECT_IS_ENV(h)                  (DUK_HOBJECT_IS_OBJENV((h)) || DUK_HOBJECT_IS_DECENV((h)))
159 #define DUK_HOBJECT_IS_ARRAY(h)                (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_ARRAY)
160 #define DUK_HOBJECT_IS_COMPILEDFUNCTION(h)     DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPILEDFUNCTION)
161 #define DUK_HOBJECT_IS_NATIVEFUNCTION(h)       DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATIVEFUNCTION)
162 #define DUK_HOBJECT_IS_BUFFEROBJECT(h)         DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFFEROBJECT)
163 #define DUK_HOBJECT_IS_THREAD(h)               DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_THREAD)
164 
165 #define DUK_HOBJECT_IS_NONBOUND_FUNCTION(h)    DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, \
166                                                         DUK_HOBJECT_FLAG_COMPILEDFUNCTION | \
167                                                         DUK_HOBJECT_FLAG_NATIVEFUNCTION)
168 
169 #define DUK_HOBJECT_IS_FUNCTION(h)             DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, \
170                                                         DUK_HOBJECT_FLAG_BOUND | \
171                                                         DUK_HOBJECT_FLAG_COMPILEDFUNCTION | \
172                                                         DUK_HOBJECT_FLAG_NATIVEFUNCTION)
173 
174 #define DUK_HOBJECT_IS_CALLABLE(h)             DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, \
175                                                         DUK_HOBJECT_FLAG_BOUND | \
176                                                         DUK_HOBJECT_FLAG_COMPILEDFUNCTION | \
177                                                         DUK_HOBJECT_FLAG_NATIVEFUNCTION)
178 
179 /* object has any exotic behavior(s) */
180 #define DUK_HOBJECT_EXOTIC_BEHAVIOR_FLAGS      (DUK_HOBJECT_FLAG_EXOTIC_ARRAY | \
181                                                 DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS | \
182                                                 DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ | \
183                                                 DUK_HOBJECT_FLAG_EXOTIC_DUKFUNC | \
184                                                 DUK_HOBJECT_FLAG_BUFFEROBJECT | \
185                                                 DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
186 
187 #define DUK_HOBJECT_HAS_EXOTIC_BEHAVIOR(h)     DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_EXOTIC_BEHAVIOR_FLAGS)
188 
189 #define DUK_HOBJECT_HAS_EXTENSIBLE(h)          DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXTENSIBLE)
190 #define DUK_HOBJECT_HAS_CONSTRUCTABLE(h)       DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CONSTRUCTABLE)
191 #define DUK_HOBJECT_HAS_BOUND(h)               DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUND)
192 #define DUK_HOBJECT_HAS_COMPILEDFUNCTION(h)    DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPILEDFUNCTION)
193 #define DUK_HOBJECT_HAS_NATIVEFUNCTION(h)      DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATIVEFUNCTION)
194 #define DUK_HOBJECT_HAS_BUFFEROBJECT(h)        DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFFEROBJECT)
195 #define DUK_HOBJECT_HAS_THREAD(h)              DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_THREAD)
196 #define DUK_HOBJECT_HAS_ARRAY_PART(h)          DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ARRAY_PART)
197 #define DUK_HOBJECT_HAS_STRICT(h)              DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_STRICT)
198 #define DUK_HOBJECT_HAS_NOTAIL(h)              DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NOTAIL)
199 #define DUK_HOBJECT_HAS_NEWENV(h)              DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NEWENV)
200 #define DUK_HOBJECT_HAS_NAMEBINDING(h)         DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NAMEBINDING)
201 #define DUK_HOBJECT_HAS_CREATEARGS(h)          DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CREATEARGS)
202 #define DUK_HOBJECT_HAS_ENVRECCLOSED(h)        DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ENVRECCLOSED)
203 #define DUK_HOBJECT_HAS_EXOTIC_ARRAY(h)        DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARRAY)
204 #define DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(h)    DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ)
205 #define DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(h)    DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS)
206 #define DUK_HOBJECT_HAS_EXOTIC_DUKFUNC(h)      DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_DUKFUNC)
207 #define DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(h)     DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
208 
209 #define DUK_HOBJECT_SET_EXTENSIBLE(h)          DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXTENSIBLE)
210 #define DUK_HOBJECT_SET_CONSTRUCTABLE(h)       DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CONSTRUCTABLE)
211 #define DUK_HOBJECT_SET_BOUND(h)               DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUND)
212 #define DUK_HOBJECT_SET_COMPILEDFUNCTION(h)    DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPILEDFUNCTION)
213 #define DUK_HOBJECT_SET_NATIVEFUNCTION(h)      DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATIVEFUNCTION)
214 #define DUK_HOBJECT_SET_BUFFEROBJECT(h)        DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFFEROBJECT)
215 #define DUK_HOBJECT_SET_THREAD(h)              DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_THREAD)
216 #define DUK_HOBJECT_SET_ARRAY_PART(h)          DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ARRAY_PART)
217 #define DUK_HOBJECT_SET_STRICT(h)              DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_STRICT)
218 #define DUK_HOBJECT_SET_NOTAIL(h)              DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NOTAIL)
219 #define DUK_HOBJECT_SET_NEWENV(h)              DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NEWENV)
220 #define DUK_HOBJECT_SET_NAMEBINDING(h)         DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NAMEBINDING)
221 #define DUK_HOBJECT_SET_CREATEARGS(h)          DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CREATEARGS)
222 #define DUK_HOBJECT_SET_ENVRECCLOSED(h)        DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ENVRECCLOSED)
223 #define DUK_HOBJECT_SET_EXOTIC_ARRAY(h)        DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARRAY)
224 #define DUK_HOBJECT_SET_EXOTIC_STRINGOBJ(h)    DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ)
225 #define DUK_HOBJECT_SET_EXOTIC_ARGUMENTS(h)    DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS)
226 #define DUK_HOBJECT_SET_EXOTIC_DUKFUNC(h)      DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_DUKFUNC)
227 #define DUK_HOBJECT_SET_EXOTIC_PROXYOBJ(h)     DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
228 
229 #define DUK_HOBJECT_CLEAR_EXTENSIBLE(h)        DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXTENSIBLE)
230 #define DUK_HOBJECT_CLEAR_CONSTRUCTABLE(h)     DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CONSTRUCTABLE)
231 #define DUK_HOBJECT_CLEAR_BOUND(h)             DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUND)
232 #define DUK_HOBJECT_CLEAR_COMPILEDFUNCTION(h)  DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPILEDFUNCTION)
233 #define DUK_HOBJECT_CLEAR_NATIVEFUNCTION(h)    DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATIVEFUNCTION)
234 #define DUK_HOBJECT_CLEAR_BUFFEROBJECT(h)      DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFFEROBJECT)
235 #define DUK_HOBJECT_CLEAR_THREAD(h)            DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_THREAD)
236 #define DUK_HOBJECT_CLEAR_ARRAY_PART(h)        DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ARRAY_PART)
237 #define DUK_HOBJECT_CLEAR_STRICT(h)            DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_STRICT)
238 #define DUK_HOBJECT_CLEAR_NOTAIL(h)            DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NOTAIL)
239 #define DUK_HOBJECT_CLEAR_NEWENV(h)            DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NEWENV)
240 #define DUK_HOBJECT_CLEAR_NAMEBINDING(h)       DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NAMEBINDING)
241 #define DUK_HOBJECT_CLEAR_CREATEARGS(h)        DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CREATEARGS)
242 #define DUK_HOBJECT_CLEAR_ENVRECCLOSED(h)      DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ENVRECCLOSED)
243 #define DUK_HOBJECT_CLEAR_EXOTIC_ARRAY(h)      DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARRAY)
244 #define DUK_HOBJECT_CLEAR_EXOTIC_STRINGOBJ(h)  DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ)
245 #define DUK_HOBJECT_CLEAR_EXOTIC_ARGUMENTS(h)  DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS)
246 #define DUK_HOBJECT_CLEAR_EXOTIC_DUKFUNC(h)    DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_DUKFUNC)
247 #define DUK_HOBJECT_CLEAR_EXOTIC_PROXYOBJ(h)   DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
248 
249 /* flags used for property attributes in duk_propdesc and packed flags */
250 #define DUK_PROPDESC_FLAG_WRITABLE              (1 << 0)    /* E5 Section 8.6.1 */
251 #define DUK_PROPDESC_FLAG_ENUMERABLE            (1 << 1)    /* E5 Section 8.6.1 */
252 #define DUK_PROPDESC_FLAG_CONFIGURABLE          (1 << 2)    /* E5 Section 8.6.1 */
253 #define DUK_PROPDESC_FLAG_ACCESSOR              (1 << 3)    /* accessor */
254 #define DUK_PROPDESC_FLAG_VIRTUAL               (1 << 4)    /* property is virtual: used in duk_propdesc, never stored
255                                                              * (used by e.g. buffer virtual properties)
256                                                              */
257 #define DUK_PROPDESC_FLAGS_MASK                 (DUK_PROPDESC_FLAG_WRITABLE | \
258                                                  DUK_PROPDESC_FLAG_ENUMERABLE | \
259                                                  DUK_PROPDESC_FLAG_CONFIGURABLE | \
260                                                  DUK_PROPDESC_FLAG_ACCESSOR)
261 
262 /* additional flags which are passed in the same flags argument as property
263  * flags but are not stored in object properties.
264  */
265 #define DUK_PROPDESC_FLAG_NO_OVERWRITE          (1 << 4)    /* internal define property: skip write silently if exists */
266 
267 /* convenience */
268 #define DUK_PROPDESC_FLAGS_NONE                 0
269 #define DUK_PROPDESC_FLAGS_W                    (DUK_PROPDESC_FLAG_WRITABLE)
270 #define DUK_PROPDESC_FLAGS_E                    (DUK_PROPDESC_FLAG_ENUMERABLE)
271 #define DUK_PROPDESC_FLAGS_C                    (DUK_PROPDESC_FLAG_CONFIGURABLE)
272 #define DUK_PROPDESC_FLAGS_WE                   (DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_ENUMERABLE)
273 #define DUK_PROPDESC_FLAGS_WC                   (DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_CONFIGURABLE)
274 #define DUK_PROPDESC_FLAGS_EC                   (DUK_PROPDESC_FLAG_ENUMERABLE | DUK_PROPDESC_FLAG_CONFIGURABLE)
275 #define DUK_PROPDESC_FLAGS_WEC                  (DUK_PROPDESC_FLAG_WRITABLE | \
276                                                  DUK_PROPDESC_FLAG_ENUMERABLE | \
277                                                  DUK_PROPDESC_FLAG_CONFIGURABLE)
278 
279 /* flags for duk_hobject_get_own_propdesc() and variants */
280 #define DUK_GETDESC_FLAG_PUSH_VALUE          (1 << 0)  /* push value to stack */
281 #define DUK_GETDESC_FLAG_IGNORE_PROTOLOOP    (1 << 1)  /* don't throw for prototype loop */
282 
283 /*
284  *  Macro for object validity check
285  *
286  *  Assert for currently guaranteed relations between flags, for instance.
287  */
288 
289 #define DUK_ASSERT_HOBJECT_VALID(h) do { \
290 		DUK_ASSERT((h) != NULL); \
291 		DUK_ASSERT(!DUK_HOBJECT_IS_CALLABLE((h)) || \
292 		           DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_FUNCTION); \
293 		DUK_ASSERT(!DUK_HOBJECT_IS_BUFFEROBJECT((h)) || \
294 		           (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_BUFFER || \
295 		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_ARRAYBUFFER || \
296 		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_DATAVIEW || \
297 		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_INT8ARRAY || \
298 		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_UINT8ARRAY || \
299 		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY || \
300 		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_INT16ARRAY || \
301 		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_UINT16ARRAY || \
302 		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_INT32ARRAY || \
303 		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_UINT32ARRAY || \
304 		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_FLOAT32ARRAY || \
305 		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_FLOAT64ARRAY)); \
306 	} while (0)
307 
308 /*
309  *  Macros to access the 'props' allocation.
310  */
311 
312 #if defined(DUK_USE_HEAPPTR16)
313 #define DUK_HOBJECT_GET_PROPS(heap,h) \
314 	((duk_uint8_t *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, ((duk_heaphdr *) (h))->h_extra16))
315 #define DUK_HOBJECT_SET_PROPS(heap,h,x) do { \
316 		((duk_heaphdr *) (h))->h_extra16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (x)); \
317 	} while (0)
318 #else
319 #define DUK_HOBJECT_GET_PROPS(heap,h) \
320 	((h)->props)
321 #define DUK_HOBJECT_SET_PROPS(heap,h,x) do { \
322 		(h)->props = (duk_uint8_t *) (x); \
323 	} while (0)
324 #endif
325 
326 #if defined(DUK_USE_HOBJECT_LAYOUT_1)
327 /* LAYOUT 1 */
328 #define DUK_HOBJECT_E_GET_KEY_BASE(heap,h) \
329 	((duk_hstring **) (void *) ( \
330 		DUK_HOBJECT_GET_PROPS((heap), (h)) \
331 	))
332 #define DUK_HOBJECT_E_GET_VALUE_BASE(heap,h) \
333 	((duk_propvalue *) (void *) ( \
334 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
335 			DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_hstring *) \
336 	))
337 #define DUK_HOBJECT_E_GET_FLAGS_BASE(heap,h) \
338 	((duk_uint8_t *) (void *) ( \
339 		DUK_HOBJECT_GET_PROPS((heap), (h)) + DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue)) \
340 	))
341 #define DUK_HOBJECT_A_GET_BASE(heap,h) \
342 	((duk_tval *) (void *) ( \
343 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
344 			DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) \
345 	))
346 #define DUK_HOBJECT_H_GET_BASE(heap,h) \
347 	((duk_uint32_t *) (void *) ( \
348 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
349 			DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
350 			DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \
351 	))
352 #define DUK_HOBJECT_P_COMPUTE_SIZE(n_ent,n_arr,n_hash) \
353 	( \
354 		(n_ent) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
355 		(n_arr) * sizeof(duk_tval) + \
356 		(n_hash) * sizeof(duk_uint32_t) \
357 	)
358 #define DUK_HOBJECT_P_SET_REALLOC_PTRS(p_base,set_e_k,set_e_pv,set_e_f,set_a,set_h,n_ent,n_arr,n_hash)  do { \
359 		(set_e_k) = (duk_hstring **) (void *) (p_base); \
360 		(set_e_pv) = (duk_propvalue *) (void *) ((set_e_k) + (n_ent)); \
361 		(set_e_f) = (duk_uint8_t *) (void *) ((set_e_pv) + (n_ent)); \
362 		(set_a) = (duk_tval *) (void *) ((set_e_f) + (n_ent)); \
363 		(set_h) = (duk_uint32_t *) (void *) ((set_a) + (n_arr)); \
364 	} while (0)
365 #elif defined(DUK_USE_HOBJECT_LAYOUT_2)
366 /* LAYOUT 2 */
367 #if (DUK_USE_ALIGN_BY == 4)
368 #define DUK_HOBJECT_E_FLAG_PADDING(e_sz) ((4 - (e_sz)) & 0x03)
369 #elif (DUK_USE_ALIGN_BY == 8)
370 #define DUK_HOBJECT_E_FLAG_PADDING(e_sz) ((8 - (e_sz)) & 0x07)
371 #elif (DUK_USE_ALIGN_BY == 1)
372 #define DUK_HOBJECT_E_FLAG_PADDING(e_sz) 0
373 #else
374 #error invalid DUK_USE_ALIGN_BY
375 #endif
376 #define DUK_HOBJECT_E_GET_KEY_BASE(heap,h) \
377 	((duk_hstring **) (void *) ( \
378 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
379 			DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_propvalue) \
380 	))
381 #define DUK_HOBJECT_E_GET_VALUE_BASE(heap,h) \
382 	((duk_propvalue *) (void *) ( \
383 		DUK_HOBJECT_GET_PROPS((heap), (h)) \
384 	))
385 #define DUK_HOBJECT_E_GET_FLAGS_BASE(heap,h) \
386 	((duk_uint8_t *) (void *) ( \
387 		DUK_HOBJECT_GET_PROPS((heap), (h)) + DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue)) \
388 	))
389 #define DUK_HOBJECT_A_GET_BASE(heap,h) \
390 	((duk_tval *) (void *) ( \
391 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
392 			DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
393 			DUK_HOBJECT_E_FLAG_PADDING(DUK_HOBJECT_GET_ESIZE((h))) \
394 	))
395 #define DUK_HOBJECT_H_GET_BASE(heap,h) \
396 	((duk_uint32_t *) (void *) ( \
397 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
398 			DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
399 			DUK_HOBJECT_E_FLAG_PADDING(DUK_HOBJECT_GET_ESIZE((h))) + \
400 			DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \
401 	))
402 #define DUK_HOBJECT_P_COMPUTE_SIZE(n_ent,n_arr,n_hash) \
403 	( \
404 		(n_ent) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
405 		DUK_HOBJECT_E_FLAG_PADDING((n_ent)) + \
406 		(n_arr) * sizeof(duk_tval) + \
407 		(n_hash) * sizeof(duk_uint32_t) \
408 	)
409 #define DUK_HOBJECT_P_SET_REALLOC_PTRS(p_base,set_e_k,set_e_pv,set_e_f,set_a,set_h,n_ent,n_arr,n_hash)  do { \
410 		(set_e_pv) = (duk_propvalue *) (void *) (p_base); \
411 		(set_e_k) = (duk_hstring **) (void *) ((set_e_pv) + (n_ent)); \
412 		(set_e_f) = (duk_uint8_t *) (void *) ((set_e_k) + (n_ent)); \
413 		(set_a) = (duk_tval *) (void *) (((duk_uint8_t *) (set_e_f)) + \
414 		                                 sizeof(duk_uint8_t) * (n_ent) + \
415 		                                 DUK_HOBJECT_E_FLAG_PADDING((n_ent))); \
416 		(set_h) = (duk_uint32_t *) (void *) ((set_a) + (n_arr)); \
417 	} while (0)
418 #elif defined(DUK_USE_HOBJECT_LAYOUT_3)
419 /* LAYOUT 3 */
420 #define DUK_HOBJECT_E_GET_KEY_BASE(heap,h) \
421 	((duk_hstring **) (void *) ( \
422 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
423 			DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_propvalue) + \
424 			DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \
425 	))
426 #define DUK_HOBJECT_E_GET_VALUE_BASE(heap,h) \
427 	((duk_propvalue *) (void *) ( \
428 		DUK_HOBJECT_GET_PROPS((heap), (h)) \
429 	))
430 #define DUK_HOBJECT_E_GET_FLAGS_BASE(heap,h) \
431 	((duk_uint8_t *) (void *) ( \
432 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
433 			DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_propvalue) + sizeof(duk_hstring *)) + \
434 			DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) + \
435 			DUK_HOBJECT_GET_HSIZE((h)) * sizeof(duk_uint32_t) \
436 	))
437 #define DUK_HOBJECT_A_GET_BASE(heap,h) \
438 	((duk_tval *) (void *) ( \
439 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
440 			DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_propvalue) \
441 	))
442 #define DUK_HOBJECT_H_GET_BASE(heap,h) \
443 	((duk_uint32_t *) (void *) ( \
444 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
445 			DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_propvalue) + sizeof(duk_hstring *)) + \
446 			DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \
447 	))
448 #define DUK_HOBJECT_P_COMPUTE_SIZE(n_ent,n_arr,n_hash) \
449 	( \
450 		(n_ent) * (sizeof(duk_propvalue) + sizeof(duk_hstring *) + sizeof(duk_uint8_t)) + \
451 		(n_arr) * sizeof(duk_tval) + \
452 		(n_hash) * sizeof(duk_uint32_t) \
453 	)
454 #define DUK_HOBJECT_P_SET_REALLOC_PTRS(p_base,set_e_k,set_e_pv,set_e_f,set_a,set_h,n_ent,n_arr,n_hash)  do { \
455 		(set_e_pv) = (duk_propvalue *) (void *) (p_base); \
456 		(set_a) = (duk_tval *) (void *) ((set_e_pv) + (n_ent)); \
457 		(set_e_k) = (duk_hstring **) (void *) ((set_a) + (n_arr)); \
458 		(set_h) = (duk_uint32_t *) (void *) ((set_e_k) + (n_ent)); \
459 		(set_e_f) = (duk_uint8_t *) (void *) ((set_h) + (n_hash)); \
460 	} while (0)
461 #else
462 #error invalid hobject layout defines
463 #endif  /* hobject property layout */
464 
465 #define DUK_HOBJECT_P_ALLOC_SIZE(h) \
466 	DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE((h)), DUK_HOBJECT_GET_ASIZE((h)), DUK_HOBJECT_GET_HSIZE((h)))
467 
468 #define DUK_HOBJECT_E_GET_KEY(heap,h,i)              (DUK_HOBJECT_E_GET_KEY_BASE((heap), (h))[(i)])
469 #define DUK_HOBJECT_E_GET_KEY_PTR(heap,h,i)          (&DUK_HOBJECT_E_GET_KEY_BASE((heap), (h))[(i)])
470 #define DUK_HOBJECT_E_GET_VALUE(heap,h,i)            (DUK_HOBJECT_E_GET_VALUE_BASE((heap), (h))[(i)])
471 #define DUK_HOBJECT_E_GET_VALUE_PTR(heap,h,i)        (&DUK_HOBJECT_E_GET_VALUE_BASE((heap), (h))[(i)])
472 #define DUK_HOBJECT_E_GET_VALUE_TVAL(heap,h,i)       (DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).v)
473 #define DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap,h,i)   (&DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).v)
474 #define DUK_HOBJECT_E_GET_VALUE_GETTER(heap,h,i)     (DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.get)
475 #define DUK_HOBJECT_E_GET_VALUE_GETTER_PTR(heap,h,i) (&DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.get)
476 #define DUK_HOBJECT_E_GET_VALUE_SETTER(heap,h,i)     (DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.set)
477 #define DUK_HOBJECT_E_GET_VALUE_SETTER_PTR(heap,h,i) (&DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.set)
478 #define DUK_HOBJECT_E_GET_FLAGS(heap,h,i)            (DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)])
479 #define DUK_HOBJECT_E_GET_FLAGS_PTR(heap,h,i)        (&DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)])
480 #define DUK_HOBJECT_A_GET_VALUE(heap,h,i)            (DUK_HOBJECT_A_GET_BASE((heap), (h))[(i)])
481 #define DUK_HOBJECT_A_GET_VALUE_PTR(heap,h,i)        (&DUK_HOBJECT_A_GET_BASE((heap), (h))[(i)])
482 #define DUK_HOBJECT_H_GET_INDEX(heap,h,i)            (DUK_HOBJECT_H_GET_BASE((heap), (h))[(i)])
483 #define DUK_HOBJECT_H_GET_INDEX_PTR(heap,h,i)        (&DUK_HOBJECT_H_GET_BASE((heap), (h))[(i)])
484 
485 #define DUK_HOBJECT_E_SET_KEY(heap,h,i,k)  do { \
486 		DUK_HOBJECT_E_GET_KEY((heap), (h), (i)) = (k); \
487 	} while (0)
488 #define DUK_HOBJECT_E_SET_VALUE(heap,h,i,v)  do { \
489 		DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)) = (v); \
490 	} while (0)
491 #define DUK_HOBJECT_E_SET_VALUE_TVAL(heap,h,i,v)  do { \
492 		DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).v = (v); \
493 	} while (0)
494 #define DUK_HOBJECT_E_SET_VALUE_GETTER(heap,h,i,v)  do { \
495 		DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.get = (v); \
496 	} while (0)
497 #define DUK_HOBJECT_E_SET_VALUE_SETTER(heap,h,i,v)  do { \
498 		DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.set = (v); \
499 	} while (0)
500 #define DUK_HOBJECT_E_SET_FLAGS(heap,h,i,f)  do { \
501 		DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) = (duk_uint8_t) (f); \
502 	} while (0)
503 #define DUK_HOBJECT_A_SET_VALUE(heap,h,i,v)  do { \
504 		DUK_HOBJECT_A_GET_VALUE((heap), (h), (i)) = (v); \
505 	} while (0)
506 #define DUK_HOBJECT_A_SET_VALUE_TVAL(heap,h,i,v) \
507 	DUK_HOBJECT_A_SET_VALUE((heap), (h), (i), (v))  /* alias for above */
508 #define DUK_HOBJECT_H_SET_INDEX(heap,h,i,v)  do { \
509 		DUK_HOBJECT_H_GET_INDEX((heap), (h), (i)) = (v); \
510 	} while (0)
511 
512 #define DUK_HOBJECT_E_SET_FLAG_BITS(heap,h,i,mask)  do { \
513 		DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)] |= (mask); \
514 	} while (0)
515 
516 #define DUK_HOBJECT_E_CLEAR_FLAG_BITS(heap,h,i,mask)  do { \
517 		DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)] &= ~(mask); \
518 	} while (0)
519 
520 #define DUK_HOBJECT_E_SLOT_IS_WRITABLE(heap,h,i)     ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_WRITABLE) != 0)
521 #define DUK_HOBJECT_E_SLOT_IS_ENUMERABLE(heap,h,i)   ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_ENUMERABLE) != 0)
522 #define DUK_HOBJECT_E_SLOT_IS_CONFIGURABLE(heap,h,i) ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_CONFIGURABLE) != 0)
523 #define DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap,h,i)     ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_ACCESSOR) != 0)
524 
525 #define DUK_HOBJECT_E_SLOT_SET_WRITABLE(heap,h,i)        DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_WRITABLE)
526 #define DUK_HOBJECT_E_SLOT_SET_ENUMERABLE(heap,h,i)      DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ENUMERABLE)
527 #define DUK_HOBJECT_E_SLOT_SET_CONFIGURABLE(heap,h,i)    DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_CONFIGURABLE)
528 #define DUK_HOBJECT_E_SLOT_SET_ACCESSOR(heap,h,i)        DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ACCESSOR)
529 
530 #define DUK_HOBJECT_E_SLOT_CLEAR_WRITABLE(heap,h,i)      DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_WRITABLE)
531 #define DUK_HOBJECT_E_SLOT_CLEAR_ENUMERABLE(heap,h,i)    DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ENUMERABLE)
532 #define DUK_HOBJECT_E_SLOT_CLEAR_CONFIGURABLE(heap,h,i)  DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_CONFIGURABLE)
533 #define DUK_HOBJECT_E_SLOT_CLEAR_ACCESSOR(heap,h,i)      DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ACCESSOR)
534 
535 #define DUK_PROPDESC_IS_WRITABLE(p)             (((p)->flags & DUK_PROPDESC_FLAG_WRITABLE) != 0)
536 #define DUK_PROPDESC_IS_ENUMERABLE(p)           (((p)->flags & DUK_PROPDESC_FLAG_ENUMERABLE) != 0)
537 #define DUK_PROPDESC_IS_CONFIGURABLE(p)         (((p)->flags & DUK_PROPDESC_FLAG_CONFIGURABLE) != 0)
538 #define DUK_PROPDESC_IS_ACCESSOR(p)             (((p)->flags & DUK_PROPDESC_FLAG_ACCESSOR) != 0)
539 
540 #define DUK_HOBJECT_HASHIDX_UNUSED              0xffffffffUL
541 #define DUK_HOBJECT_HASHIDX_DELETED             0xfffffffeUL
542 
543 /*
544  *  Macros for accessing size fields
545  */
546 
547 #if defined(DUK_USE_OBJSIZES16)
548 #define DUK_HOBJECT_GET_ESIZE(h) ((h)->e_size16)
549 #define DUK_HOBJECT_SET_ESIZE(h,v) do { (h)->e_size16 = (v); } while (0)
550 #define DUK_HOBJECT_GET_ENEXT(h) ((h)->e_next16)
551 #define DUK_HOBJECT_SET_ENEXT(h,v) do { (h)->e_next16 = (v); } while (0)
552 #define DUK_HOBJECT_POSTINC_ENEXT(h) ((h)->e_next16++)
553 #define DUK_HOBJECT_GET_ASIZE(h) ((h)->a_size16)
554 #define DUK_HOBJECT_SET_ASIZE(h,v) do { (h)->a_size16 = (v); } while (0)
555 #if defined(DUK_USE_HOBJECT_HASH_PART)
556 #define DUK_HOBJECT_GET_HSIZE(h) ((h)->h_size16)
557 #define DUK_HOBJECT_SET_HSIZE(h,v) do { (h)->h_size16 = (v); } while (0)
558 #else
559 #define DUK_HOBJECT_GET_HSIZE(h) 0
560 #define DUK_HOBJECT_SET_HSIZE(h,v) do { DUK_ASSERT((v) == 0); } while (0)
561 #endif
562 #else
563 #define DUK_HOBJECT_GET_ESIZE(h) ((h)->e_size)
564 #define DUK_HOBJECT_SET_ESIZE(h,v) do { (h)->e_size = (v); } while (0)
565 #define DUK_HOBJECT_GET_ENEXT(h) ((h)->e_next)
566 #define DUK_HOBJECT_SET_ENEXT(h,v) do { (h)->e_next = (v); } while (0)
567 #define DUK_HOBJECT_POSTINC_ENEXT(h) ((h)->e_next++)
568 #define DUK_HOBJECT_GET_ASIZE(h) ((h)->a_size)
569 #define DUK_HOBJECT_SET_ASIZE(h,v) do { (h)->a_size = (v); } while (0)
570 #if defined(DUK_USE_HOBJECT_HASH_PART)
571 #define DUK_HOBJECT_GET_HSIZE(h) ((h)->h_size)
572 #define DUK_HOBJECT_SET_HSIZE(h,v) do { (h)->h_size = (v); } while (0)
573 #else
574 #define DUK_HOBJECT_GET_HSIZE(h) 0
575 #define DUK_HOBJECT_SET_HSIZE(h,v) do { DUK_ASSERT((v) == 0); } while (0)
576 #endif
577 #endif
578 
579 /*
580  *  Misc
581  */
582 
583 /* Maximum prototype traversal depth.  Sanity limit which handles e.g.
584  * prototype loops (even complex ones like 1->2->3->4->2->3->4->2->3->4).
585  */
586 #define DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY      10000L
587 
588 /* Maximum traversal depth for "bound function" chains. */
589 #define DUK_HOBJECT_BOUND_CHAIN_SANITY          10000L
590 
591 /*
592  *  Ecmascript [[Class]]
593  */
594 
595 /* range check not necessary because all 4-bit values are mapped */
596 #define DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(n)  duk_class_number_to_stridx[(n)]
597 
598 #define DUK_HOBJECT_GET_CLASS_STRING(heap,h)          \
599 	DUK_HEAP_GET_STRING( \
600 		(heap), \
601 		DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(DUK_HOBJECT_GET_CLASS_NUMBER((h))) \
602 	)
603 
604 /*
605  *  Macros for property handling
606  */
607 
608 #if defined(DUK_USE_HEAPPTR16)
609 #define DUK_HOBJECT_GET_PROTOTYPE(heap,h) \
610 	((duk_hobject *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->prototype16))
611 #define DUK_HOBJECT_SET_PROTOTYPE(heap,h,x) do { \
612 		(h)->prototype16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (x)); \
613 	} while (0)
614 #else
615 #define DUK_HOBJECT_GET_PROTOTYPE(heap,h) \
616 	((h)->prototype)
617 #define DUK_HOBJECT_SET_PROTOTYPE(heap,h,x) do { \
618 		(h)->prototype = (x); \
619 	} while (0)
620 #endif
621 
622 /* note: this updates refcounts */
623 #define DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr,h,p)       duk_hobject_set_prototype_updref((thr), (h), (p))
624 
625 /*
626  *  Resizing and hash behavior
627  */
628 
629 /* Sanity limit on max number of properties (allocated, not necessarily used).
630  * This is somewhat arbitrary, but if we're close to 2**32 properties some
631  * algorithms will fail (e.g. hash size selection, next prime selection).
632  * Also, we use negative array/entry table indices to indicate 'not found',
633  * so anything above 0x80000000 will cause trouble now.
634  */
635 #if defined(DUK_USE_OBJSIZES16)
636 #define DUK_HOBJECT_MAX_PROPERTIES       0x0000ffffUL
637 #else
638 #define DUK_HOBJECT_MAX_PROPERTIES       0x7fffffffUL   /* 2**31-1 ~= 2G properties */
639 #endif
640 
641 /* higher value conserves memory; also note that linear scan is cache friendly */
642 #define DUK_HOBJECT_E_USE_HASH_LIMIT     32
643 
644 /* hash size relative to entries size: for value X, approx. hash_prime(e_size + e_size / X) */
645 #define DUK_HOBJECT_H_SIZE_DIVISOR       4  /* hash size approx. 1.25 times entries size */
646 
647 /* if new_size < L * old_size, resize without abandon check; L = 3-bit fixed point, e.g. 9 -> 9/8 = 112.5% */
648 #define DUK_HOBJECT_A_FAST_RESIZE_LIMIT  9  /* 112.5%, i.e. new size less than 12.5% higher -> fast resize */
649 
650 /* if density < L, abandon array part, L = 3-bit fixed point, e.g. 2 -> 2/8 = 25% */
651 /* limit is quite low: one array entry is 8 bytes, one normal entry is 4+1+8+4 = 17 bytes (with hash entry) */
652 #define DUK_HOBJECT_A_ABANDON_LIMIT      2  /* 25%, i.e. less than 25% used -> abandon */
653 
654 /* internal align target for props allocation, must be 2*n for some n */
655 #if (DUK_USE_ALIGN_BY == 4)
656 #define DUK_HOBJECT_ALIGN_TARGET         4
657 #elif (DUK_USE_ALIGN_BY == 8)
658 #define DUK_HOBJECT_ALIGN_TARGET         8
659 #elif (DUK_USE_ALIGN_BY == 1)
660 #define DUK_HOBJECT_ALIGN_TARGET         1
661 #else
662 #error invalid DUK_USE_ALIGN_BY
663 #endif
664 
665 /* controls for minimum entry part growth */
666 #define DUK_HOBJECT_E_MIN_GROW_ADD       16
667 #define DUK_HOBJECT_E_MIN_GROW_DIVISOR   8  /* 2^3 -> 1/8 = 12.5% min growth */
668 
669 /* controls for minimum array part growth */
670 #define DUK_HOBJECT_A_MIN_GROW_ADD       16
671 #define DUK_HOBJECT_A_MIN_GROW_DIVISOR   8  /* 2^3 -> 1/8 = 12.5% min growth */
672 
673 /* probe sequence */
674 #define DUK_HOBJECT_HASH_INITIAL(hash,h_size)  ((hash) % (h_size))
675 #define DUK_HOBJECT_HASH_PROBE_STEP(hash)      DUK_UTIL_GET_HASH_PROBE_STEP((hash))
676 
677 /*
678  *  PC-to-line constants
679  */
680 
681 #define DUK_PC2LINE_SKIP    64
682 
683 /* maximum length for a SKIP-1 diffstream: 35 bits per entry, rounded up to bytes */
684 #define DUK_PC2LINE_MAX_DIFF_LENGTH    (((DUK_PC2LINE_SKIP - 1) * 35 + 7) / 8)
685 
686 /*
687  *  Struct defs
688  */
689 
690 struct duk_propaccessor {
691 	duk_hobject *get;
692 	duk_hobject *set;
693 };
694 
695 union duk_propvalue {
696 	/* The get/set pointers could be 16-bit pointer compressed but it
697 	 * would make no difference on 32-bit platforms because duk_tval is
698 	 * 8 bytes or more anyway.
699 	 */
700 	duk_tval v;
701 	duk_propaccessor a;
702 };
703 
704 struct duk_propdesc {
705 	/* read-only values 'lifted' for ease of use */
706 	duk_small_int_t flags;
707 	duk_hobject *get;
708 	duk_hobject *set;
709 
710 	/* for updating (all are set to < 0 for virtual properties) */
711 	duk_int_t e_idx;  /* prop index in 'entry part', < 0 if not there */
712 	duk_int_t h_idx;  /* prop index in 'hash part', < 0 if not there */
713 	duk_int_t a_idx;  /* prop index in 'array part', < 0 if not there */
714 };
715 
716 struct duk_hobject {
717 	duk_heaphdr hdr;
718 
719 	/*
720 	 *  'props' contains {key,value,flags} entries, optional array entries, and
721 	 *  an optional hash lookup table for non-array entries in a single 'sliced'
722 	 *  allocation.  There are several layout options, which differ slightly in
723 	 *  generated code size/speed and alignment/padding; duk_features.h selects
724 	 *  the layout used.
725 	 *
726 	 *  Layout 1 (DUK_USE_HOBJECT_LAYOUT_1):
727 	 *
728 	 *    e_size * sizeof(duk_hstring *)         bytes of   entry keys (e_next gc reachable)
729 	 *    e_size * sizeof(duk_propvalue)         bytes of   entry values (e_next gc reachable)
730 	 *    e_size * sizeof(duk_uint8_t)           bytes of   entry flags (e_next gc reachable)
731 	 *    a_size * sizeof(duk_tval)              bytes of   (opt) array values (plain only) (all gc reachable)
732 	 *    h_size * sizeof(duk_uint32_t)          bytes of   (opt) hash indexes to entries (e_size),
733 	 *                                                      0xffffffffUL = unused, 0xfffffffeUL = deleted
734 	 *
735 	 *  Layout 2 (DUK_USE_HOBJECT_LAYOUT_2):
736 	 *
737 	 *    e_size * sizeof(duk_propvalue)         bytes of   entry values (e_next gc reachable)
738 	 *    e_size * sizeof(duk_hstring *)         bytes of   entry keys (e_next gc reachable)
739 	 *    e_size * sizeof(duk_uint8_t) + pad     bytes of   entry flags (e_next gc reachable)
740 	 *    a_size * sizeof(duk_tval)              bytes of   (opt) array values (plain only) (all gc reachable)
741 	 *    h_size * sizeof(duk_uint32_t)          bytes of   (opt) hash indexes to entries (e_size),
742 	 *                                                      0xffffffffUL = unused, 0xfffffffeUL = deleted
743 	 *
744 	 *  Layout 3 (DUK_USE_HOBJECT_LAYOUT_3):
745 	 *
746 	 *    e_size * sizeof(duk_propvalue)         bytes of   entry values (e_next gc reachable)
747 	 *    a_size * sizeof(duk_tval)              bytes of   (opt) array values (plain only) (all gc reachable)
748 	 *    e_size * sizeof(duk_hstring *)         bytes of   entry keys (e_next gc reachable)
749 	 *    h_size * sizeof(duk_uint32_t)          bytes of   (opt) hash indexes to entries (e_size),
750 	 *                                                      0xffffffffUL = unused, 0xfffffffeUL = deleted
751 	 *    e_size * sizeof(duk_uint8_t)           bytes of   entry flags (e_next gc reachable)
752 	 *
753 	 *  In layout 1, the 'e_next' count is rounded to 4 or 8 on platforms
754 	 *  requiring 4 or 8 byte alignment.  This ensures proper alignment
755 	 *  for the entries, at the cost of memory footprint.  However, it's
756 	 *  probably preferable to use another layout on such platforms instead.
757 	 *
758 	 *  In layout 2, the key and value parts are swapped to avoid padding
759 	 *  the key array on platforms requiring alignment by 8.  The flags part
760 	 *  is padded to get alignment for array entries.  The 'e_next' count does
761 	 *  not need to be rounded as in layout 1.
762 	 *
763 	 *  In layout 3, entry values and array values are always aligned properly,
764 	 *  and assuming pointers are at most 8 bytes, so are the entry keys.  Hash
765 	 *  indices will be properly aligned (assuming pointers are at least 4 bytes).
766 	 *  Finally, flags don't need additional alignment.  This layout provides
767 	 *  compact allocations without padding (even on platforms with alignment
768 	 *  requirements) at the cost of a bit slower lookups.
769 	 *
770 	 *  Objects with few keys don't have a hash index; keys are looked up linearly,
771 	 *  which is cache efficient because the keys are consecutive.  Larger objects
772 	 *  have a hash index part which contains integer indexes to the entries part.
773 	 *
774 	 *  A single allocation reduces memory allocation overhead but requires more
775 	 *  work when any part needs to be resized.  A sliced allocation for entries
776 	 *  makes linear key matching faster on most platforms (more locality) and
777 	 *  skimps on flags size (which would be followed by 3 bytes of padding in
778 	 *  most architectures if entries were placed in a struct).
779 	 *
780 	 *  'props' also contains internal properties distinguished with a non-BMP
781 	 *  prefix.  Often used properties should be placed early in 'props' whenever
782 	 *  possible to make accessing them as fast a possible.
783 	 */
784 
785 #if defined(DUK_USE_HEAPPTR16)
786 	/* Located in duk_heaphdr h_extra16.  Subclasses of duk_hobject (like
787 	 * duk_hcompiledfunction) are not free to use h_extra16 for this reason.
788 	 */
789 #else
790 	duk_uint8_t *props;
791 #endif
792 
793 	/* prototype: the only internal property lifted outside 'e' as it is so central */
794 #if defined(DUK_USE_HEAPPTR16)
795 	duk_uint16_t prototype16;
796 #else
797 	duk_hobject *prototype;
798 #endif
799 
800 #if defined(DUK_USE_OBJSIZES16)
801 	duk_uint16_t e_size16;
802 	duk_uint16_t e_next16;
803 	duk_uint16_t a_size16;
804 #if defined(DUK_USE_HOBJECT_HASH_PART)
805 	duk_uint16_t h_size16;
806 #endif
807 #else
808 	duk_uint32_t e_size;  /* entry part size */
809 	duk_uint32_t e_next;  /* index for next new key ([0,e_next[ are gc reachable) */
810 	duk_uint32_t a_size;  /* array part size (entirely gc reachable) */
811 #if defined(DUK_USE_HOBJECT_HASH_PART)
812 	duk_uint32_t h_size;  /* hash part size or 0 if unused */
813 #endif
814 #endif
815 };
816 
817 /*
818  *  Exposed data
819  */
820 
821 #if !defined(DUK_SINGLE_FILE)
822 DUK_INTERNAL_DECL duk_uint8_t duk_class_number_to_stridx[32];
823 #endif  /* !DUK_SINGLE_FILE */
824 
825 /*
826  *  Prototypes
827  */
828 
829 /* alloc and init */
830 DUK_INTERNAL_DECL duk_hobject *duk_hobject_alloc(duk_heap *heap, duk_uint_t hobject_flags);
831 #if 0  /* unused */
832 DUK_INTERNAL_DECL duk_hobject *duk_hobject_alloc_checked(duk_hthread *thr, duk_uint_t hobject_flags);
833 #endif
834 DUK_INTERNAL_DECL duk_hcompiledfunction *duk_hcompiledfunction_alloc(duk_heap *heap, duk_uint_t hobject_flags);
835 DUK_INTERNAL_DECL duk_hnativefunction *duk_hnativefunction_alloc(duk_heap *heap, duk_uint_t hobject_flags);
836 DUK_INTERNAL duk_hbufferobject *duk_hbufferobject_alloc(duk_heap *heap, duk_uint_t hobject_flags);
837 DUK_INTERNAL_DECL duk_hthread *duk_hthread_alloc(duk_heap *heap, duk_uint_t hobject_flags);
838 
839 /* low-level property functions */
840 DUK_INTERNAL_DECL void duk_hobject_find_existing_entry(duk_heap *heap, duk_hobject *obj, duk_hstring *key, duk_int_t *e_idx, duk_int_t *h_idx);
841 DUK_INTERNAL_DECL duk_tval *duk_hobject_find_existing_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_hstring *key);
842 DUK_INTERNAL_DECL duk_tval *duk_hobject_find_existing_entry_tval_ptr_and_attrs(duk_heap *heap, duk_hobject *obj, duk_hstring *key, duk_int_t *out_attrs);
843 DUK_INTERNAL_DECL duk_tval *duk_hobject_find_existing_array_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_uarridx_t i);
844 DUK_INTERNAL_DECL duk_bool_t duk_hobject_get_own_propdesc(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *out_desc, duk_small_uint_t flags);
845 
846 /* XXX: when optimizing for guaranteed property slots, use a guaranteed
847  * slot for internal value; this call can then access it directly.
848  */
849 #define duk_hobject_get_internal_value_tval_ptr(heap,obj) \
850 	duk_hobject_find_existing_entry_tval_ptr((heap), (obj), DUK_HEAP_STRING_INT_VALUE((heap)))
851 
852 /* core property functions */
853 DUK_INTERNAL_DECL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key);
854 DUK_INTERNAL_DECL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key, duk_tval *tv_val, duk_bool_t throw_flag);
855 DUK_INTERNAL_DECL duk_bool_t duk_hobject_delprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key, duk_bool_t throw_flag);
856 DUK_INTERNAL_DECL duk_bool_t duk_hobject_hasprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key);
857 
858 /* internal property functions */
859 #define DUK_DELPROP_FLAG_THROW  (1 << 0)
860 #define DUK_DELPROP_FLAG_FORCE  (1 << 1)
861 DUK_INTERNAL_DECL duk_bool_t duk_hobject_delprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_small_uint_t flags);
862 DUK_INTERNAL_DECL duk_bool_t duk_hobject_hasprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key);
863 DUK_INTERNAL_DECL void duk_hobject_define_property_internal(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_small_uint_t flags);
864 DUK_INTERNAL_DECL void duk_hobject_define_property_internal_arridx(duk_hthread *thr, duk_hobject *obj, duk_uarridx_t arr_idx, duk_small_uint_t flags);
865 DUK_INTERNAL_DECL void duk_hobject_define_accessor_internal(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_hobject *getter, duk_hobject *setter, duk_small_uint_t propflags);
866 DUK_INTERNAL_DECL void duk_hobject_set_length(duk_hthread *thr, duk_hobject *obj, duk_uint32_t length);  /* XXX: duk_uarridx_t? */
867 DUK_INTERNAL_DECL void duk_hobject_set_length_zero(duk_hthread *thr, duk_hobject *obj);
868 DUK_INTERNAL_DECL duk_uint32_t duk_hobject_get_length(duk_hthread *thr, duk_hobject *obj);  /* XXX: duk_uarridx_t? */
869 
870 /* helpers for defineProperty() and defineProperties() */
871 DUK_INTERNAL_DECL
872 void duk_hobject_prepare_property_descriptor(duk_context *ctx,
873                                              duk_idx_t idx_in,
874                                              duk_uint_t *out_defprop_flags,
875                                              duk_idx_t *out_idx_value,
876                                              duk_hobject **out_getter,
877                                              duk_hobject **out_setter);
878 DUK_INTERNAL_DECL
879 void duk_hobject_define_property_helper(duk_context *ctx,
880                                         duk_uint_t defprop_flags,
881                                         duk_hobject *obj,
882                                         duk_hstring *key,
883                                         duk_idx_t idx_value,
884                                         duk_hobject *get,
885                                         duk_hobject *set);
886 
887 /* Object built-in methods */
888 DUK_INTERNAL_DECL duk_ret_t duk_hobject_object_get_own_property_descriptor(duk_context *ctx);
889 DUK_INTERNAL_DECL void duk_hobject_object_seal_freeze_helper(duk_hthread *thr, duk_hobject *obj, duk_bool_t is_freeze);
890 DUK_INTERNAL_DECL duk_bool_t duk_hobject_object_is_sealed_frozen_helper(duk_hthread *thr, duk_hobject *obj, duk_bool_t is_frozen);
891 DUK_INTERNAL_DECL duk_bool_t duk_hobject_object_ownprop_helper(duk_context *ctx, duk_small_uint_t required_desc_flags);
892 
893 /* internal properties */
894 DUK_INTERNAL_DECL duk_bool_t duk_hobject_get_internal_value(duk_heap *heap, duk_hobject *obj, duk_tval *tv);
895 DUK_INTERNAL_DECL duk_hstring *duk_hobject_get_internal_value_string(duk_heap *heap, duk_hobject *obj);
896 
897 /* hobject management functions */
898 DUK_INTERNAL_DECL void duk_hobject_compact_props(duk_hthread *thr, duk_hobject *obj);
899 
900 /* ES6 proxy */
901 #if defined(DUK_USE_ES6_PROXY)
902 DUK_INTERNAL_DECL duk_bool_t duk_hobject_proxy_check(duk_hthread *thr, duk_hobject *obj, duk_hobject **out_target, duk_hobject **out_handler);
903 DUK_INTERNAL_DECL duk_hobject *duk_hobject_resolve_proxy_target(duk_hthread *thr, duk_hobject *obj);
904 #endif
905 
906 /* enumeration */
907 DUK_INTERNAL_DECL void duk_hobject_enumerator_create(duk_context *ctx, duk_small_uint_t enum_flags);
908 DUK_INTERNAL_DECL duk_ret_t duk_hobject_get_enumerated_keys(duk_context *ctx, duk_small_uint_t enum_flags);
909 DUK_INTERNAL_DECL duk_bool_t duk_hobject_enumerator_next(duk_context *ctx, duk_bool_t get_value);
910 
911 /* macros */
912 DUK_INTERNAL_DECL void duk_hobject_set_prototype_updref(duk_hthread *thr, duk_hobject *h, duk_hobject *p);
913 
914 /* finalization */
915 DUK_INTERNAL_DECL void duk_hobject_run_finalizer(duk_hthread *thr, duk_hobject *obj);
916 
917 /* pc2line */
918 #if defined(DUK_USE_PC2LINE)
919 DUK_INTERNAL_DECL void duk_hobject_pc2line_pack(duk_hthread *thr, duk_compiler_instr *instrs, duk_uint_fast32_t length);
920 DUK_INTERNAL_DECL duk_uint_fast32_t duk_hobject_pc2line_query(duk_context *ctx, duk_idx_t idx_func, duk_uint_fast32_t pc);
921 #endif
922 
923 /* misc */
924 DUK_INTERNAL_DECL duk_bool_t duk_hobject_prototype_chain_contains(duk_hthread *thr, duk_hobject *h, duk_hobject *p, duk_bool_t ignore_loop);
925 
926 #endif  /* DUK_HOBJECT_H_INCLUDED */
927