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 
8 extern "C" void abort (void);
9 extern "C" void exit (int);
10 volatile bool do_exit = true;
11 struct JSScript;
12 struct JITScript { int i; };
13 #pragma GCC visibility push(hidden)
14 typedef struct JSCompartment JSCompartment;
15 typedef struct JSContext JSContext;
16 namespace 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;
beginVector29     T *begin () { return mBegin; }
30     T & operator[] (unsigned i) { return begin ()[i]; }
31     template <class U>
32     __attribute__((noinline, noclone))
appendVector33     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;
kindCompilerOutput56       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 }
73 struct JSScript
74 {
75   struct JITScriptHandle
76   {
77     static volatile JITScript *UNJITTABLE __attribute__((visibility ("default")));
78     JITScript *value;
isValidJSScript::JITScriptHandle79     bool isValid () { return value != UNJITTABLE; }
getValidJSScript::JITScriptHandle80     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;
jitHandleJSScript90   JITScriptHandle *jitHandle (bool constructing, bool barriers)
91   {
92     return constructing ? (barriers ? &mJITInfo->jitHandleCtorBarriered
93 				    : &mJITInfo->jitHandleCtor)
94 			: (barriers ? &mJITInfo->jitHandleNormalBarriered
95 				    : &mJITInfo->jitHandleNormal);
96   }
getJITJSScript97   JITScript *getJIT (bool constructing, bool barriers)
98   {
99     JITScriptHandle *jith = jitHandle (constructing, barriers);
100     return jith->isValid () ? jith->getValid () : __null;
101   }
102 };
103 struct JSContext : js::ContextFriendFields
104 {
105 };
106 namespace js
107 {
108   __attribute__((noinline, noclone))
CancelOffThreadIonCompile(JSCompartment *,JSScript *)109   void CancelOffThreadIonCompile (JSCompartment *, JSScript *)
110   {
111     if (do_exit)
112       exit (0);
113   }
114 }
115 struct JSCompartment
116 {
117   js::types::TypeCompartment types;
118 };
119 namespace js
120 {
121   namespace types
122   {
isValid()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     }
compilerOutput(TypeCompartment & types)140     inline CompilerOutput *RecompileInfo::compilerOutput (TypeCompartment & types) const
141     {
142       return &(*types.constrainedOutputs)[outputIndex];
143     }
compilerOutput(JSContext * cx)144     inline CompilerOutput *RecompileInfo::compilerOutput (JSContext *cx) const
145     {
146       return compilerOutput (cx->compartment->types);
147     }
148   }
149 }
150 using namespace js::types;
151 __attribute__((noinline, noclone)) void
addPendingRecompile(JSContext * cx,const RecompileInfo & info)152 TypeCompartment::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 }
161 volatile JITScript *JSScript::JITScriptHandle::UNJITTABLE;
162 #pragma GCC visibility pop
163 int
main()164 main ()
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