blob: 8d89ffa16944b7d5cda8da17b54e6ec27b2b530e [file] [log] [blame]
// 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 <class T>
struct Vector
{
T *mBegin;
T *begin () { return mBegin; }
T & operator[] (unsigned i) { return begin ()[i]; }
template <class U>
__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 <Kind> (kindInt); }
bool isValid () const;
};
struct RecompileInfo
{
unsigned outputIndex;
CompilerOutput *compilerOutput (TypeCompartment & types) const;
CompilerOutput *compilerOutput (JSContext *cx) const;
};
struct TypeCompartment
{
Vector <CompilerOutput> *constrainedOutputs;
Vector <RecompileInfo> *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<CompilerOutput> 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 ();
}