1 // -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*-
2 // vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */
4 // ***** BEGIN LICENSE BLOCK *****
5 // Version: MPL 1.1/GPL 2.0/LGPL 2.1
7 // The contents of this file are subject to the Mozilla Public License Version
8 // 1.1 (the "License"); you may not use this file except in compliance with
9 // the License. You may obtain a copy of the License at
10 // http://www.mozilla.org/MPL/
12 // Software distributed under the License is distributed on an "AS IS" basis,
13 // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 // for the specific language governing rights and limitations under the
17 // The Original Code is [Open Source Virtual Machine.].
19 // The Initial Developer of the Original Code is
20 // Adobe System Incorporated.
21 // Portions created by the Initial Developer are Copyright (C) 2004-2006
22 // the Initial Developer. All Rights Reserved.
27 // Alternatively, the contents of this file may be used under the terms of
28 // either the GNU General Public License Version 2 or later (the "GPL"), or
29 // the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 // in which case the provisions of the GPL or the LGPL are applicable instead
31 // of those above. If you wish to allow use of your version of this file only
32 // under the terms of either the GPL or the LGPL, and not to allow others to
33 // use your version of this file under the terms of the MPL, indicate your
34 // decision by deleting the provisions above and replace them with the notice
35 // and other provisions required by the GPL or the LGPL. If you do not delete
36 // the provisions above, a recipient may use your version of this file under
37 // the terms of any one of the MPL, the GPL or the LGPL.
39 // ***** END LICENSE BLOCK ***** */
46 class DeleteInFinalizer : public GCFinalizedObject {
48 // note "small" is a reserved identifier in Visual C++ for Windows Mobile (#defined to be 'char')
49 DeleteInFinalizer(GCFinalizedObject *big, GCFinalizedObject *small_) : big(big), small_(small_) {};
50 ~DeleteInFinalizer() { delete big; delete small_; }
52 GCFinalizedObject *big;
53 GCFinalizedObject *small_;
56 // Any small object would do
57 class AllocInFinalizer2 : public GCObject {
62 class AllocInFinalizer : public GCFinalizedObject {
65 ~AllocInFinalizer() { new (GC::GetGC(this)) AllocInFinalizer2(); }
72 MMgc::FixedMalloc *fm;
75 gc=new MMgc::GC(MMgc::GCHeap::GetGCHeap(), MMgc::GC::kIncrementalGC);
78 gc=new MMgc::GC(MMgc::GCHeap::GetGCHeap(), MMgc::GC::kIncrementalGC);
84 %%test create_gc_instance
87 %%test create_gc_object
89 MyGCObject *mygcobject;
90 mygcobject = (MyGCObject *)new (gc) MyGCObject();
91 %%verify mygcobject!=NULL
93 %%verify mygcobject->i==10
97 MyGCObject *mygcobject;
98 int inuse=(int)gc->GetBytesInUse();
99 mygcobject = (MyGCObject *)new (gc) MyGCObject();
100 // AvmLog("bytes in use before %d after %d\n",inuse,(int)gc->GetBytesInUse());
101 %%verify gc->GetBytesInUse()==inuse + sizeof(MyGCObject) + DebugSize()
106 MyGCObject *mygcobject;
107 int inuse=(int)gc->GetBytesInUse();
108 mygcobject = (MyGCObject *)new (gc) MyGCObject();
109 %%verify (int)gc->GetBytesInUse()>inuse
111 // AvmLog("collect: inuse=%d current=%d\n",inuse,(int)gc->GetBytesInUse());
113 // AvmLog("collect: inuse=%d current=%d\n",inuse,(int)gc->GetBytesInUse());
114 %%verify (int)gc->GetBytesInUse()<=inuse
117 %%verify gc->GetGCHeap()!=NULL
120 MMgc::FixedAlloc *fa;
121 fa=new MMgc::FixedAlloc(2048,MMgc::GCHeap::GetGCHeap());
122 %%verify (int)fa->GetMaxAlloc()==0
123 %%verify (int)fa->GetNumBlocks()==0
124 void *data1=fa->Alloc(2048);
125 %%verify MMgc::FixedAlloc::GetFixedAlloc(data1)==fa
126 %%verify fa->GetBytesInUse()==DebugSize()+2048
127 %%verify fa->GetItemSize()==2048
128 void *data2=fa->Alloc(2048);
129 %%verify MMgc::FixedAlloc::GetFixedAlloc(data2)==fa
130 // AvmLog("fa->GetItemSize=%d\n",(int)fa->GetItemSize());
131 %%verify (int)fa->GetItemSize()==2048
133 %%verify (int)fa->GetItemSize()==2048
134 %%verify (int)fa->GetMaxAlloc()==1
135 %%verify (int)fa->GetNumBlocks()==1
140 fm=MMgc::FixedMalloc::GetFixedMalloc();
141 int start=(int)fm->GetBytesInUse();
142 int starttotal=(int)fm->GetTotalSize();
143 // AvmLog("fm->GetBytesInUse()=%d\n",(int)fm->GetBytesInUse());
144 %%verify (int)fm->GetBytesInUse()==start
145 // AvmLog("fm->GetTotalSize()=%d\n",(int)fm->GetTotalSize());
146 %%verify (int)fm->GetTotalSize()==starttotal
147 void *obj=fm->Alloc(8192);
148 // AvmLog("fm->GetBytesInUse()=%d\n",(int)fm->GetBytesInUse());
149 // %%verify fm->GetBytesInUse()==start + 8192 + MMgc::DebugSize()
150 // AvmLog("fm->GetTotalSize()=%d\n",(int)fm->GetTotalSize());
151 // %%verify (int)fm->GetTotalSize()==starttotal+2
153 // AvmLog("fm->GetBytesInUse()=%d\n",(int)fm->GetBytesInUse());
154 %%verify (int)fm->GetBytesInUse()==start
155 // AvmLog("fm->GetTotalSize()=%d\n",(int)fm->GetTotalSize());
156 %%verify (int)fm->GetTotalSize()==starttotal
157 obj=fm->Calloc(1024,10);
158 // AvmLog("fm->GetBytesInUse()=%d\n",(int)fm->GetBytesInUse());
159 // FixedMalloc is currently (as of redux 3229) tracking large allocs using a list of
160 // small objects, in some debug modes. So we can't have a precise test here.
161 %%verify (int)fm->GetBytesInUse()>=start+1024*12 && (int)fm->GetBytesInUse()<=start+1024*12+64
162 // AvmLog("fm->GetTotalSize()=%d\n",(int)fm->GetTotalSize());
163 %%verify (int)fm->GetTotalSize()==starttotal+3
165 %%verify (int)fm->GetBytesInUse()==start
166 %%verify (int)fm->GetTotalSize()==starttotal
169 MMgc::GCHeap *gh=MMgc::GCHeap::GetGCHeap();
170 int startfreeheap=(int)gh->GetFreeHeapSize();
171 // %%verify (int)gh->GetTotalHeapSize()==128
172 // AvmLog("gh->GetFreeHeapSize()=%d\n",(int)gh->GetFreeHeapSize());
173 %%verify (int)gh->GetFreeHeapSize()==startfreeheap
174 //gh->Config().heapLimit = 1024;
175 // %%verify (int)gh->GetTotalHeapSize()==128
176 // AvmLog("gh->GetFreeHeapSize()=%d\n",(int)gh->GetFreeHeapSize());
177 %%verify (int)gh->GetFreeHeapSize()==startfreeheap
178 void *data = gh->Alloc(10,MMgc::GCHeap::kExpand | MMgc::GCHeap::kZero);
179 %%verify (int)gh->GetTotalHeapSize()>startfreeheap
180 // AvmLog("gh->GetFreeHeapSize()=%d\n",(int)gh->GetFreeHeapSize());
181 gh->FreeNoProfile(data);
184 MMgc::GCHeap *gh=MMgc::GCHeap::GetGCHeap();
186 // Tricky: try to provoke some internal asserts
188 for ( unsigned i=0 ; i < ARRAY_SIZE(d) ; i++ ) {
190 void *data = gh->Alloc(10,MMgc::GCHeap::flags_Alloc, 4);
193 for ( unsigned i=0 ; i < ARRAY_SIZE(d) ; i++ )
197 for ( size_t k=2 ; k <= 256 ; k *= 2 ) {
198 void *data = gh->Alloc(10,MMgc::GCHeap::flags_Alloc, k);
199 %%verify ((uintptr_t)data & (k*MMgc::GCHeap::kBlockSize - 1)) == 0
200 %%verify gh->Size(data) == 10
206 MyGCObject *mygcobject;
207 mygcobject = (MyGCObject *)new (gc) MyGCObject();
208 %%verify (MyGCObject *)gc->FindBeginningGuarded(mygcobject)==mygcobject
209 %%verify (MyGCObject *)gc->FindBeginningFast(mygcobject)==mygcobject
211 // Bugzilla 542529 - in debug mode we would assert here due to logic flaws in the allocatr
212 %%test finalizerAlloc
214 new (gc) AllocInFinalizer();
218 %%test finalizerDelete
220 new (gc) DeleteInFinalizer(new (gc, 100) GCFinalizedObject(), new (gc) GCFinalizedObject());
221 //delete m; delete m; // this verifies we crash, it does
224 GCFinalizedObject *gcfo = new (gc) GCFinalizedObject();
225 gcfo->~GCFinalizedObject();
226 gcfo->~GCFinalizedObject(); // this used to be a deleteing dtor and would crash, not anymore
231 GC *gcb = new GC(GCHeap::GetGCHeap(), GC::kIncrementalGC);
233 void *a = gc->Alloc(8);
244 // just fishing for asserts/hangs/crashes
248 %%test collectDormantGC
250 GC *gcb = new GC(GCHeap::GetGCHeap(), GC::kIncrementalGC);
256 // this will cause a Collection in gcb
257 GCHeap::SignalExternalFreeMemory();
260 // just fishing for asserts/hangs/crashes
264 %%test regression_551169
266 GC *testGC = new GC(GCHeap::GetGCHeap(), GC::kIncrementalGC);
268 MMGC_GCENTER(testGC);
269 testGC->StartIncrementalMark();
270 // self test for tricky GCRoot deletion logic
271 // do this a bunch, idea is to try to hit GetItemAbove border edge cases
272 for(int i=0;i<10000;i++) {
273 GCRoot *fauxRoot = new GCRoot(testGC, new char[GC::kMarkItemSplitThreshold*2], GC::kMarkItemSplitThreshold*2);
274 testGC->MarkAllRoots();
275 // tail of fauxRoot is on stack
276 GCWorkItem *sentinel = fauxRoot->GetMarkStackSentinelPointer();
278 %%verify sentinel->GetSentinelPointer() == fauxRoot
279 GCWorkItem *tail = testGC->m_incrementalWork.GetItemAbove(sentinel);
280 %%verify tail->iptr + tail->GetSize() == (uintptr_t) fauxRoot->End()
281 %%verify sentinel != NULL
283 delete [] (char*)fauxRoot->Get();
286 %%verify sentinel->GetSentinelType() == GCWorkItem::kDeadItem
287 %%verify testGC->m_incrementalWork.GetItemAbove(sentinel)->GetSentinelType() == GCWorkItem::kDeadItem
291 testGC->ClearMarkStack();
292 testGC->ClearMarks();