mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 710032 - CollectNativeRegions() utility to simplify handling of inlined frames. r=bhackett
--HG-- extra : rebase_source : 310d2cc0b58bad53d07e09924ae4d37762542457
This commit is contained in:
parent
3d50ba406c
commit
dc03ae210d
@ -55,6 +55,10 @@
|
||||
#include "jsscript.h"
|
||||
#include "jsstr.h"
|
||||
|
||||
#ifdef JS_METHODJIT
|
||||
# include "methodjit/Compiler.h"
|
||||
#endif
|
||||
|
||||
#include "jsobjinlines.h"
|
||||
|
||||
#define TYPEOF(cx,v) (JSVAL_IS_NULL(v) ? JSTYPE_NULL : JS_TypeOfValue(cx,v))
|
||||
@ -114,16 +118,115 @@ Probes::JITGranularityRequested()
|
||||
return want;
|
||||
}
|
||||
|
||||
/*
|
||||
* Flatten the tree of inlined frames into a series of native code regions, one
|
||||
* for each contiguous section of native code that belongs to a single
|
||||
* ActiveFrame. (Note that some of these regions may be zero-length, for
|
||||
* example if two ActiveFrames end at the same place.)
|
||||
*/
|
||||
typedef mjit::Compiler::ActiveFrame ActiveFrame;
|
||||
|
||||
bool
|
||||
Probes::JITWatcher::CollectNativeRegions(RegionVector ®ions,
|
||||
JSRuntime *rt,
|
||||
mjit::JITScript *jit,
|
||||
mjit::JSActiveFrame *outerFrame,
|
||||
mjit::JSActiveFrame **inlineFrames)
|
||||
{
|
||||
regions.resize(jit->nInlineFrames * 2 + 2);
|
||||
|
||||
mjit::JSActiveFrame **stack =
|
||||
rt->array_new<mjit::JSActiveFrame*>(jit->nInlineFrames+2);
|
||||
if (!stack)
|
||||
return false;
|
||||
uint32_t depth = 0;
|
||||
uint32_t ip = 0;
|
||||
|
||||
stack[depth++] = NULL;
|
||||
stack[depth++] = outerFrame;
|
||||
regions[0].frame = outerFrame;
|
||||
regions[0].script = outerFrame->script;
|
||||
regions[0].pc = outerFrame->script->code;
|
||||
regions[0].enter = true;
|
||||
ip++;
|
||||
|
||||
for (uint32_t i = 0; i <= jit->nInlineFrames; i++) {
|
||||
mjit::JSActiveFrame *frame = (i < jit->nInlineFrames) ? inlineFrames[i] : outerFrame;
|
||||
|
||||
// Not a down frame; pop the current frame, then pop until we reach
|
||||
// this frame's parent, recording subframe ends as we go
|
||||
while (stack[depth-1] != frame->parent) {
|
||||
depth--;
|
||||
JS_ASSERT(depth > 0);
|
||||
// Pop up from regions[ip-1].frame to top of the stack: start a
|
||||
// region in the destination frame and close off the source
|
||||
// (origin) frame at the end of its script
|
||||
mjit::JSActiveFrame *src = regions[ip-1].frame;
|
||||
mjit::JSActiveFrame *dst = stack[depth-1];
|
||||
JS_ASSERT_IF(!dst, i == jit->nInlineFrames);
|
||||
regions[ip].frame = dst;
|
||||
regions[ip].script = dst ? dst->script : NULL;
|
||||
regions[ip].pc = src->parentPC + 1;
|
||||
regions[ip-1].endpc = src->script->code + src->script->length;
|
||||
regions[ip].enter = false;
|
||||
ip++;
|
||||
}
|
||||
|
||||
if (i < jit->nInlineFrames) {
|
||||
// Push a frame (enter an inlined function). Start a region at the
|
||||
// beginning of the new frame's script, and end the previous region
|
||||
// at parentPC.
|
||||
stack[depth++] = frame;
|
||||
|
||||
regions[ip].frame = frame;
|
||||
regions[ip].script = frame->script;
|
||||
regions[ip].pc = frame->script->code;
|
||||
regions[ip-1].endpc = frame->parentPC;
|
||||
regions[ip].enter = true;
|
||||
ip++;
|
||||
}
|
||||
}
|
||||
|
||||
// Final region is always zero-length and not particularly useful
|
||||
ip--;
|
||||
regions.popBack();
|
||||
|
||||
mjit::JSActiveFrame *prev = NULL;
|
||||
for (NativeRegion *iter = regions.begin(); iter != regions.end(); ++iter) {
|
||||
mjit::JSActiveFrame *frame = iter->frame;
|
||||
if (iter->enter) {
|
||||
// Pushing down a frame, so region starts at the beginning of the
|
||||
// (destination) frame
|
||||
iter->mainOffset = frame->mainCodeStart;
|
||||
iter->stubOffset = frame->stubCodeStart;
|
||||
} else {
|
||||
// Popping up a level, so region starts at the end of the (source) frame
|
||||
iter->mainOffset = prev->mainCodeEnd;
|
||||
iter->stubOffset = prev->stubCodeEnd;
|
||||
}
|
||||
prev = frame;
|
||||
}
|
||||
|
||||
JS_ASSERT(ip == 2 * jit->nInlineFrames + 1);
|
||||
rt->array_delete(stack);
|
||||
|
||||
// All of the stub code comes immediately after the main code
|
||||
for (NativeRegion *iter = regions.begin(); iter != regions.end(); ++iter)
|
||||
iter->stubOffset += outerFrame->mainCodeEnd;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef JS_METHODJIT
|
||||
void
|
||||
Probes::registerMJITCode(JSContext *cx, js::mjit::JITScript *jscr,
|
||||
JSScript *script, JSFunction *fun,
|
||||
js::mjit::Compiler_ActiveFrame **inlineFrames,
|
||||
js::mjit::JSActiveFrame *outerFrame,
|
||||
js::mjit::JSActiveFrame **inlineFrames,
|
||||
void *mainCodeAddress, size_t mainCodeSize,
|
||||
void *stubCodeAddress, size_t stubCodeSize)
|
||||
{
|
||||
for (JITWatcher **p = jitWatchers.begin(); p != jitWatchers.end(); ++p)
|
||||
(*p)->registerMJITCode(cx, jscr, script, fun,
|
||||
(*p)->registerMJITCode(cx, jscr, outerFrame,
|
||||
inlineFrames,
|
||||
mainCodeAddress, mainCodeSize,
|
||||
stubCodeAddress, stubCodeSize);
|
||||
|
@ -52,7 +52,7 @@ namespace js {
|
||||
|
||||
namespace mjit {
|
||||
struct NativeAddressInfo;
|
||||
struct Compiler_ActiveFrame;
|
||||
struct JSActiveFrame;
|
||||
}
|
||||
|
||||
namespace Probes {
|
||||
@ -230,12 +230,31 @@ enum JITReportGranularity {
|
||||
*/
|
||||
class JITWatcher {
|
||||
public:
|
||||
struct NativeRegion {
|
||||
mjit::JSActiveFrame *frame;
|
||||
JSScript *script;
|
||||
size_t inlinedOffset;
|
||||
jsbytecode *pc;
|
||||
jsbytecode *endpc;
|
||||
uintptr_t mainOffset;
|
||||
uintptr_t stubOffset;
|
||||
bool enter;
|
||||
};
|
||||
|
||||
typedef Vector<NativeRegion, 0, RuntimeAllocPolicy> RegionVector;
|
||||
|
||||
static bool CollectNativeRegions(RegionVector ®ions,
|
||||
JSRuntime *rt,
|
||||
mjit::JITScript *jit,
|
||||
mjit::JSActiveFrame *outerFrame,
|
||||
mjit::JSActiveFrame **inlineFrames);
|
||||
|
||||
virtual JITReportGranularity granularityRequested() = 0;
|
||||
|
||||
#ifdef JS_METHODJIT
|
||||
virtual void registerMJITCode(JSContext *cx, js::mjit::JITScript *jscr,
|
||||
JSScript *script, JSFunction *fun,
|
||||
mjit::Compiler_ActiveFrame** inlineFrames,
|
||||
mjit::JSActiveFrame *outerFrame,
|
||||
mjit::JSActiveFrame **inlineFrames,
|
||||
void *mainCodeAddress, size_t mainCodeSize,
|
||||
void *stubCodeAddress, size_t stubCodeSize) = 0;
|
||||
|
||||
@ -282,8 +301,8 @@ JITGranularityRequested();
|
||||
*/
|
||||
void
|
||||
registerMJITCode(JSContext *cx, js::mjit::JITScript *jscr,
|
||||
JSScript *script, JSFunction *fun,
|
||||
mjit::Compiler_ActiveFrame** inlineFrames,
|
||||
mjit::JSActiveFrame *outerFrame,
|
||||
mjit::JSActiveFrame **inlineFrames,
|
||||
void *mainCodeAddress, size_t mainCodeSize,
|
||||
void *stubCodeAddress, size_t stubCodeSize);
|
||||
|
||||
|
@ -486,8 +486,10 @@ void
|
||||
mjit::Compiler::popActiveFrame()
|
||||
{
|
||||
JS_ASSERT(a->parent);
|
||||
a->mainCodeEnd = masm.size();
|
||||
a->stubCodeEnd = stubcc.size();
|
||||
this->PC = a->parentPC;
|
||||
this->a = a->parent;
|
||||
this->a = (ActiveFrame *) a->parent;
|
||||
this->script = a->script;
|
||||
this->analysis = this->script->analysis();
|
||||
|
||||
@ -551,9 +553,14 @@ mjit::Compiler::performCompilation(JITScript **jitp)
|
||||
|
||||
#undef CHECK_STATUS
|
||||
|
||||
mjit::JSActiveFrame::JSActiveFrame()
|
||||
: parent(NULL), parentPC(NULL), script(NULL), inlineIndex(UINT32_MAX)
|
||||
{
|
||||
}
|
||||
|
||||
mjit::Compiler::ActiveFrame::ActiveFrame(JSContext *cx)
|
||||
: parent(NULL), parentPC(NULL), script(NULL), jumpMap(NULL),
|
||||
inlineIndex(UINT32_MAX), varTypes(NULL), needReturnValue(false),
|
||||
: jumpMap(NULL),
|
||||
varTypes(NULL), needReturnValue(false),
|
||||
syncReturnValue(false), returnValueDouble(false), returnSet(false),
|
||||
returnEntry(NULL), returnJumps(NULL), exitState(NULL)
|
||||
{}
|
||||
@ -922,6 +929,9 @@ mjit::Compiler::finishThisUp(JITScript **jitp)
|
||||
return Compile_Abort;
|
||||
}
|
||||
|
||||
a->mainCodeEnd = masm.size();
|
||||
a->stubCodeEnd = stubcc.size();
|
||||
|
||||
for (size_t i = 0; i < branchPatches.length(); i++) {
|
||||
Label label = labelOf(branchPatches[i].pc, branchPatches[i].inlineIndex);
|
||||
branchPatches[i].jump.linkTo(label, &masm);
|
||||
@ -1385,8 +1395,9 @@ mjit::Compiler::finishThisUp(JITScript **jitp)
|
||||
JSC::ExecutableAllocator::makeExecutable(result, masm.size() + stubcc.size());
|
||||
JSC::ExecutableAllocator::cacheFlush(result, masm.size() + stubcc.size());
|
||||
|
||||
Probes::registerMJITCode(cx, jit, script, script->function() ? script->function() : NULL,
|
||||
(mjit::Compiler_ActiveFrame**) inlineFrames.begin(),
|
||||
Probes::registerMJITCode(cx, jit,
|
||||
a,
|
||||
(JSActiveFrame**) inlineFrames.begin(),
|
||||
result, masm.size(),
|
||||
result + masm.size(), stubcc.size());
|
||||
|
||||
|
@ -62,6 +62,27 @@ struct InvariantCodePatch {
|
||||
InvariantCodePatch() : hasPatch(false) {}
|
||||
};
|
||||
|
||||
struct JSActiveFrame {
|
||||
JSActiveFrame *parent;
|
||||
jsbytecode *parentPC;
|
||||
JSScript *script;
|
||||
|
||||
/*
|
||||
* Index into inlineFrames or OUTER_FRAME, matches this frame's index in
|
||||
* the cross script SSA.
|
||||
*/
|
||||
uint32_t inlineIndex;
|
||||
|
||||
/* JIT code generation tracking state */
|
||||
size_t mainCodeStart;
|
||||
size_t stubCodeStart;
|
||||
size_t mainCodeEnd;
|
||||
size_t stubCodeEnd;
|
||||
size_t inlinePCOffset;
|
||||
|
||||
JSActiveFrame();
|
||||
};
|
||||
|
||||
class Compiler : public BaseCompiler
|
||||
{
|
||||
friend class StubCompiler;
|
||||
@ -355,26 +376,12 @@ class Compiler : public BaseCompiler
|
||||
*/
|
||||
|
||||
public:
|
||||
struct ActiveFrame {
|
||||
ActiveFrame *parent;
|
||||
jsbytecode *parentPC;
|
||||
JSScript *script;
|
||||
struct ActiveFrame : public JSActiveFrame {
|
||||
Label *jumpMap;
|
||||
|
||||
/*
|
||||
* Index into inlineFrames or OUTER_FRAME, matches this frame's index
|
||||
* in the cross script SSA.
|
||||
*/
|
||||
uint32_t inlineIndex;
|
||||
|
||||
/* Current types for non-escaping vars in the script. */
|
||||
VarType *varTypes;
|
||||
|
||||
/* JIT code generation tracking state */
|
||||
size_t mainCodeStart;
|
||||
size_t stubCodeStart;
|
||||
size_t inlinePCOffset;
|
||||
|
||||
/* State for managing return from inlined frames. */
|
||||
bool needReturnValue; /* Return value will be used. */
|
||||
bool syncReturnValue; /* Return value should be fully synced. */
|
||||
@ -470,7 +477,7 @@ private:
|
||||
return PC;
|
||||
ActiveFrame *scan = a;
|
||||
while (scan && scan->parent != outer)
|
||||
scan = scan->parent;
|
||||
scan = static_cast<ActiveFrame *>(scan->parent);
|
||||
return scan->parentPC;
|
||||
}
|
||||
|
||||
@ -491,7 +498,7 @@ private:
|
||||
while (na->parent) {
|
||||
if (na->exitState)
|
||||
return true;
|
||||
na = na->parent;
|
||||
na = static_cast<ActiveFrame *>(na->parent);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user