1// PR rtl-optimization/56999
2// { dg-do run }
3// { dg-options "-O2" }
4// { dg-additional-options "-fpic" { target fpic } }
5// { dg-additional-options "-march=i686 -mtune=atom" { target ia32 } }
6// { dg-require-visibility "" }
7
8extern "C" void abort (void);
9extern "C" void exit (int);
10volatile bool do_exit = true;
11struct JSScript;
12struct JITScript { int i; };
13#pragma GCC visibility push(hidden)
14typedef struct JSCompartment JSCompartment;
15typedef struct JSContext JSContext;
16namespace js
17{
18  struct ContextFriendFields
19  {
20    JSCompartment *compartment;
21  };
22  struct TempAllocPolicy
23  {
24  };
25  template <class T>
26  struct Vector
27  {
28    T *mBegin;
29    T *begin () { return mBegin; }
30    T & operator[] (unsigned i) { return begin ()[i]; }
31    template <class U>
32    __attribute__((noinline, noclone))
33    bool append (U) { asm volatile ("" : : : "memory"); if (do_exit) abort (); return false; }
34  };
35  namespace types
36  {
37    struct TypeCompartment;
38  }
39  namespace mjit
40  {
41  }
42  namespace ion
43  {
44    struct IonScript;
45  }
46  namespace types
47  {
48    struct CompilerOutput
49    {
50      enum Kind { MethodJIT, ParallelIon };
51      JSScript *script;
52      unsigned kindInt : 2;
53      bool constructing : 1;
54      bool barriers : 1;
55      bool pendingRecompilation : 1;
56      Kind kind () const { return static_cast <Kind> (kindInt); }
57      bool isValid () const;
58    };
59    struct RecompileInfo
60    {
61      unsigned outputIndex;
62      CompilerOutput *compilerOutput (TypeCompartment & types) const;
63      CompilerOutput *compilerOutput (JSContext *cx) const;
64    };
65    struct TypeCompartment
66    {
67      Vector <CompilerOutput> *constrainedOutputs;
68      Vector <RecompileInfo> *pendingRecompiles;
69      void addPendingRecompile (JSContext *cx, const RecompileInfo & info);
70    };
71  }
72}
73struct JSScript
74{
75  struct JITScriptHandle
76  {
77    static volatile JITScript *UNJITTABLE __attribute__((visibility ("default")));
78    JITScript *value;
79    bool isValid () { return value != UNJITTABLE; }
80    JITScript *getValid () { return value; }
81  };
82  struct JITScriptSet
83  {
84    JITScriptHandle jitHandleNormal, jitHandleNormalBarriered;
85    JITScriptHandle jitHandleCtor, jitHandleCtorBarriered;
86    JITScriptHandle jitNull1, jitNull2;
87  };
88  JITScriptSet *mJITInfo;
89  void *ion;
90  JITScriptHandle *jitHandle (bool constructing, bool barriers)
91  {
92    return constructing ? (barriers ? &mJITInfo->jitHandleCtorBarriered
93				    : &mJITInfo->jitHandleCtor)
94			: (barriers ? &mJITInfo->jitHandleNormalBarriered
95				    : &mJITInfo->jitHandleNormal);
96  }
97  JITScript *getJIT (bool constructing, bool barriers)
98  {
99    JITScriptHandle *jith = jitHandle (constructing, barriers);
100    return jith->isValid () ? jith->getValid () : __null;
101  }
102};
103struct JSContext : js::ContextFriendFields
104{
105};
106namespace js
107{
108  __attribute__((noinline, noclone))
109  void CancelOffThreadIonCompile (JSCompartment *, JSScript *)
110  {
111    if (do_exit)
112      exit (0);
113  }
114}
115struct JSCompartment
116{
117  js::types::TypeCompartment types;
118};
119namespace js
120{
121  namespace types
122  {
123    inline bool CompilerOutput::isValid () const
124    {
125      if (!script)
126	return false;
127      switch (kind ())
128	{
129	case MethodJIT:
130	  {
131	    JITScript *jit = script->getJIT (constructing, barriers);
132	    if (!jit)
133	      return false;
134	  }
135	case ParallelIon:
136	  return true;
137	}
138      return false;
139    }
140    inline CompilerOutput *RecompileInfo::compilerOutput (TypeCompartment & types) const
141    {
142      return &(*types.constrainedOutputs)[outputIndex];
143    }
144    inline CompilerOutput *RecompileInfo::compilerOutput (JSContext *cx) const
145    {
146      return compilerOutput (cx->compartment->types);
147    }
148  }
149}
150using namespace js::types;
151__attribute__((noinline, noclone)) void
152TypeCompartment::addPendingRecompile (JSContext *cx, const RecompileInfo & info)
153{
154  CompilerOutput *co = info.compilerOutput (cx);
155  if (co->pendingRecompilation)
156    if (co->isValid ())
157      CancelOffThreadIonCompile (cx->compartment, co->script);
158  if (co->isValid ())
159    pendingRecompiles->append (info);
160}
161volatile JITScript *JSScript::JITScriptHandle::UNJITTABLE;
162#pragma GCC visibility pop
163int
164main ()
165{
166  JSContext cx;
167  JSCompartment com;
168  RecompileInfo info;
169  cx.compartment = &com;
170  info.outputIndex = 0;
171  js::Vector<CompilerOutput> v;
172  JITScript js;
173  JSScript::JITScriptSet set;
174  __builtin_memset (&set, 0, sizeof set);
175  set.jitHandleCtor.value = &js;
176  JSScript s;
177  s.mJITInfo = &set;
178  CompilerOutput co;
179  co.kindInt = 0;
180  co.constructing = true;
181  co.barriers = false;
182  co.pendingRecompilation = true;
183  co.script = &s;
184  v.mBegin = &co;
185  com.types.constrainedOutputs = &v;
186  com.types.pendingRecompiles = __null;
187  com.types.addPendingRecompile (&cx, info);
188  abort ();
189}
190