Bug 604547: Set expectedfail for deep failure (r=cpeyer)
[tamarin-stm.git] / extensions / ST_mmgc_basics.st
blob8c4eb73e1a8579dad7ff666866bab9dfd78a9c06
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) */
3 //
4 // ***** BEGIN LICENSE BLOCK *****
5 // Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 //
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
15 // License.
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.
24 // Contributor(s):
25 //   Adobe AS3 Team
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 ***** */
41 %%component mmgc
42 %%category basics
44 %%methods
45 using namespace MMgc;
46 class DeleteInFinalizer : public GCFinalizedObject {
47  public:
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_; }
51  private:
52   GCFinalizedObject *big;
53   GCFinalizedObject *small_;
56 // Any small object would do
57 class AllocInFinalizer2 : public GCObject {
58 public:
59     void* dummy;
62 class AllocInFinalizer : public GCFinalizedObject {
63 public:
64     AllocInFinalizer() {}
65     ~AllocInFinalizer() { new (GC::GetGC(this)) AllocInFinalizer2(); }
68 %%decls
69 private:
70     MMgc::GC *gc;
71     MMgc::FixedAlloc *fa;
72     MMgc::FixedMalloc *fm;
74 %%prologue
75     gc=new MMgc::GC(MMgc::GCHeap::GetGCHeap(), MMgc::GC::kIncrementalGC);
76     if (gc==NULL) {
77         MMgc::GCHeap::Init();
78         gc=new MMgc::GC(MMgc::GCHeap::GetGCHeap(), MMgc::GC::kIncrementalGC);
79     }
81 %%epilogue
82 delete gc;
84 %%test create_gc_instance
85     %%verify gc != NULL
87 %%test create_gc_object
88     MMGC_GCENTER(gc);
89     MyGCObject *mygcobject;
90     mygcobject = (MyGCObject *)new (gc) MyGCObject();
91     %%verify mygcobject!=NULL
92     mygcobject->i=10;
93     %%verify mygcobject->i==10
95 %%test get_bytesinuse
96     MMGC_GCENTER(gc);
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()
102     delete mygcobject;
104 %%test collect
105     MMGC_GCENTER(gc);
106     MyGCObject *mygcobject;
107     int inuse=(int)gc->GetBytesInUse();
108     mygcobject = (MyGCObject *)new (gc) MyGCObject();
109     %%verify (int)gc->GetBytesInUse()>inuse
110     delete mygcobject;
111 //    AvmLog("collect: inuse=%d current=%d\n",inuse,(int)gc->GetBytesInUse());
112     gc->Collect();
113 //    AvmLog("collect: inuse=%d current=%d\n",inuse,(int)gc->GetBytesInUse());
114     %%verify (int)gc->GetBytesInUse()<=inuse
116 %%test getgcheap
117     %%verify gc->GetGCHeap()!=NULL
119 %%test fixedAlloc
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
132     fa->Free(data1);
133     %%verify (int)fa->GetItemSize()==2048
134     %%verify (int)fa->GetMaxAlloc()==1
135     %%verify (int)fa->GetNumBlocks()==1
136     fa->Free(data2);
137     delete fa;
139 %%test fixedMalloc
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
152     fm->Free(obj);
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
164     fm->Free(obj);
165     %%verify (int)fm->GetBytesInUse()==start
166     %%verify (int)fm->GetTotalSize()==starttotal
168 %%test gcheap
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);
182        
183 %%test gcheapAlign
184     MMgc::GCHeap *gh=MMgc::GCHeap::GetGCHeap();
186     // Tricky: try to provoke some internal asserts
187     void *d[1000];
188     for ( unsigned i=0 ; i < ARRAY_SIZE(d) ; i++ ) {
189         d[i] = gh->Alloc(1);
190         void *data = gh->Alloc(10,MMgc::GCHeap::flags_Alloc, 4);
191         gh->Free(data);
192     }
193     for ( unsigned i=0 ; i < ARRAY_SIZE(d) ; i++ )
194         gh->Free(d[i]);
196     // 
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
201         gh->Free(data);
202     }
204 %%test gcmethods
205     MMGC_GCENTER(gc);
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
213     MMGC_GCENTER(gc);
214     new (gc) AllocInFinalizer();
215     gc->Collect(false);
216     %%verify true
218 %%test finalizerDelete
219     MMGC_GCENTER(gc);
220     new (gc) DeleteInFinalizer(new (gc, 100) GCFinalizedObject(), new (gc) GCFinalizedObject());
221     //delete m; delete m; // this verifies we crash, it does
222     gc->Collect(false);
223     %%verify true
224     GCFinalizedObject *gcfo = new (gc) GCFinalizedObject();
225     gcfo->~GCFinalizedObject();
226     gcfo->~GCFinalizedObject(); // this used to be a deleteing dtor and would crash, not anymore
230 %%test nestedGCs
231     GC *gcb = new GC(GCHeap::GetGCHeap(), GC::kIncrementalGC);
232     MMGC_GCENTER(gc);
233     void *a = gc->Alloc(8);
234     {
235         MMGC_GCENTER(gcb);
236         a = gcb->Alloc(8);
237         {
238             MMGC_GCENTER(gc);
239             a = gc->Alloc(8);
240         }
241         a = gcb->Alloc(8);
242     }
243     a = gc->Alloc(8);
244     // just fishing for asserts/hangs/crashes
245     %%verify true
246     delete gcb;
248 %%test collectDormantGC
249     {
250         GC *gcb = new GC(GCHeap::GetGCHeap(), GC::kIncrementalGC);
251         {
252             MMGC_GCENTER(gcb);
253             gcb->Alloc(8);
254         }
256         // this will cause a Collection in gcb
257         GCHeap::SignalExternalFreeMemory();
258         delete gcb;
260         // just fishing for asserts/hangs/crashes
261         %%verify true
262     }
264 %%test regression_551169
265     {
266         GC *testGC = new GC(GCHeap::GetGCHeap(), GC::kIncrementalGC);
267         {
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();
277                 if(sentinel) {
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
282                 }
283                 delete [] (char*)fauxRoot->Get();
284                 delete fauxRoot;
285                 if(sentinel) {
286                     %%verify sentinel->GetSentinelType() == GCWorkItem::kDeadItem
287                     %%verify testGC->m_incrementalWork.GetItemAbove(sentinel)->GetSentinelType() == GCWorkItem::kDeadItem
288                 }
289             }
290             testGC->Mark();
291             testGC->ClearMarkStack();
292             testGC->ClearMarks();
293         }
294         delete testGC;
295     }