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