forked from adobe-flash/avmplus
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathSelftestExec.cpp
5829 lines (5095 loc) · 194 KB
/
SelftestExec.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
// Generated from ST_avmplus_basics.st, ST_avmplus_builtins.st, ST_avmplus_peephole.st, ST_avmplus_vector_accessors.st, ST_mmgc_543560.st, ST_mmgc_575631.st, ST_mmgc_580603.st, ST_mmgc_603411.st, ST_mmgc_637993.st, ST_mmgc_basics.st, ST_mmgc_dependent.st, ST_mmgc_exact.st, ST_mmgc_externalalloc.st, ST_mmgc_finalize_uninit.st, ST_mmgc_fixedmalloc_findbeginning.st, ST_mmgc_gcheap.st, ST_mmgc_gcoption.st, ST_mmgc_mmfx_array.st, ST_mmgc_threads.st, ST_mmgc_weakref.st, ST_nanojit_codealloc.st, ST_vmbase_concurrency.st, ST_vmbase_safepoints.st, ST_vmpi_threads.st, ST_workers_Buffer.st, ST_workers_NoSyncSingleItemBuffer.st, ST_workers_Promise.st
// Generated from ST_avmplus_basics.st
// -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*-
// vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include "avmshell.h"
#ifdef VMCFG_SELFTEST
namespace avmplus {
namespace ST_avmplus_basics {
class ST_avmplus_basics : public Selftest {
public:
ST_avmplus_basics(AvmCore* core);
virtual void run(int n);
private:
static const char* ST_names[];
static const bool ST_explicits[];
void test0();
void test1();
void test2();
void test3();
void test4();
void test5();
void test6();
void test7();
};
ST_avmplus_basics::ST_avmplus_basics(AvmCore* core)
: Selftest(core, "avmplus", "basics", ST_avmplus_basics::ST_names,ST_avmplus_basics::ST_explicits)
{}
const char* ST_avmplus_basics::ST_names[] = {"unsigned_int","signed_int","equalsLatin1","containsLatin1","indexOfLatin1","matchesLatin1","matchesLatin1_caseless","bug562101", NULL };
const bool ST_avmplus_basics::ST_explicits[] = {false,false,false,false,false,false,false,false, false };
void ST_avmplus_basics::run(int n) {
switch(n) {
case 0: test0(); return;
case 1: test1(); return;
case 2: test2(); return;
case 3: test3(); return;
case 4: test4(); return;
case 5: test5(); return;
case 6: test6(); return;
case 7: test7(); return;
}
}
void ST_avmplus_basics::test0() {
// Does right shift of unsigned quantities work?
// line 14 "ST_avmplus_basics.st"
verifyPass((int)(~0U >> 1) > 0, "(int)(~0U >> 1) > 0", __FILE__, __LINE__);
}
void ST_avmplus_basics::test1() {
// Does right shift of signed quantities work?
// line 19 "ST_avmplus_basics.st"
verifyPass((-1 >> 1) == -1, "(-1 >> 1) == -1", __FILE__, __LINE__);
// verify that the "latin1" literal string calls work properly for hi-bit latin1 chars
}
void ST_avmplus_basics::test2() {
Stringp s = core->newConstantStringLatin1("ev\xADident");
bool equals = s->equalsLatin1("ev\xADident");
// line 25 "ST_avmplus_basics.st"
verifyPass(equals == true, "equals == true", __FILE__, __LINE__);
}
void ST_avmplus_basics::test3() {
Stringp s = core->newConstantStringLatin1("ev\xADident");
bool found = s->containsLatin1("\xAD");
// line 30 "ST_avmplus_basics.st"
verifyPass(found == true, "found == true", __FILE__, __LINE__);
}
void ST_avmplus_basics::test4() {
Stringp s = core->newConstantStringLatin1("ev\xADident");
int index = s->indexOfLatin1("\xAD");
// line 35 "ST_avmplus_basics.st"
verifyPass(index == 2, "index == 2", __FILE__, __LINE__);
}
void ST_avmplus_basics::test5() {
Stringp s = core->newConstantStringLatin1("ev\xADident");
bool matches1 = s->matchesLatin1("\xADi", 2, 2);
// line 40 "ST_avmplus_basics.st"
verifyPass(matches1 == true, "matches1 == true", __FILE__, __LINE__);
}
void ST_avmplus_basics::test6() {
Stringp s = core->newConstantStringLatin1("ev\xADident");
bool matches2 = s->matchesLatin1_caseless("\xADIDENT", 2, 2);
// line 45 "ST_avmplus_basics.st"
verifyPass(matches2 == true, "matches2 == true", __FILE__, __LINE__);
}
void ST_avmplus_basics::test7() {
// XMLParser omits the last char of a DOCTYPE node
Stringp str = core->newConstantStringLatin1("<?xml version=\"1.0\"?><!DOCTYPE greeting SYSTEM><greeting>Hello, world!</greeting>");
XMLParser parser(core, str);
MMgc::GC *gc = core->GetGC();
XMLTag tag(gc);
int m_status;
bool pass = false;
while ((m_status = parser.getNext(tag)) == XMLParser::kNoError)
{
switch (tag.nodeType)
{
case XMLTag::kDocTypeDeclaration:
{
pass = false;
pass = tag.text->equalsLatin1("<!DOCTYPE greeting SYSTEM>");
}
break;
}
}
// line 68 "ST_avmplus_basics.st"
verifyPass(pass == true, "pass == true", __FILE__, __LINE__);
// FIXME: this needs a "register this object with the GC" mechanism; this abuse of the GCRoot mechanism
// is no longer allowed
//%%test bug610022
// Stringp str = core->newConstantStringLatin1("some string that is likely to be unique");
// WeakRefList<String> list(core->GetGC(), 0);
// We are going to skip scanning the stack (so that "str" won't hold the string in place)
// but that means we need a root to ensure that "list" doesn't also get collected.
//
//MMgc::GCRoot root(core->GetGC(), &list, sizeof(list));
//list.add(str);
//str = NULL;
//core->GetGC()->Collect(/*scanStack*/false);
//int removed = list.removeCollectedItems();
//int count = list.length();
//%%verify removed == 1 && count == 0
}
void create_avmplus_basics(AvmCore* core) { new ST_avmplus_basics(core); }
}
}
#endif
// Generated from ST_avmplus_builtins.st
// -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*-
// vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include "avmshell.h"
#ifdef VMCFG_SELFTEST
namespace avmplus {
namespace ST_avmplus_builtins {
class ST_avmplus_builtins : public Selftest {
public:
ST_avmplus_builtins(AvmCore* core);
virtual void run(int n);
private:
static const char* ST_names[];
static const bool ST_explicits[];
void test0();
};
ST_avmplus_builtins::ST_avmplus_builtins(AvmCore* core)
: Selftest(core, "avmplus", "builtins", ST_avmplus_builtins::ST_names,ST_avmplus_builtins::ST_explicits)
{}
const char* ST_avmplus_builtins::ST_names[] = {"WeakValueHashTable", NULL };
const bool ST_avmplus_builtins::ST_explicits[] = {false, false };
void ST_avmplus_builtins::run(int n) {
switch(n) {
case 0: test0(); return;
}
}
void ST_avmplus_builtins::test0() {
WeakValueHashtable* tbl = WeakValueHashtable::create(core->gc);
String* fhtagn = String::createLatin1(core, "Fhtagn!");
MMgc::GCObjectLock* fhtagn_lock = core->gc->LockObject(fhtagn);
fhtagn = NULL;
for ( int i=0 ; i < 500 ; i++ ) {
tbl->add(atomFromIntptrValue(i), (i & 1) ? String::createLatin1(core, "Cthulhu!")->atom() : ((String*)core->gc->GetLockedObject(fhtagn_lock))->atom());
}
core->gc->Collect();
core->gc->Collect();
int sum = 0;
for ( int i=0 ; i < 500 ; i++ ) {
Atom a = tbl->get(atomFromIntptrValue(i));
if (a != AtomConstants::undefinedAtom)
sum++;
}
core->gc->UnlockObject(fhtagn_lock);
printf("fhtagn sum: %d\n", sum);
// Retain at least 250, but it would be unreasonable to retain more than 300
// line 31 "ST_avmplus_builtins.st"
verifyPass(sum >= 250 && sum <= 300, "sum >= 250 && sum <= 300", __FILE__, __LINE__);
}
void create_avmplus_builtins(AvmCore* core) { new ST_avmplus_builtins(core); }
}
}
#endif
// Generated from ST_avmplus_peephole.st
// -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*-
// vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include "avmshell.h"
#ifdef VMCFG_SELFTEST
#if defined AVMPLUS_PEEPHOLE_OPTIMIZER
namespace avmplus {
namespace ST_avmplus_peephole {
class ST_avmplus_peephole : public Selftest {
public:
ST_avmplus_peephole(AvmCore* core);
virtual void run(int n);
virtual void prologue();
virtual void epilogue();
private:
static const char* ST_names[];
static const bool ST_explicits[];
void test0();
private:
#ifdef AVMPLUS_DIRECT_THREADED
void** opcode_labels; // the name is not arbitrary
#endif
};
ST_avmplus_peephole::ST_avmplus_peephole(AvmCore* core)
: Selftest(core, "avmplus", "peephole", ST_avmplus_peephole::ST_names,ST_avmplus_peephole::ST_explicits)
{}
const char* ST_avmplus_peephole::ST_names[] = {"get2locals", NULL };
const bool ST_avmplus_peephole::ST_explicits[] = {false, false };
void ST_avmplus_peephole::run(int n) {
switch(n) {
case 0: test0(); return;
}
}
void ST_avmplus_peephole::prologue() {
#ifdef AVMPLUS_DIRECT_THREADED
opcode_labels = interpGetOpcodeLabels();
#endif
}
void ST_avmplus_peephole::epilogue() {
#ifdef AVMPLUS_DIRECT_THREADED
opcode_labels = NULL; // interpGetOpcodeLables() returns a pointer to static data
#endif
}
void ST_avmplus_peephole::test0() {
WordcodeEmitter* t = new WordcodeEmitter(core, NULL);
t->emitOp1(WOP_getlocal, 5);
t->emitOp1(WOP_getlocal, 4);
t->emitOp1(WOP_getlocal, 65536);
t->emitOp1(WOP_getlocal, 7);
t->emitOp1(WOP_getlocal, 6);
uintptr_t* code;
uint32_t len = (uint32_t)t->epilogue(&code);
// line 43 "ST_avmplus_peephole.st"
verifyPass(len == 6, "len == 6", __FILE__, __LINE__);
// line 44 "ST_avmplus_peephole.st"
verifyPass(code[0] == NEW_OPCODE(WOP_get2locals), "code[0] == NEW_OPCODE(WOP_get2locals)", __FILE__, __LINE__);
// line 45 "ST_avmplus_peephole.st"
verifyPass(code[1] == ((4 << 16) | 5), "code[1] == ((4 << 16) | 5)", __FILE__, __LINE__);
// line 46 "ST_avmplus_peephole.st"
verifyPass(code[2] == NEW_OPCODE(WOP_getlocal), "code[2] == NEW_OPCODE(WOP_getlocal)", __FILE__, __LINE__);
// line 47 "ST_avmplus_peephole.st"
verifyPass(code[3] == 65536, "code[3] == 65536", __FILE__, __LINE__);
// line 48 "ST_avmplus_peephole.st"
verifyPass(code[4] == NEW_OPCODE(WOP_get2locals), "code[4] == NEW_OPCODE(WOP_get2locals)", __FILE__, __LINE__);
// line 49 "ST_avmplus_peephole.st"
verifyPass(code[5] == ((6 << 16) | 7), "code[5] == ((6 << 16) | 7)", __FILE__, __LINE__);
delete t;
}
void create_avmplus_peephole(AvmCore* core) { new ST_avmplus_peephole(core); }
}
}
#endif
#endif
// Generated from ST_avmplus_vector_accessors.st
// -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*-
// vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
// Bugzilla 609145 - VectorObject needs fast inline getter/setters
// Make sure the APIs, which are used by the Flash Player and AIR only, do not disappear.
//
// NOTE, the following comment is stale and we can fix the code, see the code for
// VectorAccessor further down for how to access a toplevel.
//
// We can't test them because we don't have access to a Toplevel*, but we can reference
// them, and a link error will ensue if they disappear.
//
// Code coverage will get worse with this test, not better. C'est la guerre.
#include "avmshell.h"
#ifdef VMCFG_SELFTEST
namespace avmplus {
namespace ST_avmplus_vector_accessors {
int32_t reference_getUintPropertyFast(IntVectorObject* obj, uint32_t x)
{
return obj->getUintPropertyFast(x);
}
void reference_setUintPropertyFast(IntVectorObject* obj, uint32_t x, int32_t v)
{
obj->setUintPropertyFast(x, v);
}
class ST_avmplus_vector_accessors : public Selftest {
public:
ST_avmplus_vector_accessors(AvmCore* core);
virtual void run(int n);
private:
static const char* ST_names[];
static const bool ST_explicits[];
void test0();
void test1();
void test2();
void test3();
void test4();
};
ST_avmplus_vector_accessors::ST_avmplus_vector_accessors(AvmCore* core)
: Selftest(core, "avmplus", "vector_accessors", ST_avmplus_vector_accessors::ST_names,ST_avmplus_vector_accessors::ST_explicits)
{}
const char* ST_avmplus_vector_accessors::ST_names[] = {"getOrSetUintPropertyFast","DataListAccessor_on_int","DataListAccessor_on_float4","VectorAccessor_on_int","VectorAccessor_on_float4", NULL };
const bool ST_avmplus_vector_accessors::ST_explicits[] = {false,false,false,false,false, false };
void ST_avmplus_vector_accessors::run(int n) {
switch(n) {
case 0: test0(); return;
case 1: test1(); return;
case 2: test2(); return;
case 3: test3(); return;
case 4: test4(); return;
}
}
void ST_avmplus_vector_accessors::test0() {
// line 36 "ST_avmplus_vector_accessors.st"
verifyPass(true, "true", __FILE__, __LINE__);
}
void ST_avmplus_vector_accessors::test1() {
DataList<int> dl(core->GetGC(), 3);
dl.add(1);
dl.add(1);
dl.add(2);
dl.add(3);
dl.add(5);
dl.add(8);
dl.add(13);
DataListAccessor<int> dla(&dl);
int* xs = dla.addr();
// line 51 "ST_avmplus_vector_accessors.st"
verifyPass(xs[0] == 1, "xs[0] == 1", __FILE__, __LINE__);
// line 52 "ST_avmplus_vector_accessors.st"
verifyPass(xs[1] == 1, "xs[1] == 1", __FILE__, __LINE__);
// line 53 "ST_avmplus_vector_accessors.st"
verifyPass(xs[2] == 2, "xs[2] == 2", __FILE__, __LINE__);
// line 54 "ST_avmplus_vector_accessors.st"
verifyPass(xs[3] == 3, "xs[3] == 3", __FILE__, __LINE__);
// line 55 "ST_avmplus_vector_accessors.st"
verifyPass(xs[4] == 5, "xs[4] == 5", __FILE__, __LINE__);
// line 56 "ST_avmplus_vector_accessors.st"
verifyPass(xs[5] == 8, "xs[5] == 8", __FILE__, __LINE__);
// line 57 "ST_avmplus_vector_accessors.st"
verifyPass(xs[6] == 13, "xs[6] == 13", __FILE__, __LINE__);
}
void ST_avmplus_vector_accessors::test2() {
#ifdef VMCFG_FLOAT
DataList<float4_t, 16> dl4(core->GetGC(), 3);
float4_t x0 = { 1,1,2,3 };
float4_t x1 = { 5,8,13,21 };
float4_t x2 = { 34,55,89,144 };
dl4.add(x0);
dl4.add(x1);
dl4.add(x2);
DataListAccessor<float4_t,16> dla4(&dl4);
float4_t* x4s = dla4.addr();
// line 73 "ST_avmplus_vector_accessors.st"
verifyPass(f4_eq_i(x4s[0], x0) == 1, "f4_eq_i(x4s[0], x0) == 1", __FILE__, __LINE__);
// line 74 "ST_avmplus_vector_accessors.st"
verifyPass(f4_eq_i(x4s[1], x1) == 1, "f4_eq_i(x4s[1], x1) == 1", __FILE__, __LINE__);
// line 75 "ST_avmplus_vector_accessors.st"
verifyPass(f4_eq_i(x4s[2], x2) == 1, "f4_eq_i(x4s[2], x2) == 1", __FILE__, __LINE__);
#else
// line 79 "ST_avmplus_vector_accessors.st"
verifyPass(true, "true", __FILE__, __LINE__);
#endif
}
void ST_avmplus_vector_accessors::test3() {
#ifdef AVMSHELL_BUILD
avmshell::ShellCore* c = (avmshell::ShellCore*)core;
avmshell::ShellToplevel* top = c->shell_toplevel;
IntVectorObject* vec = top->intVectorClass()->newVector();
vec->_setNativeUintProperty(0, 1);
vec->_setNativeUintProperty(1, 1);
vec->_setNativeUintProperty(2, 2);
vec->_setNativeUintProperty(3, 3);
vec->_setNativeUintProperty(4, 5);
vec->_setNativeUintProperty(5, 8);
vec->_setNativeUintProperty(6, 13);
IntVectorAccessor va(vec);
int* xs = va.addr();
// line 102 "ST_avmplus_vector_accessors.st"
verifyPass(xs[0] == 1, "xs[0] == 1", __FILE__, __LINE__);
// line 103 "ST_avmplus_vector_accessors.st"
verifyPass(xs[1] == 1, "xs[1] == 1", __FILE__, __LINE__);
// line 104 "ST_avmplus_vector_accessors.st"
verifyPass(xs[2] == 2, "xs[2] == 2", __FILE__, __LINE__);
// line 105 "ST_avmplus_vector_accessors.st"
verifyPass(xs[3] == 3, "xs[3] == 3", __FILE__, __LINE__);
// line 106 "ST_avmplus_vector_accessors.st"
verifyPass(xs[4] == 5, "xs[4] == 5", __FILE__, __LINE__);
// line 107 "ST_avmplus_vector_accessors.st"
verifyPass(xs[5] == 8, "xs[5] == 8", __FILE__, __LINE__);
// line 108 "ST_avmplus_vector_accessors.st"
verifyPass(xs[6] == 13, "xs[6] == 13", __FILE__, __LINE__);
#else
// line 112 "ST_avmplus_vector_accessors.st"
verifyPass(true, "true", __FILE__, __LINE__);
#endif // AVMSHELL_BUILD
}
void ST_avmplus_vector_accessors::test4() {
#if defined VMCFG_FLOAT && defined AVMSHELL_BUILD
avmshell::ShellCore* c = (avmshell::ShellCore*)core;
avmshell::ShellToplevel* top = c->shell_toplevel;
Float4VectorObject* vec = top->float4VectorClass()->newVector();
float4_t x0 = { 1,1,2,3 };
float4_t x1 = { 5,8,13,21 };
float4_t x2 = { 34,55,89,144 };
vec->_setNativeUintProperty(0, x0);
vec->_setNativeUintProperty(1, x1);
vec->_setNativeUintProperty(2, x2);
Float4VectorAccessor va(vec);
float4_t* x4s = va.addr();
// line 135 "ST_avmplus_vector_accessors.st"
verifyPass(f4_eq_i(x4s[0], x0) == 1, "f4_eq_i(x4s[0], x0) == 1", __FILE__, __LINE__);
// line 136 "ST_avmplus_vector_accessors.st"
verifyPass(f4_eq_i(x4s[1], x1) == 1, "f4_eq_i(x4s[1], x1) == 1", __FILE__, __LINE__);
// line 137 "ST_avmplus_vector_accessors.st"
verifyPass(f4_eq_i(x4s[2], x2) == 1, "f4_eq_i(x4s[2], x2) == 1", __FILE__, __LINE__);
#else
// line 141 "ST_avmplus_vector_accessors.st"
verifyPass(true, "true", __FILE__, __LINE__);
#endif // AVMSHELL_BUILD
}
void create_avmplus_vector_accessors(AvmCore* core) { new ST_avmplus_vector_accessors(core); }
}
}
#endif
// Generated from ST_mmgc_543560.st
// -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*-
// vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
// Bugzilla 543560 - here we risk deleting an object that is still on the mark stack because
// of how we perform large-object splitting. The setup is that user code that deletes the object
// gets to run after the first part of the large object has been popped off the mark stack
// but before the rest has been handled.
#include "avmshell.h"
#ifdef VMCFG_SELFTEST
#if defined AVMPLUS_WIN32
#if !defined VMCFG_ARM
namespace avmplus {
namespace ST_mmgc_bugzilla_543560 {
class ST_mmgc_bugzilla_543560 : public Selftest {
public:
ST_mmgc_bugzilla_543560(AvmCore* core);
virtual void run(int n);
virtual void prologue();
virtual void epilogue();
private:
static const char* ST_names[];
static const bool ST_explicits[];
void test0();
private:
MMgc::GC *gc;
};
ST_mmgc_bugzilla_543560::ST_mmgc_bugzilla_543560(AvmCore* core)
: Selftest(core, "mmgc", "bugzilla_543560", ST_mmgc_bugzilla_543560::ST_names,ST_mmgc_bugzilla_543560::ST_explicits)
{}
const char* ST_mmgc_bugzilla_543560::ST_names[] = {"bugzilla_543560", NULL };
const bool ST_mmgc_bugzilla_543560::ST_explicits[] = {false, false };
void ST_mmgc_bugzilla_543560::run(int n) {
switch(n) {
case 0: test0(); return;
}
}
void ST_mmgc_bugzilla_543560::prologue() {
MMgc::GCConfig config;
gc = new MMgc::GC(MMgc::GCHeap::GetGCHeap(), config);
}
void ST_mmgc_bugzilla_543560::epilogue() {
delete gc;
}
using namespace MMgc;
// allocate a bunch big things
// allocate a bunch of small things ( to pump incremental mark.... )
// explicitly free one of the big things
// ... crash
struct BigThing;
static inline unsigned getSerial()
{
static unsigned g_counter = 0;
unsigned result = g_counter;
++g_counter;
return result;
}
struct BigThing : public MMgc::GCFinalizedObject
{
BigThing() : m_next(0), m_prev(0), m_serial(getSerial())
{
VMPI_memset(&m_data, 0, sizeof(m_data));
}
virtual ~BigThing()
{
//printf("~BigThing: %u 0x%08X 0x%08X\n", m_serial, this, this + 1);
}
GCMember<BigThing> m_next;
GCMember<BigThing> m_prev;
unsigned m_serial;
char m_data[512 * 1024];
};
BigThing* makeBigThings(MMgc::GC* gc, size_t howMany)
{
BigThing* first = 0;
BigThing* curr = 0;
for (unsigned i = 0; i < howMany; ++i) {
BigThing* newThing = new (gc) BigThing();
if (!first) {
first = newThing;
}
else {
curr->m_next = newThing;
newThing->m_prev = curr;
}
curr = newThing;
}
return first;
}
struct SmallThing : public MMgc::GCFinalizedObject
{
char m_data[200];
virtual ~SmallThing()
{
}
};
struct MyRoot : public MMgc::GCRoot
{
MyRoot(MMgc::GC* gc) : MMgc::GCRoot(gc) {}
BigThing* m_bigThings;
};
void ST_mmgc_bugzilla_543560::test0() {
MMGC_GCENTER(gc);
MyRoot* theRoot = 0;
{
BigThing* volatile bigThings = makeBigThings(gc, 400);
theRoot = new MyRoot(gc);
theRoot->m_bigThings = bigThings;
}
BigThing* volatile middle = theRoot->m_bigThings;
for (int j = 0 ; j < 150; ++j)
middle = middle->m_next;
middle->m_prev->m_next = 0;
for (int j = 0; j < 50; ++j)
middle = middle->m_next;
middle->m_prev = 0;
gc->Collect();
gc->Collect();
for (int j = 0; j < 100000; ++j) {
//printf("j: %d\n", j);
for (int i = 0; i < 500; ++i) {
new (gc) SmallThing();
if ((theRoot->m_bigThings) && (MMgc::GC::GetMark(theRoot->m_bigThings))) {
while (theRoot->m_bigThings != 0) {
BigThing* curr = theRoot->m_bigThings;
theRoot->m_bigThings = theRoot->m_bigThings->m_next;
delete curr;
}
MMgc::GCHeap::GetGCHeap()->Decommit();
}
}
}
delete theRoot;
// Will crash if it fails so the %%verify is just token
// line 135 "ST_mmgc_543560.st"
verifyPass(true, "true", __FILE__, __LINE__);
}
void create_mmgc_bugzilla_543560(AvmCore* core) { new ST_mmgc_bugzilla_543560(core); }
}
}
#endif
#endif
#endif
// Generated from ST_mmgc_575631.st
// -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*-
// vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5)
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
// Bugzilla 565631 - We occasionally interleave invoking finalizers
// and clearing mark bits in GCAlloc::Finalize; so a finalizer can
// observe a live object that does not have its mark bit set.
//
// This complicates things because we want to ensure that unmarked
// weakly-referenced objects are resurrected by the GC if the weak
// reference is dereferenced during presweep, but we do not want to
// schedule collection work (or set bits that are supposed to be
// unmarked) during finalization.
//
// (Long term we might want to get rid of the interleaving of
// finalization and mark-bit clearing. Short term, lets just
// try to detect this on our own.)
#include "avmshell.h"
#ifdef VMCFG_SELFTEST
namespace avmplus {
namespace ST_mmgc_bugzilla_575631 {
using namespace MMgc;
// Upon destruction, start reading weak refs of "friends" near and far
class Snoopy : public GCFinalizedObject
{
public:
Snoopy(int key, GCWeakRef** refs, int len)
: key(key), friends(refs), len(len)
{
++alive_count;
}
~Snoopy();
static int alive_count;
private:
int key;
GCWeakRef** friends;
int len;
};
// To take D samples from an array of N elems, walk thru by floor(N/D)
// steps (but avoid the pathological case when the floor is zero).
int compute_stride(int numerator, int denominator)
{
int delta = numerator / denominator;
return (delta > 0) ? delta : 1;
}
class ST_mmgc_bugzilla_575631 : public Selftest {
public:
ST_mmgc_bugzilla_575631(AvmCore* core);
virtual void run(int n);
private:
static const char* ST_names[];
static const bool ST_explicits[];
void test0();
// collecting twice is only "sure" way to gc in presence of incrementality
void collect2() { core->gc->Collect(); core->gc->Collect(); }
};
ST_mmgc_bugzilla_575631::ST_mmgc_bugzilla_575631(AvmCore* core)
: Selftest(core, "mmgc", "bugzilla_575631", ST_mmgc_bugzilla_575631::ST_names,ST_mmgc_bugzilla_575631::ST_explicits)
{}
const char* ST_mmgc_bugzilla_575631::ST_names[] = {"drizzle", NULL };
const bool ST_mmgc_bugzilla_575631::ST_explicits[] = {false, false };
void ST_mmgc_bugzilla_575631::run(int n) {
switch(n) {
case 0: test0(); return;
}
}
/*static*/ int Snoopy::alive_count = 0;
const int arr_len = 1000;
const int lookups_per_destruct = 10;
const int destructs = 10;
Snoopy::~Snoopy()
{
int delta = compute_stride(arr_len, lookups_per_destruct);
for ( int i = 1 ; i < arr_len ; i += delta ) {
int idx = (key + i) % len;
// printf("referencing ref[%d] from Snoopy(%d)\n", idx, key);
friends[idx]->get();
}
--alive_count;
}
void ST_mmgc_bugzilla_575631::test0() {
{
GC* gc = core->gc;
Snoopy* objs[arr_len];
GCWeakRef* refs[arr_len];
// initial setup:
for (int i=0 ; i < arr_len; ++i ) {
objs[i] = new (gc) Snoopy(i, refs, arr_len);
refs[i] = objs[i]->GetWeakRef();
}
collect2();
int delta = compute_stride(arr_len, destructs);
for (int i=0; i < arr_len; i += delta) {
objs[i] = NULL;
collect2();
}
// not assert failing within get() is passing the test.
// line 99 "ST_mmgc_575631.st"
verifyPass(1, "1", __FILE__, __LINE__);
; // (make my auto-indenter happy)
// cleanup code; letting ~Snoopy occur outside test extent is big no-no.
{
for (int i=0; i < arr_len; ++i ) {
if (! refs[i]->isNull())
delete objs[i];
}
// if something went wrong above and some Snoopy's are still alive,
// we'll get burned during their destructors. Make sure that
// does not happen.
// line 112 "ST_mmgc_575631.st"
verifyPass((Snoopy::alive_count == 0), "(Snoopy::alive_count == 0)", __FILE__, __LINE__);
;
}
}
}
void create_mmgc_bugzilla_575631(AvmCore* core) { new ST_mmgc_bugzilla_575631(core); }
}
}
#endif
// Generated from ST_mmgc_580603.st
// -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*-
// vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
// Bugzilla 580603 - adversarial mmgc: dispersive w.r.t. address space
// Bugzilla 445780 - Page map needs to be sparse
//
// Tommy: "problems in 64-bit linux b/c VMPI_allocateAlignedMemory provides
// memory from low 32 bit-addresses, and mmap is giving us addresses from
// 0x7fxxxxxxxxxxxxxx so we need a 4 GB page map."
//
// This self-test attempts to replicate the problem described above
// (by coordinating with an adversarial gcheap) thus illustrating the
// need for a sparse page map.
#include "avmshell.h"
#ifdef VMCFG_SELFTEST
#if defined AVMPLUS_64BIT && defined DEBUG
namespace avmplus {
namespace ST_mmgc_bugzilla_580603 {
using namespace MMgc;
class ST_mmgc_bugzilla_580603 : public Selftest {
public:
ST_mmgc_bugzilla_580603(AvmCore* core);
virtual void run(int n);
virtual void prologue();
virtual void epilogue();
private:
static const char* ST_names[];
static const bool ST_explicits[];
void test0();
void test1();
GC *gc;
GCHeap *heap;
size_t saved_dispersiveAdversarial;
size_t saved_heapLimit;
char *min_addr;
char *max_start;
char *max_addr;
size_t min_size;
size_t max_size;
static const int m_num_sizes = 17;
static const int m_num_iters = 2;
static const int m_init_size = 16;
static const int m_dfactor = 2;
void print_minmax()
{
intptr_t delta = max_addr - min_addr;
intptr_t v = delta;
unsigned r = 0; // r will be floor(log_2(v))
while (v >>= 1)
r++;
printf("min_size: 0x%15lx max_size: 0x%15lx\n",
(unsigned long)min_size, (unsigned long)max_size);
printf("min_addr: 0x%15lx max_addr: 0x%15lx delta:% 15ld (>= 2^%u)\n",
(unsigned long)min_addr, (unsigned long)max_addr, delta, r);
fflush(NULL);
}
enum alloc_method_t { via_gc, via_heap };
const char* method_string(alloc_method_t m)
{
switch (m) {
case via_gc: return "via_gc";
case via_heap: return "via_heap";
default: return 0;
}
}
char *my_alloc(size_t size, alloc_method_t m)
{
char *ret;
// Took heap-zeroing and heap-profiling out of flags;
// avoid wasting time mapping in memory to initialize to 0.
int heapFlags = (MMgc::GCHeap::kExpand);
size_t sizeInPages = (size+(GCHeap::kBlockSize-1))/GCHeap::kBlockSize;
switch (m) {
case via_gc: ret = (char*)gc->Alloc(size); break;
case via_heap:
ret = (char*)heap->Alloc(sizeInPages, heapFlags);
break;
default: ret = 0; break;
}
if (size < min_size)
min_size = size;
if (size > max_size)
max_size = size;
if (ret < min_addr)
min_addr = ret;
if (ret > max_start)
max_start = ret;
if (ret+size > max_addr)
max_addr = ret+size;
// printf("my_alloc(%10ld, %10s) => %p\n", size, method_string(m), ret);
// fflush(NULL);
return ret;
}
void my_free(char *p, alloc_method_t m)
{
switch (m) {
case via_gc: gc->Free(p); return;
case via_heap: heap->FreeNoProfile(p); return;
default: AvmAssert(p == 0); return;
}
}
// fills recv[] with the addresses of a series of N allocated and
// freed blocks, where N = (m_num_iters * m_num_sizes).
//
// For each iteration:
//
// 1. allocate m_num_sizes blocks of distinct (and exponentially
// growing) size.
// 2. after finishing the allocations from (1.), free the blocks
// allocated in the *previous* iteration.
//
// The intention is to allocate blocks covering a wide range of
// sizes in order to tickle the memory subsystem's ability to
// track blocks of different sizes. Keeping each iteration's
// blocks alive across the next iteration is meant to ensure
// that the set of allocated addresses have many wide gaps,
// stressing the memory subsystem's ability to represent
// the meta-data for disparately allocated ranges.
//
// The loop attempts to keep the block sizes distinct both within any
// particular iteration (the exponential growth) and also across the
// distinct iterations. This was an artifact of trying to force the
// memory subsystem to be unable to return back blocks that had been
// previously freed. It may or may not still be necessary with the
// addition of the dispersiveAdversarial gcheap config mode; it does
// not seem to hurt the effectiveness of this test, since one can
// observe OOM failures when using PageMap::Uniform using this test;
// see notes in prologue code below.
void do_allocs(char **recv, alloc_method_t m)
{
size_t init = m_init_size;
int num_iters = m_num_iters;
int num_sizes = m_num_sizes;
int dfactor = m_dfactor;
for (int j=num_iters-1; j >= 0; j--) {
for (int i=0, factor=1; i < num_sizes; i++, factor*=dfactor) {
size_t size = factor*init+num_iters-j;
// size_t size = factor*init;
char *result = my_alloc(size, m);
recv[j*num_sizes+i] = result;
}
if (j < num_iters - 1) {
for (int i=0; i < num_sizes; i++) {
my_free(recv[(j+1)*num_sizes+i], m);
}
}
}
for (int i=0; i < num_sizes; i++) {
my_free(recv[0*num_sizes+i], m);
}
}
};
ST_mmgc_bugzilla_580603::ST_mmgc_bugzilla_580603(AvmCore* core)
: Selftest(core, "mmgc", "bugzilla_580603", ST_mmgc_bugzilla_580603::ST_names,ST_mmgc_bugzilla_580603::ST_explicits)
{}
const char* ST_mmgc_bugzilla_580603::ST_names[] = {"alloc_loop_mmgc_viaheap_far","alloc_loop_mmgc_viagc_far", NULL };
const bool ST_mmgc_bugzilla_580603::ST_explicits[] = {false,false, false };
void ST_mmgc_bugzilla_580603::run(int n) {
switch(n) {
case 0: test0(); return;
case 1: test1(); return;
}
}