// PR rtl-optimization/56999 // { dg-do run } // { dg-options "-O2" } // { dg-additional-options "-fpic" { target fpic } } // { dg-additional-options "-march=i686 -mtune=atom" { target ia32 } } // { dg-require-visibility "" } extern "C" void abort (void); extern "C" void exit (int); volatile bool do_exit = true; struct JSScript; struct JITScript { int i; }; #pragma GCC visibility push(hidden) typedef struct JSCompartment JSCompartment; typedef struct JSContext JSContext; namespace js { struct ContextFriendFields { JSCompartment *compartment; }; struct TempAllocPolicy { }; template struct Vector { T *mBegin; T *begin () { return mBegin; } T & operator[] (unsigned i) { return begin ()[i]; } template __attribute__((noinline, noclone)) bool append (U) { asm volatile ("" : : : "memory"); if (do_exit) abort (); return false; } }; namespace types { struct TypeCompartment; } namespace mjit { } namespace ion { struct IonScript; } namespace types { struct CompilerOutput { enum Kind { MethodJIT, ParallelIon }; JSScript *script; unsigned kindInt : 2; bool constructing : 1; bool barriers : 1; bool pendingRecompilation : 1; Kind kind () const { return static_cast (kindInt); } bool isValid () const; }; struct RecompileInfo { unsigned outputIndex; CompilerOutput *compilerOutput (TypeCompartment & types) const; CompilerOutput *compilerOutput (JSContext *cx) const; }; struct TypeCompartment { Vector *constrainedOutputs; Vector *pendingRecompiles; void addPendingRecompile (JSContext *cx, const RecompileInfo & info); }; } } struct JSScript { struct JITScriptHandle { static volatile JITScript *UNJITTABLE __attribute__((visibility ("default"))); JITScript *value; bool isValid () { return value != UNJITTABLE; } JITScript *getValid () { return value; } }; struct JITScriptSet { JITScriptHandle jitHandleNormal, jitHandleNormalBarriered; JITScriptHandle jitHandleCtor, jitHandleCtorBarriered; JITScriptHandle jitNull1, jitNull2; }; JITScriptSet *mJITInfo; void *ion; JITScriptHandle *jitHandle (bool constructing, bool barriers) { return constructing ? (barriers ? &mJITInfo->jitHandleCtorBarriered : &mJITInfo->jitHandleCtor) : (barriers ? &mJITInfo->jitHandleNormalBarriered : &mJITInfo->jitHandleNormal); } JITScript *getJIT (bool constructing, bool barriers) { JITScriptHandle *jith = jitHandle (constructing, barriers); return jith->isValid () ? jith->getValid () : __null; } }; struct JSContext : js::ContextFriendFields { }; namespace js { __attribute__((noinline, noclone)) void CancelOffThreadIonCompile (JSCompartment *, JSScript *) { if (do_exit) exit (0); } } struct JSCompartment { js::types::TypeCompartment types; }; namespace js { namespace types { inline bool CompilerOutput::isValid () const { if (!script) return false; switch (kind ()) { case MethodJIT: { JITScript *jit = script->getJIT (constructing, barriers); if (!jit) return false; } case ParallelIon: return true; } return false; } inline CompilerOutput *RecompileInfo::compilerOutput (TypeCompartment & types) const { return &(*types.constrainedOutputs)[outputIndex]; } inline CompilerOutput *RecompileInfo::compilerOutput (JSContext *cx) const { return compilerOutput (cx->compartment->types); } } } using namespace js::types; __attribute__((noinline, noclone)) void TypeCompartment::addPendingRecompile (JSContext *cx, const RecompileInfo & info) { CompilerOutput *co = info.compilerOutput (cx); if (co->pendingRecompilation) if (co->isValid ()) CancelOffThreadIonCompile (cx->compartment, co->script); if (co->isValid ()) pendingRecompiles->append (info); } volatile JITScript *JSScript::JITScriptHandle::UNJITTABLE; #pragma GCC visibility pop int main () { JSContext cx; JSCompartment com; RecompileInfo info; cx.compartment = &com; info.outputIndex = 0; js::Vector v; JITScript js; JSScript::JITScriptSet set; __builtin_memset (&set, 0, sizeof set); set.jitHandleCtor.value = &js; JSScript s; s.mJITInfo = &set; CompilerOutput co; co.kindInt = 0; co.constructing = true; co.barriers = false; co.pendingRecompilation = true; co.script = &s; v.mBegin = &co; com.types.constrainedOutputs = &v; com.types.pendingRecompiles = __null; com.types.addPendingRecompile (&cx, info); abort (); }