1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * vim: set ts=8 sw=4 et tw=78:
3 : *
4 : * This Source Code Form is subject to the terms of the Mozilla Public
5 : * License, v. 2.0. If a copy of the MPL was not distributed with this file,
6 : * You can obtain one at http://mozilla.org/MPL/2.0/. */
7 :
8 : #ifndef ObjectImpl_inl_h___
9 : #define ObjectImpl_inl_h___
10 :
11 : #include "mozilla/Assertions.h"
12 :
13 : #include "jscell.h"
14 : #include "jscompartment.h"
15 : #include "jsgc.h"
16 : #include "jsgcmark.h"
17 : #include "jsinterp.h"
18 :
19 : #include "js/TemplateLib.h"
20 :
21 : #include "ObjectImpl.h"
22 :
23 : namespace js {
24 :
25 : static MOZ_ALWAYS_INLINE void
26 4555234 : Debug_SetSlotRangeToCrashOnTouch(HeapSlot *vec, uint32_t len)
27 : {
28 : #ifdef DEBUG
29 4555234 : Debug_SetValueRangeToCrashOnTouch((Value *) vec, len);
30 : #endif
31 4555234 : }
32 :
33 : static MOZ_ALWAYS_INLINE void
34 900 : Debug_SetSlotRangeToCrashOnTouch(HeapSlot *begin, HeapSlot *end)
35 : {
36 : #ifdef DEBUG
37 900 : Debug_SetValueRangeToCrashOnTouch((Value *) begin, end - begin);
38 : #endif
39 900 : }
40 :
41 : } // namespace js
42 :
43 : inline bool
44 34793055 : js::ObjectImpl::isExtensible() const
45 : {
46 34793055 : return !lastProperty()->hasObjectFlag(BaseShape::NOT_EXTENSIBLE);
47 : }
48 :
49 : inline bool
50 577260863 : js::ObjectImpl::isDenseArray() const
51 : {
52 577260863 : bool result = hasClass(&ArrayClass);
53 577260863 : MOZ_ASSERT_IF(result, elements != emptyObjectElements);
54 577260863 : return result;
55 : }
56 :
57 : inline bool
58 176833456 : js::ObjectImpl::isSlowArray() const
59 : {
60 176833456 : bool result = hasClass(&SlowArrayClass);
61 176833456 : MOZ_ASSERT_IF(result, elements != emptyObjectElements);
62 176833456 : return result;
63 : }
64 :
65 : inline bool
66 176346391 : js::ObjectImpl::isArray() const
67 : {
68 176346391 : return isSlowArray() || isDenseArray();
69 : }
70 :
71 : inline uint32_t
72 127519804 : js::ObjectImpl::getDenseArrayInitializedLength()
73 : {
74 127519804 : MOZ_ASSERT(isDenseArray());
75 127519804 : return getElementsHeader()->initializedLength;
76 : }
77 :
78 : inline js::HeapSlotArray
79 839076 : js::ObjectImpl::getDenseArrayElements()
80 : {
81 839076 : MOZ_ASSERT(isDenseArray());
82 839076 : return HeapSlotArray(elements);
83 : }
84 :
85 : inline const js::Value &
86 61138891 : js::ObjectImpl::getDenseArrayElement(uint32_t idx)
87 : {
88 61138891 : MOZ_ASSERT(isDenseArray() && idx < getDenseArrayInitializedLength());
89 61138891 : return elements[idx];
90 : }
91 :
92 : inline void
93 4919164 : js::ObjectImpl::getSlotRangeUnchecked(uint32_t start, uint32_t length,
94 : HeapSlot **fixedStart, HeapSlot **fixedEnd,
95 : HeapSlot **slotsStart, HeapSlot **slotsEnd)
96 : {
97 4919164 : MOZ_ASSERT(!isDenseArray());
98 4919164 : MOZ_ASSERT(start + length >= start);
99 :
100 4919164 : uint32_t fixed = numFixedSlots();
101 4919164 : if (start < fixed) {
102 4892690 : if (start + length < fixed) {
103 1624434 : *fixedStart = &fixedSlots()[start];
104 1624434 : *fixedEnd = &fixedSlots()[start + length];
105 1624434 : *slotsStart = *slotsEnd = NULL;
106 : } else {
107 3268256 : uint32_t localCopy = fixed - start;
108 3268256 : *fixedStart = &fixedSlots()[start];
109 3268256 : *fixedEnd = &fixedSlots()[start + localCopy];
110 3268256 : *slotsStart = &slots[0];
111 3268256 : *slotsEnd = &slots[length - localCopy];
112 : }
113 : } else {
114 26474 : *fixedStart = *fixedEnd = NULL;
115 26474 : *slotsStart = &slots[start - fixed];
116 26474 : *slotsEnd = &slots[start - fixed + length];
117 : }
118 4919164 : }
119 :
120 : inline void
121 379152 : js::ObjectImpl::getSlotRange(uint32_t start, uint32_t length,
122 : HeapSlot **fixedStart, HeapSlot **fixedEnd,
123 : HeapSlot **slotsStart, HeapSlot **slotsEnd)
124 : {
125 379152 : MOZ_ASSERT(slotInRange(start + length, SENTINEL_ALLOWED));
126 379152 : getSlotRangeUnchecked(start, length, fixedStart, fixedEnd, slotsStart, slotsEnd);
127 379152 : }
128 :
129 : inline bool
130 553758 : js::ObjectImpl::hasContiguousSlots(uint32_t start, uint32_t count) const
131 : {
132 : /*
133 : * Check that the range [start, start+count) is either all inline or all
134 : * out of line.
135 : */
136 553758 : MOZ_ASSERT(slotInRange(start + count, SENTINEL_ALLOWED));
137 553758 : return start + count <= numFixedSlots() || start >= numFixedSlots();
138 : }
139 :
140 : inline void
141 450 : js::ObjectImpl::invalidateSlotRange(uint32_t start, uint32_t length)
142 : {
143 : #ifdef DEBUG
144 450 : MOZ_ASSERT(!isDenseArray());
145 :
146 : HeapSlot *fixedStart, *fixedEnd, *slotsStart, *slotsEnd;
147 450 : getSlotRange(start, length, &fixedStart, &fixedEnd, &slotsStart, &slotsEnd);
148 450 : Debug_SetSlotRangeToCrashOnTouch(fixedStart, fixedEnd);
149 450 : Debug_SetSlotRangeToCrashOnTouch(slotsStart, slotsEnd);
150 : #endif /* DEBUG */
151 450 : }
152 :
153 : inline void
154 4540012 : js::ObjectImpl::initializeSlotRange(uint32_t start, uint32_t length)
155 : {
156 : /*
157 : * No bounds check, as this is used when the object's shape does not
158 : * reflect its allocated slots (updateSlotsForSpan).
159 : */
160 : HeapSlot *fixedStart, *fixedEnd, *slotsStart, *slotsEnd;
161 4540012 : getSlotRangeUnchecked(start, length, &fixedStart, &fixedEnd, &slotsStart, &slotsEnd);
162 :
163 4540012 : JSCompartment *comp = compartment();
164 4540012 : uint32_t offset = start;
165 17637207 : for (HeapSlot *sp = fixedStart; sp < fixedEnd; sp++)
166 13097195 : sp->init(comp, this->asObjectPtr(), offset++, UndefinedValue());
167 7958091 : for (HeapSlot *sp = slotsStart; sp < slotsEnd; sp++)
168 3418079 : sp->init(comp, this->asObjectPtr(), offset++, UndefinedValue());
169 4540012 : }
170 :
171 : inline bool
172 293370951 : js::ObjectImpl::isNative() const
173 : {
174 293370951 : return lastProperty()->isNative();
175 : }
176 :
177 : inline js::HeapSlot &
178 8270165 : js::ObjectImpl::nativeGetSlotRef(uint32_t slot)
179 : {
180 8270165 : MOZ_ASSERT(isNative());
181 8270165 : MOZ_ASSERT(slot < slotSpan());
182 8270165 : return getSlotRef(slot);
183 : }
184 :
185 : inline const js::Value &
186 97855496 : js::ObjectImpl::nativeGetSlot(uint32_t slot) const
187 : {
188 97855496 : MOZ_ASSERT(isNative());
189 97855496 : MOZ_ASSERT(slot < slotSpan());
190 97855496 : return getSlot(slot);
191 : }
192 :
193 : inline void
194 59439646 : js::ObjectImpl::setSlot(uint32_t slot, const js::Value &value)
195 : {
196 59439646 : MOZ_ASSERT(slotInRange(slot));
197 59439646 : getSlotRef(slot).set(this->asObjectPtr(), slot, value);
198 59439646 : }
199 :
200 : inline void
201 153351 : js::ObjectImpl::initSlot(uint32_t slot, const js::Value &value)
202 : {
203 153351 : MOZ_ASSERT(getSlot(slot).isUndefined() || getSlot(slot).isMagic(JS_ARRAY_HOLE));
204 153351 : MOZ_ASSERT(slotInRange(slot));
205 153351 : initSlotUnchecked(slot, value);
206 153351 : }
207 :
208 : inline void
209 18642989 : js::ObjectImpl::initSlotUnchecked(uint32_t slot, const js::Value &value)
210 : {
211 18642989 : getSlotAddressUnchecked(slot)->init(this->asObjectPtr(), slot, value);
212 18642989 : }
213 :
214 : inline void
215 4049801 : js::ObjectImpl::setFixedSlot(uint32_t slot, const js::Value &value)
216 : {
217 4049801 : MOZ_ASSERT(slot < numFixedSlots());
218 4049801 : fixedSlots()[slot].set(this->asObjectPtr(), slot, value);
219 4049801 : }
220 :
221 : inline void
222 2215034 : js::ObjectImpl::initFixedSlot(uint32_t slot, const js::Value &value)
223 : {
224 2215034 : MOZ_ASSERT(slot < numFixedSlots());
225 2215034 : fixedSlots()[slot].init(this->asObjectPtr(), slot, value);
226 2215034 : }
227 :
228 : inline uint32_t
229 687711998 : js::ObjectImpl::slotSpan() const
230 : {
231 687711998 : if (inDictionaryMode())
232 218453263 : return lastProperty()->base()->slotSpan();
233 469258735 : return lastProperty()->slotSpan();
234 : }
235 :
236 : inline uint32_t
237 505693457 : js::ObjectImpl::numDynamicSlots() const
238 : {
239 505693457 : return dynamicSlotsCount(numFixedSlots(), slotSpan());
240 : }
241 :
242 : inline js::Class *
243 1681562781 : js::ObjectImpl::getClass() const
244 : {
245 1681562781 : return lastProperty()->getObjectClass();
246 : }
247 :
248 : inline JSClass *
249 2323858 : js::ObjectImpl::getJSClass() const
250 : {
251 2323858 : return Jsvalify(getClass());
252 : }
253 :
254 : inline bool
255 1210191962 : js::ObjectImpl::hasClass(const Class *c) const
256 : {
257 1210191962 : return getClass() == c;
258 : }
259 :
260 : inline const js::ObjectOps *
261 155868044 : js::ObjectImpl::getOps() const
262 : {
263 155868044 : return &getClass()->ops;
264 : }
265 :
266 : inline bool
267 32607555 : js::ObjectImpl::isDelegate() const
268 : {
269 32607555 : return lastProperty()->hasObjectFlag(BaseShape::DELEGATE);
270 : }
271 :
272 : inline bool
273 827005121 : js::ObjectImpl::inDictionaryMode() const
274 : {
275 827005121 : return lastProperty()->inDictionary();
276 : }
277 :
278 : /* static */ inline uint32_t
279 560762265 : js::ObjectImpl::dynamicSlotsCount(uint32_t nfixed, uint32_t span)
280 : {
281 560762265 : if (span <= nfixed)
282 269308014 : return 0;
283 291454251 : span -= nfixed;
284 291454251 : if (span <= SLOT_CAPACITY_MIN)
285 84106339 : return SLOT_CAPACITY_MIN;
286 :
287 207347912 : uint32_t slots = RoundUpPow2(span);
288 207347912 : MOZ_ASSERT(slots >= span);
289 207347912 : return slots;
290 : }
291 :
292 : inline size_t
293 19877247 : js::ObjectImpl::sizeOfThis() const
294 : {
295 19877247 : return arenaHeader()->getThingSize();
296 : }
297 :
298 : /* static */ inline void
299 108666 : js::ObjectImpl::readBarrier(ObjectImpl *obj)
300 : {
301 : #ifdef JSGC_INCREMENTAL
302 108666 : JSCompartment *comp = obj->compartment();
303 108666 : if (comp->needsBarrier()) {
304 153 : MOZ_ASSERT(!comp->rt->gcRunning);
305 153 : JSObject *tmp = obj->asObjectPtr();
306 153 : MarkObjectUnbarriered(comp->barrierTracer(), &tmp, "read barrier");
307 153 : MOZ_ASSERT(tmp == obj->asObjectPtr());
308 : }
309 : #endif
310 108666 : }
311 :
312 : inline void
313 2869927 : js::ObjectImpl::privateWriteBarrierPre(void **old)
314 : {
315 : #ifdef JSGC_INCREMENTAL
316 2869927 : JSCompartment *comp = compartment();
317 2869927 : if (comp->needsBarrier()) {
318 651 : if (*old && getClass()->trace)
319 160 : getClass()->trace(comp->barrierTracer(), this->asObjectPtr());
320 : }
321 : #endif
322 2869927 : }
323 :
324 : inline void
325 2869927 : js::ObjectImpl::privateWriteBarrierPost(void **old)
326 : {
327 2869927 : }
328 :
329 : /* static */ inline void
330 13547991 : js::ObjectImpl::writeBarrierPre(ObjectImpl *obj)
331 : {
332 : #ifdef JSGC_INCREMENTAL
333 : /*
334 : * This would normally be a null test, but TypeScript::global uses 0x1 as a
335 : * special value.
336 : */
337 13547991 : if (uintptr_t(obj) < 32)
338 11771551 : return;
339 :
340 1776440 : JSCompartment *comp = obj->compartment();
341 1776440 : if (comp->needsBarrier()) {
342 95 : MOZ_ASSERT(!comp->rt->gcRunning);
343 95 : JSObject *tmp = obj->asObjectPtr();
344 95 : MarkObjectUnbarriered(comp->barrierTracer(), &tmp, "write barrier");
345 95 : MOZ_ASSERT(tmp == obj->asObjectPtr());
346 : }
347 : #endif
348 : }
349 :
350 : /* static */ inline void
351 27619473 : js::ObjectImpl::writeBarrierPost(ObjectImpl *obj, void *addr)
352 : {
353 27619473 : }
354 :
355 : inline bool
356 48179401 : js::ObjectImpl::hasPrivate() const
357 : {
358 48179401 : return getClass()->hasPrivate();
359 : }
360 :
361 : inline void *&
362 48161538 : js::ObjectImpl::privateRef(uint32_t nfixed) const
363 : {
364 : /*
365 : * The private pointer of an object can hold any word sized value.
366 : * Private pointers are stored immediately after the last fixed slot of
367 : * the object.
368 : */
369 48161538 : MOZ_ASSERT(nfixed == numFixedSlots());
370 48161538 : MOZ_ASSERT(hasPrivate());
371 48161538 : HeapSlot *end = &fixedSlots()[nfixed];
372 48161538 : return *reinterpret_cast<void**>(end);
373 : }
374 :
375 : inline void *
376 43456612 : js::ObjectImpl::getPrivate() const
377 : {
378 43456612 : return privateRef(numFixedSlots());
379 : }
380 :
381 : inline void *
382 57368 : js::ObjectImpl::getPrivate(uint32_t nfixed) const
383 : {
384 57368 : return privateRef(nfixed);
385 : }
386 :
387 : inline void
388 2869927 : js::ObjectImpl::setPrivate(void *data)
389 : {
390 2869927 : void **pprivate = &privateRef(numFixedSlots());
391 :
392 2869927 : privateWriteBarrierPre(pprivate);
393 2869927 : *pprivate = data;
394 2869927 : privateWriteBarrierPost(pprivate);
395 2869927 : }
396 :
397 : inline void
398 3779 : js::ObjectImpl::setPrivateUnbarriered(void *data)
399 : {
400 3779 : void **pprivate = &privateRef(numFixedSlots());
401 3779 : *pprivate = data;
402 3779 : }
403 :
404 : inline void
405 201545 : js::ObjectImpl::initPrivate(void *data)
406 : {
407 201545 : privateRef(numFixedSlots()) = data;
408 201545 : }
409 :
410 : #endif /* ObjectImpl_inl_h__ */
|