blob: 02cf328d4f3c42d3fdd71d65c706d866feb4c2d5 [file] [log] [blame]
oliver@apple.com5fca29f2009-08-11 04:35:02 +00001/*
ggaren@apple.comb7d71072011-03-16 18:16:03 +00002 * Copyright (C) 2009, 2011 Apple Inc. All rights reserved.
oliver@apple.com5fca29f2009-08-11 04:35:02 +00003 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "MarkStack.h"
28
ggaren@apple.com0b32d092011-04-11 21:57:31 +000029#include "ConservativeRoots.h"
ggaren@apple.comb7d71072011-03-16 18:16:03 +000030#include "Heap.h"
commit-queue@webkit.orga2e15982011-12-15 12:01:30 +000031#include "Options.h"
ggaren@apple.comb7d71072011-03-16 18:16:03 +000032#include "JSArray.h"
33#include "JSCell.h"
ggaren@apple.com02bf0402011-03-16 18:35:49 +000034#include "JSObject.h"
35#include "ScopeChain.h"
ggaren@apple.comb7d71072011-03-16 18:16:03 +000036#include "Structure.h"
ggaren@apple.com3a7b4792011-10-17 20:43:43 +000037#include "WriteBarrier.h"
fpizlo@apple.com622ead72011-11-01 06:43:37 +000038#include <wtf/MainThread.h>
ggaren@apple.comb7d71072011-03-16 18:16:03 +000039
darin@apple.com9fb218b2009-09-04 18:53:02 +000040namespace JSC {
oliver@apple.com5fca29f2009-08-11 04:35:02 +000041
fpizlo@apple.com622ead72011-11-01 06:43:37 +000042MarkStackSegmentAllocator::MarkStackSegmentAllocator()
43 : m_nextFreeSegment(0)
ggaren@apple.com3a7b4792011-10-17 20:43:43 +000044{
fpizlo@apple.com622ead72011-11-01 06:43:37 +000045}
46
47MarkStackSegmentAllocator::~MarkStackSegmentAllocator()
48{
49 shrinkReserve();
50}
51
52MarkStackSegment* MarkStackSegmentAllocator::allocate()
53{
54 {
55 MutexLocker locker(m_lock);
56 if (m_nextFreeSegment) {
57 MarkStackSegment* result = m_nextFreeSegment;
58 m_nextFreeSegment = result->m_previous;
59 return result;
60 }
61 }
62
commit-queue@webkit.orga2e15982011-12-15 12:01:30 +000063 return static_cast<MarkStackSegment*>(OSAllocator::reserveAndCommit(Options::gcMarkStackSegmentSize));
fpizlo@apple.com622ead72011-11-01 06:43:37 +000064}
65
66void MarkStackSegmentAllocator::release(MarkStackSegment* segment)
67{
68 MutexLocker locker(m_lock);
69 segment->m_previous = m_nextFreeSegment;
70 m_nextFreeSegment = segment;
71}
72
73void MarkStackSegmentAllocator::shrinkReserve()
74{
75 MarkStackSegment* segments;
76 {
77 MutexLocker locker(m_lock);
78 segments = m_nextFreeSegment;
79 m_nextFreeSegment = 0;
80 }
81 while (segments) {
82 MarkStackSegment* toFree = segments;
83 segments = segments->m_previous;
commit-queue@webkit.orga2e15982011-12-15 12:01:30 +000084 OSAllocator::decommitAndRelease(toFree, Options::gcMarkStackSegmentSize);
fpizlo@apple.com622ead72011-11-01 06:43:37 +000085 }
86}
87
88MarkStackArray::MarkStackArray(MarkStackSegmentAllocator& allocator)
89 : m_allocator(allocator)
commit-queue@webkit.orga2e15982011-12-15 12:01:30 +000090 , m_segmentCapacity(MarkStackSegment::capacityFromSize(Options::gcMarkStackSegmentSize))
fpizlo@apple.com622ead72011-11-01 06:43:37 +000091 , m_top(0)
92 , m_numberOfPreviousSegments(0)
93{
94 m_topSegment = m_allocator.allocate();
95#if !ASSERT_DISABLED
96 m_topSegment->m_top = 0;
97#endif
98 m_topSegment->m_previous = 0;
ggaren@apple.com3a7b4792011-10-17 20:43:43 +000099}
100
101MarkStackArray::~MarkStackArray()
102{
fpizlo@apple.com622ead72011-11-01 06:43:37 +0000103 ASSERT(!m_topSegment->m_previous);
104 m_allocator.release(m_topSegment);
ggaren@apple.com3a7b4792011-10-17 20:43:43 +0000105}
106
107void MarkStackArray::expand()
108{
fpizlo@apple.com622ead72011-11-01 06:43:37 +0000109 ASSERT(m_topSegment->m_top == m_segmentCapacity);
110
111 m_numberOfPreviousSegments++;
112
113 MarkStackSegment* nextSegment = m_allocator.allocate();
114#if !ASSERT_DISABLED
115 nextSegment->m_top = 0;
116#endif
117 nextSegment->m_previous = m_topSegment;
118 m_topSegment = nextSegment;
119 setTopForEmptySegment();
120 validatePrevious();
ggaren@apple.com3a7b4792011-10-17 20:43:43 +0000121}
122
fpizlo@apple.com622ead72011-11-01 06:43:37 +0000123bool MarkStackArray::refill()
ggaren@apple.com3a7b4792011-10-17 20:43:43 +0000124{
fpizlo@apple.com622ead72011-11-01 06:43:37 +0000125 validatePrevious();
126 if (top())
127 return true;
128 MarkStackSegment* toFree = m_topSegment;
129 MarkStackSegment* previous = m_topSegment->m_previous;
130 if (!previous)
131 return false;
132 ASSERT(m_numberOfPreviousSegments);
133 m_numberOfPreviousSegments--;
134 m_topSegment = previous;
135 m_allocator.release(toFree);
136 setTopForFullSegment();
137 validatePrevious();
138 return true;
139}
140
141bool MarkStackArray::donateSomeCellsTo(MarkStackArray& other)
142{
143 ASSERT(m_segmentCapacity == other.m_segmentCapacity);
144 validatePrevious();
145 other.validatePrevious();
146
147 // Fast check: see if the other mark stack already has enough segments.
commit-queue@webkit.orga2e15982011-12-15 12:01:30 +0000148 if (other.m_numberOfPreviousSegments + 1 >= Options::maximumNumberOfSharedSegments)
fpizlo@apple.com622ead72011-11-01 06:43:37 +0000149 return false;
150
commit-queue@webkit.orga2e15982011-12-15 12:01:30 +0000151 size_t numberOfCellsToKeep = Options::minimumNumberOfCellsToKeep;
fpizlo@apple.com622ead72011-11-01 06:43:37 +0000152 ASSERT(m_top > numberOfCellsToKeep || m_topSegment->m_previous);
153
154 // Looks like we should donate! Give the other mark stack all of our
155 // previous segments, and then top it off.
156 MarkStackSegment* previous = m_topSegment->m_previous;
157 while (previous) {
158 ASSERT(m_numberOfPreviousSegments);
159
160 MarkStackSegment* current = previous;
161 previous = current->m_previous;
162
163 current->m_previous = other.m_topSegment->m_previous;
164 other.m_topSegment->m_previous = current;
165
166 m_numberOfPreviousSegments--;
167 other.m_numberOfPreviousSegments++;
168 }
169 ASSERT(!m_numberOfPreviousSegments);
170 m_topSegment->m_previous = 0;
171 validatePrevious();
172 other.validatePrevious();
173
174 // Now top off. We want to keep at a minimum numberOfCellsToKeep, but if
175 // we really have a lot of work, we give up half.
176 if (m_top > numberOfCellsToKeep * 2)
177 numberOfCellsToKeep = m_top / 2;
178 while (m_top > numberOfCellsToKeep)
179 other.append(removeLast());
180
181 return true;
182}
183
184void MarkStackArray::stealSomeCellsFrom(MarkStackArray& other)
185{
186 ASSERT(m_segmentCapacity == other.m_segmentCapacity);
187 validatePrevious();
188 other.validatePrevious();
189
190 // If other has an entire segment, steal it and return.
191 if (other.m_topSegment->m_previous) {
192 ASSERT(other.m_topSegment->m_previous->m_top == m_segmentCapacity);
193
194 // First remove a segment from other.
195 MarkStackSegment* current = other.m_topSegment->m_previous;
196 other.m_topSegment->m_previous = current->m_previous;
197 other.m_numberOfPreviousSegments--;
198
199 ASSERT(!!other.m_numberOfPreviousSegments == !!other.m_topSegment->m_previous);
200
201 // Now add it to this.
202 current->m_previous = m_topSegment->m_previous;
203 m_topSegment->m_previous = current;
204 m_numberOfPreviousSegments++;
205
206 validatePrevious();
207 other.validatePrevious();
ggaren@apple.com3a7b4792011-10-17 20:43:43 +0000208 return;
fpizlo@apple.com622ead72011-11-01 06:43:37 +0000209 }
210
211 // Otherwise drain 1/Nth of the shared array where N is the number of
commit-queue@webkit.orga2e15982011-12-15 12:01:30 +0000212 // workers, or Options::minimumNumberOfCellsToKeep, whichever is bigger.
213 size_t numberOfCellsToSteal = std::max((size_t)Options::minimumNumberOfCellsToKeep, other.size() / Options::numberOfGCMarkers);
fpizlo@apple.com622ead72011-11-01 06:43:37 +0000214 while (numberOfCellsToSteal-- > 0 && other.canRemoveLast())
215 append(other.removeLast());
216}
217
218#if ENABLE(PARALLEL_GC)
219void MarkStackThreadSharedData::markingThreadMain()
220{
221 WTF::registerGCThread();
mhahnenberg@apple.comc58d54d2011-12-16 19:06:44 +0000222 SlotVisitor slotVisitor(*this);
fpizlo@apple.com622ead72011-11-01 06:43:37 +0000223 ParallelModeEnabler enabler(slotVisitor);
224 slotVisitor.drainFromShared(SlotVisitor::SlaveDrain);
225}
226
227void* MarkStackThreadSharedData::markingThreadStartFunc(void* shared)
228{
229 static_cast<MarkStackThreadSharedData*>(shared)->markingThreadMain();
230 return 0;
231}
ggaren@apple.com3a7b4792011-10-17 20:43:43 +0000232#endif
fpizlo@apple.com622ead72011-11-01 06:43:37 +0000233
234MarkStackThreadSharedData::MarkStackThreadSharedData(JSGlobalData* globalData)
235 : m_globalData(globalData)
236 , m_sharedMarkStack(m_segmentAllocator)
237 , m_numberOfActiveParallelMarkers(0)
238 , m_parallelMarkersShouldExit(false)
fpizlo@apple.com622ead72011-11-01 06:43:37 +0000239{
240#if ENABLE(PARALLEL_GC)
commit-queue@webkit.orga2e15982011-12-15 12:01:30 +0000241 for (unsigned i = 1; i < Options::numberOfGCMarkers; ++i) {
fpizlo@apple.com622ead72011-11-01 06:43:37 +0000242 m_markingThreads.append(createThread(markingThreadStartFunc, this, "JavaScriptCore::Marking"));
243 ASSERT(m_markingThreads.last());
244 }
245#endif
246}
247
248MarkStackThreadSharedData::~MarkStackThreadSharedData()
249{
250#if ENABLE(PARALLEL_GC)
251 // Destroy our marking threads.
252 {
253 MutexLocker locker(m_markingLock);
254 m_parallelMarkersShouldExit = true;
255 m_markingCondition.broadcast();
256 }
257 for (unsigned i = 0; i < m_markingThreads.size(); ++i)
258 waitForThreadCompletion(m_markingThreads[i], 0);
259#endif
260}
261
262void MarkStackThreadSharedData::reset()
263{
264 ASSERT(!m_numberOfActiveParallelMarkers);
265 ASSERT(!m_parallelMarkersShouldExit);
266 ASSERT(m_sharedMarkStack.isEmpty());
267
268#if ENABLE(PARALLEL_GC)
269 m_segmentAllocator.shrinkReserve();
270 m_opaqueRoots.clear();
271#else
272 ASSERT(m_opaqueRoots.isEmpty());
273#endif
fpizlo@apple.comf8e2ef82011-11-15 06:58:19 +0000274
275 m_weakReferenceHarvesters.removeAll();
ggaren@apple.com3a7b4792011-10-17 20:43:43 +0000276}
277
ggaren@apple.com21ef0ea2011-04-06 03:44:48 +0000278void MarkStack::reset()
oliver@apple.com5fca29f2009-08-11 04:35:02 +0000279{
oliver@apple.com73792612011-10-12 00:24:12 +0000280 m_visitCount = 0;
fpizlo@apple.com622ead72011-11-01 06:43:37 +0000281 ASSERT(m_stack.isEmpty());
282#if ENABLE(PARALLEL_GC)
283 ASSERT(m_opaqueRoots.isEmpty()); // Should have merged by now.
284#else
ggaren@apple.com21ef0ea2011-04-06 03:44:48 +0000285 m_opaqueRoots.clear();
fpizlo@apple.com622ead72011-11-01 06:43:37 +0000286#endif
oliver@apple.com5fca29f2009-08-11 04:35:02 +0000287}
288
ggaren@apple.com02bf0402011-03-16 18:35:49 +0000289void MarkStack::append(ConservativeRoots& conservativeRoots)
290{
291 JSCell** roots = conservativeRoots.roots();
292 size_t size = conservativeRoots.size();
293 for (size_t i = 0; i < size; ++i)
294 internalAppend(roots[i]);
295}
296
mhahnenberg@apple.comc58d54d2011-12-16 19:06:44 +0000297ALWAYS_INLINE static void visitChildren(SlotVisitor& visitor, const JSCell* cell)
ggaren@apple.comb7d71072011-03-16 18:16:03 +0000298{
fpizlo@apple.comd6bcd372011-08-26 22:23:43 +0000299#if ENABLE(SIMPLE_HEAP_PROFILING)
300 m_visitedTypeCounts.count(cell);
301#endif
302
ggaren@apple.comb7d71072011-03-16 18:16:03 +0000303 ASSERT(Heap::isMarked(cell));
ggaren@apple.com3a7b4792011-10-17 20:43:43 +0000304
mhahnenberg@apple.comc58d54d2011-12-16 19:06:44 +0000305 if (isJSString(cell)) {
ggaren@apple.comfbf6d9a2011-10-19 02:54:29 +0000306 JSString::visitChildren(const_cast<JSCell*>(cell), visitor);
ggaren@apple.com3a7b4792011-10-17 20:43:43 +0000307 return;
ggaren@apple.comfbf6d9a2011-10-19 02:54:29 +0000308 }
ggaren@apple.com3a7b4792011-10-17 20:43:43 +0000309
mhahnenberg@apple.comc58d54d2011-12-16 19:06:44 +0000310 if (isJSFinalObject(cell)) {
ggaren@apple.com3a7b4792011-10-17 20:43:43 +0000311 JSObject::visitChildren(const_cast<JSCell*>(cell), visitor);
oliver@apple.comb2fa0dc2011-04-15 23:55:42 +0000312 return;
313 }
314
mhahnenberg@apple.comc58d54d2011-12-16 19:06:44 +0000315 if (isJSArray(cell)) {
ggaren@apple.com3a7b4792011-10-17 20:43:43 +0000316 JSArray::visitChildren(const_cast<JSCell*>(cell), visitor);
ggaren@apple.comb7d71072011-03-16 18:16:03 +0000317 return;
318 }
ggaren@apple.com3a7b4792011-10-17 20:43:43 +0000319
320 cell->methodTable()->visitChildren(const_cast<JSCell*>(cell), visitor);
oliver@apple.com5fca29f2009-08-11 04:35:02 +0000321}
ggaren@apple.comb7d71072011-03-16 18:16:03 +0000322
fpizlo@apple.com622ead72011-11-01 06:43:37 +0000323void SlotVisitor::donateSlow()
324{
325 // Refuse to donate if shared has more entries than I do.
326 if (m_shared.m_sharedMarkStack.size() > m_stack.size())
327 return;
328 MutexLocker locker(m_shared.m_markingLock);
329 if (m_stack.donateSomeCellsTo(m_shared.m_sharedMarkStack)) {
330 // Only wake up threads if the shared stack is big enough; otherwise assume that
331 // it's more profitable for us to just scan this ourselves later.
commit-queue@webkit.orga2e15982011-12-15 12:01:30 +0000332 if (m_shared.m_sharedMarkStack.size() >= Options::sharedStackWakeupThreshold)
fpizlo@apple.com622ead72011-11-01 06:43:37 +0000333 m_shared.m_markingCondition.broadcast();
334 }
335}
336
ggaren@apple.com6e1f8c12011-06-16 22:01:43 +0000337void SlotVisitor::drain()
ggaren@apple.comb7d71072011-03-16 18:16:03 +0000338{
fpizlo@apple.com622ead72011-11-01 06:43:37 +0000339 ASSERT(m_isInParallelMode);
340
fpizlo@apple.com622ead72011-11-01 06:43:37 +0000341#if ENABLE(PARALLEL_GC)
commit-queue@webkit.orga2e15982011-12-15 12:01:30 +0000342 if (Options::numberOfGCMarkers > 1) {
fpizlo@apple.com622ead72011-11-01 06:43:37 +0000343 while (!m_stack.isEmpty()) {
344 m_stack.refill();
commit-queue@webkit.orga2e15982011-12-15 12:01:30 +0000345 for (unsigned countdown = Options::minimumNumberOfScansBetweenRebalance; m_stack.canRemoveLast() && countdown--;)
mhahnenberg@apple.comc58d54d2011-12-16 19:06:44 +0000346 visitChildren(*this, m_stack.removeLast());
fpizlo@apple.com622ead72011-11-01 06:43:37 +0000347 donateKnownParallel();
348 }
349
350 mergeOpaqueRootsIfNecessary();
351 return;
352 }
353#endif
354
355 while (!m_stack.isEmpty()) {
356 m_stack.refill();
357 while (m_stack.canRemoveLast())
mhahnenberg@apple.comc58d54d2011-12-16 19:06:44 +0000358 visitChildren(*this, m_stack.removeLast());
fpizlo@apple.com622ead72011-11-01 06:43:37 +0000359 }
360}
361
362void SlotVisitor::drainFromShared(SharedDrainMode sharedDrainMode)
363{
364 ASSERT(m_isInParallelMode);
365
commit-queue@webkit.orga2e15982011-12-15 12:01:30 +0000366 ASSERT(Options::numberOfGCMarkers);
fpizlo@apple.com622ead72011-11-01 06:43:37 +0000367
368 bool shouldBeParallel;
369
370#if ENABLE(PARALLEL_GC)
commit-queue@webkit.orga2e15982011-12-15 12:01:30 +0000371 shouldBeParallel = Options::numberOfGCMarkers > 1;
fpizlo@apple.com622ead72011-11-01 06:43:37 +0000372#else
commit-queue@webkit.orga2e15982011-12-15 12:01:30 +0000373 ASSERT(Options::numberOfGCMarkers == 1);
fpizlo@apple.com622ead72011-11-01 06:43:37 +0000374 shouldBeParallel = false;
375#endif
376
377 if (!shouldBeParallel) {
378 // This call should be a no-op.
379 ASSERT_UNUSED(sharedDrainMode, sharedDrainMode == MasterDrain);
380 ASSERT(m_stack.isEmpty());
381 ASSERT(m_shared.m_sharedMarkStack.isEmpty());
382 return;
383 }
384
385#if ENABLE(PARALLEL_GC)
386 {
387 MutexLocker locker(m_shared.m_markingLock);
388 m_shared.m_numberOfActiveParallelMarkers++;
389 }
390 while (true) {
391 {
392 MutexLocker locker(m_shared.m_markingLock);
393 m_shared.m_numberOfActiveParallelMarkers--;
394
395 // How we wait differs depending on drain mode.
396 if (sharedDrainMode == MasterDrain) {
397 // Wait until either termination is reached, or until there is some work
398 // for us to do.
399 while (true) {
400 // Did we reach termination?
401 if (!m_shared.m_numberOfActiveParallelMarkers && m_shared.m_sharedMarkStack.isEmpty())
402 return;
403
404 // Is there work to be done?
405 if (!m_shared.m_sharedMarkStack.isEmpty())
406 break;
407
408 // Otherwise wait.
409 m_shared.m_markingCondition.wait(m_shared.m_markingLock);
410 }
411 } else {
412 ASSERT(sharedDrainMode == SlaveDrain);
413
414 // Did we detect termination? If so, let the master know.
415 if (!m_shared.m_numberOfActiveParallelMarkers && m_shared.m_sharedMarkStack.isEmpty())
416 m_shared.m_markingCondition.broadcast();
417
418 while (m_shared.m_sharedMarkStack.isEmpty() && !m_shared.m_parallelMarkersShouldExit)
419 m_shared.m_markingCondition.wait(m_shared.m_markingLock);
420
421 // Is the VM exiting? If so, exit this thread.
422 if (m_shared.m_parallelMarkersShouldExit)
423 return;
424 }
425
426 m_stack.stealSomeCellsFrom(m_shared.m_sharedMarkStack);
427 m_shared.m_numberOfActiveParallelMarkers++;
428 }
429
430 drain();
431 }
432#endif
433}
434
435void MarkStack::mergeOpaqueRoots()
436{
437 ASSERT(!m_opaqueRoots.isEmpty()); // Should only be called when opaque roots are non-empty.
438 {
439 MutexLocker locker(m_shared.m_opaqueRootsLock);
440 HashSet<void*>::iterator begin = m_opaqueRoots.begin();
441 HashSet<void*>::iterator end = m_opaqueRoots.end();
442 for (HashSet<void*>::iterator iter = begin; iter != end; ++iter)
443 m_shared.m_opaqueRoots.add(*iter);
444 }
445 m_opaqueRoots.clear();
ggaren@apple.comb7d71072011-03-16 18:16:03 +0000446}
447
fpizlo@apple.comd13163d2011-09-03 05:14:04 +0000448void SlotVisitor::harvestWeakReferences()
449{
fpizlo@apple.comf8e2ef82011-11-15 06:58:19 +0000450 for (WeakReferenceHarvester* current = m_shared.m_weakReferenceHarvesters.head(); current; current = current->next())
451 current->visitWeakReferences(*this);
fpizlo@apple.comf5e1fe12011-11-10 21:59:39 +0000452}
453
454void SlotVisitor::finalizeUnconditionalFinalizers()
455{
456 while (m_shared.m_unconditionalFinalizers.hasNext())
457 m_shared.m_unconditionalFinalizers.removeNext()->finalizeUnconditionally();
fpizlo@apple.comd13163d2011-09-03 05:14:04 +0000458}
459
oliver@apple.com450024a2011-05-12 00:49:58 +0000460#if ENABLE(GC_VALIDATION)
ggaren@apple.com3a7b4792011-10-17 20:43:43 +0000461void MarkStack::validate(JSCell* cell)
oliver@apple.comd5b6cfa2011-05-11 01:34:44 +0000462{
oliver@apple.com62c26102011-05-11 20:10:29 +0000463 if (!cell)
464 CRASH();
465
466 if (!cell->structure())
467 CRASH();
468
oliver@apple.comd5b6cfa2011-05-11 01:34:44 +0000469 // Both the cell's structure, and the cell's structure's structure should be the Structure Structure.
470 // I hate this sentence.
oliver@apple.com62c26102011-05-11 20:10:29 +0000471 if (cell->structure()->structure()->JSCell::classInfo() != cell->structure()->JSCell::classInfo())
472 CRASH();
oliver@apple.comd5b6cfa2011-05-11 01:34:44 +0000473}
oliver@apple.com8c798d22011-09-11 21:11:11 +0000474#else
ggaren@apple.com3a7b4792011-10-17 20:43:43 +0000475void MarkStack::validate(JSCell*)
oliver@apple.com8c798d22011-09-11 21:11:11 +0000476{
ggaren@apple.com3a7b4792011-10-17 20:43:43 +0000477}
oliver@apple.com450024a2011-05-12 00:49:58 +0000478#endif
oliver@apple.comd5b6cfa2011-05-11 01:34:44 +0000479
ggaren@apple.comb7d71072011-03-16 18:16:03 +0000480} // namespace JSC