Bug Summary

File:platform/mac/avmshell/../../../extensions/SelftestExec.cpp
Location:line 1691, column 11
Description:Value stored to 'a' during its initialization is never read

Annotated Source Code

1// Generated from ST_avmplus_basics.st, ST_avmplus_builtins.st, ST_avmplus_peephole.st, ST_mmgc_543560.st, ST_mmgc_575631.st, ST_mmgc_580603.st, ST_mmgc_637993.st, ST_mmgc_basics.st, ST_mmgc_dependent.st, ST_mmgc_exact.st, ST_mmgc_finalize_uninit.st, ST_mmgc_gcheap.st, ST_mmgc_mmfx_array.st, ST_mmgc_threads.st, ST_mmgc_weakref.st, ST_vmbase_concurrency.st, ST_vmbase_safepoints.st, ST_vmpi_threads.st
2// Generated from ST_avmplus_basics.st
3// -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*-
4// vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */
5//
6// ***** BEGIN LICENSE BLOCK *****
7// Version: MPL 1.1/GPL 2.0/LGPL 2.1
8//
9// The contents of this file are subject to the Mozilla Public License Version
10// 1.1 (the "License"); you may not use this file except in compliance with
11// the License. You may obtain a copy of the License at
12// http://www.mozilla.org/MPL/
13//
14// Software distributed under the License is distributed on an "AS IS" basis,
15// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
16// for the specific language governing rights and limitations under the
17// License.
18//
19// The Original Code is [Open Source Virtual Machine.].
20//
21// The Initial Developer of the Original Code is
22// Adobe System Incorporated.
23// Portions created by the Initial Developer are Copyright (C) 2004-2006
24// the Initial Developer. All Rights Reserved.
25//
26// Contributor(s):
27// Adobe AS3 Team
28//
29// Alternatively, the contents of this file may be used under the terms of
30// either the GNU General Public License Version 2 or later (the "GPL"), or
31// the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
32// in which case the provisions of the GPL or the LGPL are applicable instead
33// of those above. If you wish to allow use of your version of this file only
34// under the terms of either the GPL or the LGPL, and not to allow others to
35// use your version of this file under the terms of the MPL, indicate your
36// decision by deleting the provisions above and replace them with the notice
37// and other provisions required by the GPL or the LGPL. If you do not delete
38// the provisions above, a recipient may use your version of this file under
39// the terms of any one of the MPL, the GPL or the LGPL.
40//
41// ***** END LICENSE BLOCK ***** */
42
43#include "avmshell.h"
44#ifdef VMCFG_SELFTEST
45namespace avmplus {
46namespace ST_avmplus_basics {
47class ST_avmplus_basics : public Selftest {
48public:
49ST_avmplus_basics(AvmCore* core);
50virtual void run(int n);
51private:
52static const char* ST_names[];
53static const boolbool ST_explicits[];
54void test0();
55void test1();
56void test2();
57void test3();
58void test4();
59void test5();
60void test6();
61void test7();
62};
63ST_avmplus_basics::ST_avmplus_basics(AvmCore* core)
64 : Selftest(core, "avmplus", "basics", ST_avmplus_basics::ST_names,ST_avmplus_basics::ST_explicits)
65{}
66const char* ST_avmplus_basics::ST_names[] = {"unsigned_int","signed_int","equalsLatin1","containsLatin1","indexOfLatin1","matchesLatin1","matchesLatin1_caseless","bug562101", NULL__null };
67const boolbool ST_avmplus_basics::ST_explicits[] = {falsefalse,falsefalse,falsefalse,falsefalse,falsefalse,falsefalse,falsefalse,falsefalse, falsefalse };
68void ST_avmplus_basics::run(int n) {
69switch(n) {
70case 0: test0(); return;
71case 1: test1(); return;
72case 2: test2(); return;
73case 3: test3(); return;
74case 4: test4(); return;
75case 5: test5(); return;
76case 6: test6(); return;
77case 7: test7(); return;
78}
79}
80void ST_avmplus_basics::test0() {
81
82// Does right shift of unsigned quantities work?
83// line 47 "ST_avmplus_basics.st"
84verifyPass((int)(~0U >> 1) > 0, "(int)(~0U >> 1) > 0", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__84);
85
86}
87void ST_avmplus_basics::test1() {
88
89// Does right shift of signed quantities work?
90// line 52 "ST_avmplus_basics.st"
91verifyPass((-1 >> 1) == -1, "(-1 >> 1) == -1", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__91);
92
93// verify that the "latin1" literal string calls work properly for hi-bit latin1 chars
94}
95void ST_avmplus_basics::test2() {
96 Stringp s = core->newConstantStringLatin1("ev\xADident");
97 boolbool equals = s->equalsLatin1("ev\xADident");
98// line 58 "ST_avmplus_basics.st"
99verifyPass(equals == truetrue, "equals == true", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__99);
100
101}
102void ST_avmplus_basics::test3() {
103 Stringp s = core->newConstantStringLatin1("ev\xADident");
104 boolbool found = s->containsLatin1("\xAD");
105// line 63 "ST_avmplus_basics.st"
106verifyPass(found == truetrue, "found == true", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__106);
107
108}
109void ST_avmplus_basics::test4() {
110 Stringp s = core->newConstantStringLatin1("ev\xADident");
111 int index = s->indexOfLatin1("\xAD");
112// line 68 "ST_avmplus_basics.st"
113verifyPass(index == 2, "index == 2", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__113);
114
115}
116void ST_avmplus_basics::test5() {
117 Stringp s = core->newConstantStringLatin1("ev\xADident");
118 boolbool matches1 = s->matchesLatin1("\xADi", 2, 2);
119// line 73 "ST_avmplus_basics.st"
120verifyPass(matches1 == truetrue, "matches1 == true", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__120);
121
122}
123void ST_avmplus_basics::test6() {
124 Stringp s = core->newConstantStringLatin1("ev\xADident");
125 boolbool matches2 = s->matchesLatin1_caseless("\xADIDENT", 2, 2);
126// line 78 "ST_avmplus_basics.st"
127verifyPass(matches2 == truetrue, "matches2 == true", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__127);
128
129
130}
131void ST_avmplus_basics::test7() {
132// XMLParser omits the last char of a DOCTYPE node
133Stringp str = core->newConstantStringLatin1("<?xml version=\"1.0\"?><!DOCTYPE greeting SYSTEM><greeting>Hello, world!</greeting>");
134XMLParser parser(core, str);
135MMgc::GC *gc = core->GetGC();
136XMLTag tag(gc);
137int m_status;
138boolbool pass = falsefalse;
139while ((m_status = parser.getNext(tag)) == XMLParser::kNoError)
140{
141 switch (tag.nodeType)
142 {
143 case XMLTag::kDocTypeDeclaration:
144 {
145 pass = falsefalse;
146 pass = tag.text->equalsLatin1("<!DOCTYPE greeting SYSTEM>");
147 }
148 break;
149 }
150}
151// line 101 "ST_avmplus_basics.st"
152verifyPass(pass == truetrue, "pass == true", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__152);
153
154 // FIXME: this needs a "register this object with the GC" mechanism; this abuse of the GCRoot mechanism
155 // is no longer allowed
156//%%test bug610022
157// Stringp str = core->newConstantStringLatin1("some string that is likely to be unique");
158// WeakRefList<String> list(core->GetGC(), 0);
159 // We are going to skip scanning the stack (so that "str" won't hold the string in place)
160 // but that means we need a root to ensure that "list" doesn't also get collected.
161 //
162 //MMgc::GCRoot root(core->GetGC(), &list, sizeof(list));
163 //list.add(str);
164 //str = NULL;
165 //core->GetGC()->Collect(/*scanStack*/false);
166 //int removed = list.removeCollectedItems();
167 //int count = list.length();
168//%%verify removed == 1 && count == 0
169
170
171
172}
173void create_avmplus_basics(AvmCore* core) { new ST_avmplus_basics(core); }
174}
175}
176#endif
177
178// Generated from ST_avmplus_builtins.st
179// -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*-
180// vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */
181//
182// ***** BEGIN LICENSE BLOCK *****
183// Version: MPL 1.1/GPL 2.0/LGPL 2.1
184//
185// The contents of this file are subject to the Mozilla Public License Version
186// 1.1 (the "License"); you may not use this file except in compliance with
187// the License. You may obtain a copy of the License at
188// http://www.mozilla.org/MPL/
189//
190// Software distributed under the License is distributed on an "AS IS" basis,
191// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
192// for the specific language governing rights and limitations under the
193// License.
194//
195// The Original Code is [Open Source Virtual Machine.].
196//
197// The Initial Developer of the Original Code is
198// Adobe System Incorporated.
199// Portions created by the Initial Developer are Copyright (C) 2004-2006
200// the Initial Developer. All Rights Reserved.
201//
202// Contributor(s):
203// Adobe AS3 Team
204//
205// Alternatively, the contents of this file may be used under the terms of
206// either the GNU General Public License Version 2 or later (the "GPL"), or
207// the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
208// in which case the provisions of the GPL or the LGPL are applicable instead
209// of those above. If you wish to allow use of your version of this file only
210// under the terms of either the GPL or the LGPL, and not to allow others to
211// use your version of this file under the terms of the MPL, indicate your
212// decision by deleting the provisions above and replace them with the notice
213// and other provisions required by the GPL or the LGPL. If you do not delete
214// the provisions above, a recipient may use your version of this file under
215// the terms of any one of the MPL, the GPL or the LGPL.
216//
217// ***** END LICENSE BLOCK ***** */
218
219#include "avmshell.h"
220#ifdef VMCFG_SELFTEST
221namespace avmplus {
222namespace ST_avmplus_builtins {
223class ST_avmplus_builtins : public Selftest {
224public:
225ST_avmplus_builtins(AvmCore* core);
226virtual void run(int n);
227private:
228static const char* ST_names[];
229static const boolbool ST_explicits[];
230void test0();
231};
232ST_avmplus_builtins::ST_avmplus_builtins(AvmCore* core)
233 : Selftest(core, "avmplus", "builtins", ST_avmplus_builtins::ST_names,ST_avmplus_builtins::ST_explicits)
234{}
235const char* ST_avmplus_builtins::ST_names[] = {"WeakValueHashTable", NULL__null };
236const boolbool ST_avmplus_builtins::ST_explicits[] = {falsefalse, falsefalse };
237void ST_avmplus_builtins::run(int n) {
238switch(n) {
239case 0: test0(); return;
240}
241}
242void ST_avmplus_builtins::test0() {
243 WeakValueHashtable* tbl = WeakValueHashtable::create(core->gc);
244 String* fhtagn = String::createLatin1(core, "Fhtagn!");
245 MMgc::GCObjectLock* fhtagn_lock = core->gc->LockObject(fhtagn);
246 fhtagn = NULL__null;
247 for ( int i=0 ; i < 500 ; i++ ) {
248 tbl->add(atomFromIntptrValue(i), (i & 1) ? String::createLatin1(core, "Cthulhu!")->atom() : ((String*)core->gc->GetLockedObject(fhtagn_lock))->atom());
249 }
250 core->gc->Collect();
251 core->gc->Collect();
252 int sum = 0;
253 for ( int i=0 ; i < 500 ; i++ ) {
254 Atom a = tbl->get(atomFromIntptrValue(i));
255 if (a != AtomConstants::undefinedAtom)
256 sum++;
257 }
258 core->gc->UnlockObject(fhtagn_lock);
259 printf("fhtagn sum: %d\n", sum);
260
261// Retain at least 250, but it would be unreasonable to retain more than 300
262// line 64 "ST_avmplus_builtins.st"
263verifyPass(sum >= 250 && sum <= 300, "sum >= 250 && sum <= 300", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__263);
264
265}
266void create_avmplus_builtins(AvmCore* core) { new ST_avmplus_builtins(core); }
267}
268}
269#endif
270
271// Generated from ST_avmplus_peephole.st
272// -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*-
273// vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */
274//
275// ***** BEGIN LICENSE BLOCK *****
276// Version: MPL 1.1/GPL 2.0/LGPL 2.1
277//
278// The contents of this file are subject to the Mozilla Public License Version
279// 1.1 (the "License"); you may not use this file except in compliance with
280// the License. You may obtain a copy of the License at
281// http://www.mozilla.org/MPL/
282//
283// Software distributed under the License is distributed on an "AS IS" basis,
284// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
285// for the specific language governing rights and limitations under the
286// License.
287//
288// The Original Code is [Open Source Virtual Machine.].
289//
290// The Initial Developer of the Original Code is
291// Adobe System Incorporated.
292// Portions created by the Initial Developer are Copyright (C) 2004-2006
293// the Initial Developer. All Rights Reserved.
294//
295// Contributor(s):
296// Adobe AS3 Team
297//
298// Alternatively, the contents of this file may be used under the terms of
299// either the GNU General Public License Version 2 or later (the "GPL"), or
300// the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
301// in which case the provisions of the GPL or the LGPL are applicable instead
302// of those above. If you wish to allow use of your version of this file only
303// under the terms of either the GPL or the LGPL, and not to allow others to
304// use your version of this file under the terms of the MPL, indicate your
305// decision by deleting the provisions above and replace them with the notice
306// and other provisions required by the GPL or the LGPL. If you do not delete
307// the provisions above, a recipient may use your version of this file under
308// the terms of any one of the MPL, the GPL or the LGPL.
309//
310// ***** END LICENSE BLOCK ***** */
311
312#include "avmshell.h"
313#ifdef VMCFG_SELFTEST
314#if defined AVMPLUS_PEEPHOLE_OPTIMIZER
315namespace avmplus {
316namespace ST_avmplus_peephole {
317class ST_avmplus_peephole : public Selftest {
318public:
319ST_avmplus_peephole(AvmCore* core);
320virtual void run(int n);
321virtual void prologue();
322virtual void epilogue();
323private:
324static const char* ST_names[];
325static const boolbool ST_explicits[];
326void test0();
327
328private:
329#ifdef AVMPLUS_DIRECT_THREADED
330 void** opcode_labels; // the name is not arbitrary
331#endif
332
333};
334ST_avmplus_peephole::ST_avmplus_peephole(AvmCore* core)
335 : Selftest(core, "avmplus", "peephole", ST_avmplus_peephole::ST_names,ST_avmplus_peephole::ST_explicits)
336{}
337const char* ST_avmplus_peephole::ST_names[] = {"get2locals", NULL__null };
338const boolbool ST_avmplus_peephole::ST_explicits[] = {falsefalse, falsefalse };
339void ST_avmplus_peephole::run(int n) {
340switch(n) {
341case 0: test0(); return;
342}
343}
344void ST_avmplus_peephole::prologue() {
345
346#ifdef AVMPLUS_DIRECT_THREADED
347 opcode_labels = interpGetOpcodeLabels();
348#endif
349
350}
351void ST_avmplus_peephole::epilogue() {
352
353#ifdef AVMPLUS_DIRECT_THREADED
354 opcode_labels = NULL__null; // interpGetOpcodeLables() returns a pointer to static data
355#endif
356
357}
358void ST_avmplus_peephole::test0() {
359
360 WordcodeEmitter* t = new WordcodeEmitter(core, NULL__null);
361
362 t->emitOp1(WOP_getlocal, 5);
363 t->emitOp1(WOP_getlocal, 4);
364 t->emitOp1(WOP_getlocal, 65536);
365 t->emitOp1(WOP_getlocal, 7);
366 t->emitOp1(WOP_getlocal, 6);
367 uintptr_t* code;
368uint32_t len = (uint32_t)t->epilogue(&code);
369
370// line 76 "ST_avmplus_peephole.st"
371verifyPass(len == 6, "len == 6", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__371);
372// line 77 "ST_avmplus_peephole.st"
373verifyPass(code[0] == NEW_OPCODE(WOP_get2locals), "code[0] == NEW_OPCODE(WOP_get2locals)", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__373);
374// line 78 "ST_avmplus_peephole.st"
375verifyPass(code[1] == ((4 << 16) | 5), "code[1] == ((4 << 16) | 5)", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__375);
376// line 79 "ST_avmplus_peephole.st"
377verifyPass(code[2] == NEW_OPCODE(WOP_getlocal), "code[2] == NEW_OPCODE(WOP_getlocal)", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__377);
378// line 80 "ST_avmplus_peephole.st"
379verifyPass(code[3] == 65536, "code[3] == 65536", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__379);
380// line 81 "ST_avmplus_peephole.st"
381verifyPass(code[4] == NEW_OPCODE(WOP_get2locals), "code[4] == NEW_OPCODE(WOP_get2locals)", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__381);
382// line 82 "ST_avmplus_peephole.st"
383verifyPass(code[5] == ((6 << 16) | 7), "code[5] == ((6 << 16) | 7)", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__383);
384
385 delete t;
386
387
388}
389void create_avmplus_peephole(AvmCore* core) { new ST_avmplus_peephole(core); }
390}
391}
392#endif
393#endif
394
395// Generated from ST_mmgc_543560.st
396// -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*-
397// vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */
398//
399// ***** BEGIN LICENSE BLOCK *****
400// Version: MPL 1.1/GPL 2.0/LGPL 2.1
401//
402// The contents of this file are subject to the Mozilla Public License Version
403// 1.1 (the "License"); you may not use this file except in compliance with
404// the License. You may obtain a copy of the License at
405// http://www.mozilla.org/MPL/
406//
407// Software distributed under the License is distributed on an "AS IS" basis,
408// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
409// for the specific language governing rights and limitations under the
410// License.
411//
412// The Original Code is [Open Source Virtual Machine.].
413//
414// The Initial Developer of the Original Code is
415// Adobe System Incorporated.
416// Portions created by the Initial Developer are Copyright (C) 2004-2006
417// the Initial Developer. All Rights Reserved.
418//
419// Contributor(s):
420// Adobe AS3 Team
421//
422// Alternatively, the contents of this file may be used under the terms of
423// either the GNU General Public License Version 2 or later (the "GPL"), or
424// the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
425// in which case the provisions of the GPL or the LGPL are applicable instead
426// of those above. If you wish to allow use of your version of this file only
427// under the terms of either the GPL or the LGPL, and not to allow others to
428// use your version of this file under the terms of the MPL, indicate your
429// decision by deleting the provisions above and replace them with the notice
430// and other provisions required by the GPL or the LGPL. If you do not delete
431// the provisions above, a recipient may use your version of this file under
432// the terms of any one of the MPL, the GPL or the LGPL.
433//
434// ***** END LICENSE BLOCK ***** */
435
436// Bugzilla 543560 - here we risk deleting an object that is still on the mark stack because
437// of how we perform large-object splitting. The setup is that user code that deletes the object
438// gets to run after the first part of the large object has been popped off the mark stack
439// but before the rest has been handled.
440
441#include "avmshell.h"
442#ifdef VMCFG_SELFTEST
443#if defined AVMPLUS_WIN32
444#if !defined VMCFG_ARM
445namespace avmplus {
446namespace ST_mmgc_bugzilla_543560 {
447class ST_mmgc_bugzilla_543560 : public Selftest {
448public:
449ST_mmgc_bugzilla_543560(AvmCore* core);
450virtual void run(int n);
451virtual void prologue();
452virtual void epilogue();
453private:
454static const char* ST_names[];
455static const boolbool ST_explicits[];
456void test0();
457private:
458 MMgc::GC *gc;
459
460};
461ST_mmgc_bugzilla_543560::ST_mmgc_bugzilla_543560(AvmCore* core)
462 : Selftest(core, "mmgc", "bugzilla_543560", ST_mmgc_bugzilla_543560::ST_names,ST_mmgc_bugzilla_543560::ST_explicits)
463{}
464const char* ST_mmgc_bugzilla_543560::ST_names[] = {"bugzilla_543560", NULL__null };
465const boolbool ST_mmgc_bugzilla_543560::ST_explicits[] = {falsefalse, falsefalse };
466void ST_mmgc_bugzilla_543560::run(int n) {
467switch(n) {
468case 0: test0(); return;
469}
470}
471void ST_mmgc_bugzilla_543560::prologue() {
472 MMgc::GCConfig config;
473 gc = new MMgc::GC(MMgc::GCHeap::GetGCHeap(), config);
474
475}
476void ST_mmgc_bugzilla_543560::epilogue() {
477 delete gc;
478
479}
480using namespace MMgc;
481
482// allocate a bunch big things
483// allocate a bunch of small things ( to pump incremental mark.... )
484// explicitly free one of the big things
485// ... crash
486
487struct BigThing;
488
489static inline unsigned getSerial()
490{
491 static unsigned g_counter = 0;
492 unsigned result = g_counter;
493 ++g_counter;
494 return result;
495}
496
497struct BigThing : public MMgc::GCFinalizedObject
498{
499 BigThing() : m_next(0), m_prev(0), m_serial(getSerial())
500 {
501 VMPI_memset::memset(&m_data, 0, sizeof(m_data));
502 }
503
504 virtual ~BigThing()
505 {
506 //printf("~BigThing: %u 0x%08X 0x%08X\n", m_serial, this, this + 1);
507 }
508 GCMember<BigThing> m_next;
509 GCMember<BigThing> m_prev;
510 unsigned m_serial;
511 char m_data[512 * 1024];
512};
513
514BigThing* makeBigThings(MMgc::GC* gc, size_t howMany)
515{
516 BigThing* first = 0;
517 BigThing* curr = 0;
518 for (unsigned i = 0; i < howMany; ++i) {
519 BigThing* newThing = new (gc) BigThing();
520 if (!first) {
521 first = newThing;
522 }
523 else {
524 curr->m_next = newThing;
525 newThing->m_prev = curr;
526 }
527 curr = newThing;
528 }
529 return first;
530}
531
532struct SmallThing : public MMgc::GCFinalizedObject
533{
534 char m_data[200];
535 virtual ~SmallThing()
536 {
537 }
538};
539
540struct MyRoot : public MMgc::GCRoot
541{
542 MyRoot(MMgc::GC* gc) : MMgc::GCRoot(gc) {}
543 BigThing* m_bigThings;
544};
545
546void ST_mmgc_bugzilla_543560::test0() {
547 MMGC_GCENTER(gc)MMgc::GCAutoEnter __mmgc_auto_enter(gc);;
548
549 MyRoot* theRoot = 0;
550 {
551 BigThing* volatile bigThings = makeBigThings(gc, 400);
552 theRoot = new MyRoot(gc);
553 theRoot->m_bigThings = bigThings;
554 }
555 BigThing* volatile middle = theRoot->m_bigThings;
556 for (int j = 0 ; j < 150; ++j)
557 middle = middle->m_next;
558
559 middle->m_prev->m_next = 0;
560 for (int j = 0; j < 50; ++j)
561 middle = middle->m_next;
562
563 middle->m_prev = 0;
564 gc->Collect();
565 gc->Collect();
566
567 for (int j = 0; j < 100000; ++j) {
568 //printf("j: %d\n", j);
569 for (int i = 0; i < 500; ++i) {
570 new (gc) SmallThing();
571 if ((theRoot->m_bigThings) && (MMgc::GC::GetMark(theRoot->m_bigThings))) {
572 while (theRoot->m_bigThings != 0) {
573 BigThing* curr = theRoot->m_bigThings;
574 theRoot->m_bigThings = theRoot->m_bigThings->m_next;
575 delete curr;
576 }
577 MMgc::GCHeap::GetGCHeap()->Decommit();
578 }
579 }
580
581 }
582 delete theRoot;
583
584 // Will crash if it fails so the %%verify is just token
585// line 168 "ST_mmgc_543560.st"
586verifyPass(truetrue, "true", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__586);
587
588}
589void create_mmgc_bugzilla_543560(AvmCore* core) { new ST_mmgc_bugzilla_543560(core); }
590}
591}
592#endif
593#endif
594#endif
595
596// Generated from ST_mmgc_575631.st
597// -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*-
598// vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5)
599//
600// ***** BEGIN LICENSE BLOCK *****
601// Version: MPL 1.1/GPL 2.0/LGPL 2.1
602//
603// The contents of this file are subject to the Mozilla Public License Version
604// 1.1 (the "License"); you may not use this file except in compliance with
605// the License. You may obtain a copy of the License at
606// http://www.mozilla.org/MPL/
607//
608// Software distributed under the License is distributed on an "AS IS" basis,
609// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
610// for the specific language governing rights and limitations under the
611// License.
612//
613// The Original Code is [Open Source Virtual Machine.].
614//
615// The Initial Developer of the Original Code is
616// Adobe System Incorporated.
617// Portions created by the Initial Developer are Copyright (C) 2004-2006
618// the Initial Developer. All Rights Reserved.
619//
620// Contributor(s):
621// Adobe AS3 Team
622//
623// Alternatively, the contents of this file may be used under the terms of
624// either the GNU General Public License Version 2 or later (the "GPL"), or
625// the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
626// in which case the provisions of the GPL or the LGPL are applicable instead
627// of those above. If you wish to allow use of your version of this file only
628// under the terms of either the GPL or the LGPL, and not to allow others to
629// use your version of this file under the terms of the MPL, indicate your
630// decision by deleting the provisions above and replace them with the notice
631// and other provisions required by the GPL or the LGPL. If you do not delete
632// the provisions above, a recipient may use your version of this file under
633// the terms of any one of the MPL, the GPL or the LGPL.
634//
635// ***** END LICENSE BLOCK ***** */
636
637// Bugzilla 565631 - We occasionally interleave invoking finalizers
638// and clearing mark bits in GCAlloc::Finalize; so a finalizer can
639// observe a live object that does not have its mark bit set.
640//
641// This complicates things because we want to ensure that unmarked
642// weakly-referenced objects are resurrected by the GC if the weak
643// reference is dereferenced during presweep, but we do not want to
644// schedule collection work (or set bits that are supposed to be
645// unmarked) during finalization.
646//
647// (Long term we might want to get rid of the interleaving of
648// finalization and mark-bit clearing. Short term, lets just
649// try to detect this on our own.)
650
651#include "avmshell.h"
652#ifdef VMCFG_SELFTEST
653namespace avmplus {
654namespace ST_mmgc_bugzilla_575631 {
655using namespace MMgc;
656
657// Upon destruction, start reading weak refs of "friends" near and far
658class Snoopy : public GCFinalizedObject
659{
660public:
661 Snoopy(int key, GCWeakRef** refs, int len)
662 : key(key), friends(refs), len(len)
663 {
664 ++alive_count;
665 }
666 ~Snoopy();
667 static int alive_count;
668private:
669 int key;
670 GCWeakRef** friends;
671 int len;
672};
673
674// To take D samples from an array of N elems, walk thru by floor(N/D)
675// steps (but avoid the pathological case when the floor is zero).
676int compute_stride(int numerator, int denominator)
677{
678 int delta = numerator / denominator;
679 return (delta > 0) ? delta : 1;
680}
681
682class ST_mmgc_bugzilla_575631 : public Selftest {
683public:
684ST_mmgc_bugzilla_575631(AvmCore* core);
685virtual void run(int n);
686private:
687static const char* ST_names[];
688static const boolbool ST_explicits[];
689void test0();
690// collecting twice is only "sure" way to gc in presence of incrementality
691void collect2() { core->gc->Collect(); core->gc->Collect(); }
692
693};
694ST_mmgc_bugzilla_575631::ST_mmgc_bugzilla_575631(AvmCore* core)
695 : Selftest(core, "mmgc", "bugzilla_575631", ST_mmgc_bugzilla_575631::ST_names,ST_mmgc_bugzilla_575631::ST_explicits)
696{}
697const char* ST_mmgc_bugzilla_575631::ST_names[] = {"drizzle", NULL__null };
698const boolbool ST_mmgc_bugzilla_575631::ST_explicits[] = {falsefalse, falsefalse };
699void ST_mmgc_bugzilla_575631::run(int n) {
700switch(n) {
701case 0: test0(); return;
702}
703}
704
705/*static*/ int Snoopy::alive_count = 0;
706
707const int arr_len = 1000;
708const int lookups_per_destruct = 10;
709const int destructs = 10;
710Snoopy::~Snoopy()
711{
712 int delta = compute_stride(arr_len, lookups_per_destruct);
713
714 for ( int i = 1 ; i < arr_len ; i += delta ) {
715 int idx = (key + i) % len;
716 // printf("referencing ref[%d] from Snoopy(%d)\n", idx, key);
717 friends[idx]->get();
718 }
719 --alive_count;
720}
721
722void ST_mmgc_bugzilla_575631::test0() {
723{
724 GC* gc = core->gc;
725
726 Snoopy* objs[arr_len];
727 GCWeakRef* refs[arr_len];
728
729 // initial setup:
730 for (int i=0 ; i < arr_len; ++i ) {
731 objs[i] = new (gc) Snoopy(i, refs, arr_len);
732 refs[i] = objs[i]->GetWeakRef();
733 }
734
735 collect2();
736
737 int delta = compute_stride(arr_len, destructs);
738
739 for (int i=0; i < arr_len; i += delta) {
740 objs[i] = NULL__null;
741 collect2();
742 }
743
744 // not assert failing within get() is passing the test.
745// line 132 "ST_mmgc_575631.st"
746verifyPass(1, "1", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__746);
747 ; // (make my auto-indenter happy)
748
749 // cleanup code; letting ~Snoopy occur outside test extent is big no-no.
750 {
751 for (int i=0; i < arr_len; ++i ) {
752 if (! refs[i]->isNull())
753 delete objs[i];
754 }
755
756 // if something went wrong above and some Snoopy's are still alive,
757 // we'll get burned during their destructors. Make sure that
758 // does not happen.
759// line 145 "ST_mmgc_575631.st"
760verifyPass((Snoopy::alive_count == 0), "(Snoopy::alive_count == 0)", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__760);
761 ;
762 }
763}
764
765}
766void create_mmgc_bugzilla_575631(AvmCore* core) { new ST_mmgc_bugzilla_575631(core); }
767}
768}
769#endif
770
771// Generated from ST_mmgc_580603.st
772// -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*-
773// vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */
774//
775// ***** BEGIN LICENSE BLOCK *****
776// Version: MPL 1.1/GPL 2.0/LGPL 2.1
777//
778// The contents of this file are subject to the Mozilla Public License Version
779// 1.1 (the "License"); you may not use this file except in compliance with
780// the License. You may obtain a copy of the License at
781// http://www.mozilla.org/MPL/
782//
783// Software distributed under the License is distributed on an "AS IS" basis,
784// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
785// for the specific language governing rights and limitations under the
786// License.
787//
788// The Original Code is [Open Source Virtual Machine.].
789//
790// The Initial Developer of the Original Code is
791// Adobe System Incorporated.
792// Portions created by the Initial Developer are Copyright (C) 2004-2006
793// the Initial Developer. All Rights Reserved.
794//
795// Contributor(s):
796// Adobe AS3 Team
797//
798// Alternatively, the contents of this file may be used under the terms of
799// either the GNU General Public License Version 2 or later (the "GPL"), or
800// the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
801// in which case the provisions of the GPL or the LGPL are applicable instead
802// of those above. If you wish to allow use of your version of this file only
803// under the terms of either the GPL or the LGPL, and not to allow others to
804// use your version of this file under the terms of the MPL, indicate your
805// decision by deleting the provisions above and replace them with the notice
806// and other provisions required by the GPL or the LGPL. If you do not delete
807// the provisions above, a recipient may use your version of this file under
808// the terms of any one of the MPL, the GPL or the LGPL.
809//
810// ***** END LICENSE BLOCK ***** */
811
812// Bugzilla 580603 - adversarial mmgc: dispersive w.r.t. address space
813// Bugzilla 445780 - Page map needs to be sparse
814//
815// Tommy: "problems in 64-bit linux b/c VMPI_allocateAlignedMemory provides
816// memory from low 32 bit-addresses, and mmap is giving us addresses from
817// 0x7fxxxxxxxxxxxxxx so we need a 4 GB page map."
818//
819// This self-test attempts to replicate the problem described above
820// (by coordinating with an adversarial gcheap) thus illustrating the
821// need for a sparse page map.
822
823#include "avmshell.h"
824#ifdef VMCFG_SELFTEST
825#if defined AVMPLUS_64BIT && defined DEBUG
826namespace avmplus {
827namespace ST_mmgc_bugzilla_580603 {
828using namespace MMgc;
829
830class ST_mmgc_bugzilla_580603 : public Selftest {
831public:
832ST_mmgc_bugzilla_580603(AvmCore* core);
833virtual void run(int n);
834virtual void prologue();
835virtual void epilogue();
836private:
837static const char* ST_names[];
838static const boolbool ST_explicits[];
839void test0();
840void test1();
841
842GC *gc;
843GCHeap *heap;
844
845size_t saved_dispersiveAdversarial;
846size_t saved_heapLimit;
847
848char *min_addr;
849char *max_start;
850char *max_addr;
851size_t min_size;
852size_t max_size;
853
854static const int m_num_sizes = 17;
855static const int m_num_iters = 2;
856static const int m_init_size = 16;
857static const int m_dfactor = 2;
858
859void print_minmax()
860{
861 intptr_t delta = max_addr - min_addr;
862 intptr_t v = delta;
863 unsigned r = 0; // r will be floor(log_2(v))
864
865 while (v >>= 1)
866 r++;
867
868 printf("min_size: 0x%15lx max_size: 0x%15lx\n",
869 (unsigned long)min_size, (unsigned long)max_size);
870 printf("min_addr: 0x%15lx max_addr: 0x%15lx delta:% 15ld (>= 2^%u)\n",
871 (unsigned long)min_addr, (unsigned long)max_addr, delta, r);
872 fflush(NULL__null);
873}
874
875enum alloc_method_t { via_gc, via_heap };
876
877const char* method_string(alloc_method_t m)
878{
879 switch (m) {
880 case via_gc: return "via_gc";
881 case via_heap: return "via_heap";
882 default: return 0;
883 }
884}
885
886char *my_alloc(size_t size, alloc_method_t m)
887{
888 char *ret;
889
890 // Took heap-zeroing and heap-profiling out of flags;
891 // avoid wasting time mapping in memory to initialize to 0.
892 int heapFlags = (MMgc::GCHeap::kExpand);
893 size_t sizeInPages = (size+(GCHeap::kBlockSize-1))/GCHeap::kBlockSize;
894
895 switch (m) {
896 case via_gc: ret = (char*)gc->Alloc(size); break;
897 case via_heap:
898 ret = (char*)heap->Alloc(sizeInPages, heapFlags);
899 break;
900 default: ret = 0; break;
901 }
902
903 if (size < min_size)
904 min_size = size;
905 if (size > max_size)
906 max_size = size;
907 if (ret < min_addr)
908 min_addr = ret;
909 if (ret > max_start)
910 max_start = ret;
911 if (ret+size > max_addr)
912 max_addr = ret+size;
913
914 // printf("my_alloc(%10ld, %10s) => %p\n", size, method_string(m), ret);
915 // fflush(NULL);
916 return ret;
917}
918
919void my_free(char *p, alloc_method_t m)
920{
921 switch (m) {
922 case via_gc: gc->Free(p); return;
923 case via_heap: heap->FreeNoProfile(p); return;
924 default: AvmAssert(p == 0)do { } while (0); return;
925 }
926}
927
928// fills recv[] with the addresses of a series of N allocated and
929// freed blocks, where N = (m_num_iters * m_num_sizes).
930//
931// For each iteration:
932//
933// 1. allocate m_num_sizes blocks of distinct (and exponentially
934// growing) size.
935// 2. after finishing the allocations from (1.), free the blocks
936// allocated in the *previous* iteration.
937//
938// The intention is to allocate blocks covering a wide range of
939// sizes in order to tickle the memory subsystem's ability to
940// track blocks of different sizes. Keeping each iteration's
941// blocks alive across the next iteration is meant to ensure
942// that the set of allocated addresses have many wide gaps,
943// stressing the memory subsystem's ability to represent
944// the meta-data for disparately allocated ranges.
945//
946// The loop attempts to keep the block sizes distinct both within any
947// particular iteration (the exponential growth) and also across the
948// distinct iterations. This was an artifact of trying to force the
949// memory subsystem to be unable to return back blocks that had been
950// previously freed. It may or may not still be necessary with the
951// addition of the dispersiveAdversarial gcheap config mode; it does
952// not seem to hurt the effectiveness of this test, since one can
953// observe OOM failures when using PageMap::Uniform using this test;
954// see notes in prologue code below.
955
956void do_allocs(char **recv, alloc_method_t m)
957{
958 size_t init = m_init_size;
959 int num_iters = m_num_iters;
960 int num_sizes = m_num_sizes;
961 int dfactor = m_dfactor;
962 for (int j=num_iters-1; j >= 0; j--) {
963 for (int i=0, factor=1; i < num_sizes; i++, factor*=dfactor) {
964 size_t size = factor*init+num_iters-j;
965 // size_t size = factor*init;
966 char *result = my_alloc(size, m);
967 recv[j*num_sizes+i] = result;
968 }
969 if (j < num_iters - 1) {
970 for (int i=0; i < num_sizes; i++) {
971 my_free(recv[(j+1)*num_sizes+i], m);
972 }
973 }
974 }
975 for (int i=0; i < num_sizes; i++) {
976 my_free(recv[0*num_sizes+i], m);
977 }
978}
979
980
981};
982ST_mmgc_bugzilla_580603::ST_mmgc_bugzilla_580603(AvmCore* core)
983 : Selftest(core, "mmgc", "bugzilla_580603", ST_mmgc_bugzilla_580603::ST_names,ST_mmgc_bugzilla_580603::ST_explicits)
984{}
985const char* ST_mmgc_bugzilla_580603::ST_names[] = {"alloc_loop_mmgc_viaheap_far","alloc_loop_mmgc_viagc_far", NULL__null };
986const boolbool ST_mmgc_bugzilla_580603::ST_explicits[] = {falsefalse,falsefalse, falsefalse };
987void ST_mmgc_bugzilla_580603::run(int n) {
988switch(n) {
989case 0: test0(); return;
990case 1: test1(); return;
991}
992}
993void ST_mmgc_bugzilla_580603::prologue() {
994{
995 min_addr = (char*)(void*)-1;
996 min_size = (size_t)(void*)-1;
997 max_addr = 0;
998 max_size = 0;
999
1000 // based on ST_mmgc_basics.st
1001 heap = MMgc::GCHeap::GetGCHeap();
1002
1003 // Constants determining test parameters; see comments below.
1004 const int k1 = 40;
1005 const int k2 = 15;
1006
1007 // filler that GCHeap attempts to insert between allocations,
1008 // in bytes (not that the precise number matters).
1009 saved_dispersiveAdversarial = heap->Config().dispersiveAdversarial;
1010 heap->Config().dispersiveAdversarial = size_t(1) << k1;
1011 // limit is measured in pages; 1 page = kBlockSize bytes.
1012 // its default value is absurdly large; cut it down to something
1013 // where we'll see a failure without first hosing the host machine.
1014 saved_heapLimit = heap->Config().heapLimit;
1015 heap->Config().heapLimit = ((1 << k2)-1);
1016
1017 // Some pairs of (k1,k2) for filler = 2**k1 and limit = 2**k2 - 1,
1018 // where the (decreasing) value of k2 has just passed threshold to
1019 // expose OOM from PageMap::Uniform (i.e. limit = 2**(k2+1) - 1
1020 // won't OOM); test bed is 64-bit DEBUG avmshell on Mac OS X 10.6.4.
1021 //
1022 // k1, k2
1023 // ------
1024 // 43, 18
1025 // 42, 17
1026 // 41, 16
1027 // 40, 15
1028 // 39, 14
1029 // 38, 13
1030 // 37, 12
1031 // 36, 12
1032 // 35, 11
1033 // 34, 11
1034 //
1035 // For k1 < 34, test won't OOM for k2 >= 11.
1036 // For k2 < 11, test will OOM w/o dispersiveAdversarial at all.
1037
1038 gc = core->gc;
1039}
1040
1041}
1042void ST_mmgc_bugzilla_580603::epilogue() {
1043{
1044 // restore original values to limit disruption to remaining selftests
1045 heap->Config().heapLimit = this->saved_heapLimit;
1046 heap->Config().dispersiveAdversarial = saved_dispersiveAdversarial;
1047}
1048
1049}
1050
1051void ST_mmgc_bugzilla_580603::test0() {
1052{
1053 char *h[3];
1054 h[0] = my_alloc( 256*GCHeap::kBlockSize, via_heap);
1055 h[1] = my_alloc( 256*GCHeap::kBlockSize, via_heap);
1056 my_free(h[0], via_heap);
1057 my_free(h[1], via_heap);
1058 // print_minmax();
1059
1060 char *g[m_num_iters*m_num_sizes]; (void)g;
1061 do_allocs(g, via_heap);
1062
1063 // print_minmax();
1064
1065// line 275 "ST_mmgc_580603.st"
1066verifyPass(1, "1", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__1066);
1067}
1068
1069}
1070void ST_mmgc_bugzilla_580603::test1() {
1071{
1072 char *h[3];
1073 h[0] = my_alloc( 256*GCHeap::kBlockSize, via_heap);
1074 h[1] = my_alloc( 256*GCHeap::kBlockSize, via_heap);
1075 my_free(h[0], via_heap);
1076 my_free(h[1], via_heap);
1077 // print_minmax();
1078
1079 char *g[m_num_iters*m_num_sizes]; (void)g;
1080 do_allocs(g, via_gc);
1081
1082 // print_minmax();
1083
1084// line 292 "ST_mmgc_580603.st"
1085verifyPass(1, "1", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__1085);
1086}
1087
1088}
1089void create_mmgc_bugzilla_580603(AvmCore* core) { new ST_mmgc_bugzilla_580603(core); }
1090}
1091}
1092#endif
1093#endif
1094
1095// Generated from ST_mmgc_637993.st
1096// -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*-
1097// vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */
1098//
1099// ***** BEGIN LICENSE BLOCK *****
1100// Version: MPL 1.1/GPL 2.0/LGPL 2.1
1101//
1102// The contents of this file are subject to the Mozilla Public License Version
1103// 1.1 (the "License"); you may not use this file except in compliance with
1104// the License. You may obtain a copy of the License at
1105// http://www.mozilla.org/MPL/
1106//
1107// Software distributed under the License is distributed on an "AS IS" basis,
1108// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
1109// for the specific language governing rights and limitations under the
1110// License.
1111//
1112// The Original Code is [Open Source Virtual Machine.].
1113//
1114// The Initial Developer of the Original Code is
1115// Adobe System Incorporated.
1116// Portions created by the Initial Developer are Copyright (C) 2004-2006
1117// the Initial Developer. All Rights Reserved.
1118//
1119// Contributor(s):
1120// Adobe AS3 Team
1121//
1122// Alternatively, the contents of this file may be used under the terms of
1123// either the GNU General Public License Version 2 or later (the "GPL"), or
1124// the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
1125// in which case the provisions of the GPL or the LGPL are applicable instead
1126// of those above. If you wish to allow use of your version of this file only
1127// under the terms of either the GPL or the LGPL, and not to allow others to
1128// use your version of this file under the terms of the MPL, indicate your
1129// decision by deleting the provisions above and replace them with the notice
1130// and other provisions required by the GPL or the LGPL. If you do not delete
1131// the provisions above, a recipient may use your version of this file under
1132// the terms of any one of the MPL, the GPL or the LGPL.
1133//
1134// ***** END LICENSE BLOCK ***** */
1135
1136// Bugzilla 637993: rehashing a GCHashtable in the midst of iteration
1137// is unsound; here we check that we are guarding against it.
1138
1139#include "avmshell.h"
1140#ifdef VMCFG_SELFTEST
1141namespace avmplus {
1142namespace ST_mmgc_bugzilla_637993 {
1143class ST_mmgc_bugzilla_637993 : public Selftest {
1144public:
1145ST_mmgc_bugzilla_637993(AvmCore* core);
1146virtual void run(int n);
1147private:
1148static const char* ST_names[];
1149static const boolbool ST_explicits[];
1150void test0();
1151void test1();
1152void test2();
1153void test3();
1154void test4();
1155
1156const static size_t elem_count = 1000;
1157int32_t *elems;
1158MMgc::GCHashtable m_table;
1159
1160void add_first_half() {
1161 for (size_t i=0; i < elem_count/2; i++)
1162 m_table.put(&elems[i], &elems[i+1]);
1163}
1164
1165void add_second_half() {
1166 for (size_t i=elem_count/2; i < elem_count; i++)
1167 m_table.put(&elems[i], &elems[i+1]);
1168}
1169
1170};
1171ST_mmgc_bugzilla_637993::ST_mmgc_bugzilla_637993(AvmCore* core)
1172 : Selftest(core, "mmgc", "bugzilla_637993", ST_mmgc_bugzilla_637993::ST_names,ST_mmgc_bugzilla_637993::ST_explicits)
1173{}
1174const char* ST_mmgc_bugzilla_637993::ST_names[] = {"delete_during_iteration_okay_if_norehash","delete_during_iteration_asserts_if_rehash","rehash_after_iteration_succeeds","rehash_during_iteration_assert_fails_1","rehash_during_iteration_assert_fails_2", NULL__null };
1175const boolbool ST_mmgc_bugzilla_637993::ST_explicits[] = {falsefalse,truetrue,falsefalse,truetrue,truetrue, falsefalse };
1176void ST_mmgc_bugzilla_637993::run(int n) {
1177switch(n) {
1178case 0: test0(); return;
1179case 1: test1(); return;
1180case 2: test2(); return;
1181case 3: test3(); return;
1182case 4: test4(); return;
1183}
1184}
1185void ST_mmgc_bugzilla_637993::test0() {
1186 elems = new int32_t[elem_count];
1187 add_first_half();
1188 {
1189 MMgc::GCHashtable::Iterator it(&m_table);
1190 while (it.nextKey()) {
1191 m_table.remove(it.value(), /*allowrehash=*/falsefalse);
1192 }
1193 }
1194 m_table.clear();
1195 delete elems;
1196// line 74 "ST_mmgc_637993.st"
1197verifyPass(truetrue, "true", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__1197);
1198 ;
1199
1200}
1201void ST_mmgc_bugzilla_637993::test1() {
1202 elems = new int32_t[elem_count];
1203 add_first_half();
1204 {
1205 MMgc::GCHashtable::Iterator it(&m_table);
1206 while (it.nextKey()) {
1207 m_table.remove(it.value());
1208 }
1209 }
1210 m_table.clear();
1211 delete elems;
1212// line 88 "ST_mmgc_637993.st"
1213verifyPass(falsefalse, "false", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__1213);
1214 ;
1215
1216// This test is a trivial success; it is meant to be compared against
1217// the cases that *fail* below, in order to make it clear what is
1218// wrong with the intentionally asserting cases.
1219}
1220void ST_mmgc_bugzilla_637993::test2() {
1221 elems = new int32_t[elem_count];
1222 add_first_half();
1223 {
1224 MMgc::GCHashtable::Iterator it(&m_table);
1225 it.nextKey();
1226 it.nextKey();
1227 }
1228 add_second_half(); // rule satisfied; (Iterator is out of scope).
1229 m_table.clear();
1230 delete elems;
1231// line 105 "ST_mmgc_637993.st"
1232verifyPass(truetrue, "true", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__1232);
1233 ;
1234
1235 // (This test should definitely assert.)
1236}
1237void ST_mmgc_bugzilla_637993::test3() {
1238 elems = new int32_t[elem_count];
1239 add_first_half();
1240 {
1241 MMgc::GCHashtable::Iterator it(&m_table);
1242 it.nextKey();
1243 add_second_half(); // this is where we break the rule
1244 it.nextKey();
1245 }
1246
1247 m_table.clear();
1248 delete elems;
1249 // we should never get here, the assertion should happen up above.
1250// line 122 "ST_mmgc_637993.st"
1251verifyPass(falsefalse, "false", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__1251);
1252 ;
1253
1254// This test will assert even though the iteration is "done",
1255// because the rule is that we cannot modify the hashtable while
1256// any iterator is still "in scope"
1257}
1258void ST_mmgc_bugzilla_637993::test4() {
1259 elems = new int32_t[elem_count];
1260 add_first_half();
1261 {
1262 MMgc::GCHashtable::Iterator it(&m_table);
1263 it.nextKey();
1264 it.nextKey();
1265 add_second_half(); // this is where we break the rule
1266 }
1267
1268 m_table.clear();
1269 delete elems;
1270 // we should never get here, the assertion should happen up above.
1271// line 141 "ST_mmgc_637993.st"
1272verifyPass(falsefalse, "false", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__1272);
1273 ;
1274
1275}
1276void create_mmgc_bugzilla_637993(AvmCore* core) { new ST_mmgc_bugzilla_637993(core); }
1277}
1278}
1279#endif
1280
1281// Generated from ST_mmgc_basics.st
1282// -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*-
1283// vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */
1284//
1285// ***** BEGIN LICENSE BLOCK *****
1286// Version: MPL 1.1/GPL 2.0/LGPL 2.1
1287//
1288// The contents of this file are subject to the Mozilla Public License Version
1289// 1.1 (the "License"); you may not use this file except in compliance with
1290// the License. You may obtain a copy of the License at
1291// http://www.mozilla.org/MPL/
1292//
1293// Software distributed under the License is distributed on an "AS IS" basis,
1294// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
1295// for the specific language governing rights and limitations under the
1296// License.
1297//
1298// The Original Code is [Open Source Virtual Machine.].
1299//
1300// The Initial Developer of the Original Code is
1301// Adobe System Incorporated.
1302// Portions created by the Initial Developer are Copyright (C) 2004-2006
1303// the Initial Developer. All Rights Reserved.
1304//
1305// Contributor(s):
1306// Adobe AS3 Team
1307//
1308// Alternatively, the contents of this file may be used under the terms of
1309// either the GNU General Public License Version 2 or later (the "GPL"), or
1310// the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
1311// in which case the provisions of the GPL or the LGPL are applicable instead
1312// of those above. If you wish to allow use of your version of this file only
1313// under the terms of either the GPL or the LGPL, and not to allow others to
1314// use your version of this file under the terms of the MPL, indicate your
1315// decision by deleting the provisions above and replace them with the notice
1316// and other provisions required by the GPL or the LGPL. If you do not delete
1317// the provisions above, a recipient may use your version of this file under
1318// the terms of any one of the MPL, the GPL or the LGPL.
1319//
1320// ***** END LICENSE BLOCK ***** */
1321
1322#include "avmshell.h"
1323#ifdef VMCFG_SELFTEST
1324namespace avmplus {
1325namespace ST_mmgc_basics {
1326class ST_mmgc_basics : public Selftest {
1327public:
1328ST_mmgc_basics(AvmCore* core);
1329virtual void run(int n);
1330virtual void prologue();
1331virtual void epilogue();
1332private:
1333static const char* ST_names[];
1334static const boolbool ST_explicits[];
1335void test0();
1336void test1();
1337void test2();
1338void test3();
1339void test4();
1340void test5();
1341void test6();
1342void test7();
1343void test8();
1344void test9();
1345void test10();
1346void test11();
1347void test12();
1348void test13();
1349void test14();
1350void test15();
1351void test16();
1352private:
1353 MMgc::GC *gc;
1354 MMgc::FixedAlloc *fa;
1355 MMgc::FixedMalloc *fm;
1356
1357};
1358ST_mmgc_basics::ST_mmgc_basics(AvmCore* core)
1359 : Selftest(core, "mmgc", "basics", ST_mmgc_basics::ST_names,ST_mmgc_basics::ST_explicits)
1360{}
1361const char* ST_mmgc_basics::ST_names[] = {"create_gc_instance","create_gc_object","get_bytesinuse","collect","getgcheap","fixedAlloc","fixedMalloc","gcheap","gcheapAlign","gcmethods","finalizerAlloc","finalizerDelete","nestedGCs","collectDormantGC","lockObject","regression_551169","blacklisting", NULL__null };
1362const boolbool ST_mmgc_basics::ST_explicits[] = {falsefalse,falsefalse,falsefalse,falsefalse,falsefalse,falsefalse,falsefalse,falsefalse,falsefalse,falsefalse,falsefalse,falsefalse,falsefalse,falsefalse,falsefalse,falsefalse,falsefalse, falsefalse };
1363void ST_mmgc_basics::run(int n) {
1364switch(n) {
1365case 0: test0(); return;
1366case 1: test1(); return;
1367case 2: test2(); return;
1368case 3: test3(); return;
1369case 4: test4(); return;
1370case 5: test5(); return;
1371case 6: test6(); return;
1372case 7: test7(); return;
1373case 8: test8(); return;
1374case 9: test9(); return;
1375case 10: test10(); return;
1376case 11: test11(); return;
1377case 12: test12(); return;
1378case 13: test13(); return;
1379case 14: test14(); return;
1380case 15: test15(); return;
1381case 16: test16(); return;
1382}
1383}
1384void ST_mmgc_basics::prologue() {
1385 MMgc::GCConfig config;
1386 gc=new MMgc::GC(MMgc::GCHeap::GetGCHeap(), config);
1387 if (gc==NULL__null) {
1388 MMgc::GCHeap::Init();
1389 gc=new MMgc::GC(MMgc::GCHeap::GetGCHeap(), config);
1390 }
1391
1392}
1393void ST_mmgc_basics::epilogue() {
1394delete gc;
1395
1396}
1397using namespace MMgc;
1398class DeleteInFinalizer : public GCFinalizedObject {
1399 public:
1400 // note "small" is a reserved identifier in Visual C++ for Windows Mobile (#defined to be 'char')
1401 DeleteInFinalizer(GCFinalizedObject *big, GCFinalizedObject *small_) : big(big), small_(small_) {};
1402 ~DeleteInFinalizer() { delete big; delete small_; }
1403 private:
1404 GCFinalizedObject *big;
1405 GCFinalizedObject *small_;
1406};
1407
1408// Any small object would do
1409class AllocInFinalizer2 : public GCObject {
1410public:
1411 void* dummy;
1412};
1413
1414class AllocInFinalizer : public GCFinalizedObject {
1415public:
1416 AllocInFinalizer() {}
1417 ~AllocInFinalizer() { new (GC::GetGC(this)) AllocInFinalizer2(); }
1418};
1419
1420class LockableObject : public GCFinalizedObject {
1421public:
1422 LockableObject(int* counter) : counter(counter) {}
1423 virtual ~LockableObject() {
1424 *counter = *counter + 1;
1425 }
1426 int * const counter;
1427};
1428
1429class LockerAndUnlocker
1430{
1431public:
1432 static const int numlocked = 100;
1433 static GCObjectLock* lock[numlocked];
1434 static GCObjectLock* lock2[numlocked];
1435 static int counter;
1436
1437 static boolbool createAndLockObjects(GC* gc) {
1438 counter = 0;
1439 for ( int i=0 ; i < numlocked ; i++ )
1440 lock[i] = gc->LockObject(new (gc) LockableObject(&counter));
1441 return truetrue;
1442 }
1443
1444 static boolbool lockLevel2(GC* gc) {
1445 for ( int i=0 ; i < numlocked ; i++ )
1446 lock2[i] = gc->LockObject(gc->GetLockedObject(lock[i]));
1447 return truetrue;
1448 }
1449
1450 static boolbool testLocksHeld(GC* gc, int level) {
1451 if (counter != 0)
1452 return falsefalse;
1453
1454 int held = 0;
1455 for ( int i=0 ; i < numlocked ; i++ )
1456 held += boolbool(gc->GetLockedObject(lock[i]) != NULL__null);
1457 if (level > 1)
1458 for ( int i=0 ; i < numlocked ; i++ )
1459 held += boolbool(gc->GetLockedObject(lock2[i]) != NULL__null);
1460
1461 if (held != level*numlocked)
1462 return falsefalse;
1463
1464 return truetrue;
1465 }
1466
1467 static boolbool testLocksNotHeld(GC*) {
1468 // At least some of the destructors should have run...
1469 if (counter < numlocked/2)
1470 return falsefalse;
1471 return truetrue;
1472 }
1473
1474 static boolbool unlockLevel2(GC* gc) {
1475 for ( int i=0 ; i < numlocked ; i++ )
1476 gc->UnlockObject(lock2[i]);
1477 return truetrue;
1478 }
1479
1480 static boolbool unlockLevel1(GC* gc) {
1481 for ( int i=0 ; i < numlocked ; i++ ) {
1482#ifdef MMGC_HEAP_GRAPH
1483 gc->addToBlacklist(gc->GetLockedObject(lock[i]));
1484#endif
1485 gc->UnlockObject(lock[i]);
1486 }
1487 return truetrue;
1488 }
1489};
1490
1491GCObjectLock* LockerAndUnlocker::lock[numlocked];
1492GCObjectLock* LockerAndUnlocker::lock2[numlocked];
1493int LockerAndUnlocker::counter = 0;
1494
1495void ST_mmgc_basics::test0() {
1496// line 161 "ST_mmgc_basics.st"
1497verifyPass(gc != NULL__null, "gc != NULL", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__1497);
1498
1499}
1500void ST_mmgc_basics::test1() {
1501 MMGC_GCENTER(gc)MMgc::GCAutoEnter __mmgc_auto_enter(gc);;
1502 MyGCObject *mygcobject;
1503 mygcobject = (MyGCObject *)new (gc) MyGCObject();
1504// line 167 "ST_mmgc_basics.st"
1505verifyPass(mygcobject!=NULL__null, "mygcobject!=NULL", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__1505);
1506 mygcobject->i=10;
1507// line 169 "ST_mmgc_basics.st"
1508verifyPass(mygcobject->i==10, "mygcobject->i==10", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__1508);
1509
1510}
1511void ST_mmgc_basics::test2() {
1512 MMGC_GCENTER(gc)MMgc::GCAutoEnter __mmgc_auto_enter(gc);;
1513 MyGCObject *mygcobject;
1514 int inuse=(int)gc->GetBytesInUse();
1515 mygcobject = (MyGCObject *)new (gc) MyGCObject();
1516// AvmLog("bytes in use before %d after %d\n",inuse,(int)gc->GetBytesInUse());
1517// line 177 "ST_mmgc_basics.st"
1518verifyPass(gc->GetBytesInUse()==inuse + sizeof(MyGCObject) + DebugSize()0, "gc->GetBytesInUse()==inuse + sizeof(MyGCObject) + DebugSize()", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__1518);
1519 delete mygcobject;
1520
1521}
1522void ST_mmgc_basics::test3() {
1523 MMGC_GCENTER(gc)MMgc::GCAutoEnter __mmgc_auto_enter(gc);;
1524 MyGCObject *mygcobject;
1525 int inuse=(int)gc->GetBytesInUse();
1526 mygcobject = (MyGCObject *)new (gc) MyGCObject();
1527// line 185 "ST_mmgc_basics.st"
1528verifyPass((int)gc->GetBytesInUse()>inuse, "(int)gc->GetBytesInUse()>inuse", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__1528);
1529 delete mygcobject;
1530// AvmLog("collect: inuse=%d current=%d\n",inuse,(int)gc->GetBytesInUse());
1531 gc->Collect();
1532// AvmLog("collect: inuse=%d current=%d\n",inuse,(int)gc->GetBytesInUse());
1533// line 190 "ST_mmgc_basics.st"
1534verifyPass((int)gc->GetBytesInUse()<=inuse, "(int)gc->GetBytesInUse()<=inuse", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__1534);
1535
1536}
1537void ST_mmgc_basics::test4() {
1538// line 193 "ST_mmgc_basics.st"
1539verifyPass(gc->GetGCHeap()!=NULL__null, "gc->GetGCHeap()!=NULL", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__1539);
1540
1541}
1542void ST_mmgc_basics::test5() {
1543 MMgc::FixedAlloc *fa;
1544 fa=new MMgc::FixedAlloc(2048,MMgc::GCHeap::GetGCHeap());
1545// line 198 "ST_mmgc_basics.st"
1546verifyPass((int)fa->GetMaxAlloc()==0, "(int)fa->GetMaxAlloc()==0", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__1546);
1547// line 199 "ST_mmgc_basics.st"
1548verifyPass((int)fa->GetNumBlocks()==0, "(int)fa->GetNumBlocks()==0", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__1548);
1549 void *data1=fa->Alloc(2048);
1550// line 201 "ST_mmgc_basics.st"
1551verifyPass(MMgc::FixedAlloc::GetFixedAlloc(data1)==fa, "MMgc::FixedAlloc::GetFixedAlloc(data1)==fa", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__1551);
1552// line 202 "ST_mmgc_basics.st"
1553verifyPass(fa->GetBytesInUse()==DebugSize()0+2048, "fa->GetBytesInUse()==DebugSize()+2048", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__1553);
1554// line 203 "ST_mmgc_basics.st"
1555verifyPass(fa->GetItemSize()==2048, "fa->GetItemSize()==2048", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__1555);
1556 void *data2=fa->Alloc(2048);
1557// line 205 "ST_mmgc_basics.st"
1558verifyPass(MMgc::FixedAlloc::GetFixedAlloc(data2)==fa, "MMgc::FixedAlloc::GetFixedAlloc(data2)==fa", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__1558);
1559// AvmLog("fa->GetItemSize=%d\n",(int)fa->GetItemSize());
1560// line 207 "ST_mmgc_basics.st"
1561verifyPass((int)fa->GetItemSize()==2048, "(int)fa->GetItemSize()==2048", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__1561);
1562 fa->Free(data1);
1563// line 209 "ST_mmgc_basics.st"
1564verifyPass((int)fa->GetItemSize()==2048, "(int)fa->GetItemSize()==2048", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__1564);
1565// line 210 "ST_mmgc_basics.st"
1566verifyPass((int)fa->GetMaxAlloc()==1, "(int)fa->GetMaxAlloc()==1", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__1566);
1567// line 211 "ST_mmgc_basics.st"
1568verifyPass((int)fa->GetNumBlocks()==1, "(int)fa->GetNumBlocks()==1", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__1568);
1569 fa->Free(data2);
1570 delete fa;
1571
1572}
1573void ST_mmgc_basics::test6() {
1574 fm=MMgc::FixedMalloc::GetFixedMalloc();
1575 int start=(int)fm->GetBytesInUse();
1576 int starttotal=(int)fm->GetTotalSize();
1577// AvmLog("fm->GetBytesInUse()=%d\n",(int)fm->GetBytesInUse());
1578// line 220 "ST_mmgc_basics.st"
1579verifyPass((int)fm->GetBytesInUse()==start, "(int)fm->GetBytesInUse()==start", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__1579);
1580// AvmLog("fm->GetTotalSize()=%d\n",(int)fm->GetTotalSize());
1581// line 222 "ST_mmgc_basics.st"
1582verifyPass((int)fm->GetTotalSize()==starttotal, "(int)fm->GetTotalSize()==starttotal", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__1582);
1583 void *obj=fm->Alloc(8192);
1584// AvmLog("fm->GetBytesInUse()=%d\n",(int)fm->GetBytesInUse());
1585// %%verify fm->GetBytesInUse()==start + 8192 + MMgc::DebugSize()
1586// AvmLog("fm->GetTotalSize()=%d\n",(int)fm->GetTotalSize());
1587// %%verify (int)fm->GetTotalSize()==starttotal+2
1588 fm->Free(obj);
1589// AvmLog("fm->GetBytesInUse()=%d\n",(int)fm->GetBytesInUse());
1590// line 230 "ST_mmgc_basics.st"
1591verifyPass((int)fm->GetBytesInUse()==start, "(int)fm->GetBytesInUse()==start", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__1591);
1592// AvmLog("fm->GetTotalSize()=%d\n",(int)fm->GetTotalSize());
1593// line 232 "ST_mmgc_basics.st"
1594verifyPass((int)fm->GetTotalSize()==starttotal, "(int)fm->GetTotalSize()==starttotal", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__1594);
1595 obj=fm->Calloc(1024,10);
1596// AvmLog("fm->GetBytesInUse()=%d\n",(int)fm->GetBytesInUse());
1597// FixedMalloc is currently (as of redux 3229) tracking large allocs using a list of
1598// small objects, in some debug modes. So we can't have a precise test here.
1599// line 237 "ST_mmgc_basics.st"
1600verifyPass((int)fm->GetBytesInUse()>=start+1024*12 && (int)fm->GetBytesInUse()<=start+1024*12+64, "(int)fm->GetBytesInUse()>=start+1024*12 && (int)fm->GetBytesInUse()<=start+1024*12+64", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__1600);
1601// AvmLog("fm->GetTotalSize()=%d\n",(int)fm->GetTotalSize());
1602// line 239 "ST_mmgc_basics.st"
1603verifyPass((int)fm->GetTotalSize()==starttotal+3, "(int)fm->GetTotalSize()==starttotal+3", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__1603);
1604 fm->Free(obj);
1605// line 241 "ST_mmgc_basics.st"
1606verifyPass((int)fm->GetBytesInUse()==start, "(int)fm->GetBytesInUse()==start", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__1606);
1607// line 242 "ST_mmgc_basics.st"
1608verifyPass((int)fm->GetTotalSize()==starttotal, "(int)fm->GetTotalSize()==starttotal", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__1608);
1609
1610}
1611void ST_mmgc_basics::test7() {
1612 MMgc::GCHeap *gh=MMgc::GCHeap::GetGCHeap();
1613 int startfreeheap=(int)gh->GetFreeHeapSize();
1614// %%verify (int)gh->GetTotalHeapSize()==128
1615// AvmLog("gh->GetFreeHeapSize()=%d\n",(int)gh->GetFreeHeapSize());
1616// line 249 "ST_mmgc_basics.st"
1617verifyPass((int)gh->GetFreeHeapSize()==startfreeheap, "(int)gh->GetFreeHeapSize()==startfreeheap", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__1617);
1618//gh->Config().heapLimit = 1024;
1619// %%verify (int)gh->GetTotalHeapSize()==128
1620// AvmLog("gh->GetFreeHeapSize()=%d\n",(int)gh->GetFreeHeapSize());
1621// line 253 "ST_mmgc_basics.st"
1622verifyPass((int)gh->GetFreeHeapSize()==startfreeheap, "(int)gh->GetFreeHeapSize()==startfreeheap", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__1622);
1623 void *data = gh->Alloc(10,MMgc::GCHeap::kExpand | MMgc::GCHeap::kZero);
1624// line 255 "ST_mmgc_basics.st"
1625verifyPass((int)gh->GetTotalHeapSize()>startfreeheap, "(int)gh->GetTotalHeapSize()>startfreeheap", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__1625);
1626// AvmLog("gh->GetFreeHeapSize()=%d\n",(int)gh->GetFreeHeapSize());
1627 gh->FreeNoProfile(data);
1628
1629}
1630void ST_mmgc_basics::test8() {
1631 MMgc::GCHeap *gh=MMgc::GCHeap::GetGCHeap();
1632
1633 // Tricky: try to provoke some internal asserts
1634 void *d[1000];
1635 for ( unsigned i=0 ; i < ARRAY_SIZE(d)(sizeof(d)/sizeof(d[0])) ; i++ ) {
1636 d[i] = gh->Alloc(1);
1637 void *data = gh->Alloc(10,MMgc::GCHeap::flags_Alloc, 4);
1638 gh->Free(data);
1639 }
1640 for ( unsigned i=0 ; i < ARRAY_SIZE(d)(sizeof(d)/sizeof(d[0])) ; i++ )
1641 gh->Free(d[i]);
1642
1643 //
1644 for ( size_t k=2 ; k <= 256 ; k *= 2 ) {
1645 void *data = gh->Alloc(10,MMgc::GCHeap::flags_Alloc, k);
1646// line 275 "ST_mmgc_basics.st"
1647verifyPass(((uintptr_t)data & (k*MMgc::GCHeap::kBlockSize - 1)) == 0, "((uintptr_t)data & (k*MMgc::GCHeap::kBlockSize - 1)) == 0", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__1647);
1648// line 276 "ST_mmgc_basics.st"
1649verifyPass(gh->Size(data) == 10, "gh->Size(data) == 10", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__1649);
1650 gh->Free(data);
1651 }
1652
1653}
1654void ST_mmgc_basics::test9() {
1655 MMGC_GCENTER(gc)MMgc::GCAutoEnter __mmgc_auto_enter(gc);;
1656 MyGCObject *mygcobject;
1657 mygcobject = (MyGCObject *)new (gc) MyGCObject();
1658// line 284 "ST_mmgc_basics.st"
1659verifyPass((MyGCObject *)gc->FindBeginningGuarded(mygcobject)==mygcobject, "(MyGCObject *)gc->FindBeginningGuarded(mygcobject)==mygcobject", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__1659);
1660// line 285 "ST_mmgc_basics.st"
1661verifyPass((MyGCObject *)gc->FindBeginningFast(mygcobject)==mygcobject, "(MyGCObject *)gc->FindBeginningFast(mygcobject)==mygcobject", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__1661);
1662
1663// Bugzilla 542529 - in debug mode we would assert here due to logic flaws in the allocatr
1664}
1665void ST_mmgc_basics::test10() {
1666 MMGC_GCENTER(gc)MMgc::GCAutoEnter __mmgc_auto_enter(gc);;
1667 new (gc) AllocInFinalizer();
1668 gc->Collect(falsefalse);
1669// line 292 "ST_mmgc_basics.st"
1670verifyPass(truetrue, "true", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__1670);
1671
1672}
1673void ST_mmgc_basics::test11() {
1674 MMGC_GCENTER(gc)MMgc::GCAutoEnter __mmgc_auto_enter(gc);;
1675 new (gc) DeleteInFinalizer(new (gc, 100) GCFinalizedObject(), new (gc) GCFinalizedObject());
1676 //delete m; delete m; // this verifies we crash, it does
1677 gc->Collect(falsefalse);
1678// line 299 "ST_mmgc_basics.st"
1679verifyPass(truetrue, "true", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__1679);
1680 GCFinalizedObject *gcfo = new (gc) GCFinalizedObject();
1681 gcfo->~GCFinalizedObject();
1682 gcfo->~GCFinalizedObject(); // this used to be a deleteing dtor and would crash, not anymore
1683
1684
1685
1686}
1687void ST_mmgc_basics::test12() {
1688 GCConfig config;
1689 GC *gcb = new GC(GCHeap::GetGCHeap(), config);
1690 MMGC_GCENTER(gc)MMgc::GCAutoEnter __mmgc_auto_enter(gc);;
1691 void *a = gc->Alloc(8);
Value stored to 'a' during its initialization is never read
1692 {
1693 MMGC_GCENTER(gcb)MMgc::GCAutoEnter __mmgc_auto_enter(gcb);;
1694 a = gcb->Alloc(8);
1695 {
1696 MMGC_GCENTER(gc)MMgc::GCAutoEnter __mmgc_auto_enter(gc);;
1697 a = gc->Alloc(8);
1698 }
1699 a = gcb->Alloc(8);
1700 }
1701 a = gc->Alloc(8);
1702 // just fishing for asserts/hangs/crashes
1703// line 322 "ST_mmgc_basics.st"
1704verifyPass(truetrue, "true", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__1704);
1705 delete gcb;
1706
1707}
1708void ST_mmgc_basics::test13() {
1709 {
1710 GCConfig config;
1711 GC *gcb = new GC(GCHeap::GetGCHeap(), config);
1712 {
1713 MMGC_GCENTER(gcb)MMgc::GCAutoEnter __mmgc_auto_enter(gcb);;
1714 gcb->Alloc(8);
1715 }
1716
1717 // this will cause a Collection in gcb
1718 GCHeap::SignalExternalFreeMemory();
1719 delete gcb;
1720
1721 // just fishing for asserts/hangs/crashes
1722// line 339 "ST_mmgc_basics.st"
1723verifyPass(truetrue, "true", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__1723);
1724 }
1725
1726}
1727void ST_mmgc_basics::test14() {
1728 {
1729 GCConfig config;
1730 GC *gc = new GC(GCHeap::GetGCHeap(), config);
1731 MMGC_GCENTER(gc)MMgc::GCAutoEnter __mmgc_auto_enter(gc);;
1732
1733// line 348 "ST_mmgc_basics.st"
1734verifyPass(LockerAndUnlocker::createAndLockObjects(gc), "LockerAndUnlocker::createAndLockObjects(gc)", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__1734);
1735 gc->Collect();
1736 gc->Collect();
1737// line 351 "ST_mmgc_basics.st"
1738verifyPass(LockerAndUnlocker::testLocksHeld(gc, 1), "LockerAndUnlocker::testLocksHeld(gc, 1)", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__1738);
1739 gc->Collect();
1740 gc->Collect();
1741// line 354 "ST_mmgc_basics.st"
1742verifyPass(LockerAndUnlocker::lockLevel2(gc), "LockerAndUnlocker::lockLevel2(gc)", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__1742);
1743 gc->Collect();
1744 gc->Collect();
1745// line 357 "ST_mmgc_basics.st"
1746verifyPass(LockerAndUnlocker::testLocksHeld(gc, 2), "LockerAndUnlocker::testLocksHeld(gc, 2)", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__1746);
1747 gc->Collect();
1748 gc->Collect();
1749// line 360 "ST_mmgc_basics.st"
1750verifyPass(LockerAndUnlocker::unlockLevel2(gc), "LockerAndUnlocker::unlockLevel2(gc)", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__1750);
1751 gc->Collect();
1752 gc->Collect();
1753// line 363 "ST_mmgc_basics.st"
1754verifyPass(LockerAndUnlocker::testLocksHeld(gc, 1), "LockerAndUnlocker::testLocksHeld(gc, 1)", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__1754);
1755 gc->Collect();
1756 gc->Collect();
1757// line 366 "ST_mmgc_basics.st"
1758verifyPass(LockerAndUnlocker::unlockLevel1(gc), "LockerAndUnlocker::unlockLevel1(gc)", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__1758);
1759
1760 // Bug 637695: be aware: conservative retention may foil verify below
1761 gc->Collect();
1762 gc->Collect();
1763// line 371 "ST_mmgc_basics.st"
1764verifyPass(LockerAndUnlocker::testLocksNotHeld(gc), "LockerAndUnlocker::testLocksNotHeld(gc)", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__1764);
1765
1766 delete gc;
1767 }
1768
1769}
1770void ST_mmgc_basics::test15() {
1771 {
1772 GCConfig config;
1773 GC *testGC = new GC(GCHeap::GetGCHeap(), config);
1774 {
1775 MMGC_GCENTER(testGC)MMgc::GCAutoEnter __mmgc_auto_enter(testGC);;
1776 testGC->StartIncrementalMark();
1777 // self test for tricky GCRoot deletion logic
1778 // do this a bunch, idea is to try to hit GetItemAbove border edge cases
1779 //GCMarkStack& ms = testGC->m_incrementalWork;
1780 for(int i=0;i<10000;i++) {
1781 //GCRoot *fauxRoot = new GCRoot(testGC, new char[GC::kMarkItemSplitThreshold*2], GC::kMarkItemSplitThreshold*2);
1782 //testGC->MarkAllRoots();
1783 // tail of fauxRoot is on stack
1784 //uintptr_t sentinel = fauxRoot->GetMarkStackSentinelPointer();
1785 //if(sentinel) {
1786 // const void* ptr;
1787 // ms.Read_RootProtector(sentinel, ptr);
1788 // %%verify ptr == fauxRoot
1789 // uintptr_t tail = ms.GetItemAbove(sentinel);
1790 // %%verify ms.GetEndAt(tail) == fauxRoot->End()
1791 // %%verify sentinel != 0
1792 //}
1793 //delete [] (char*)fauxRoot->Get();
1794 //delete fauxRoot;
1795 //if(sentinel) {
1796 // %%verify ms.P(sentinel) == GCMarkStack::kDeadItem
1797 // %%verify ms.GetSentinel1TypeAt(ms.GetItemAbove(sentinel)) == GCMarkStack::kDeadItem
1798 //}
1799// line 405 "ST_mmgc_basics.st"
1800verifyPass(truetrue, "true", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__1800);
1801 }
1802 testGC->Mark();
1803 testGC->ClearMarkStack();
1804 testGC->ClearMarks();
1805 }
1806 delete testGC;
1807 }
1808
1809
1810}
1811void ST_mmgc_basics::test16() {
1812#ifdef MMGC_HEAP_GRAPH
1813 GCConfig config;
1814 GC *gc = new GC(GCHeap::GetGCHeap(), config);
1815 MMGC_GCENTER(gc)MMgc::GCAutoEnter __mmgc_auto_enter(gc);;
1816 MyGCObject *mygcobject;
1817 mygcobject = (MyGCObject *)new (gc) MyGCObject();
1818 gc->addToBlacklist(mygcobject);
1819 gc->Collect();
1820 gc->removeFromBlacklist(mygcobject);
1821 delete gc;
1822#endif
1823// line 427 "ST_mmgc_basics.st"
1824verifyPass(truetrue, "true", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__1824);
1825
1826
1827}
1828void create_mmgc_basics(AvmCore* core) { new ST_mmgc_basics(core); }
1829}
1830}
1831#endif
1832
1833// Generated from ST_mmgc_dependent.st
1834// -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*-
1835// vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */
1836//
1837// ***** BEGIN LICENSE BLOCK *****
1838// Version: MPL 1.1/GPL 2.0/LGPL 2.1
1839//
1840// The contents of this file are subject to the Mozilla Public License Version
1841// 1.1 (the "License"); you may not use this file except in compliance with
1842// the License. You may obtain a copy of the License at
1843// http://www.mozilla.org/MPL/
1844//
1845// Software distributed under the License is distributed on an "AS IS" basis,
1846// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
1847// for the specific language governing rights and limitations under the
1848// License.
1849//
1850// The Original Code is [Open Source Virtual Machine.].
1851//
1852// The Initial Developer of the Original Code is
1853// Adobe System Incorporated.
1854// Portions created by the Initial Developer are Copyright (C) 2004-2006
1855// the Initial Developer. All Rights Reserved.
1856//
1857// Contributor(s):
1858// Adobe AS3 Team
1859//
1860// Alternatively, the contents of this file may be used under the terms of
1861// either the GNU General Public License Version 2 or later (the "GPL"), or
1862// the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
1863// in which case the provisions of the GPL or the LGPL are applicable instead
1864// of those above. If you wish to allow use of your version of this file only
1865// under the terms of either the GPL or the LGPL, and not to allow others to
1866// use your version of this file under the terms of the MPL, indicate your
1867// decision by deleting the provisions above and replace them with the notice
1868// and other provisions required by the GPL or the LGPL. If you do not delete
1869// the provisions above, a recipient may use your version of this file under
1870// the terms of any one of the MPL, the GPL or the LGPL.
1871//
1872// ***** END LICENSE BLOCK ***** */
1873
1874// Bugzilla 543560 - here we risk deleting an object that is still on the mark stack because
1875// of how we perform large-object splitting. The setup is that user code that deletes the object
1876// gets to run after the first part of the large object has been popped off the mark stack
1877// but before the rest has been handled.
1878
1879#include "avmshell.h"
1880#ifdef VMCFG_SELFTEST
1881namespace avmplus {
1882namespace ST_mmgc_dependent {
1883using namespace MMgc;
1884
1885static const size_t nbytes = 16*1024*1024;
1886
1887class DependentAllocHolder : public GCFinalizedObject {
1888public:
1889
1890 DependentAllocHolder() {
1891 memory = (char*)FixedMalloc::GetFixedMalloc()->Alloc(nbytes);
1892 GC::GetGC(this)->SignalDependentAllocation(nbytes);
1893 }
1894
1895 virtual ~DependentAllocHolder() {
1896 FixedMalloc::GetFixedMalloc()->Free(memory);
1897 memory = NULL__null;
1898 GC::GetGC(this)->SignalDependentDeallocation(nbytes);
1899 }
1900 private:
1901 char* memory;
1902};
1903
1904class ST_mmgc_dependent : public Selftest {
1905public:
1906ST_mmgc_dependent(AvmCore* core);
1907virtual void run(int n);
1908virtual void prologue();
1909virtual void epilogue();
1910private:
1911static const char* ST_names[];
1912static const boolbool ST_explicits[];
1913void test0();
1914private:
1915 MMgc::GC *gc;
1916
1917};
1918ST_mmgc_dependent::ST_mmgc_dependent(AvmCore* core)
1919 : Selftest(core, "mmgc", "dependent", ST_mmgc_dependent::ST_names,ST_mmgc_dependent::ST_explicits)
1920{}
1921const char* ST_mmgc_dependent::ST_names[] = {"dependent_alloc", NULL__null };
1922const boolbool ST_mmgc_dependent::ST_explicits[] = {falsefalse, falsefalse };
1923void ST_mmgc_dependent::run(int n) {
1924switch(n) {
1925case 0: test0(); return;
1926}
1927}
1928void ST_mmgc_dependent::prologue() {
1929 GCConfig config;
1930 gc = new GC(GCHeap::GetGCHeap(), config);
1931
1932}
1933void ST_mmgc_dependent::epilogue() {
1934 delete gc;
1935
1936}
1937void ST_mmgc_dependent::test0() {
1938 size_t maxheap = 0;
1939 {
1940 MMGC_GCENTER(gc)MMgc::GCAutoEnter __mmgc_auto_enter(gc);;
1941
1942 int count = 100;
1943 for (int c=0; c<count; c++) {
1944 (void)(new (gc) DependentAllocHolder());
1945 size_t heapsize = gc->policy.blocksOwnedByGC() * GCHeap::kBlockSize;
1946 // printf("%lu\n", (unsigned long)heapsize);
1947 if (heapsize > maxheap)
1948 maxheap = heapsize;
1949 }
1950 }
1951
1952 // This is tricky to get right but for this test the 16MB blocks will dominate
1953 // completely. So assume that heap size must stay below L*2*16MB for the
1954 // L that applies at 32MB.
1955
1956// line 101 "ST_mmgc_dependent.st"
1957verifyPass(size_t(gc->policy.queryLoadForHeapsize(double(2*nbytes)) * 2.0 * double(nbytes)) >= maxheap, "size_t(gc->policy.queryLoadForHeapsize(double(2*nbytes)) * 2.0 * double(nbytes)) >= maxheap", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__1957);
1958
1959
1960}
1961void create_mmgc_dependent(AvmCore* core) { new ST_mmgc_dependent(core); }
1962}
1963}
1964#endif
1965
1966// Generated from ST_mmgc_exact.st
1967// -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*-
1968// vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */
1969//
1970// ***** BEGIN LICENSE BLOCK *****
1971// Version: MPL 1.1/GPL 2.0/LGPL 2.1
1972//
1973// The contents of this file are subject to the Mozilla Public License Version
1974// 1.1 (the "License"); you may not use this file except in compliance with
1975// the License. You may obtain a copy of the License at
1976// http://www.mozilla.org/MPL/
1977//
1978// Software distributed under the License is distributed on an "AS IS" basis,
1979// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
1980// for the specific language governing rights and limitations under the
1981// License.
1982//
1983// The Original Code is [Open Source Virtual Machine.].
1984//
1985// The Initial Developer of the Original Code is
1986// Adobe System Incorporated.
1987// Portions created by the Initial Developer are Copyright (C) 2004-2006
1988// the Initial Developer. All Rights Reserved.
1989//
1990// Contributor(s):
1991// Adobe AS3 Team
1992//
1993// Alternatively, the contents of this file may be used under the terms of
1994// either the GNU General Public License Version 2 or later (the "GPL"), or
1995// the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
1996// in which case the provisions of the GPL or the LGPL are applicable instead
1997// of those above. If you wish to allow use of your version of this file only
1998// under the terms of either the GPL or the LGPL, and not to allow others to
1999// use your version of this file under the terms of the MPL, indicate your
2000// decision by deleting the provisions above and replace them with the notice
2001// and other provisions required by the GPL or the LGPL. If you do not delete
2002// the provisions above, a recipient may use your version of this file under
2003// the terms of any one of the MPL, the GPL or the LGPL.
2004//
2005// ***** END LICENSE BLOCK ***** */
2006
2007#include "avmshell.h"
2008#ifdef VMCFG_SELFTEST
2009namespace avmplus {
2010namespace ST_mmgc_exact {
2011
2012class Cthulhu : public MMgc::GCTraceableObject
2013{
2014public:
2015 static Cthulhu* create(MMgc::GC* gc) {
2016 return new (gc, MMgc::kExact) Cthulhu();
2017 }
2018
2019 virtual boolbool gcTrace(MMgc::GC* gc, size_t cursor) {
2020 (void)gc;
2021 // Incorrectly say that there's more to do even when the object is small
2022 if (cursor == 0)
2023 return truetrue;
2024 // Concede
2025 return falsefalse;
2026 }
2027};
2028
2029// This test triggers a particular edge case in GC::SplitExactGCObject where
2030// a small object that returns 'true' from its gcTrace method is synchronously
2031// marked until the method returns 'false'; a 'true' return is only ever expected
2032// from the gcTrace methods of large objects.
2033
2034class ST_mmgc_exact : public Selftest {
2035public:
2036ST_mmgc_exact(AvmCore* core);
2037virtual void run(int n);
2038private:
2039static const char* ST_names[];
2040static const boolbool ST_explicits[];
2041void test0();
2042};
2043ST_mmgc_exact::ST_mmgc_exact(AvmCore* core)
2044 : Selftest(core, "mmgc", "exact", ST_mmgc_exact::ST_names,ST_mmgc_exact::ST_explicits)
2045{}
2046const char* ST_mmgc_exact::ST_names[] = {"IncorrectlySplitSmallObject", NULL__null };
2047const boolbool ST_mmgc_exact::ST_explicits[] = {falsefalse, falsefalse };
2048void ST_mmgc_exact::run(int n) {
2049switch(n) {
2050case 0: test0(); return;
2051}
2052}
2053void ST_mmgc_exact::test0() {
2054 // Create an object that stays alive so that its tracer will be called
2055 MMgc::GCObjectLock* lock = core->gc->LockObject(Cthulhu::create(core->gc));
2056 core->gc->Collect();
2057 core->gc->Collect();
2058 core->gc->UnlockObject(lock);
2059
2060// line 75 "ST_mmgc_exact.st"
2061verifyPass(truetrue, "true", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__2061);
2062
2063
2064}
2065void create_mmgc_exact(AvmCore* core) { new ST_mmgc_exact(core); }
2066}
2067}
2068#endif
2069
2070// Generated from ST_mmgc_finalize_uninit.st
2071// -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*-
2072// vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */
2073
2074// Bugzilla 573737 - a throw from an argument to a constructor can
2075// cause an object to be allocated on the gc-heap before it has been
2076// fully initialized. (In particular, its vtable could be missing.)
2077// Since finalizers use the virtual destructor method, a missing
2078// vtable is a problem.
2079//
2080// Its a little tricky to test this because the "order of evaluation
2081// to an operator new() to get memory and the evaluation of arguments
2082// to constructors is undefined"; see details below.
2083
2084#include "avmshell.h"
2085#ifdef VMCFG_SELFTEST
2086namespace avmplus {
2087namespace ST_mmgc_finalize_uninit {
2088
2089using namespace MMgc;
2090
2091class D : public GCFinalizedObject
2092{
2093public:
2094 D(int dummyArgument) { (void)dummyArgument; }
2095 ~D() { ++finalized; }
2096 static int finalized_count() { return D::finalized; }
2097 static void reset_finalized_count() { finalized = 0; }
2098 // "usual" overload of placement new used in mmgc client code
2099 void * operator new(size_t size, GC *gc) {
2100 return GCFinalizedObject::operator new(size, gc);
2101 }
2102 // hack to explicitly order new-allocation + ctor-arg eval; see below
2103 // (but reallys its just good ol' placement new!)
2104 void * operator new(size_t size, GC *gc, void *raw) {
2105 (void)size; (void)gc;
2106 return raw;
2107 }
2108private:
2109 static int finalized;
2110};
2111
2112/*static*/
2113int D::finalized;
2114
2115int deathValue(AvmCore *core)
2116{
2117 core->throwAtom(atomFromIntptrValue(1)); /* won't return */
2118
2119 return 0; /* silence compiler warnings */
2120}
2121
2122// Test checks that finalizers themselves have not broken; here,
2123// constructor argument subexpression evaluates cleanly.
2124class ST_mmgc_finalize_uninit : public Selftest {
2125public:
2126ST_mmgc_finalize_uninit(AvmCore* core);
2127virtual void run(int n);
2128private:
2129static const char* ST_names[];
2130static const boolbool ST_explicits[];
2131void test0();
2132void test1();
2133void test2();
2134void test3();
2135};
2136ST_mmgc_finalize_uninit::ST_mmgc_finalize_uninit(AvmCore* core)
2137 : Selftest(core, "mmgc", "finalize_uninit", ST_mmgc_finalize_uninit::ST_names,ST_mmgc_finalize_uninit::ST_explicits)
2138{}
2139const char* ST_mmgc_finalize_uninit::ST_names[] = {"check_finalizers_still_work","original_death","desugared_check_finalizers_still_work","desugared_death", NULL__null };
2140const boolbool ST_mmgc_finalize_uninit::ST_explicits[] = {falsefalse,falsefalse,falsefalse,falsefalse, falsefalse };
2141void ST_mmgc_finalize_uninit::run(int n) {
2142switch(n) {
2143case 0: test0(); return;
2144case 1: test1(); return;
2145case 2: test2(); return;
2146case 3: test3(); return;
2147}
2148}
2149void ST_mmgc_finalize_uninit::test0() {
2150{
2151 D::reset_finalized_count();
2152 D* d;
2153 int i;
2154
2155 // loop to alloc many (and subsequently reclaim >=expected percentage)
2156 for (i = 0; i < 100; i++) {
2157 d = new (core->gc) D(1);
2158 }
2159 (void) d;
2160
2161 core->gc->Collect(); // finish any prior incremental work ...
2162 core->gc->Collect(); // ... and ensure we got fresh + complete gc.
2163
2164 // printf("D::finalized_count(): %d\n", D::finalized_count());
2165
2166// line 71 "ST_mmgc_finalize_uninit.st"
2167verifyPass((D::finalized_count() > 90), "(D::finalized_count() > 90)", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__2167);
2168}
2169
2170// Test illustrates of the kind of code that exposed the original bug;
2171// here, constructor argument subexpression throws.
2172}
2173void ST_mmgc_finalize_uninit::test1() {
2174{
2175 D* d;
2176 volatile int i;
2177
2178 // Here, constructor argument subexpression throws
2179
2180 // Just one allocation attempt alone would risk false retention of
2181 // intermediate values, so loop a bit to ensure that *some* D's,
2182 // if allocated at all, will be considered garbage.
2183 for (i = 0; i < 5; i++) {
2184 TRY (core, kCatchAction_Ignore){ avmplus::ExceptionFrame _ef; _ef.beginTry(core); _ef.catchAction
= (kCatchAction_Ignore); int _setjmpVal = ::_setjmp(_ef.jmpbuf
); avmplus::Exception* _ee = core->exceptionAddr; if (!_setjmpVal
)
{
2185 d = new (core->gc) D(deathValue(core));
2186 } CATCH (Exception *e)else { _ef.beginCatch(); Exception *e = _ee; {
2187 (void)e;
2188 }
2189 END_CATCH}
2190 END_TRY}
2191 }
2192 (void) d;
2193
2194 // if things go badly, one of the collections below will segfault
2195 // during finalization.
2196 core->gc->Collect();
2197 core->gc->Collect();
2198
2199 // (not dying is passing.)
2200// line 103 "ST_mmgc_finalize_uninit.st"
2201verifyPass(truetrue, "true", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__2201);
2202}
2203
2204// C++ standard says "The order of evaluation to an operator new() to
2205// get memory and the evaluation of arguments to constructors is
2206// undefined."
2207//
2208// Unfortunately, it is difficult to directly express the particular
2209// order of evaluation that exposes the bug in question, because
2210// allocation and construction are tied together.
2211//
2212// So, here we manually decompose the tests above to control
2213// evaluation order of operator new() and constructor arguments, to
2214// express suitable evil (namely: allocation; args eval; construction)
2215// for selftest.
2216//
2217// The desugaring iteself is:
2218// desugar[[ new (gc-exp) D(arg-exp) ]]
2219// ==> mem = D::operator new(sizeof(D), arg), new (gc-exp, mem) D(arg-exp)
2220
2221// Test illustrates desugaring is "sound"; keep in sync with
2222// check_finalizers_still_work above.
2223}
2224void ST_mmgc_finalize_uninit::test2() {
2225{
2226 D::reset_finalized_count();
2227 D* d;
2228 int i;
2229
2230 // loop to alloc many (and subsequently reclaim >=expected percentage)
2231 for (i = 0; i < 100; i++) {
2232 // d = new (core->gc) D(s);
2233 void *mem = D::operator new(sizeof(D), core->gc);
2234 d = new (core->gc, mem) D(1);
2235 }
2236 (void) d;
2237
2238 core->gc->Collect(); // finish any prior incremental work ...
2239 core->gc->Collect(); // ... and ensure we got fresh + complete gc.
2240
2241 // printf("D::finalized_count(): %d\n", D::finalized_count());
2242
2243// line 144 "ST_mmgc_finalize_uninit.st"
2244verifyPass((D::finalized_count() > 90), "(D::finalized_count() > 90)", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__2244);
2245}
2246
2247
2248// Test forces evil order of evaluation via desugaring of
2249// construction; keep in sync with original_death above.
2250}
2251void ST_mmgc_finalize_uninit::test3() {
2252{
2253 D* d;
2254 volatile int i;
2255
2256 // Here, constructor argument subexpression throws
2257
2258 // Just one allocation attempt alone would risk false retention of
2259 // intermediate values, so loop a bit to ensure that *some* D's,
2260 // which are forcibly allocated here, will be considered garbage.
2261 for (i = 0; i < 5; i++) {
2262 TRY (core, kCatchAction_Ignore){ avmplus::ExceptionFrame _ef; _ef.beginTry(core); _ef.catchAction
= (kCatchAction_Ignore); int _setjmpVal = ::_setjmp(_ef.jmpbuf
); avmplus::Exception* _ee = core->exceptionAddr; if (!_setjmpVal
)
{
2263 // d = new (core->gc) D(deathValue());
2264 void *mem = D::operator new(sizeof(D), core->gc);
2265 d = new (core->gc, mem) D(deathValue(core));
2266 } CATCH (Exception *e)else { _ef.beginCatch(); Exception *e = _ee; {
2267 (void)e;
2268 }
2269 END_CATCH}
2270 END_TRY}
2271 }
2272 (void) d;
2273
2274 // if things go badly, one of the collections below will segfault
2275 // during finalization.
2276 core->gc->Collect();
2277 core->gc->Collect();
2278
2279 // (not dying is passing.)
2280// line 179 "ST_mmgc_finalize_uninit.st"
2281verifyPass(truetrue, "true", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__2281);
2282}
2283
2284}
2285void create_mmgc_finalize_uninit(AvmCore* core) { new ST_mmgc_finalize_uninit(core); }
2286}
2287}
2288#endif
2289
2290// Generated from ST_mmgc_gcheap.st
2291// -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */
2292//
2293// ***** BEGIN LICENSE BLOCK *****
2294// Version: MPL 1.1/GPL 2.0/LGPL 2.1
2295//
2296// The contents of this file are subject to the Mozilla Public License Version
2297// 1.1 (the "License"); you may not use this file except in compliance with
2298// the License. You may obtain a copy of the License at
2299// http://www.mozilla.org/MPL/
2300//
2301// Software distributed under the License is distributed on an "AS IS" basis,
2302// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
2303// for the specific language governing rights and limitations under the
2304// License.
2305//
2306// The Original Code is [Open Source Virtual Machine.].
2307//
2308// The Initial Developer of the Original Code is
2309// Adobe System Incorporated.
2310// Portions created by the Initial Developer are Copyright (C) 2004-2006
2311// the Initial Developer. All Rights Reserved.
2312//
2313// Contributor(s):
2314// Adobe AS3 Team
2315//
2316// Alternatively, the contents of this file may be used under the terms of
2317// either the GNU General Public License Version 2 or later (the "GPL"), or
2318// the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
2319// in which case the provisions of the GPL or the LGPL are applicable instead
2320// of those above. If you wish to allow use of your version of this file only
2321// under the terms of either the GPL or the LGPL, and not to allow others to
2322// use your version of this file under the terms of the MPL, indicate your
2323// decision by deleting the provisions above and replace them with the notice
2324// and other provisions required by the GPL or the LGPL. If you do not delete
2325// the provisions above, a recipient may use your version of this file under
2326// the terms of any one of the MPL, the GPL or the LGPL.
2327//
2328// ***** END LICENSE BLOCK ***** */
2329
2330#include "avmshell.h"
2331#ifdef VMCFG_SELFTEST
2332namespace avmplus {
2333namespace ST_mmgc_gcheap {
2334class ST_mmgc_gcheap : public Selftest {
2335public:
2336ST_mmgc_gcheap(AvmCore* core);
2337virtual void run(int n);
2338private:
2339static const char* ST_names[];
2340static const boolbool ST_explicits[];
2341void test0();
2342void test1();
2343};
2344ST_mmgc_gcheap::ST_mmgc_gcheap(AvmCore* core)
2345 : Selftest(core, "mmgc", "gcheap", ST_mmgc_gcheap::ST_names,ST_mmgc_gcheap::ST_explicits)
2346{}
2347const char* ST_mmgc_gcheap::ST_names[] = {"largeAlloc","largeAllocAlignment", NULL__null };
2348const boolbool ST_mmgc_gcheap::ST_explicits[] = {falsefalse,falsefalse, falsefalse };
2349void ST_mmgc_gcheap::run(int n) {
2350switch(n) {
2351case 0: test0(); return;
2352case 1: test1(); return;
2353}
2354}
2355using namespace MMgc;
2356
2357void ST_mmgc_gcheap::test0() {
2358 GCHeap *heap = GCHeap::GetGCHeap();
2359 for(int i=1;i<4;i++) {
2360 void *item = heap->Alloc(GCHeap::kOSAllocThreshold*i);
2361// line 50 "ST_mmgc_gcheap.st"
2362verifyPass(heap->Size(item) == GCHeap::kOSAllocThreshold*i, "heap->Size(item) == GCHeap::kOSAllocThreshold*i", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__2362);
2363 heap->Free(item);
2364 }
2365// line 53 "ST_mmgc_gcheap.st"
2366verifyPass(truetrue, "true", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__2366);
2367
2368}
2369void ST_mmgc_gcheap::test1() {
2370 GCHeap *heap = GCHeap::GetGCHeap();
2371 for(int i=1;i<10;i++) {
2372 void *item = heap->Alloc(GCHeap::kOSAllocThreshold*i, GCHeap::flags_Alloc, 1<<i);
2373// line 59 "ST_mmgc_gcheap.st"
2374verifyPass(heap->Size(item) == GCHeap::kOSAllocThreshold*i, "heap->Size(item) == GCHeap::kOSAllocThreshold*i", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__2374);
2375// line 60 "ST_mmgc_gcheap.st"
2376verifyPass(uintptr_t(((GCHeap::kBlockSize<<(i-1))-1) & uintptr_t(item)) == 0, "uintptr_t(((GCHeap::kBlockSize<<(i-1))-1) & uintptr_t(item)) == 0", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__2376);
2377 heap->Free(item);
2378 }
2379
2380
2381}
2382void create_mmgc_gcheap(AvmCore* core) { new ST_mmgc_gcheap(core); }
2383}
2384}
2385#endif
2386
2387// Generated from ST_mmgc_mmfx_array.st
2388// -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */
2389//
2390// ***** BEGIN LICENSE BLOCK *****
2391// Version: MPL 1.1/GPL 2.0/LGPL 2.1
2392//
2393// The contents of this file are subject to the Mozilla Public License Version
2394// 1.1 (the "License"); you may not use this file except in compliance with
2395// the License. You may obtain a copy of the License at
2396// http://www.mozilla.org/MPL/
2397//
2398// Software distributed under the License is distributed on an "AS IS" basis,
2399// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
2400// for the specific language governing rights and limitations under the
2401// License.
2402//
2403// The Original Code is [Open Source Virtual Machine.].
2404//
2405// The Initial Developer of the Original Code is
2406// Adobe System Incorporated.
2407// Portions created by the Initial Developer are Copyright (C) 2011
2408// the Initial Developer. All Rights Reserved.
2409//
2410// Contributor(s):
2411// Adobe AS3 Team
2412//
2413// Alternatively, the contents of this file may be used under the terms of
2414// either the GNU General Public License Version 2 or later (the "GPL"), or
2415// the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
2416// in which case the provisions of the GPL or the LGPL are applicable instead
2417// of those above. If you wish to allow use of your version of this file only
2418// under the terms of either the GPL or the LGPL, and not to allow others to
2419// use your version of this file under the terms of the MPL, indicate your
2420// decision by deleting the provisions above and replace them with the notice
2421// and other provisions required by the GPL or the LGPL. If you do not delete
2422// the provisions above, a recipient may use your version of this file under
2423// the terms of any one of the MPL, the GPL or the LGPL.
2424//
2425// ***** END LICENSE BLOCK ***** */
2426
2427#include "avmshell.h"
2428#ifdef VMCFG_SELFTEST
2429namespace avmplus {
2430namespace ST_mmgc_mmfx_array {
2431class ST_mmgc_mmfx_array : public Selftest {
2432public:
2433ST_mmgc_mmfx_array(AvmCore* core);
2434virtual void run(int n);
2435private:
2436static const char* ST_names[];
2437static const boolbool ST_explicits[];
2438void test0();
2439void test1();
2440void test2();
2441};
2442ST_mmgc_mmfx_array::ST_mmgc_mmfx_array(AvmCore* core)
2443 : Selftest(core, "mmgc", "mmfx_array", ST_mmgc_mmfx_array::ST_names,ST_mmgc_mmfx_array::ST_explicits)
2444{}
2445const char* ST_mmgc_mmfx_array::ST_names[] = {"mmfx_new_array_oom","mmfx_new_array_opts_canFail","mmfx_new_array_opts_oom", NULL__null };
2446const boolbool ST_mmgc_mmfx_array::ST_explicits[] = {truetrue,truetrue,truetrue, falsefalse };
2447void ST_mmgc_mmfx_array::run(int n) {
2448switch(n) {
2449case 0: test0(); return;
2450case 1: test1(); return;
2451case 2: test2(); return;
2452}
2453}
2454using namespace MMgc;
2455
2456// There are different failure modes.
2457// 1) if you call mmfx_new_array() it can OOM:
2458// -> it should OOM and shutdown
2459// 2) if you call mmfx_new_array_opts(canFail) and it OOMs:
2460// -> it should return NULL and NOT OOM
2461// 3) if you call mmfx_new_aray_opts() without the canFail flag:
2462// -> it should OOM and shutdown
2463
2464
2465void ST_mmgc_mmfx_array::test0() {
2466 // This will cause an OOM abort and exit, run with -memlimit 1024
2467 int* m_ints = mmfx_new_array(int, 1048576)::MMgcConstructTaggedArray((int*)__null, 1048576, MMgc::kNone
)
;
2468 mmfx_delete_array(m_ints)::MMgcDestructTaggedArrayChecked(m_ints);
2469 m_ints = NULL__null;
2470// line 60 "ST_mmgc_mmfx_array.st"
2471verifyPass(falsefalse, "false", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__2471);
2472
2473}
2474void ST_mmgc_mmfx_array::test1() {
2475 // This should fail and return NULL, run with -memlimit 1024
2476 int* m_ints = mmfx_new_array_opt(int, 1048576, MMgc::kCanFail)::MMgcConstructTaggedArray((int*)__null, 1048576, MMgc::kCanFail
)
;
2477// line 65 "ST_mmgc_mmfx_array.st"
2478verifyPass(m_ints == NULL__null, "m_ints == NULL", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__2478);
2479 mmfx_delete_array(m_ints)::MMgcDestructTaggedArrayChecked(m_ints);
2480 m_ints = NULL__null;
2481
2482}
2483void ST_mmgc_mmfx_array::test2() {
2484 // This will cause an OOM abort and exit, run with -memlimit 1024
2485 int* m_ints = mmfx_new_array_opt(int, 1048576, MMgc::kZero)::MMgcConstructTaggedArray((int*)__null, 1048576, MMgc::kZero
)
;
2486 mmfx_delete_array(m_ints)::MMgcDestructTaggedArrayChecked(m_ints);
2487 m_ints = NULL__null;
2488// line 74 "ST_mmgc_mmfx_array.st"
2489verifyPass(falsefalse, "false", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__2489);
2490
2491
2492
2493}
2494void create_mmgc_mmfx_array(AvmCore* core) { new ST_mmgc_mmfx_array(core); }
2495}
2496}
2497#endif
2498
2499// Generated from ST_mmgc_threads.st
2500// -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*-
2501// vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */
2502//
2503// ***** BEGIN LICENSE BLOCK *****
2504// Version: MPL 1.1/GPL 2.0/LGPL 2.1
2505//
2506// The contents of this file are subject to the Mozilla Public License Version
2507// 1.1 (the "License"); you may not use this file except in compliance with
2508// the License. You may obtain a copy of the License at
2509// http://www.mozilla.org/MPL/
2510//
2511// Software distributed under the License is distributed on an "AS IS" basis,
2512// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
2513// for the specific language governing rights and limitations under the
2514// License.
2515//
2516// The Original Code is [Open Source Virtual Machine.].
2517//
2518// The Initial Developer of the Original Code is
2519// Adobe System Incorporated.
2520// Portions created by the Initial Developer are Copyright (C) 2004-2006
2521// the Initial Developer. All Rights Reserved.
2522//
2523// Contributor(s):
2524// Adobe AS3 Team
2525//
2526// Alternatively, the contents of this file may be used under the terms of
2527// either the GNU General Public License Version 2 or later (the "GPL"), or
2528// the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
2529// in which case the provisions of the GPL or the LGPL are applicable instead
2530// of those above. If you wish to allow use of your version of this file only
2531// under the terms of either the GPL or the LGPL, and not to allow others to
2532// use your version of this file under the terms of the MPL, indicate your
2533// decision by deleting the provisions above and replace them with the notice
2534// and other provisions required by the GPL or the LGPL. If you do not delete
2535// the provisions above, a recipient may use your version of this file under
2536// the terms of any one of the MPL, the GPL or the LGPL.
2537//
2538// ***** END LICENSE BLOCK ***** */
2539
2540#include "avmshell.h"
2541#ifdef VMCFG_SELFTEST
2542#if defined VMCFG_WORKERTHREADS
2543namespace avmplus {
2544namespace ST_mmgc_threads {
2545class ST_mmgc_threads : public Selftest {
2546public:
2547ST_mmgc_threads(AvmCore* core);
2548virtual void run(int n);
2549virtual void prologue();
2550virtual void epilogue();
2551private:
2552static const char* ST_names[];
2553static const boolbool ST_explicits[];
2554void test0();
2555
2556private:
2557 MMgc::GC *gc;
2558 MMgc::FixedAlloc *fa;
2559 MMgc::FixedMalloc *fm;
2560 boolbool waiting;
2561 boolbool result;
2562 boolbool isDead;
2563 pthread_t pthread;
2564 pthread_mutex_t pmutex;
2565 pthread_cond_t pcond;
2566
2567 static void* slaveRunner(void *arg)
2568 {
2569 ((ST_mmgc_threads*)arg)->slaveRun();
2570 return NULL__null;
2571 }
2572
2573 void slaveRun()
2574 {
2575 wait();
2576 {
2577 MMGC_ENTER_VOIDMMgc::GCHeap::EnterLock(); if(MMgc::GCHeap::ShouldNotEnter())
{ MMgc::GCHeap::EnterRelease(); return; } MMgc::EnterFrame _ef
; MMgc::GCHeap::EnterRelease(); _ef.status = ::_setjmp(_ef.jmpbuf
); if(_ef.status != 0) return;
;
2578 MMGC_GCENTER(gc)MMgc::GCAutoEnter __mmgc_auto_enter(gc);;
2579 result &= !isDead;
2580 gc->ReapZCT();
2581 result &= !isDead;
2582 gc->Collect();
2583 result &= !isDead;
2584 }
2585 kick();
2586 }
2587
2588 void startSlave()
2589 {
2590 pthread_create(&pthread, NULL__null, slaveRunner, this);
2591 }
2592
2593 void kick()
2594 {
2595 pthread_mutex_lock (&pmutex);
2596 while(!waiting) {
2597 pthread_mutex_unlock (&pmutex);
2598 usleep(100);
2599 pthread_mutex_lock (&pmutex);
2600 }
2601 pthread_cond_signal (&pcond);
2602 while(waiting) {
2603 pthread_mutex_unlock (&pmutex);
2604 usleep(100);
2605 pthread_mutex_lock (&pmutex);
2606 }
2607 pthread_mutex_unlock (&pmutex);
2608 }
2609
2610 void wait()
2611 {
2612 pthread_mutex_lock (&pmutex);
2613 GCAssert(waiting == false)do { } while (0);
2614 waiting = truetrue;
2615 pthread_cond_wait (&pcond, &pmutex);
2616 waiting = falsefalse;
2617 pthread_mutex_unlock (&pmutex);
2618 }
2619
2620 static void kickAndWait(void* arg)
2621 {
2622 ST_mmgc_threads* self = (ST_mmgc_threads*)arg;
2623 self->kick();
2624 self->wait();
2625 }
2626
2627};
2628ST_mmgc_threads::ST_mmgc_threads(AvmCore* core)
2629 : Selftest(core, "mmgc", "threads", ST_mmgc_threads::ST_names,ST_mmgc_threads::ST_explicits)
2630{}
2631const char* ST_mmgc_threads::ST_names[] = {"mmgc_gc_root_thread", NULL__null };
2632const boolbool ST_mmgc_threads::ST_explicits[] = {falsefalse, falsefalse };
2633void ST_mmgc_threads::run(int n) {
2634switch(n) {
2635case 0: test0(); return;
2636}
2637}
2638void ST_mmgc_threads::prologue() {
2639 MMgc::GCConfig config;
2640 gc=new MMgc::GC(MMgc::GCHeap::GetGCHeap(), config);
2641 if (gc==NULL__null) {
2642 MMgc::GCHeap::Init();
2643 gc=new MMgc::GC(MMgc::GCHeap::GetGCHeap(), config);
2644 }
2645 pthread_mutex_init(&pmutex, NULL__null);
2646 pthread_cond_init(&pcond, NULL__null);
2647 result = truetrue;
2648 isDead = falsefalse;
2649 waiting = falsefalse;
2650
2651}
2652void ST_mmgc_threads::epilogue() {
2653 pthread_mutex_destroy(&pmutex);
2654 pthread_cond_destroy(&pcond);
2655 delete gc;
2656
2657}
2658using namespace MMgc;
2659
2660class RCObjectNotifier : public RCObject
2661{
2662public:
2663 RCObjectNotifier(boolbool *isDead) : isDead(isDead) {}
2664 ~RCObjectNotifier() { *isDead = truetrue; isDead = NULL__null; }
2665 boolbool *isDead;
2666};
2667
2668void ST_mmgc_threads::test0() {
2669 startSlave();
2670 MMGC_GCENTER(gc)MMgc::GCAutoEnter __mmgc_auto_enter(gc);;
2671 RCObjectNotifier *obj = new (gc) RCObjectNotifier(&isDead);
2672 {
2673 gc->CreateRootFromCurrentStack(kickAndWait, this);
2674 }
2675
2676// line 155 "ST_mmgc_threads.st"
2677verifyPass(result, "result", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__2677);
2678
2679// line 157 "ST_mmgc_threads.st"
2680verifyPass(!isDead, "!isDead", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__2680);
2681 gc->ReapZCT();
2682// line 159 "ST_mmgc_threads.st"
2683verifyPass(!isDead, "!isDead", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__2683);
2684 gc->Collect();
2685// line 161 "ST_mmgc_threads.st"
2686verifyPass(!isDead, "!isDead", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__2686);
2687
2688 pthread_join(pthread, NULL__null);
2689
2690 printf("Ignore this: %d\n", *obj->isDead);
2691
2692}
2693void create_mmgc_threads(AvmCore* core) { new ST_mmgc_threads(core); }
2694}
2695}
2696#endif
2697#endif
2698
2699// Generated from ST_mmgc_weakref.st
2700// -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*-
2701// vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */
2702//
2703// ***** BEGIN LICENSE BLOCK *****
2704// Version: MPL 1.1/GPL 2.0/LGPL 2.1
2705//
2706// The contents of this file are subject to the Mozilla Public License Version
2707// 1.1 (the "License"); you may not use this file except in compliance with
2708// the License. You may obtain a copy of the License at
2709// http://www.mozilla.org/MPL/
2710//
2711// Software distributed under the License is distributed on an "AS IS" basis,
2712// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
2713// for the specific language governing rights and limitations under the
2714// License.
2715//
2716// The Original Code is [Open Source Virtual Machine.].
2717//
2718// The Initial Developer of the Original Code is
2719// Adobe System Incorporated.
2720// Portions created by the Initial Developer are Copyright (C) 2004-2006
2721// the Initial Developer. All Rights Reserved.
2722//
2723// Contributor(s):
2724// Adobe AS3 Team
2725//
2726// Alternatively, the contents of this file may be used under the terms of
2727// either the GNU General Public License Version 2 or later (the "GPL"), or
2728// the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
2729// in which case the provisions of the GPL or the LGPL are applicable instead
2730// of those above. If you wish to allow use of your version of this file only
2731// under the terms of either the GPL or the LGPL, and not to allow others to
2732// use your version of this file under the terms of the MPL, indicate your
2733// decision by deleting the provisions above and replace them with the notice
2734// and other provisions required by the GPL or the LGPL. If you do not delete
2735// the provisions above, a recipient may use your version of this file under
2736// the terms of any one of the MPL, the GPL or the LGPL.
2737//
2738// ***** END LICENSE BLOCK ***** */
2739
2740#include "avmshell.h"
2741#ifdef VMCFG_SELFTEST
2742namespace avmplus {
2743namespace ST_mmgc_weakref {
2744using namespace MMgc;
2745
2746class C : public GCFinalizedObject
2747{
2748public:
2749 C(int key) : key(key) {}
2750 ~C() { key = -1; }
2751 int key;
2752 GCMember<C> next;
2753};
2754
2755class MyCallback : public GCCallback
2756{
2757public:
2758 MyCallback(GC* gc, GCWeakRef** refs, C** objs, int n)
2759 : GCCallback(gc)
2760 , refs(refs)
2761 , objs(objs)
2762 , n(n)
2763 {
2764 }
2765
2766 virtual void presweep() {
2767 for ( int i=1 ; i < 1000 ; i+=2 )
2768 objs[i]->next = (C*)(void *)(refs[i-1]->get());
2769 }
2770
2771private:
2772 GCWeakRef** refs;
2773 C** objs;
2774 int n;
2775};
2776
2777class D : public GCFinalizedObject
2778{
2779public:
2780 ~D() { GC::GetWeakRef(this); }
2781};
2782
2783class ST_mmgc_weakref : public Selftest {
2784public:
2785ST_mmgc_weakref(AvmCore* core);
2786virtual void run(int n);
2787private:
2788static const char* ST_names[];
2789static const boolbool ST_explicits[];
2790void test0();
2791void test1();
2792};
2793ST_mmgc_weakref::ST_mmgc_weakref(AvmCore* core)
2794 : Selftest(core, "mmgc", "weakref", ST_mmgc_weakref::ST_names,ST_mmgc_weakref::ST_explicits)
2795{}
2796const char* ST_mmgc_weakref::ST_names[] = {"unmarked_object_presweep","unmarked_object_finalize", NULL__null };
2797const boolbool ST_mmgc_weakref::ST_explicits[] = {falsefalse,truetrue, falsefalse };
2798void ST_mmgc_weakref::run(int n) {
2799switch(n) {
2800case 0: test0(); return;
2801case 1: test1(); return;
2802}
2803}
2804void ST_mmgc_weakref::test0() {
2805
2806 // Bugzilla 572331 - it's possible for a weak reference to yield up a pointer to an unmarked
2807 // object in a presweep handler, and for that pointer to be stored into the heap even with
2808 // a WB macro, without the barrier triggering.
2809
2810{
2811 GC* gc = core->gc;
2812
2813 // Stack allocated storage, so automatically these arrays are roots
2814
2815 GCWeakRef* refs[1000];
2816 C* objs[1000];
2817
2818 // Create weak and strong references to 1000 objects
2819
2820 for ( int i=0 ; i < 1000 ; i++ ) {
2821 objs[i] = new (gc) C(i);
2822 refs[i] = objs[i]->GetWeakRef();
2823 }
2824
2825 // Get the collector into a reasonable state.
2826
2827 gc->Collect();
2828 gc->Collect();
2829
2830 // Remove the even-numbered strong refs.
2831
2832 for ( int i=0 ; i < 1000 ; i+=2 )
2833 objs[i] = NULL__null;
2834
2835 // Introduce mischief. The presweep callback will extract
2836 // pointers from the even-numbered weak refs and insert them into
2837 // the objects in the odd-numbered slots (which are strongly
2838 // held). Most of the objects referenced from the even-numbered
2839 // weak refs should be weakly held and unmarked. We hope to catch
2840 // the collector picking up an unmarked object.
2841
2842 MyCallback* cb = new MyCallback(gc, refs, objs, 1000);
2843
2844 // Now trigger the collector again.
2845
2846 gc->Collect();
2847
2848 // Prevent more mischief from happening.
2849
2850 delete cb;
2851
2852 // Now reference all the odd-numbered objects and check the
2853 // integrity of their 'next' objects. There's a chance this may
2854 // crash.
2855
2856 for ( int i=1 ; i < 1000 ; i+= 2 ) {
2857// line 137 "ST_mmgc_weakref.st"
2858verifyPass(objs[i]->next->key == i-1, "objs[i]->next->key == i-1", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__2858);
2859 }
2860
2861 // Clean up
2862 VMPI_memset::memset(refs, 0, sizeof(refs));
2863 VMPI_memset::memset(objs, 0, sizeof(objs));
2864}
2865
2866}
2867void ST_mmgc_weakref::test1() {
2868
2869 // Bugzilla 647155 - ditto as the previous test, but now it's the object's destructor that tries
2870 // to store a pointer to an unmarked object (in this case the object itself) into a weak ref.
2871 // This will assert in debug builds, so the test is marked "explicit" for that reason: in a
2872 // debug build we want to verify that the assert is hit, in a release build we want to verify that
2873 // the test does not crash.
2874
2875{
2876 GC* gc = core->gc;
2877
2878 // Stack allocated storage, so automatically these arrays are roots
2879
2880 D* objs[1000];
2881
2882 // Create strong references to 1000 objects
2883
2884 for ( int i=0 ; i < 1000 ; i++ ) {
2885 objs[i] = new (gc) D();
2886 }
2887
2888 // Get the collector into a reasonable state.
2889
2890 gc->Collect();
2891 gc->Collect();
2892
2893 // Remove the even-numbered strong refs.
2894
2895 for ( int i=0 ; i < 1000 ; i+=2 )
2896 objs[i] = NULL__null;
2897
2898 // Now trigger the collector again.
2899
2900 gc->Collect();
2901
2902// line 180 "ST_mmgc_weakref.st"
2903verifyPass(truetrue, "true", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__2903);
2904}
2905
2906
2907}
2908void create_mmgc_weakref(AvmCore* core) { new ST_mmgc_weakref(core); }
2909}
2910}
2911#endif
2912
2913// Generated from ST_vmbase_concurrency.st
2914// -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*-
2915// vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */
2916//
2917// ***** BEGIN LICENSE BLOCK *****
2918// Version: MPL 1.1/GPL 2.0/LGPL 2.1
2919//
2920// The contents of this file are subject to the Mozilla Public License Version
2921// 1.1 (the "License"); you may not use this file except in compliance with
2922// the License. You may obtain a copy of the License at
2923// http://www.mozilla.org/MPL/
2924//
2925// Software distributed under the License is distributed on an "AS IS" basis,
2926// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
2927// for the specific language governing rights and limitations under the
2928// License.
2929//
2930// The Original Code is [Open Source Virtual Machine.].
2931//
2932// The Initial Developer of the Original Code is
2933// Adobe System Incorporated.
2934// Portions created by the Initial Developer are Copyright (C) 2004-2006
2935// the Initial Developer. All Rights Reserved.
2936//
2937// Contributor(s):
2938// Adobe AS3 Team
2939//
2940// Alternatively, the contents of this file may be used under the terms of
2941// either the GNU General Public License Version 2 or later (the "GPL"), or
2942// the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
2943// in which case the provisions of the GPL or the LGPL are applicable instead
2944// of those above. If you wish to allow use of your version of this file only
2945// under the terms of either the GPL or the LGPL, and not to allow others to
2946// use your version of this file under the terms of the MPL, indicate your
2947// decision by deleting the provisions above and replace them with the notice
2948// and other provisions required by the GPL or the LGPL. If you do not delete
2949// the provisions above, a recipient may use your version of this file under
2950// the terms of any one of the MPL, the GPL or the LGPL.
2951//
2952// ***** END LICENSE BLOCK ***** */
2953
2954#include "avmshell.h"
2955#ifdef VMCFG_SELFTEST
2956namespace avmplus {
2957namespace ST_vmbase_concurrency {
2958using namespace MMgc;
2959using namespace vmbase;
2960
2961// We use the same testing method as that for ST_vmpi_threads:
2962// Each construct is tested by (1) using it in the implementation of a mutator that
2963// modifies a counter for a fixed number of iterations, and then (2) running
2964// duplicates of that mutator in parallel. The final counter value ends up in
2965// sharedCounter, which is guarded by m_monitor (except for in CASTest).
2966// Each test checks that the sharedCounter ends up with a statically determined
2967// end value.
2968// (Description courtesy of Felix)
2969
2970// We need a specific namespace as ST_vmpi_threads uses the same test class names
2971namespace selftestconcurrency {
2972
2973 class ThreadTestBase : public Runnable {
2974 public:
2975 ThreadTestBase(int iterations) : m_iterations(iterations), sharedCounter(0) {
2976 }
2977 virtual ~ThreadTestBase() {
2978 }
2979
2980 protected:
2981 WaitNotifyMonitor m_monitor;
2982 const int m_iterations;
2983
2984 public:
2985 int sharedCounter;
2986 };
2987
2988 class TestRunner {
2989 public:
2990 struct ThreadRecord {
2991 VMThread* thread;
2992 boolbool startupOk;
2993 };
2994
2995 TestRunner(int threadQty, boolbool doJoin = truetrue) : m_threadQty(threadQty), m_doJoin(doJoin) {
2996 }
2997 virtual ~TestRunner() {
2998 }
2999
3000 void runTest(ThreadTestBase& test) {
3001
3002 m_threads = mmfx_new_array(ThreadRecord, m_threadQty)::MMgcConstructTaggedArray((ThreadRecord*)__null, m_threadQty
, MMgc::kNone)
;
3003
3004 // Start up the threads
3005 for (int i = 0; i < m_threadQty; i++) {
3006 m_threads[i].thread = mmfx_new(VMThread(&test))new (MMgc::kUseFixedMalloc) VMThread(&test);
3007 m_threads[i].startupOk = m_threads[i].thread->start();
3008 }
3009
3010 // ...then block until they all terminate
3011 for (int i = 0; i < m_threadQty; i++) {
3012 if (m_doJoin && m_threads[i].startupOk) {
3013 m_threads[i].thread->join();
3014 }
3015 mmfx_delete(m_threads[i].thread)::MMgcDestructTaggedScalarChecked(m_threads[i].thread);
3016 }
3017
3018 mmfx_delete_array(m_threads)::MMgcDestructTaggedArrayChecked(m_threads);
3019 }
3020
3021 private:
3022 const int m_threadQty;
3023 ThreadRecord* m_threads;
3024 boolbool m_doJoin;
3025 };
3026
3027 class MutexTest : public ThreadTestBase {
3028 public:
3029 MutexTest(int iterations) : ThreadTestBase(iterations) {}
3030 virtual ~MutexTest() {}
3031
3032 virtual void run() {
3033 AvmAssert(m_iterations % 2 == 0)do { } while (0);
3034 for (int i = 0; i < m_iterations/2; i++) {
3035 SCOPE_LOCK(m_monitor)if (vmbase::MutexLocker<vmbase::IMPLICIT_SAFEPOINT> __locker
= m_monitor) {} else
{
3036 SCOPE_LOCK(m_monitor)if (vmbase::MutexLocker<vmbase::IMPLICIT_SAFEPOINT> __locker
= m_monitor) {} else
{
3037 sharedCounter++;
3038 }
3039 }
3040 }
3041 for (int i = 0; i < m_iterations/2; i++) {
3042 SCOPE_LOCK_NAMED(locker, m_monitor)if (vmbase::MonitorLocker<vmbase::IMPLICIT_SAFEPOINT> locker
= m_monitor) {} else
{
3043 SCOPE_LOCK_NAMED(locker, m_monitor)if (vmbase::MonitorLocker<vmbase::IMPLICIT_SAFEPOINT> locker
= m_monitor) {} else
{
3044 sharedCounter++;
3045 }
3046 }
3047 }
3048 }
3049 };
3050 class ConditionTest : public ThreadTestBase {
3051 public:
3052 ConditionTest(int iterations, int threadQty) : ThreadTestBase(iterations), m_threadQty(threadQty) {}
3053 virtual ~ConditionTest() {}
3054
3055 virtual void run() {
3056
3057 AvmAssert(m_threadQty >= 2)do { } while (0);
3058
3059 for (int i = 0; i < m_iterations; i++) {
3060 SCOPE_LOCK_NAMED(locker, m_monitor)if (vmbase::MonitorLocker<vmbase::IMPLICIT_SAFEPOINT> locker
= m_monitor) {} else
{
3061 sharedCounter++;
3062 // If there's another thread still active then wait.
3063 if (m_threadQty > 1) {
3064 locker.notify();
3065 locker.wait();
3066 }
3067 // This thread has finished, so let's wake everyone else up
3068 if (i == m_iterations - 1) {
3069 --m_threadQty;
3070 locker.notifyAll();
3071 }
3072 }
3073
3074 }
3075
3076 }
3077
3078 private:
3079 int m_threadQty;
3080 };
3081
3082 class AtomicCounterTest : public ThreadTestBase {
3083 public:
3084 AtomicCounterTest(int iterations, int threadQty) : ThreadTestBase(iterations), m_threadQty(threadQty) {}
3085 virtual ~AtomicCounterTest() {}
3086
3087 virtual void run() {
3088
3089 AvmAssert(m_iterations % 4 == 0)do { } while (0);
3090
3091 for (int i = 0; i < m_iterations/4; i++) {
3092 m_counter++;
3093 }
3094 for (int i = 0; i < m_iterations/4; i++) {
3095 m_counter--;
3096 }
3097 for (int i = 0; i < m_iterations/4; i++) {
3098 ++m_counter;
3099 }
3100 for (int i = 0; i < m_iterations/4; i++) {
3101 --m_counter;
3102 }
3103
3104 SCOPE_LOCK(m_monitor)if (vmbase::MutexLocker<vmbase::IMPLICIT_SAFEPOINT> __locker
= m_monitor) {} else
{
3105 if (--m_threadQty == 0) {
3106 sharedCounter = m_counter;
3107 }
3108 }
3109 }
3110 private:
3111 AtomicCounter32 m_counter;
3112 int m_threadQty;
3113 };
3114
3115 class CASTest : public ThreadTestBase {
3116 public:
3117 CASTest(int iterations, boolbool withBarrier) : ThreadTestBase(iterations), m_withBarrier(withBarrier) {}
3118 virtual ~CASTest() {}
3119
3120 virtual void run() {
3121 if (m_withBarrier) {
3122 for (int i = 0; i < m_iterations; i++) {
3123 int32_t current, next;
3124 do {
3125 current = sharedCounter;
3126 next = current + 1;
3127 } while (!AtomicOps::compareAndSwap32WithBarrier(current, next, &sharedCounter));
3128 }
3129 } else {
3130 for (int i = 0; i < m_iterations; i++) {
3131 int32_t current, next;
3132 do {
3133 current = sharedCounter;
3134 next = current + 1;
3135 } while (!AtomicOps::compareAndSwap32(current, next, &sharedCounter));
3136 }
3137 }
3138 }
3139 private:
3140 boolbool m_withBarrier;
3141 };
3142
3143 /**
3144 * We protect a shared counter with a Dekker-style lock that has been made
3145 * sequentially consistent with memory barriers.
3146 *
3147 * The idea is that if the barriers are correct, then two threads can compete
3148 * to update the counter n times each, so that the final counter value is 2n. If
3149 * the final value is not 2n, then the barriers have failed to ensure sequential
3150 * consistency.
3151 *
3152 * FIXME: bug 609943
3153 * This seems way too complicated. We have to be confident in the algorithm
3154 * before considering the barrier implementations, and I'm not convinced as yet.
3155 * Is there something simpler?
3156 * Note that the barriers below are extremely conservative.
3157 *
3158 * This is test is not actually run. The verifyPass below just returns true.
3159 */
3160 class MemoryBarrierTest : public ThreadTestBase {
3161 public:
3162 MemoryBarrierTest(int iterations) : ThreadTestBase(iterations), m_thread0(0), m_thread1(0), m_turn(NULL__null) {}
3163 virtual ~MemoryBarrierTest() {}
3164
3165 virtual void run() {
3166
3167 volatile int* me;
3168 volatile int* other;
3169 volatile int* const counterp = &sharedCounter;
3170
3171 SCOPE_LOCK(m_monitor)if (vmbase::MutexLocker<vmbase::IMPLICIT_SAFEPOINT> __locker
= m_monitor) {} else
{
3172 if (m_turn == NULL__null) {
3173 me = &m_thread0;
3174 other = &m_thread1;
3175 m_turn = me;
3176 } else {
3177 me = &m_thread1;
3178 other = &m_thread0;
3179 }
3180 }
3181
3182 for (int i = 0; i < m_iterations; i++) {
3183 // Dekker lock
3184 *me = 1;
3185 MemoryBarrier::readWrite();
3186 while (*other == 1) {
3187 MemoryBarrier::readWrite();
3188 if (m_turn == other) {
3189 MemoryBarrier::readWrite();
3190 *me = 0;
3191 MemoryBarrier::readWrite();
3192 while (m_turn == other) {
3193 MemoryBarrier::readWrite();
3194 }
3195 MemoryBarrier::readWrite();
3196 *me = 1;
3197 MemoryBarrier::readWrite();
3198 }
3199 }
3200 MemoryBarrier::readWrite();
3201 (*counterp)++;
3202 MemoryBarrier::readWrite();
3203 m_turn = other;
3204 MemoryBarrier::readWrite();
3205 *me = 0;
3206 MemoryBarrier::readWrite();
3207 }
3208 }
3209 private:
3210 volatile int m_thread0;
3211 volatile int m_thread1;
3212 volatile int* volatile m_turn;
3213 };
3214
3215 class ConditionWithWaitTest : public ThreadTestBase {
3216 public:
3217 ConditionWithWaitTest(int iterations) : ThreadTestBase(iterations) {}
3218 virtual ~ConditionWithWaitTest() {}
3219
3220 virtual void run() {
3221 for (int i = 0; i < m_iterations; i++) {
3222 SCOPE_LOCK_NAMED(locker, m_monitor)if (vmbase::MonitorLocker<vmbase::IMPLICIT_SAFEPOINT> locker
= m_monitor) {} else
{
3223 sharedCounter++;
3224 locker.wait(1);
3225 }
3226 }
3227 }
3228 };
3229
3230 class SleepTest : public ThreadTestBase {
3231 public:
3232 SleepTest(int iterations) : ThreadTestBase(iterations) {}
3233 virtual ~SleepTest() {}
3234
3235 virtual void run() {
3236 for (int i = 0; i < m_iterations; i++) {
3237 SCOPE_LOCK(m_monitor)if (vmbase::MutexLocker<vmbase::IMPLICIT_SAFEPOINT> __locker
= m_monitor) {} else
{
3238 sharedCounter++;
3239 }
3240 VMThread::sleep(1);
3241 }
3242 }
3243 };
3244
3245 class VMThreadLocalTest : public ThreadTestBase {
3246 public:
3247 VMThreadLocalTest(int iterations) : ThreadTestBase(iterations) {}
3248 virtual ~VMThreadLocalTest() {}
3249
3250 virtual void run() {
3251 for (int i = 0; i < m_iterations; i++) {
3252 m_localCounter.set(m_localCounter.get() + 1);
3253 }
3254 SCOPE_LOCK(m_monitor)if (vmbase::MutexLocker<vmbase::IMPLICIT_SAFEPOINT> __locker
= m_monitor) {} else
{
3255 sharedCounter += (int)m_localCounter;
3256 }
3257 }
3258 private:
3259 VMThreadLocal<uintptr_t> m_localCounter;
3260 };
3261}
3262
3263// This needs to be at least 2 for ConditionTest
3264#define THREAD_QTY4 4
3265#define ITERATIONS100000 100000
3266
3267using namespace selftestconcurrency;
3268
3269class ST_vmbase_concurrency : public Selftest {
3270public:
3271ST_vmbase_concurrency(AvmCore* core);
3272virtual void run(int n);
3273private:
3274static const char* ST_names[];
3275static const boolbool ST_explicits[];
3276void test0();
3277void test1();
3278void test2();
3279void test3();
3280void test4();
3281void test5();
3282void test6();
3283void test7();
3284void test8();
3285void test9();
3286};
3287ST_vmbase_concurrency::ST_vmbase_concurrency(AvmCore* core)
3288 : Selftest(core, "vmbase", "concurrency", ST_vmbase_concurrency::ST_names,ST_vmbase_concurrency::ST_explicits)
3289{}
3290const char* ST_vmbase_concurrency::ST_names[] = {"mutexes","conditions","atomic_counter","compare_and_swap_without_barrier","compare_and_swap_with_barrier","memory_barrier","condition_with_wait","sleep","vmthreadlocal","join", NULL__null };
3291const boolbool ST_vmbase_concurrency::ST_explicits[] = {falsefalse,falsefalse,falsefalse,falsefalse,falsefalse,falsefalse,falsefalse,falsefalse,falsefalse,falsefalse, falsefalse };
3292void ST_vmbase_concurrency::run(int n) {
3293switch(n) {
3294case 0: test0(); return;
3295case 1: test1(); return;
3296case 2: test2(); return;
3297case 3: test3(); return;
3298case 4: test4(); return;
3299case 5: test5(); return;
3300case 6: test6(); return;
3301case 7: test7(); return;
3302case 8: test8(); return;
3303case 9: test9(); return;
3304}
3305}
3306void ST_vmbase_concurrency::test0() {
3307#ifndef UNDER_CE
3308 TestRunner runner(THREAD_QTY4);
3309 MutexTest test(ITERATIONS100000);
3310 runner.runTest(test);
3311// line 361 "ST_vmbase_concurrency.st"
3312verifyPass(test.sharedCounter == THREAD_QTY4 * ITERATIONS100000, "test.sharedCounter == THREAD_QTY * ITERATIONS", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__3312);
3313#endif
3314
3315}
3316void ST_vmbase_concurrency::test1() {
3317#ifndef UNDER_CE
3318 TestRunner runner(THREAD_QTY4);
3319 ConditionTest test(ITERATIONS100000, THREAD_QTY4);
3320 runner.runTest(test);
3321// line 369 "ST_vmbase_concurrency.st"
3322verifyPass(test.sharedCounter == THREAD_QTY4 * ITERATIONS100000, "test.sharedCounter == THREAD_QTY * ITERATIONS", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__3322);
3323#endif
3324
3325}
3326void ST_vmbase_concurrency::test2() {
3327#ifndef UNDER_CE
3328 TestRunner runner(THREAD_QTY4);
3329 AtomicCounterTest test(ITERATIONS100000, THREAD_QTY4);
3330 runner.runTest(test);
3331// line 377 "ST_vmbase_concurrency.st"
3332verifyPass(test.sharedCounter == 0, "test.sharedCounter == 0", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__3332);
3333#endif
3334
3335}
3336void ST_vmbase_concurrency::test3() {
3337#ifndef UNDER_CE
3338 TestRunner runner(THREAD_QTY4);
3339 CASTest test(ITERATIONS100000, falsefalse);
3340 runner.runTest(test);
3341// line 385 "ST_vmbase_concurrency.st"
3342verifyPass(test.sharedCounter == THREAD_QTY4 * ITERATIONS100000, "test.sharedCounter == THREAD_QTY * ITERATIONS", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__3342);
3343#endif
3344
3345}
3346void ST_vmbase_concurrency::test4() {
3347#ifndef UNDER_CE
3348 TestRunner runner(THREAD_QTY4);
3349 CASTest test(ITERATIONS100000, truetrue);
3350 runner.runTest(test);
3351// line 393 "ST_vmbase_concurrency.st"
3352verifyPass(test.sharedCounter == THREAD_QTY4 * ITERATIONS100000, "test.sharedCounter == THREAD_QTY * ITERATIONS", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__3352);
3353#endif
3354
3355}
3356void ST_vmbase_concurrency::test5() {
3357#ifndef UNDER_CE
3358 /* This test is failing on Windows and Mac OSX 10.4.
3359 * For Windows, see bug 609820.
3360 * For Mac, are the 10.4 APIs not reliable?
3361 * It could also be the test, or the compiler!
3362 * FIXME: bug 609943 Selftests to stress memory barriers (fences)
3363
3364 // Note that the memory barrier test is based on a Dekker lock, so we
3365 // only ever use 2 threads.
3366 TestRunner runner(2);
3367 MemoryBarrierTest test(ITERATIONS);
3368 runner.runTest(test);
3369// line 409 "ST_vmbase_concurrency.st"
3370verifyPass(test.sharedCounter == 2 * ITERATIONS, "test.sharedCounter == 2 * ITERATIONS", __FILE__, __LINE__);
3371 */
3372
3373// line 412 "ST_vmbase_concurrency.st"
3374verifyPass(truetrue, "true", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__3374);
3375#endif
3376
3377}
3378void ST_vmbase_concurrency::test6() {
3379#ifndef UNDER_CE
3380 TestRunner runner(THREAD_QTY4);
3381 ConditionWithWaitTest test(2000); // Use 2000 iterations with a 1 ms wait
3382 runner.runTest(test);
3383// line 420 "ST_vmbase_concurrency.st"
3384verifyPass(test.sharedCounter == THREAD_QTY4 * 2000, "test.sharedCounter == THREAD_QTY * 2000", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__3384);
3385#endif
3386
3387}
3388void ST_vmbase_concurrency::test7() {
3389#ifndef UNDER_CE
3390 TestRunner runner(THREAD_QTY4);
3391 SleepTest test(2000); // Use 2000 iterations with a 1 ms sleep
3392 runner.runTest(test);
3393// line 428 "ST_vmbase_concurrency.st"
3394verifyPass(test.sharedCounter == THREAD_QTY4 * 2000, "test.sharedCounter == THREAD_QTY * 2000", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__3394);
3395#endif
3396
3397}
3398void ST_vmbase_concurrency::test8() {
3399#ifndef UNDER_CE
3400 TestRunner runner(THREAD_QTY4);
3401 VMThreadLocalTest test(ITERATIONS100000);
3402 runner.runTest(test);
3403// line 436 "ST_vmbase_concurrency.st"
3404verifyPass(test.sharedCounter == THREAD_QTY4 * ITERATIONS100000, "test.sharedCounter == THREAD_QTY * ITERATIONS", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__3404);
3405#endif
3406
3407}
3408void ST_vmbase_concurrency::test9() {
3409#ifndef UNDER_CE
3410 // We should be able to run the dtor of a non-started VMThread.
3411 {
3412 VMThread vmthread;
3413 }
3414 // Run the mutex test but call the VMThread dtors without joining first
3415 TestRunner runner(THREAD_QTY4, falsefalse);
3416 MutexTest test(ITERATIONS100000);
3417 runner.runTest(test);
3418// line 449 "ST_vmbase_concurrency.st"
3419verifyPass(test.sharedCounter == THREAD_QTY4 * ITERATIONS100000, "test.sharedCounter == THREAD_QTY * ITERATIONS", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__3419);
3420#endif
3421
3422
3423
3424
3425
3426}
3427void create_vmbase_concurrency(AvmCore* core) { new ST_vmbase_concurrency(core); }
3428}
3429}
3430#endif
3431
3432// Generated from ST_vmbase_safepoints.st
3433// -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*-
3434// vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */
3435//
3436// ***** BEGIN LICENSE BLOCK *****
3437// Version: MPL 1.1/GPL 2.0/LGPL 2.1
3438//
3439// The contents of this file are subject to the Mozilla Public License Version
3440// 1.1 (the "License"); you may not use this file except in compliance with
3441// the License. You may obtain a copy of the License at
3442// http://www.mozilla.org/MPL/
3443//
3444// Software distributed under the License is distributed on an "AS IS" basis,
3445// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
3446// for the specific language governing rights and limitations under the
3447// License.
3448//
3449// The Original Code is [Open Source Virtual Machine.].
3450//
3451// The Initial Developer of the Original Code is
3452// Adobe System Incorporated.
3453// Portions created by the Initial Developer are Copyright (C) 2004-2006
3454// the Initial Developer. All Rights Reserved.
3455//
3456// Contributor(s):
3457// Adobe AS3 Team
3458//
3459// Alternatively, the contents of this file may be used under the terms of
3460// either the GNU General Public License Version 2 or later (the "GPL"), or
3461// the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
3462// in which case the provisions of the GPL or the LGPL are applicable instead
3463// of those above. If you wish to allow use of your version of this file only
3464// under the terms of either the GPL or the LGPL, and not to allow others to
3465// use your version of this file under the terms of the MPL, indicate your
3466// decision by deleting the provisions above and replace them with the notice
3467// and other provisions required by the GPL or the LGPL. If you do not delete
3468// the provisions above, a recipient may use your version of this file under
3469// the terms of any one of the MPL, the GPL or the LGPL.
3470//
3471// ***** END LICENSE BLOCK ***** */
3472
3473#include "avmshell.h"
3474#ifdef VMCFG_SELFTEST
3475#if defined VMCFG_SAFEPOINTS
3476namespace avmplus {
3477namespace ST_vmbase_safepoints {
3478using namespace MMgc;
3479using namespace vmbase;
3480
3481 /**
3482 * Base class for tests run by a TestRunner.
3483 * Sub-classes should override runInSafepointManagerContext().
3484 */
3485 class SafepointTestBase : public Runnable
3486 {
3487 public:
3488 SafepointTestBase(SafepointManager& safepointManager, int iterations, int threadQty)
3489 : m_safepointManager(safepointManager)
3490 , m_iterations(iterations)
3491 , m_threadQty(threadQty)
3492 , sharedCounter(0)
3493 {
3494 }
3495
3496 virtual ~SafepointTestBase()
3497 {
3498 }
3499
3500 virtual void run()
3501 {
3502 // Enter the safepoint context shared by the primordial and worker threads
3503 SafepointRecord spRecord;
3504 m_safepointManager.enter(&spRecord);
3505
3506 runInSafepointManagerContext();
3507
3508 // Cleanup
3509 m_safepointManager.leave(&spRecord);
3510 }
3511
3512 // Tests should override this function
3513 virtual void runInSafepointManagerContext() = 0;
3514
3515 int threadQty()
3516 {
3517 return m_threadQty;
3518 }
3519
3520 protected:
3521 SafepointManager& m_safepointManager;
3522 WaitNotifyMonitor m_monitor;
3523 const int m_iterations;
3524 const int m_threadQty;
3525
3526 public:
3527 int sharedCounter;
3528 };
3529
3530 /**
3531 * Creates the given number of VMThreads, and passes each the SafepointTestBase to execute.
3532 * The TestRunner contains the SafepointManager with which the primordial and each worker
3533 * thread will register their topmost SafepointRecord.
3534 */
3535 class TestRunner
3536 {
3537 public:
3538 struct ThreadRecord
3539 {
3540 VMThread* thread;
3541 boolbool startupOk;
3542 };
3543
3544 TestRunner(boolbool doJoin = truetrue)
3545 : m_doJoin(doJoin)
3546 {
3547 }
3548
3549 virtual ~TestRunner()
3550 {
3551 }
3552
3553 void runTest(SafepointTestBase& test)
3554 {
3555 // Enter the safepoint context shared by the primordial and worker threads
3556 SafepointRecord spRecord;
3557 m_safepointManager.enter(&spRecord);
3558
3559 m_threads = mmfx_new_array(ThreadRecord, test.threadQty())::MMgcConstructTaggedArray((ThreadRecord*)__null, test.threadQty
(), MMgc::kNone)
;
3560
3561 // Start up the threads.
3562 // Each should also enter m_safepointManager
3563 for (int i = 0; i < test.threadQty(); i++) {
3564 m_threads[i].thread = mmfx_new(VMThread(&test))new (MMgc::kUseFixedMalloc) VMThread(&test);
3565 m_threads[i].startupOk = m_threads[i].thread->start();
3566 }
3567
3568 // ...then block until they all terminate.
3569 // Whilst performing the join, this thread will
3570 // be implicitly safepointed.
3571 for (int i = 0; i < test.threadQty(); i++) {
3572 if (m_doJoin && m_threads[i].startupOk) {
3573 m_threads[i].thread->join();
3574 }
3575 mmfx_delete(m_threads[i].thread)::MMgcDestructTaggedScalarChecked(m_threads[i].thread);
3576 }
3577
3578 mmfx_delete_array(m_threads)::MMgcDestructTaggedArrayChecked(m_threads);
3579
3580 // Cleanup
3581 m_safepointManager.leave(&spRecord);
3582 }
3583
3584 SafepointManager& safepointManager()
3585 {
3586 return m_safepointManager;
3587 }
3588
3589 private:
3590 ThreadRecord* m_threads;
3591 boolbool m_doJoin;
3592 SafepointManager m_safepointManager;
3593 };
3594
3595 /**
3596 * Threads increment a shared counter.
3597 * Thread safety is guaranteed by only performing the increment within a safepoint task.
3598 */
3599 class SimpleTest : public SafepointTestBase
3600 {
3601 class SimpleSafepointTask : public SafepointTask
3602 {
3603 public:
3604 SimpleSafepointTask(int& counter)
3605 : m_counter(counter)
3606 {
3607 }
3608
3609 void run()
3610 {
3611 // We're in the safepoint task, so update
3612 // the shared counter;
3613 m_counter++;
3614 }
3615
3616 private:
3617 int& m_counter;
3618 };
3619
3620 public:
3621 SimpleTest(SafepointManager& safepointManager, int iterations, int threadQty)
3622 : SafepointTestBase(safepointManager, iterations, threadQty)
3623 {
3624 }
3625
3626 virtual ~SimpleTest()
3627 {
3628 }
3629
3630 // Thread entrypoint
3631 virtual void runInSafepointManagerContext()
3632 {
3633 for (int i = 0; i < m_iterations; i++) {
3634 // Increment shared counter in a safepoint task
3635 SimpleSafepointTask task(sharedCounter);
3636 m_safepointManager.requestSafepointTask(task);
3637 }
3638 }
3639 };
3640
3641 /**
3642 * Producer-consumer with safepoints.
3643 *
3644 * Producer threads each increment a *private* counter in a tight
3645 * loop which includes a safepoint.
3646 *
3647 * A single consumer thread executes a tight loop which continually
3648 * requests that the producers be safepointed. In the safepoint task
3649 * the consumer 'steals' and then zeros the private counter of the
3650 * producers. Each stolen counter value is added to the consumer's
3651 * private counter.
3652 *
3653 * This continues until the producers have executed a fixed number of
3654 * iterations. At the end of this process the consumer should have
3655 * a deterministic private counter value.
3656 *
3657 */
3658 class ProducerConsumerTest : public SafepointTestBase
3659 {
3660 public:
3661
3662 class ConsumerSafepointTask : public SafepointTask
3663 {
3664 public:
3665 ConsumerSafepointTask(int* producerCounters, int numProducers)
3666 : m_producerCounters(producerCounters)
3667 , m_numProducers(numProducers)
3668 , m_producerStolenCounter(0)
3669 {
3670 }
3671
3672 void run()
3673 {
3674 // We're in the safepoint task, so we can steal and then zero
3675 // the producers' counters.
3676 // Note that we don't know how many producer threads are still
3677 // alive, m_numProducers is just the length of the array
3678 // we inspect.
3679 for (int i = 0; i < m_numProducers; i++) {
3680 m_producerStolenCounter += m_producerCounters[i];
3681 m_producerCounters[i] = 0;
3682 }
3683 }
3684
3685 int producerStolenCounter()
3686 {
3687 return m_producerStolenCounter;
3688 }
3689
3690 private:
3691 int* const m_producerCounters;
3692 const int m_numProducers;
3693 int m_producerStolenCounter;
3694 };
3695
3696 public:
3697 ProducerConsumerTest(SafepointManager& safepointManager, int iterations, int threadQty)
3698 : SafepointTestBase(safepointManager, iterations, threadQty)
3699 , m_producerCounts(mmfx_new_array_opt(int, threadQty - 1, kZero)::MMgcConstructTaggedArray((int*)__null, threadQty - 1, kZero
)
)
3700 {
3701 }
3702
3703 virtual ~ProducerConsumerTest()
3704 {
3705 }
3706
3707 // Thread entrypoint
3708 virtual void runInSafepointManagerContext()
3709 {
3710 // Wait for all the threads to startup to force as much
3711 // contention as possible.
3712 const int threadIndex = m_threadIn++;
3713 SCOPE_LOCK_SP_NAMED(locker, m_monitor)if (vmbase::MonitorLocker<vmbase::IMPLICIT_SAFEPOINT> locker
= m_monitor) {} else
{
3714 locker.notifyAll();
3715 while (m_threadIn < m_threadQty) {
3716 locker.wait();
3717 }
3718 }
3719
3720 // Setup one of the threads as the consumer, the others are producers
3721 if (threadIndex == m_threadQty - 1) {
3722 // The consumer continually makes SafepointTask requests on
3723 // the SafepointManager, leading to safepointed producers.
3724 // In each SafepointTask the consumer takes each producer's
3725 // currently accrued, private counter, and adds it
3726 // to its own total count, then zeroes the producers counter.
3727 int consumerCount = 0;
3728 enum State
3729 {
3730 RUNNING, DRAINING, DONE
3731 };
3732 State state = RUNNING;
3733 do {
3734 ConsumerSafepointTask task(m_producerCounts, m_threadQty - 1);
3735 m_safepointManager.requestSafepointTask(task);
3736 consumerCount += task.producerStolenCounter();
3737 if (state == DRAINING) {
3738 state = DONE;
3739 } else if (m_threadOut == m_threadQty - 1) {
3740 state = DRAINING;
3741 }
3742 } while (state != DONE);
3743
3744 // sharedCounter is verified by the selftest runner
3745 sharedCounter = consumerCount + m_iterations;
3746
3747 // Can't do this in the dtor, if the selftest verify fails, it will
3748 // throw an exception and the dtor will not run.
3749 mmfx_delete_array(m_producerCounts)::MMgcDestructTaggedArrayChecked(m_producerCounts);
3750 } else {
3751 // The producers increment their private counter, but we make sure that they
3752 // reach an explicit safepoint every iteration.
3753 for (int i = 0; i < m_iterations; i++) {
3754 SAFEPOINT_POLL_FAST(m_safepointManager)do { } while (0); do { if (m_safepointManager.hasRequest()) vmbase
::SafepointGate::gateWithRegistersSaved(); } while (0)
;
3755 m_producerCounts[threadIndex]++;
3756 if (i % 100 == 0)
3757 VMPI_threadYield(); // Try to allow some interesting interleavings
3758 }
3759 }
3760 m_threadOut++;
3761 }
3762 private:
3763 int* m_producerCounts;
3764 AtomicCounter32 m_threadIn;
3765 AtomicCounter32 m_threadOut;
3766 };
3767
3768 /**
3769 * Producer-consumer with nested/recursive (arbitrary depth) SafepointManagers.
3770 *
3771 * This test uses the same idea as ProducerConsumerTest, but instead of
3772 * having only one SafepointManager which is entered by all the producer
3773 * threads, there are N SafepointManagers which the producers continually
3774 * nest in and out of. Each producer maintains a private counter for each
3775 * SafepointManager nesting level, which it only increments when in the
3776 * context of the corresponding SafepointManager.
3777 *
3778 * Similar to the producers, the consumer continually nests in and out of
3779 * the stack of SafepointManagers. At each nesting level the consumer
3780 * requests that the producers be safepointed with respect to the
3781 * SafepointManager at that nesting level. In the safepoint task
3782 * the consumer 'steals' and then zeros the private counter of the
3783 * producers for that level. Each stolen counter value is added to
3784 * the consumer's private counter.
3785 *
3786 * This continues until the producers have executed a fixed number of
3787 * iterations for each nesting level. At the end of this process the
3788 * consumer should have a deterministic private counter value.
3789 *
3790 * Note, to test both recursive and nested SafepointManager entry,
3791 * the SafepointManager used for the final nesting level is the
3792 * same as the first.
3793 */
3794 class NestedProducerConsumerTest : public SafepointTestBase
3795 {
3796
3797 public:
3798 NestedProducerConsumerTest(SafepointManager& safepointManager, int iterations, int threadQty, int nestingDepth)
3799 : SafepointTestBase(safepointManager, iterations, threadQty)
3800 , m_nestingDepth(nestingDepth)
3801 {
3802 m_nestedManagers = mmfx_new_array(SafepointManager, m_nestingDepth)::MMgcConstructTaggedArray((SafepointManager*)__null, m_nestingDepth
, MMgc::kNone)
;
3803 m_producerCounters = mmfx_new_array(int*, m_nestingDepth + 1)::MMgcConstructTaggedArray((int**)__null, m_nestingDepth + 1,
MMgc::kNone)
;
3804 for (int i = 0; i < m_nestingDepth + 1; i++) {
3805 m_producerCounters[i] = mmfx_new_array_opt(int, threadQty - 1, kZero)::MMgcConstructTaggedArray((int*)__null, threadQty - 1, kZero
)
;
3806 }
3807 }
3808
3809 virtual ~NestedProducerConsumerTest()
3810 {
3811 }
3812
3813 int nestedConsume(int depth)
3814 {
3815 if (depth == -1) {
3816 // Fish for asserts:
3817 // At the deepest nesting level recurse into the oldest SafepointManager on the stack.
3818 SafepointRecord record;
3819 m_safepointManager.enter(&record);
3820 ProducerConsumerTest::ConsumerSafepointTask task(m_producerCounters[0], m_threadQty - 1);
3821 m_safepointManager.requestSafepointTask(task);
3822 m_safepointManager.leave(&record);
3823 return task.producerStolenCounter();;
3824 }
3825 SafepointRecord record;
3826 m_nestedManagers[depth].enter(&record);
3827 ProducerConsumerTest::ConsumerSafepointTask task(m_producerCounters[depth + 1], m_threadQty - 1);
3828 m_nestedManagers[depth].requestSafepointTask(task);
3829 int consumerCount = task.producerStolenCounter();
3830
3831 // Next SafepointManager
3832 consumerCount += nestedConsume(depth - 1);
3833
3834 m_nestedManagers[depth].leave(&record);
3835 return consumerCount;
3836 }
3837
3838 void nestedProduce(int depth, int iterations, int threadIndex)
3839 {
3840 if (depth == -1) {
3841 // Fish for asserts:
3842 // At the deepest nesting level recurse into the oldest SafepointManager on the stack.
3843 SafepointRecord record;
3844 m_safepointManager.enter(&record);
3845 for (int i = 0; i < iterations; i++) {
3846 SAFEPOINT_POLL_FAST(m_safepointManager)do { } while (0); do { if (m_safepointManager.hasRequest()) vmbase
::SafepointGate::gateWithRegistersSaved(); } while (0)
;
3847 m_producerCounters[0][threadIndex]++;
3848 }
3849 m_safepointManager.leave(&record);
3850 return;
3851 }
3852 SafepointRecord record;
3853 m_nestedManagers[depth].enter(&record);
3854 for (int i = 0; i < iterations; i++) {
3855 SAFEPOINT_POLL_FAST(m_nestedManagers[depth])do { } while (0); do { if (m_nestedManagers[depth].hasRequest
()) vmbase::SafepointGate::gateWithRegistersSaved(); } while (
0)
;
3856 m_producerCounters[depth + 1][threadIndex]++;
3857 }
3858 VMPI_threadYield(); // Try to allow some interesting interleavings
3859
3860 // Next SafepointManager
3861 nestedProduce(depth - 1, iterations, threadIndex);
3862
3863 m_nestedManagers[depth].leave(&record);
3864 }
3865
3866 // Thread entrypoint
3867 virtual void runInSafepointManagerContext()
3868 {
3869 // Wait for all the threads to startup to force as much
3870 // contention as possible.
3871 const int threadIndex = m_threadIn++;
3872 SCOPE_LOCK_SP_NAMED(locker, m_monitor)if (vmbase::MonitorLocker<vmbase::IMPLICIT_SAFEPOINT> locker
= m_monitor) {} else
{
3873 locker.notifyAll();
3874 while (m_threadIn < m_threadQty) {
3875 locker.wait();
3876 }
3877 }
3878
3879 // Setup one of the threads as the consumer, the others are producers
3880 if (threadIndex == m_threadQty - 1) {
3881 // The consumer continually makes SafepointTask requests on
3882 // the SafepointManager at each nesting level, leading to
3883 // safepointed producers. In each SafepointTask the consumer
3884 // takes each producer's currently accrued, private counter at
3885 // the current nesting depth, and adds it to its own total count,
3886 // then zeroes the producers counter.
3887 int consumerCount = 0;
3888 enum State
3889 {
3890 RUNNING, DRAINING, DONE
3891 };
3892 State state = RUNNING;
3893 do {
3894 ProducerConsumerTest::ConsumerSafepointTask task(m_producerCounters[0], m_threadQty - 1);
3895 m_safepointManager.requestSafepointTask(task);
3896 consumerCount += task.producerStolenCounter();
3897 consumerCount += nestedConsume(m_nestingDepth - 1);
3898 if (state == DRAINING) {
3899 state = DONE;
3900 } else if (m_threadOut == m_threadQty - 1) {
3901 state = DRAINING;
3902 }
3903 } while (state != DONE);
3904
3905 // sharedCounter is verified by the selftest runner
3906 sharedCounter = consumerCount + m_iterations;
3907
3908 // Can't do this in the dtor, if the selftest verify fails, it will
3909 // throw an exception and the dtor will not run.
3910 for (int i = 0; i < m_nestingDepth + 1; i++) {
3911 mmfx_delete_array(m_producerCounters[i])::MMgcDestructTaggedArrayChecked(m_producerCounters[i]);
3912 }
3913 mmfx_delete_array(m_producerCounters)::MMgcDestructTaggedArrayChecked(m_producerCounters);
3914 mmfx_delete_array(m_nestedManagers)::MMgcDestructTaggedArrayChecked(m_nestedManagers);
3915 } else {
3916 // How many increments should we perform each time we visit
3917 // a nesting depth?
3918 const int incPerDepth = m_iterations / 1000;
3919 const int iterations = m_iterations / (incPerDepth * (m_nestingDepth + 2));
3920 // The producers increment their private counter at each nesting depth,
3921 // but we make sure that they reach an explicit safepoint every iteration.
3922 for (int i = 0; i < iterations; i++) {
3923 for (int j = 0; j < incPerDepth; j++) {
3924 SAFEPOINT_POLL_FAST(m_safepointManager)do { } while (0); do { if (m_safepointManager.hasRequest()) vmbase
::SafepointGate::gateWithRegistersSaved(); } while (0)
;
3925 m_producerCounters[0][threadIndex]++;
3926 }
3927 nestedProduce(m_nestingDepth - 1, incPerDepth, threadIndex);
3928 VMPI_threadYield(); // Try to allow some interesting interleavings
3929 }
3930 const int balance = m_iterations % (incPerDepth * (m_nestingDepth + 2));
3931 for (int i = 0; i < balance; i++) {
3932 SAFEPOINT_POLL_FAST(m_safepointManager)do { } while (0); do { if (m_safepointManager.hasRequest()) vmbase
::SafepointGate::gateWithRegistersSaved(); } while (0)
;
3933 m_producerCounters[0][threadIndex]++;
3934 }
3935 }
3936 m_threadOut++;
3937 }
3938 private:
3939 int** m_producerCounters;
3940 const int m_nestingDepth;
3941 SafepointManager* m_nestedManagers;
3942 AtomicCounter32 m_threadIn;
3943 AtomicCounter32 m_threadOut;
3944 };
3945
3946// Must be >=2 for ProducerConsumerTest and NestedProducerConsumerTest
3947#define THREAD_QTY4 4
3948
3949// Must be >= 1000 for NestedProducerConsumerTest
3950#define ITERATIONS100000 100000
3951
3952// For NestedProducerConsumerTest
3953#define NESTING_DEPTH7 7
3954
3955class ST_vmbase_safepoints : public Selftest {
3956public:
3957ST_vmbase_safepoints(AvmCore* core);
3958virtual void run(int n);
3959private:
3960static const char* ST_names[];
3961static const boolbool ST_explicits[];
3962void test0();
3963void test1();
3964void test2();
3965};
3966ST_vmbase_safepoints::ST_vmbase_safepoints(AvmCore* core)
3967 : Selftest(core, "vmbase", "safepoints", ST_vmbase_safepoints::ST_names,ST_vmbase_safepoints::ST_explicits)
3968{}
3969const char* ST_vmbase_safepoints::ST_names[] = {"simple","producer_consumer","nested_producer_consumer", NULL__null };
3970const boolbool ST_vmbase_safepoints::ST_explicits[] = {falsefalse,falsefalse,falsefalse, falsefalse };
3971void ST_vmbase_safepoints::run(int n) {
3972switch(n) {
3973case 0: test0(); return;
3974case 1: test1(); return;
3975case 2: test2(); return;
3976}
3977}
3978void ST_vmbase_safepoints::test0() {
3979#ifndef UNDER_CE
3980 TestRunner runner(THREAD_QTY4!=0);
3981 SimpleTest test(runner.safepointManager(), ITERATIONS100000, THREAD_QTY4);
3982 runner.runTest(test);
3983// line 528 "ST_vmbase_safepoints.st"
3984verifyPass(test.sharedCounter == THREAD_QTY4 * ITERATIONS100000, "test.sharedCounter == THREAD_QTY * ITERATIONS", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__3984);
3985#endif
3986
3987}
3988void ST_vmbase_safepoints::test1() {
3989#ifndef UNDER_CE
3990 TestRunner runner(THREAD_QTY4!=0);
3991 ProducerConsumerTest test(runner.safepointManager(), ITERATIONS100000, THREAD_QTY4);
3992 runner.runTest(test);
3993// line 536 "ST_vmbase_safepoints.st"
3994verifyPass(test.sharedCounter == THREAD_QTY4 * ITERATIONS100000, "test.sharedCounter == THREAD_QTY * ITERATIONS", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__3994);
3995#endif
3996
3997}
3998void ST_vmbase_safepoints::test2() {
3999#ifndef UNDER_CE
4000 TestRunner runner(THREAD_QTY4!=0);
4001 NestedProducerConsumerTest test(runner.safepointManager(), ITERATIONS100000 * 100, THREAD_QTY4, NESTING_DEPTH7);
4002 runner.runTest(test);
4003// line 544 "ST_vmbase_safepoints.st"
4004verifyPass(test.sharedCounter == THREAD_QTY4 * ITERATIONS100000 * 100, "test.sharedCounter == THREAD_QTY * ITERATIONS * 100", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__4004);
4005#endif
4006
4007
4008
4009
4010}
4011void create_vmbase_safepoints(AvmCore* core) { new ST_vmbase_safepoints(core); }
4012}
4013}
4014#endif
4015#endif
4016
4017// Generated from ST_vmpi_threads.st
4018// -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*-
4019// vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */
4020//
4021// ***** BEGIN LICENSE BLOCK *****
4022// Version: MPL 1.1/GPL 2.0/LGPL 2.1
4023//
4024// The contents of this file are subject to the Mozilla Public License Version
4025// 1.1 (the "License"); you may not use this file except in compliance with
4026// the License. You may obtain a copy of the License at
4027// http://www.mozilla.org/MPL/
4028//
4029// Software distributed under the License is distributed on an "AS IS" basis,
4030// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
4031// for the specific language governing rights and limitations under the
4032// License.
4033//
4034// The Original Code is [Open Source Virtual Machine.].
4035//
4036// The Initial Developer of the Original Code is
4037// Adobe System Incorporated.
4038// Portions created by the Initial Developer are Copyright (C) 2004-2006
4039// the Initial Developer. All Rights Reserved.
4040//
4041// Contributor(s):
4042// Adobe AS3 Team
4043//
4044// Alternatively, the contents of this file may be used under the terms of
4045// either the GNU General Public License Version 2 or later (the "GPL"), or
4046// the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
4047// in which case the provisions of the GPL or the LGPL are applicable instead
4048// of those above. If you wish to allow use of your version of this file only
4049// under the terms of either the GPL or the LGPL, and not to allow others to
4050// use your version of this file under the terms of the MPL, indicate your
4051// decision by deleting the provisions above and replace them with the notice
4052// and other provisions required by the GPL or the LGPL. If you do not delete
4053// the provisions above, a recipient may use your version of this file under
4054// the terms of any one of the MPL, the GPL or the LGPL.
4055//
4056// ***** END LICENSE BLOCK ***** */
4057
4058// Bugzilla 543560 - here we risk deleting an object that is still on the mark stack because
4059// of how we perform large-object splitting. The setup is that user code that deletes the object
4060// gets to run after the first part of the large object has been popped off the mark stack
4061// but before the rest has been handled.
4062
4063#include "avmshell.h"
4064#ifdef VMCFG_SELFTEST
4065namespace avmplus {
4066namespace ST_vmpi_threads {
4067using namespace MMgc;
4068
4069 class ThreadTestBase {
4070 public:
4071 struct ThreadRecord {
4072 vmpi_thread_t thread;
4073 int id;
4074 boolbool startupOk;
4075 };
4076
4077 ThreadTestBase(int threadQty, int iterations) : m_threadQty(threadQty), m_iterations(iterations), sharedCounter(0) {
4078 VMPI_recursiveMutexInit(&m_mutex);
4079 VMPI_condVarInit(&m_condition);
4080 }
4081 virtual ~ThreadTestBase() {
4082 VMPI_recursiveMutexDestroy(&m_mutex);
4083 VMPI_condVarDestroy(&m_condition);
4084 }
4085
4086 void runTest() {
4087
4088 ThreadRecord* threads = mmfx_new_array(ThreadRecord, m_threadQty)::MMgcConstructTaggedArray((ThreadRecord*)__null, m_threadQty
, MMgc::kNone)
;
4089
4090 // Start up the threads
4091 for (int i = 0; i < m_threadQty; i++) {
4092 threads[i].id = i;
4093 threads[i].startupOk = VMPI_threadCreate(&threads[i].thread, NULL__null, _workerThreadEntry, this);
4094 }
4095
4096 // ...then block until they all terminate
4097 for (int i = 0; i < m_threadQty; i++) {
4098 if (threads[i].startupOk) {
4099 VMPI_threadJoin(threads[i].thread);
4100 }
4101 }
4102
4103 mmfx_delete_array(threads)::MMgcDestructTaggedArrayChecked(threads);
4104 }
4105
4106 static vmpi_thread_rtn_t VMPI_THREAD_START_CC detachbleThreadEntry(vmpi_thread_arg_t) {
4107 VMPI_threadDetach(VMPI_currentThread());
4108 return NULL__null;
4109 }
4110
4111 static vmpi_thread_rtn_t VMPI_THREAD_START_CC joinableThreadEntry(vmpi_thread_arg_t) {
4112 return NULL__null;
4113 }
4114
4115 protected:
4116 virtual void workerThreadEntry() {}
4117
4118 private:
4119 static vmpi_thread_rtn_t VMPI_THREAD_START_CC _workerThreadEntry(vmpi_thread_arg_t arg) {
4120 ((ThreadTestBase*)arg)->workerThreadEntry();
4121 return NULL__null;
4122 }
4123
4124 protected:
4125 const int m_threadQty;
4126 vmpi_mutex_t m_mutex;
4127 vmpi_condvar_t m_condition;
4128 const int m_iterations;
4129
4130 public:
4131 int sharedCounter;
4132 };
4133
4134 class MutexTest : public ThreadTestBase {
4135 public:
4136 MutexTest(int threadQty, int iterations) : ThreadTestBase(threadQty, iterations) {}
4137 virtual ~MutexTest() {}
4138
4139 virtual void workerThreadEntry() {
4140 for (int i = 0; i < m_iterations; i++) {
4141 VMPI_recursiveMutexLock(&m_mutex);
4142 VMPI_recursiveMutexLock(&m_mutex);
4143 sharedCounter++;
4144 VMPI_recursiveMutexUnlock(&m_mutex);
4145 VMPI_recursiveMutexUnlock(&m_mutex);
4146 }
4147 }
4148 };
4149
4150
4151 class ConditionTest : public ThreadTestBase {
4152 public:
4153 ConditionTest(int threadQty, int iterations) : ThreadTestBase(threadQty, iterations), m_finishedQty(0) {}
4154 virtual ~ConditionTest() {}
4155
4156 virtual void workerThreadEntry() {
4157 if (m_threadQty < 2) {
4158 return;
4159 }
4160
4161 for (int i = 0; i < m_iterations; i++) {
4162 VMPI_recursiveMutexLock(&m_mutex);
4163 sharedCounter++;
4164
4165 // If there's another thread still active then wait.
4166 if (m_finishedQty < m_threadQty - 1) {
4167 VMPI_condVarSignal(&m_condition);
4168 VMPI_condVarWait(&m_condition, &m_mutex);
4169 }
4170
4171 // This thread has finished, so let's wake everyone else up
4172 if (i == m_iterations - 1) {
4173 m_finishedQty++;
4174 VMPI_condVarBroadcast(&m_condition);
4175 }
4176 VMPI_recursiveMutexUnlock(&m_mutex);
4177
4178 }
4179
4180 }
4181
4182 private:
4183 int m_finishedQty;
4184 };
4185
4186 class AtomicIncrementTest : public ThreadTestBase {
4187 public:
4188 AtomicIncrementTest(int threadQty, int iterations, boolbool withBarrier) : ThreadTestBase(threadQty, iterations), m_withBarrier(withBarrier) {}
4189 virtual ~AtomicIncrementTest() {}
4190
4191 virtual void workerThreadEntry() {
4192 if (m_withBarrier) {
4193 for (int i = 0; i < m_iterations; i++) {
4194 VMPI_atomicIncAndGet32WithBarrier(&sharedCounter);
4195 }
4196 } else {
4197 for (int i = 0; i < m_iterations; i++) {
4198 VMPI_atomicIncAndGet32(&sharedCounter);
4199 }
4200 }
4201 }
4202 private:
4203 boolbool m_withBarrier;
4204 };
4205
4206 class AtomicDecrementTest : public ThreadTestBase {
4207 public:
4208 AtomicDecrementTest(int threadQty, int iterations, boolbool withBarrier) : ThreadTestBase(threadQty, iterations), m_withBarrier(withBarrier) {}
4209 virtual ~AtomicDecrementTest() {}
4210
4211 virtual void workerThreadEntry() {
4212 if (m_withBarrier) {
4213 for (int i = 0; i < m_iterations; i++) {
4214 VMPI_atomicDecAndGet32WithBarrier(&sharedCounter);
4215 }
4216 } else {
4217 for (int i = 0; i < m_iterations; i++) {
4218 VMPI_atomicDecAndGet32(&sharedCounter);
4219 }
4220 }
4221 }
4222 private:
4223 boolbool m_withBarrier;
4224 };
4225
4226 class CASTest : public ThreadTestBase {
4227 public:
4228 CASTest(int threadQty, int iterations, boolbool withBarrier) : ThreadTestBase(threadQty, iterations), m_withBarrier(withBarrier) {}
4229 virtual ~CASTest() {}
4230
4231 virtual void workerThreadEntry() {
4232 if (m_withBarrier) {
4233 for (int i = 0; i < m_iterations; i++) {
4234 int32_t current, next;
4235 do {
4236 current = sharedCounter;
4237 next = current + 1;
4238 } while (!VMPI_compareAndSwap32WithBarrier(current, next, &sharedCounter));
4239 }
4240 } else {
4241 for (int i = 0; i < m_iterations; i++) {
4242 int32_t current, next;
4243 do {
4244 current = sharedCounter;
4245 next = current + 1;
4246 } while (!VMPI_compareAndSwap32(current, next, &sharedCounter));
4247 }
4248 }
4249 }
4250 private:
4251 boolbool m_withBarrier;
4252 };
4253
4254 /**
4255 * We protect a shared counter with a Dekker-style lock that has been made
4256 * sequentially consistent with memory barriers.
4257 *
4258 * The idea is that if the barriers are correct, then two threads can compete
4259 * to update the counter n times each, so that the final counter value is 2n. If
4260 * the final value is not 2n, then the barriers have failed to ensure sequential
4261 * consistency.
4262 *
4263 * FIXME: bug 609943
4264 * This seems way too complicated. We have to be confident in the algorithm
4265 * before considering the barrier implementations, and I'm not convinced as yet.
4266 * Is there something simpler?
4267 *
4268 * This is test is not actually run. The verifyPass below just returns true.
4269 */
4270 class MemoryBarrierTest : public ThreadTestBase {
4271 public:
4272 MemoryBarrierTest(int iterations) : ThreadTestBase(2, iterations), m_thread0(0), m_thread1(0), m_turn(NULL__null) {}
4273 virtual ~MemoryBarrierTest() {}
4274
4275 virtual void workerThreadEntry() {
4276
4277 volatile int* me;
4278 volatile int* other;
4279 volatile int* const counterp = &sharedCounter;
4280
4281 VMPI_recursiveMutexLock(&m_mutex);
4282 if (m_turn == NULL__null) {
4283 me = &m_thread0;
4284 other = &m_thread1;
4285 m_turn = me;
4286 } else {
4287 me = &m_thread1;
4288 other = &m_thread0;
4289 }
4290 VMPI_recursiveMutexUnlock(&m_mutex);
4291
4292 for (int i = 0; i < m_iterations; i++) {
4293 // Dekker lock
4294 *me = 1;
4295 VMPI_memoryBarrier();
4296 while (*other == 1) {
4297 VMPI_memoryBarrier();
4298 if (m_turn == other) {
4299 VMPI_memoryBarrier();
4300 *me = 0;
4301 VMPI_memoryBarrier();
4302 while (m_turn == other) {
4303 VMPI_memoryBarrier();
4304 }
4305 VMPI_memoryBarrier();
4306 *me = 1;
4307 VMPI_memoryBarrier();
4308 }
4309 }
4310 VMPI_memoryBarrier();
4311 (*counterp)++;
4312 VMPI_memoryBarrier();
4313 m_turn = other;
4314 VMPI_memoryBarrier();
4315 *me = 0;
4316 VMPI_memoryBarrier();
4317 }
4318 }
4319 private:
4320 volatile int m_thread0;
4321 volatile int m_thread1;
4322 volatile int* volatile m_turn;
4323 };
4324
4325 class TryLockTest : public ThreadTestBase {
4326 public:
4327 TryLockTest(int threadQty, int iterations) : ThreadTestBase(threadQty, iterations) {}
4328 virtual ~TryLockTest() {}
4329
4330 virtual void workerThreadEntry() {
4331 for (int i = 0; i < m_iterations; i++) {
4332 int counter = 0;
4333 while (!VMPI_recursiveMutexTryLock(&m_mutex)) {
4334 ++counter;
4335 if((counter & 63) == 0) {
4336 VMPI_threadSleep(1);
4337 }
4338 }
4339 sharedCounter++;
4340 VMPI_recursiveMutexUnlock(&m_mutex);
4341 }
4342 }
4343 };
4344
4345 class ConditionWithWaitTest : public ThreadTestBase {
4346 public:
4347 ConditionWithWaitTest(int threadQty, int iterations) : ThreadTestBase(threadQty, iterations) {}
4348 virtual ~ConditionWithWaitTest() {}
4349
4350 virtual void workerThreadEntry() {
4351 for (int i = 0; i < m_iterations; i++) {
4352 VMPI_recursiveMutexLock(&m_mutex);
4353 sharedCounter++;
4354 VMPI_condVarTimedWait(&m_condition, &m_mutex, 1);
4355 VMPI_recursiveMutexUnlock(&m_mutex);
4356 }
4357 }
4358 };
4359
4360 class SleepTest : public ThreadTestBase {
4361 public:
4362 SleepTest(int threadQty, int iterations) : ThreadTestBase(threadQty, iterations) {}
4363 virtual ~SleepTest() {}
4364
4365 virtual void workerThreadEntry() {
4366 for (int i = 0; i < m_iterations; i++) {
4367 VMPI_recursiveMutexLock(&m_mutex);
4368 sharedCounter++;
4369 VMPI_recursiveMutexUnlock(&m_mutex);
4370 VMPI_threadSleep(1);
4371 }
4372 }
4373 };
4374
4375// This needs to be at least 2 for ConditionTest
4376#define THREAD_QTY4 4
4377
4378#define ITERATIONS100000 100000
4379
4380class ST_vmpi_threads : public Selftest {
4381public:
4382ST_vmpi_threads(AvmCore* core);
4383virtual void run(int n);
4384private:
4385static const char* ST_names[];
4386static const boolbool ST_explicits[];
4387void test0();
4388void test1();
4389void test2();
4390void test3();
4391void test4();
4392void test5();
4393void test6();
4394void test7();
4395void test8();
4396void test9();
4397void test10();
4398void test11();
4399void test12();
4400void test13();
4401};
4402ST_vmpi_threads::ST_vmpi_threads(AvmCore* core)
4403 : Selftest(core, "vmpi", "threads", ST_vmpi_threads::ST_names,ST_vmpi_threads::ST_explicits)
4404{}
4405const char* ST_vmpi_threads::ST_names[] = {"mutexes","conditions","atomic_increment_without_barrier","atomic_decrement_without_barrier","compare_and_swap_without_barrier","atomic_increment_with_barrier","atomic_decrement_with_barrier","compare_and_swap_with_barrier","memory_barrier","try_lock","condition_with_wait","sleep","detach","thread_attributes", NULL__null };
4406const boolbool ST_vmpi_threads::ST_explicits[] = {falsefalse,falsefalse,falsefalse,falsefalse,falsefalse,falsefalse,falsefalse,falsefalse,falsefalse,falsefalse,falsefalse,falsefalse,falsefalse,falsefalse, falsefalse };
4407void ST_vmpi_threads::run(int n) {
4408switch(n) {
4409case 0: test0(); return;
4410case 1: test1(); return;
4411case 2: test2(); return;
4412case 3: test3(); return;
4413case 4: test4(); return;
4414case 5: test5(); return;
4415case 6: test6(); return;
4416case 7: test7(); return;
4417case 8: test8(); return;
4418case 9: test9(); return;
4419case 10: test10(); return;
4420case 11: test11(); return;
4421case 12: test12(); return;
4422case 13: test13(); return;
4423}
4424}
4425void ST_vmpi_threads::test0() {
4426#ifndef UNDER_CE
4427 MutexTest mutexTest(THREAD_QTY4, ITERATIONS100000);
4428 mutexTest.runTest();
4429// line 367 "ST_vmpi_threads.st"
4430verifyPass(mutexTest.sharedCounter == THREAD_QTY4 * ITERATIONS100000, "mutexTest.sharedCounter == THREAD_QTY * ITERATIONS", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__4430);
4431#endif
4432
4433}
4434void ST_vmpi_threads::test1() {
4435#ifndef UNDER_CE
4436 ConditionTest conditionTest(THREAD_QTY4, ITERATIONS100000);
4437 conditionTest.runTest();
4438// line 374 "ST_vmpi_threads.st"
4439verifyPass(conditionTest.sharedCounter == THREAD_QTY4 * ITERATIONS100000, "conditionTest.sharedCounter == THREAD_QTY * ITERATIONS", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__4439);
4440#endif
4441
4442}
4443void ST_vmpi_threads::test2() {
4444#ifndef UNDER_CE
4445 AtomicIncrementTest atomicIncrementTest(THREAD_QTY4, ITERATIONS100000, falsefalse);
4446 atomicIncrementTest.runTest();
4447// line 381 "ST_vmpi_threads.st"
4448verifyPass(atomicIncrementTest.sharedCounter == THREAD_QTY4 * ITERATIONS100000, "atomicIncrementTest.sharedCounter == THREAD_QTY * ITERATIONS", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__4448);
4449#endif
4450
4451}
4452void ST_vmpi_threads::test3() {
4453#ifndef UNDER_CE
4454 AtomicDecrementTest atomicDecrementTest(THREAD_QTY4, ITERATIONS100000, falsefalse);
4455 atomicDecrementTest.runTest();
4456// line 388 "ST_vmpi_threads.st"
4457verifyPass(atomicDecrementTest.sharedCounter == -(THREAD_QTY4 * ITERATIONS100000), "atomicDecrementTest.sharedCounter == -(THREAD_QTY * ITERATIONS)", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__4457);
4458#endif
4459
4460}
4461void ST_vmpi_threads::test4() {
4462#ifndef UNDER_CE
4463 CASTest casTest(THREAD_QTY4, ITERATIONS100000, falsefalse);
4464 casTest.runTest();
4465// line 395 "ST_vmpi_threads.st"
4466verifyPass(casTest.sharedCounter == THREAD_QTY4 * ITERATIONS100000, "casTest.sharedCounter == THREAD_QTY * ITERATIONS", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__4466);
4467#endif
4468
4469}
4470void ST_vmpi_threads::test5() {
4471#ifndef UNDER_CE
4472 AtomicIncrementTest atomicIncrementTest(THREAD_QTY4, ITERATIONS100000, truetrue);
4473 atomicIncrementTest.runTest();
4474// line 402 "ST_vmpi_threads.st"
4475verifyPass(atomicIncrementTest.sharedCounter == THREAD_QTY4 * ITERATIONS100000, "atomicIncrementTest.sharedCounter == THREAD_QTY * ITERATIONS", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__4475);
4476#endif
4477
4478}
4479void ST_vmpi_threads::test6() {
4480#ifndef UNDER_CE
4481 AtomicDecrementTest atomicDecrementTest(THREAD_QTY4, ITERATIONS100000, truetrue);
4482 atomicDecrementTest.runTest();
4483// line 409 "ST_vmpi_threads.st"
4484verifyPass(atomicDecrementTest.sharedCounter == -(THREAD_QTY4 * ITERATIONS100000), "atomicDecrementTest.sharedCounter == -(THREAD_QTY * ITERATIONS)", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__4484);
4485#endif
4486
4487}
4488void ST_vmpi_threads::test7() {
4489#ifndef UNDER_CE
4490 CASTest casTest(THREAD_QTY4, ITERATIONS100000, truetrue);
4491 casTest.runTest();
4492// line 416 "ST_vmpi_threads.st"
4493verifyPass(casTest.sharedCounter == THREAD_QTY4 * ITERATIONS100000, "casTest.sharedCounter == THREAD_QTY * ITERATIONS", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__4493);
4494#endif
4495
4496}
4497void ST_vmpi_threads::test8() {
4498#ifndef UNDER_CE
4499 /* This test is failing on Windows and Mac OSX 10.4.
4500 * For Windows, see bug 609820.
4501 * For Mac, are the 10.4 APIs not reliable?
4502 * It could also be the test, or the compiler!
4503 * FIXME: bug 609943 Selftests to stress memory barriers (fences)
4504
4505 // Note that the memory barrier test is based on a Dekker lock, so we
4506 // only ever use 2 threads.
4507 MemoryBarrierTest memoryBarrierTest(ITERATIONS);
4508 memoryBarrierTest.runTest();
4509// line 431 "ST_vmpi_threads.st"
4510verifyPass(memoryBarrierTest.sharedCounter == 2 * ITERATIONS, "memoryBarrierTest.sharedCounter == 2 * ITERATIONS", __FILE__, __LINE__);
4511
4512 */
4513// line 434 "ST_vmpi_threads.st"
4514verifyPass(truetrue, "true", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__4514);
4515#endif
4516
4517}
4518void ST_vmpi_threads::test9() {
4519#ifndef UNDER_CE
4520 TryLockTest tryLockTest(THREAD_QTY4, ITERATIONS100000);
4521 tryLockTest.runTest();
4522// line 441 "ST_vmpi_threads.st"
4523verifyPass(tryLockTest.sharedCounter == THREAD_QTY4 * ITERATIONS100000, "tryLockTest.sharedCounter == THREAD_QTY * ITERATIONS", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__4523);
4524#endif
4525
4526}
4527void ST_vmpi_threads::test10() {
4528#ifndef UNDER_CE
4529 // Use 2000 iterations with a 1 ms wait
4530 ConditionWithWaitTest conditionWithWaitTest(THREAD_QTY4, 2000);
4531 conditionWithWaitTest.runTest();
4532// line 449 "ST_vmpi_threads.st"
4533verifyPass(conditionWithWaitTest.sharedCounter == THREAD_QTY4 * 2000, "conditionWithWaitTest.sharedCounter == THREAD_QTY * 2000", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__4533);
4534#endif
4535
4536}
4537void ST_vmpi_threads::test11() {
4538#ifndef UNDER_CE
4539 // Use 2000 iterations with a 1 ms sleep
4540 SleepTest sleepTest(THREAD_QTY4, 2000);
4541 sleepTest.runTest();
4542// line 457 "ST_vmpi_threads.st"
4543verifyPass(sleepTest.sharedCounter == THREAD_QTY4 * 2000, "sleepTest.sharedCounter == THREAD_QTY * 2000", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__4543);
4544#endif
4545
4546}
4547void ST_vmpi_threads::test12() {
4548#ifndef UNDER_CE
4549 // We can't really test for much here...
4550 vmpi_thread_t thread;
4551 VMPI_threadCreate(&thread, NULL__null, ThreadTestBase::detachbleThreadEntry, NULL__null);
4552// line 465 "ST_vmpi_threads.st"
4553verifyPass(truetrue, "true", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__4553);
4554#endif
4555
4556}
4557void ST_vmpi_threads::test13() {
4558#ifndef UNDER_CE
4559 vmpi_thread_attr_t attr;
4560// line 471 "ST_vmpi_threads.st"
4561verifyPass(VMPI_threadAttrInit(&attr) == truetrue, "VMPI_threadAttrInit(&attr) == true", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__4561);
4562
4563 VMPI_threadAttrSetGuardSize(&attr, VMPI_threadAttrDefaultGuardSize());
4564 VMPI_threadAttrSetStackSize(&attr, VMPI_threadAttrDefaultStackSize());
4565 VMPI_threadAttrSetPriorityLow(&attr);
4566 VMPI_threadAttrSetPriorityNormal(&attr);
4567 VMPI_threadAttrSetPriorityHigh(&attr);
4568
4569 vmpi_thread_t thread;
4570 boolbool started = VMPI_threadCreate(&thread, &attr, ThreadTestBase::joinableThreadEntry, NULL__null);
4571// line 481 "ST_vmpi_threads.st"
4572verifyPass(started == truetrue, "started == true", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__4572);
4573 if (started) {
4574 VMPI_threadJoin(thread);
4575 }
4576
4577// line 486 "ST_vmpi_threads.st"
4578verifyPass(VMPI_threadAttrDestroy(&attr) == truetrue, "VMPI_threadAttrDestroy(&attr) == true", __FILE__"/Users/treilly/dev/tamarin-redux/platform/mac/avmshell/../../../extensions/SelftestExec.cpp", __LINE__4578);
4579#endif
4580
4581
4582}
4583void create_vmpi_threads(AvmCore* core) { new ST_vmpi_threads(core); }
4584}
4585}
4586#endif
4587