зеркало из https://github.com/mozilla/gecko-dev.git
Clean up exec pool and LinkBuffer use (bug 601041, r=dmandelin).
This commit is contained in:
Родитель
46880287d4
Коммит
28a60376f5
|
@ -67,7 +67,7 @@ public:
|
|||
// m_code uses m_executablePool, *not* executablePool, since this is no longer valid.
|
||||
LinkBuffer(MacroAssembler* masm, ExecutablePool* executablePool)
|
||||
: m_executablePool(executablePool)
|
||||
, m_code(masm->m_assembler.executableCopy(m_executablePool))
|
||||
, m_code(executableCopy(*masm, executablePool))
|
||||
, m_size(masm->m_assembler.size())
|
||||
#ifndef NDEBUG
|
||||
, m_completed(false)
|
||||
|
@ -75,6 +75,16 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
LinkBuffer()
|
||||
: m_executablePool(NULL)
|
||||
, m_code(NULL)
|
||||
, m_size(0)
|
||||
#ifndef NDEBUG
|
||||
, m_completed(false)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
LinkBuffer(uint8* ncode, size_t size)
|
||||
: m_executablePool(NULL)
|
||||
, m_code(ncode)
|
||||
|
@ -179,7 +189,7 @@ public:
|
|||
return CodeLocationLabel(code());
|
||||
}
|
||||
|
||||
private:
|
||||
protected:
|
||||
// Keep this private! - the underlying code should only be obtained externally via
|
||||
// finalizeCode() or finalizeCodeAddendum().
|
||||
void* code()
|
||||
|
@ -187,6 +197,11 @@ private:
|
|||
return m_code;
|
||||
}
|
||||
|
||||
void *executableCopy(MacroAssembler &masm, ExecutablePool *pool)
|
||||
{
|
||||
return masm.m_assembler.executableCopy(pool);
|
||||
}
|
||||
|
||||
void performFinalization()
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
|
|
|
@ -244,7 +244,7 @@ namespace mjit {
|
|||
|
||||
struct ThreadData
|
||||
{
|
||||
JSC::ExecutableAllocator *execPool;
|
||||
JSC::ExecutableAllocator *execAlloc;
|
||||
|
||||
// Trampolines for JIT code.
|
||||
Trampolines trampolines;
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
#include "jstl.h"
|
||||
#include "assembler/assembler/MacroAssemblerCodeRef.h"
|
||||
#include "assembler/assembler/MacroAssembler.h"
|
||||
#include "assembler/assembler/RepatchBuffer.h"
|
||||
#include "assembler/assembler/LinkBuffer.h"
|
||||
#include "assembler/moco/MocoStubs.h"
|
||||
#include "methodjit/MethodJIT.h"
|
||||
#include "methodjit/MachineRegs.h"
|
||||
|
@ -91,11 +91,11 @@ struct ImmIntPtr : public JSC::MacroAssembler::ImmPtr
|
|||
class BaseAssembler : public JSC::MacroAssembler
|
||||
{
|
||||
struct CallPatch {
|
||||
CallPatch(ptrdiff_t distance, void *fun)
|
||||
: distance(distance), fun(fun)
|
||||
CallPatch(Call cl, void *fun)
|
||||
: call(cl), fun(fun)
|
||||
{ }
|
||||
|
||||
ptrdiff_t distance;
|
||||
Call call;
|
||||
JSC::FunctionPtr fun;
|
||||
};
|
||||
|
||||
|
@ -326,8 +326,7 @@ static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = JSC::ARMRegiste
|
|||
|
||||
Call call(void *fun) {
|
||||
Call cl = JSC::MacroAssembler::call();
|
||||
|
||||
callPatches.append(CallPatch(differenceBetween(startLabel, cl), fun));
|
||||
callPatches.append(CallPatch(cl, fun));
|
||||
return cl;
|
||||
}
|
||||
|
||||
|
@ -335,14 +334,10 @@ static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = JSC::ARMRegiste
|
|||
return MacroAssembler::call(reg);
|
||||
}
|
||||
|
||||
void finalize(uint8 *ncode) {
|
||||
JSC::JITCode jc(ncode, size());
|
||||
JSC::CodeBlock cb(jc);
|
||||
JSC::RepatchBuffer repatchBuffer(&cb);
|
||||
|
||||
void finalize(JSC::LinkBuffer &linker) {
|
||||
for (size_t i = 0; i < callPatches.length(); i++) {
|
||||
JSC::MacroAssemblerCodePtr cp(ncode + callPatches[i].distance);
|
||||
repatchBuffer.relink(JSC::CodeLocationCall(cp), callPatches[i].fun);
|
||||
CallPatch &patch = callPatches[i];
|
||||
linker.link(patch.call, JSC::FunctionPtr(patch.fun));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -43,31 +43,89 @@
|
|||
#include "jscntxt.h"
|
||||
#include "jstl.h"
|
||||
#include "assembler/assembler/MacroAssembler.h"
|
||||
#include "assembler/assembler/LinkBuffer.h"
|
||||
|
||||
namespace js {
|
||||
namespace mjit {
|
||||
|
||||
class CompilerBase
|
||||
class BaseCompiler
|
||||
{
|
||||
protected:
|
||||
typedef JSC::MacroAssembler::Label Label;
|
||||
typedef JSC::MacroAssembler::ImmPtr ImmPtr;
|
||||
typedef JSC::MacroAssembler::RegisterID RegisterID;
|
||||
typedef JSC::MacroAssembler::Address Address;
|
||||
typedef JSC::MacroAssembler MacroAssembler;
|
||||
|
||||
private:
|
||||
JSContext *cx;
|
||||
|
||||
public:
|
||||
CompilerBase(JSContext *cx)
|
||||
: cx(cx)
|
||||
BaseCompiler() : cx(NULL)
|
||||
{ }
|
||||
|
||||
BaseCompiler(JSContext *cx) : cx(cx)
|
||||
{ }
|
||||
|
||||
protected:
|
||||
JSC::ExecutablePool *getExecPool(size_t size) {
|
||||
typedef JSC::MacroAssembler::Label Label;
|
||||
typedef JSC::MacroAssembler::Imm32 Imm32;
|
||||
typedef JSC::MacroAssembler::ImmPtr ImmPtr;
|
||||
typedef JSC::MacroAssembler::RegisterID RegisterID;
|
||||
typedef JSC::MacroAssembler::FPRegisterID FPRegisterID;
|
||||
typedef JSC::MacroAssembler::Address Address;
|
||||
typedef JSC::MacroAssembler::BaseIndex BaseIndex;
|
||||
typedef JSC::MacroAssembler::AbsoluteAddress AbsoluteAddress;
|
||||
typedef JSC::MacroAssembler MacroAssembler;
|
||||
typedef JSC::MacroAssembler::Jump Jump;
|
||||
typedef JSC::MacroAssembler::JumpList JumpList;
|
||||
typedef JSC::MacroAssembler::Call Call;
|
||||
typedef JSC::MacroAssembler::DataLabelPtr DataLabelPtr;
|
||||
typedef JSC::MacroAssembler::DataLabel32 DataLabel32;
|
||||
typedef JSC::FunctionPtr FunctionPtr;
|
||||
typedef JSC::RepatchBuffer RepatchBuffer;
|
||||
typedef JSC::CodeBlock CodeBlock;
|
||||
typedef JSC::CodeLocationLabel CodeLocationLabel;
|
||||
typedef JSC::JITCode JITCode;
|
||||
typedef JSC::ReturnAddressPtr ReturnAddressPtr;
|
||||
typedef JSC::MacroAssemblerCodePtr MacroAssemblerCodePtr;
|
||||
|
||||
JSC::ExecutablePool *
|
||||
getExecPool(size_t size) {
|
||||
return BaseCompiler::GetExecPool(cx, size);
|
||||
}
|
||||
|
||||
public:
|
||||
static JSC::ExecutablePool *
|
||||
GetExecPool(JSContext *cx, size_t size) {
|
||||
ThreadData *jaegerData = &JS_METHODJIT_DATA(cx);
|
||||
return jaegerData->execPool->poolForSize(size);
|
||||
JSC::ExecutablePool *pool = jaegerData->execAlloc->poolForSize(size);
|
||||
if (!pool)
|
||||
js_ReportOutOfMemory(cx);
|
||||
return pool;
|
||||
}
|
||||
};
|
||||
|
||||
// This class wraps JSC::LinkBuffer for Mozilla-specific memory handling.
|
||||
// Every return |false| guarantees an OOM that has been correctly propagated,
|
||||
// and should continue to propagate.
|
||||
class LinkerHelper : public JSC::LinkBuffer
|
||||
{
|
||||
protected:
|
||||
JSContext *cx;
|
||||
|
||||
public:
|
||||
LinkerHelper(JSContext *cx) : cx(cx)
|
||||
{ }
|
||||
|
||||
JSC::ExecutablePool *init(Assembler &masm) {
|
||||
// The pool is incref'd after this call, so it's necessary to release()
|
||||
// on any failure.
|
||||
JSC::ExecutablePool *ep = BaseCompiler::GetExecPool(cx, masm.size());
|
||||
if (!ep)
|
||||
return ep;
|
||||
|
||||
m_size = masm.size();
|
||||
m_code = executableCopy(masm, ep);
|
||||
if (!m_code) {
|
||||
ep->release();
|
||||
js_ReportOutOfMemory(cx);
|
||||
return NULL;
|
||||
}
|
||||
return ep;
|
||||
}
|
||||
};
|
||||
|
|
@ -75,7 +75,11 @@ static const char *OpcodeNames[] = {
|
|||
#endif
|
||||
|
||||
mjit::Compiler::Compiler(JSContext *cx, JSScript *script, JSFunction *fun, JSObject *scopeChain)
|
||||
: cx(cx), script(script), scopeChain(scopeChain), globalObj(scopeChain->getGlobal()), fun(fun),
|
||||
: BaseCompiler(cx),
|
||||
script(script),
|
||||
scopeChain(scopeChain),
|
||||
globalObj(scopeChain->getGlobal()),
|
||||
fun(fun),
|
||||
analysis(cx, script), jumpMap(NULL), frame(cx, script, masm),
|
||||
branchPatches(ContextAllocPolicy(cx)),
|
||||
#if defined JS_MONOIC
|
||||
|
@ -450,21 +454,11 @@ mjit::Compiler::finishThisUp()
|
|||
#endif /* JS_MONOIC */
|
||||
|
||||
for (size_t i = 0; i < callPatches.length(); i++) {
|
||||
void *joinPoint = fullCode.locationOf(callPatches[i].joinPoint).executableAddress();
|
||||
CallPatchInfo &patch = callPatches[i];
|
||||
|
||||
/* Patch the write of ncode in the hot path. */
|
||||
JSC::CodeLocationDataLabelPtr fastNcode =
|
||||
fullCode.locationOf(callPatches[i].fastNcodePatch);
|
||||
JSC::RepatchBuffer fastRepatch((uint8*)fastNcode.executableAddress() - 32, 64, false);
|
||||
fastRepatch.repatch(fastNcode, joinPoint);
|
||||
|
||||
/* Patch the write of ncode in the slow path. */
|
||||
if (callPatches[i].hasSlowNcode) {
|
||||
JSC::CodeLocationDataLabelPtr slowNcode =
|
||||
stubCode.locationOf(callPatches[i].slowNcodePatch);
|
||||
JSC::RepatchBuffer slowRepatch((uint8*)slowNcode.executableAddress() - 32, 64, false);
|
||||
slowRepatch.repatch(slowNcode, joinPoint);
|
||||
}
|
||||
fullCode.patch(patch.fastNcodePatch, fullCode.locationOf(patch.joinPoint));
|
||||
if (patch.hasSlowNcode)
|
||||
stubCode.patch(patch.slowNcodePatch, fullCode.locationOf(patch.joinPoint));
|
||||
}
|
||||
|
||||
#if defined JS_POLYIC
|
||||
|
@ -525,8 +519,8 @@ mjit::Compiler::finishThisUp()
|
|||
}
|
||||
|
||||
/* Patch all outgoing calls. */
|
||||
masm.finalize(result);
|
||||
stubcc.finalize(result + masm.size());
|
||||
masm.finalize(fullCode);
|
||||
stubcc.masm.finalize(stubCode);
|
||||
|
||||
JSC::ExecutableAllocator::makeExecutable(result, masm.size() + stubcc.size());
|
||||
JSC::ExecutableAllocator::cacheFlush(result, masm.size() + stubcc.size());
|
||||
|
@ -534,6 +528,7 @@ mjit::Compiler::finishThisUp()
|
|||
script->ncode = (uint8 *)(result + masm.distanceOf(invokeLabel));
|
||||
|
||||
/* Build the table of call sites. */
|
||||
script->jit->nCallSites = callSites.length();
|
||||
if (callSites.length()) {
|
||||
CallSite *callSiteList = (CallSite *)cursor;
|
||||
cursor += sizeof(CallSite) * callSites.length();
|
||||
|
@ -1691,13 +1686,6 @@ mjit::Compiler::labelOf(jsbytecode *pc)
|
|||
return jumpMap[offs];
|
||||
}
|
||||
|
||||
JSC::ExecutablePool *
|
||||
mjit::Compiler::getExecPool(size_t size)
|
||||
{
|
||||
ThreadData *jaegerData = &JS_METHODJIT_DATA(cx);
|
||||
return jaegerData->execPool->poolForSize(size);
|
||||
}
|
||||
|
||||
uint32
|
||||
mjit::Compiler::fullAtomIndex(jsbytecode *pc)
|
||||
{
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#include "BytecodeAnalyzer.h"
|
||||
#include "MethodJIT.h"
|
||||
#include "CodeGenIncludes.h"
|
||||
#include "BaseCompiler.h"
|
||||
#include "StubCompiler.h"
|
||||
#include "MonoIC.h"
|
||||
#include "PolyIC.h"
|
||||
|
@ -52,21 +53,8 @@
|
|||
namespace js {
|
||||
namespace mjit {
|
||||
|
||||
class Compiler
|
||||
class Compiler : public BaseCompiler
|
||||
{
|
||||
typedef JSC::MacroAssembler::Label Label;
|
||||
typedef JSC::MacroAssembler::Imm32 Imm32;
|
||||
typedef JSC::MacroAssembler::ImmPtr ImmPtr;
|
||||
typedef JSC::MacroAssembler::RegisterID RegisterID;
|
||||
typedef JSC::MacroAssembler::FPRegisterID FPRegisterID;
|
||||
typedef JSC::MacroAssembler::Address Address;
|
||||
typedef JSC::MacroAssembler::AbsoluteAddress AbsoluteAddress;
|
||||
typedef JSC::MacroAssembler::BaseIndex BaseIndex;
|
||||
typedef JSC::MacroAssembler::Jump Jump;
|
||||
typedef JSC::MacroAssembler::JumpList JumpList;
|
||||
typedef JSC::MacroAssembler::Call Call;
|
||||
typedef JSC::MacroAssembler::DataLabelPtr DataLabelPtr;
|
||||
typedef JSC::MacroAssembler::DataLabel32 DataLabel32;
|
||||
|
||||
struct BranchPatch {
|
||||
BranchPatch(const Jump &j, jsbytecode *pc)
|
||||
|
@ -208,7 +196,6 @@ class Compiler
|
|||
bool ool;
|
||||
};
|
||||
|
||||
JSContext *cx;
|
||||
JSScript *script;
|
||||
JSObject *scopeChain;
|
||||
JSObject *globalObj;
|
||||
|
@ -259,7 +246,6 @@ class Compiler
|
|||
/* Non-emitting helpers. */
|
||||
uint32 fullAtomIndex(jsbytecode *pc);
|
||||
void jumpInScript(Jump j, jsbytecode *pc);
|
||||
JSC::ExecutablePool *getExecPool(size_t size);
|
||||
bool compareTwoValues(JSContext *cx, JSOp op, const Value &lhs, const Value &rhs);
|
||||
void addCallSite(uint32 id, bool stub);
|
||||
|
||||
|
|
|
@ -685,13 +685,13 @@ JS_STATIC_ASSERT(JSVAL_PAYLOAD_MASK == 0x00007FFFFFFFFFFFLL);
|
|||
bool
|
||||
ThreadData::Initialize()
|
||||
{
|
||||
execPool = new JSC::ExecutableAllocator();
|
||||
if (!execPool)
|
||||
execAlloc = new JSC::ExecutableAllocator();
|
||||
if (!execAlloc)
|
||||
return false;
|
||||
|
||||
TrampolineCompiler tc(execPool, &trampolines);
|
||||
TrampolineCompiler tc(execAlloc, &trampolines);
|
||||
if (!tc.compile()) {
|
||||
delete execPool;
|
||||
delete execAlloc;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -709,7 +709,7 @@ void
|
|||
ThreadData::Finish()
|
||||
{
|
||||
TrampolineCompiler::release(&trampolines);
|
||||
delete execPool;
|
||||
delete execAlloc;
|
||||
#ifdef JS_METHODJIT_PROFILE_STUBS
|
||||
FILE *fp = fopen("/tmp/stub-profiling", "wt");
|
||||
# define OPDEF(op,val,name,image,length,nuses,ndefs,prec,format) \
|
||||
|
|
|
@ -277,28 +277,24 @@ SlowNewFromIC(VMFrame &f, uint32 index)
|
|||
* scripted native, then a small stub is generated which inlines the native
|
||||
* invocation.
|
||||
*/
|
||||
class CallCompiler
|
||||
class CallCompiler : public BaseCompiler
|
||||
{
|
||||
VMFrame &f;
|
||||
JSContext *cx;
|
||||
CallICInfo ⁣
|
||||
Value *vp;
|
||||
bool callingNew;
|
||||
|
||||
public:
|
||||
CallCompiler(VMFrame &f, CallICInfo &ic, bool callingNew)
|
||||
: f(f), cx(f.cx), ic(ic), vp(f.regs.sp - (ic.argc + 2)), callingNew(callingNew)
|
||||
: BaseCompiler(f.cx), f(f), ic(ic), vp(f.regs.sp - (ic.argc + 2)), callingNew(callingNew)
|
||||
{
|
||||
}
|
||||
|
||||
JSC::ExecutablePool *poolForSize(size_t size, CallICInfo::PoolIndex index)
|
||||
{
|
||||
mjit::ThreadData *jm = &JS_METHODJIT_DATA(cx);
|
||||
JSC::ExecutablePool *ep = jm->execPool->poolForSize(size);
|
||||
if (!ep) {
|
||||
js_ReportOutOfMemory(f.cx);
|
||||
JSC::ExecutablePool *ep = getExecPool(size);
|
||||
if (!ep)
|
||||
return NULL;
|
||||
}
|
||||
JS_ASSERT(!ic.pools[index]);
|
||||
ic.pools[index] = ep;
|
||||
return ep;
|
||||
|
|
|
@ -40,7 +40,9 @@
|
|||
#include "StubCalls.h"
|
||||
#include "CodeGenIncludes.h"
|
||||
#include "StubCalls-inl.h"
|
||||
#include "BaseCompiler.h"
|
||||
#include "assembler/assembler/LinkBuffer.h"
|
||||
#include "assembler/assembler/RepatchBuffer.h"
|
||||
#include "jsscope.h"
|
||||
#include "jsnum.h"
|
||||
#include "jsobjinlines.h"
|
||||
|
@ -58,21 +60,32 @@ using namespace js::mjit::ic;
|
|||
/* Rough over-estimate of how much memory we need to unprotect. */
|
||||
static const uint32 INLINE_PATH_LENGTH = 64;
|
||||
|
||||
typedef JSC::FunctionPtr FunctionPtr;
|
||||
typedef JSC::RepatchBuffer RepatchBuffer;
|
||||
typedef JSC::CodeBlock CodeBlock;
|
||||
typedef JSC::CodeLocationLabel CodeLocationLabel;
|
||||
typedef JSC::JITCode JITCode;
|
||||
typedef JSC::MacroAssembler::Jump Jump;
|
||||
typedef JSC::MacroAssembler::RegisterID RegisterID;
|
||||
typedef JSC::MacroAssembler::Label Label;
|
||||
typedef JSC::MacroAssembler::Imm32 Imm32;
|
||||
typedef JSC::MacroAssembler::ImmPtr ImmPtr;
|
||||
typedef JSC::MacroAssembler::Address Address;
|
||||
typedef JSC::ReturnAddressPtr ReturnAddressPtr;
|
||||
typedef JSC::MacroAssemblerCodePtr MacroAssemblerCodePtr;
|
||||
// Helper class to simplify LinkBuffer usage in PIC stub generators.
|
||||
// This guarantees correct OOM and refcount handling for buffers while they
|
||||
// are instantiated and rooted.
|
||||
class PICLinker : public LinkerHelper
|
||||
{
|
||||
ic::PICInfo &pic;
|
||||
|
||||
class PICStubCompiler
|
||||
public:
|
||||
PICLinker(JSContext *cx, ic::PICInfo &pic)
|
||||
: LinkerHelper(cx), pic(pic)
|
||||
{ }
|
||||
|
||||
bool init(Assembler &masm) {
|
||||
JSC::ExecutablePool *pool = LinkerHelper::init(masm);
|
||||
if (!pool)
|
||||
return false;
|
||||
if (!pic.execPools.append(pool)) {
|
||||
pool->release();
|
||||
js_ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class PICStubCompiler : public BaseCompiler
|
||||
{
|
||||
protected:
|
||||
const char *type;
|
||||
|
@ -82,7 +95,7 @@ class PICStubCompiler
|
|||
|
||||
public:
|
||||
PICStubCompiler(const char *type, VMFrame &f, JSScript *script, ic::PICInfo &pic)
|
||||
: type(type), f(f), script(script), pic(pic)
|
||||
: BaseCompiler(f.cx), type(type), f(f), script(script), pic(pic)
|
||||
{ }
|
||||
|
||||
bool isCallOp() const
|
||||
|
@ -115,19 +128,13 @@ class PICStubCompiler
|
|||
return true;
|
||||
}
|
||||
|
||||
JSC::ExecutablePool *getExecPool(size_t size)
|
||||
{
|
||||
mjit::ThreadData *jd = &JS_METHODJIT_DATA(f.cx);
|
||||
return jd->execPool->poolForSize(size);
|
||||
}
|
||||
|
||||
protected:
|
||||
void spew(const char *event, const char *op)
|
||||
{
|
||||
#ifdef JS_METHODJIT_SPEW
|
||||
JaegerSpew(JSpew_PICs, "%s %s: %s (%s: %d)\n",
|
||||
type, event, op, script->filename,
|
||||
js_FramePCToLineNumber(f.cx, f.fp()));
|
||||
js_FramePCToLineNumber(cx, f.fp()));
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
@ -308,8 +315,8 @@ class SetPropCompiler : public PICStubCompiler
|
|||
bool generateStub(uint32 initialShape, const Shape *shape, bool adding)
|
||||
{
|
||||
/* Exits to the slow path. */
|
||||
Vector<Jump, 8> slowExits(f.cx);
|
||||
Vector<Jump, 8> otherGuards(f.cx);
|
||||
Vector<Jump, 8> slowExits(cx);
|
||||
Vector<Jump, 8> otherGuards(cx);
|
||||
|
||||
Assembler masm;
|
||||
|
||||
|
@ -488,15 +495,10 @@ class SetPropCompiler : public PICStubCompiler
|
|||
pic.secondShapeGuard = 0;
|
||||
}
|
||||
|
||||
JSC::ExecutablePool *ep = getExecPool(masm.size());
|
||||
if (!ep || !pic.execPools.append(ep)) {
|
||||
if (ep)
|
||||
ep->release();
|
||||
js_ReportOutOfMemory(f.cx);
|
||||
PICLinker buffer(cx, pic);
|
||||
if (!buffer.init(masm))
|
||||
return false;
|
||||
}
|
||||
|
||||
JSC::LinkBuffer buffer(&masm, ep);
|
||||
buffer.link(shapeGuard, pic.slowPathStart);
|
||||
if (slowExit.isSet())
|
||||
buffer.link(slowExit.get(), pic.slowPathStart);
|
||||
|
@ -556,7 +558,7 @@ class SetPropCompiler : public PICStubCompiler
|
|||
return disable("ops set property hook");
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
if (!CX_OWNS_OBJECT_TITLE(f.cx, obj))
|
||||
if (!CX_OWNS_OBJECT_TITLE(cx, obj))
|
||||
return disable("shared object");
|
||||
#endif
|
||||
|
||||
|
@ -564,12 +566,12 @@ class SetPropCompiler : public PICStubCompiler
|
|||
|
||||
JSObject *holder;
|
||||
JSProperty *prop = NULL;
|
||||
if (!obj->lookupProperty(f.cx, id, &holder, &prop))
|
||||
if (!obj->lookupProperty(cx, id, &holder, &prop))
|
||||
return false;
|
||||
|
||||
/* If the property exists but is on a prototype, treat as addprop. */
|
||||
if (prop && holder != obj) {
|
||||
AutoPropertyDropper dropper(f.cx, holder, prop);
|
||||
AutoPropertyDropper dropper(cx, holder, prop);
|
||||
const Shape *shape = (const Shape *) prop;
|
||||
|
||||
if (!holder->isNative())
|
||||
|
@ -603,7 +605,7 @@ class SetPropCompiler : public PICStubCompiler
|
|||
|
||||
uint32 initialShape = obj->shape();
|
||||
|
||||
if (!obj->ensureClassReservedSlots(f.cx))
|
||||
if (!obj->ensureClassReservedSlots(cx))
|
||||
return false;
|
||||
|
||||
uint32 slots = obj->numSlots();
|
||||
|
@ -623,7 +625,7 @@ class SetPropCompiler : public PICStubCompiler
|
|||
}
|
||||
|
||||
const Shape *shape =
|
||||
obj->putProperty(f.cx, id, getter, clasp->setProperty,
|
||||
obj->putProperty(cx, id, getter, clasp->setProperty,
|
||||
SHAPE_INVALID_SLOT, JSPROP_ENUMERATE, flags, 0);
|
||||
|
||||
if (!shape)
|
||||
|
@ -660,7 +662,7 @@ class SetPropCompiler : public PICStubCompiler
|
|||
return generateStub(initialShape, shape, true);
|
||||
}
|
||||
|
||||
AutoPropertyDropper dropper(f.cx, holder, prop);
|
||||
AutoPropertyDropper dropper(cx, holder, prop);
|
||||
|
||||
const Shape *shape = (const Shape *) prop;
|
||||
if (pic.kind == ic::PICInfo::SETMETHOD && !shape->isMethod())
|
||||
|
@ -803,15 +805,10 @@ class GetPropCompiler : public PICStubCompiler
|
|||
masm.move(ImmType(JSVAL_TYPE_INT32), pic.shapeReg);
|
||||
Jump done = masm.jump();
|
||||
|
||||
JSC::ExecutablePool *ep = getExecPool(masm.size());
|
||||
if (!ep || !pic.execPools.append(ep)) {
|
||||
if (ep)
|
||||
ep->release();
|
||||
js_ReportOutOfMemory(f.cx);
|
||||
PICLinker buffer(cx, pic);
|
||||
if (!buffer.init(masm))
|
||||
return false;
|
||||
}
|
||||
|
||||
JSC::LinkBuffer buffer(&masm, ep);
|
||||
buffer.link(notArgs, pic.slowPathStart);
|
||||
buffer.link(overridden, pic.slowPathStart);
|
||||
buffer.link(done, pic.storeBack);
|
||||
|
@ -846,15 +843,10 @@ class GetPropCompiler : public PICStubCompiler
|
|||
masm.move(ImmType(JSVAL_TYPE_INT32), pic.shapeReg);
|
||||
Jump done = masm.jump();
|
||||
|
||||
JSC::ExecutablePool *ep = getExecPool(masm.size());
|
||||
if (!ep || !pic.execPools.append(ep)) {
|
||||
if (ep)
|
||||
ep->release();
|
||||
js_ReportOutOfMemory(f.cx);
|
||||
PICLinker buffer(cx, pic);
|
||||
if (!buffer.init(masm))
|
||||
return false;
|
||||
}
|
||||
|
||||
JSC::LinkBuffer buffer(&masm, ep);
|
||||
buffer.link(notArray, pic.slowPathStart);
|
||||
buffer.link(oob, pic.slowPathStart);
|
||||
buffer.link(done, pic.storeBack);
|
||||
|
@ -881,12 +873,12 @@ class GetPropCompiler : public PICStubCompiler
|
|||
|
||||
JSObject *holder;
|
||||
JSProperty *prop;
|
||||
if (!obj->lookupProperty(f.cx, ATOM_TO_JSID(atom), &holder, &prop))
|
||||
if (!obj->lookupProperty(cx, ATOM_TO_JSID(atom), &holder, &prop))
|
||||
return false;
|
||||
if (!prop)
|
||||
return disable("property not found");
|
||||
|
||||
AutoPropertyDropper dropper(f.cx, holder, prop);
|
||||
AutoPropertyDropper dropper(cx, holder, prop);
|
||||
const Shape *shape = (const Shape *)prop;
|
||||
if (holder != obj)
|
||||
return disable("proto walk on String.prototype");
|
||||
|
@ -937,21 +929,15 @@ class GetPropCompiler : public PICStubCompiler
|
|||
|
||||
Jump done = masm.jump();
|
||||
|
||||
JSC::ExecutablePool *ep = getExecPool(masm.size());
|
||||
if (!ep || !pic.execPools.append(ep)) {
|
||||
if (ep)
|
||||
ep->release();
|
||||
js_ReportOutOfMemory(f.cx);
|
||||
PICLinker buffer(cx, pic);
|
||||
if (!buffer.init(masm))
|
||||
return false;
|
||||
}
|
||||
|
||||
JSC::LinkBuffer patchBuffer(&masm, ep);
|
||||
buffer.link(notString, pic.slowPathStart.labelAtOffset(pic.u.get.typeCheckOffset));
|
||||
buffer.link(shapeMismatch, pic.slowPathStart);
|
||||
buffer.link(done, pic.storeBack);
|
||||
|
||||
patchBuffer.link(notString, pic.slowPathStart.labelAtOffset(pic.u.get.typeCheckOffset));
|
||||
patchBuffer.link(shapeMismatch, pic.slowPathStart);
|
||||
patchBuffer.link(done, pic.storeBack);
|
||||
|
||||
CodeLocationLabel cs = patchBuffer.finalizeCodeAddendum();
|
||||
CodeLocationLabel cs = buffer.finalizeCodeAddendum();
|
||||
JaegerSpew(JSpew_PICs, "generate string call stub at %p\n",
|
||||
cs.executableAddress());
|
||||
|
||||
|
@ -980,19 +966,14 @@ class GetPropCompiler : public PICStubCompiler
|
|||
masm.move(ImmType(JSVAL_TYPE_INT32), pic.shapeReg);
|
||||
Jump done = masm.jump();
|
||||
|
||||
JSC::ExecutablePool *ep = getExecPool(masm.size());
|
||||
if (!ep || !pic.execPools.append(ep)) {
|
||||
if (ep)
|
||||
ep->release();
|
||||
js_ReportOutOfMemory(f.cx);
|
||||
PICLinker buffer(cx, pic);
|
||||
if (!buffer.init(masm))
|
||||
return false;
|
||||
}
|
||||
|
||||
JSC::LinkBuffer patchBuffer(&masm, ep);
|
||||
patchBuffer.link(notString, pic.slowPathStart.labelAtOffset(pic.u.get.typeCheckOffset));
|
||||
patchBuffer.link(done, pic.storeBack);
|
||||
buffer.link(notString, pic.slowPathStart.labelAtOffset(pic.u.get.typeCheckOffset));
|
||||
buffer.link(done, pic.storeBack);
|
||||
|
||||
CodeLocationLabel start = patchBuffer.finalizeCodeAddendum();
|
||||
CodeLocationLabel start = buffer.finalizeCodeAddendum();
|
||||
JaegerSpew(JSpew_PICs, "generate string length stub at %p\n",
|
||||
start.executableAddress());
|
||||
|
||||
|
@ -1048,7 +1029,7 @@ class GetPropCompiler : public PICStubCompiler
|
|||
|
||||
bool generateStub(JSObject *holder, const Shape *shape)
|
||||
{
|
||||
Vector<Jump, 8> shapeMismatches(f.cx);
|
||||
Vector<Jump, 8> shapeMismatches(cx);
|
||||
|
||||
Assembler masm;
|
||||
|
||||
|
@ -1143,20 +1124,9 @@ class GetPropCompiler : public PICStubCompiler
|
|||
}
|
||||
Jump done = masm.jump();
|
||||
|
||||
JSC::ExecutablePool *ep = getExecPool(masm.size());
|
||||
if (!ep) {
|
||||
js_ReportOutOfMemory(f.cx);
|
||||
PICLinker buffer(cx, pic);
|
||||
if (!buffer.init(masm))
|
||||
return false;
|
||||
}
|
||||
|
||||
// :TODO: this can OOM
|
||||
JSC::LinkBuffer buffer(&masm, ep);
|
||||
|
||||
if (!pic.execPools.append(ep)) {
|
||||
ep->release();
|
||||
js_ReportOutOfMemory(f.cx);
|
||||
return false;
|
||||
}
|
||||
|
||||
// The guard exit jumps to the original slow case.
|
||||
for (Jump *pj = shapeMismatches.begin(); pj != shapeMismatches.end(); ++pj)
|
||||
|
@ -1219,13 +1189,13 @@ class GetPropCompiler : public PICStubCompiler
|
|||
|
||||
JSObject *holder;
|
||||
JSProperty *prop;
|
||||
if (!aobj->lookupProperty(f.cx, ATOM_TO_JSID(atom), &holder, &prop))
|
||||
if (!aobj->lookupProperty(cx, ATOM_TO_JSID(atom), &holder, &prop))
|
||||
return false;
|
||||
|
||||
if (!prop)
|
||||
return disable("lookup failed");
|
||||
|
||||
AutoPropertyDropper dropper(f.cx, holder, prop);
|
||||
AutoPropertyDropper dropper(cx, holder, prop);
|
||||
|
||||
if (!holder->isNative())
|
||||
return disable("non-native holder");
|
||||
|
@ -1414,7 +1384,7 @@ class GetElemCompiler : public PICStubCompiler
|
|||
bool generateStub(JSObject *holder, const Shape *shape)
|
||||
{
|
||||
JS_ASSERT(pic.u.get.idReg != pic.shapeReg);
|
||||
Vector<Jump, 8> shapeMismatches(f.cx);
|
||||
Vector<Jump, 8> shapeMismatches(cx);
|
||||
|
||||
Assembler masm;
|
||||
|
||||
|
@ -1506,20 +1476,9 @@ class GetElemCompiler : public PICStubCompiler
|
|||
}
|
||||
Jump done = masm.jump();
|
||||
|
||||
JSC::ExecutablePool *ep = getExecPool(masm.size());
|
||||
if (!ep) {
|
||||
js_ReportOutOfMemory(f.cx);
|
||||
PICLinker buffer(cx, pic);
|
||||
if (!buffer.init(masm))
|
||||
return false;
|
||||
}
|
||||
|
||||
// :TODO: this can OOM
|
||||
JSC::LinkBuffer buffer(&masm, ep);
|
||||
|
||||
if (!pic.execPools.append(ep)) {
|
||||
ep->release();
|
||||
js_ReportOutOfMemory(f.cx);
|
||||
return false;
|
||||
}
|
||||
|
||||
// The guard exit jumps to the original slow case.
|
||||
for (Jump *pj = shapeMismatches.begin(); pj != shapeMismatches.end(); ++pj)
|
||||
|
@ -1529,11 +1488,11 @@ class GetElemCompiler : public PICStubCompiler
|
|||
buffer.link(done, pic.storeBack);
|
||||
CodeLocationLabel cs = buffer.finalizeCodeAddendum();
|
||||
#if DEBUG
|
||||
char *chars = js_DeflateString(f.cx, id->chars(), id->length());
|
||||
char *chars = js_DeflateString(cx, id->chars(), id->length());
|
||||
JaegerSpew(JSpew_PICs, "generated %s stub at %p for atom 0x%x (\"%s\") shape 0x%x (%s: %d)\n",
|
||||
type, cs.executableAddress(), id, chars, holder->shape(), script->filename,
|
||||
js_FramePCToLineNumber(f.cx, f.fp()));
|
||||
f.cx->free(chars);
|
||||
js_FramePCToLineNumber(cx, f.fp()));
|
||||
cx->free(chars);
|
||||
#endif
|
||||
|
||||
PICRepatchBuffer repatcher(pic, pic.lastPathStart());
|
||||
|
@ -1563,18 +1522,18 @@ class GetElemCompiler : public PICStubCompiler
|
|||
return true;
|
||||
}
|
||||
|
||||
JSAtom *atom = js_AtomizeString(f.cx, id, 0);
|
||||
JSAtom *atom = js_AtomizeString(cx, id, 0);
|
||||
if (!atom)
|
||||
return false;
|
||||
JSObject *holder;
|
||||
JSProperty *prop;
|
||||
if (!obj->lookupProperty(f.cx, ATOM_TO_JSID(atom), &holder, &prop))
|
||||
if (!obj->lookupProperty(cx, ATOM_TO_JSID(atom), &holder, &prop))
|
||||
return false;
|
||||
|
||||
if (!prop)
|
||||
return disable("lookup failed");
|
||||
|
||||
AutoPropertyDropper dropper(f.cx, holder, prop);
|
||||
AutoPropertyDropper dropper(cx, holder, prop);
|
||||
|
||||
if (!obj->isNative())
|
||||
return disable("non-native obj");
|
||||
|
@ -1681,7 +1640,7 @@ class ScopeNameCompiler : public PICStubCompiler
|
|||
bool generateGlobalStub()
|
||||
{
|
||||
Assembler masm;
|
||||
JumpList fails(f.cx);
|
||||
JumpList fails(cx);
|
||||
|
||||
/* For GETXPROP, the object is already in objReg. */
|
||||
if (pic.kind == ic::PICInfo::NAME)
|
||||
|
@ -1724,20 +1683,9 @@ class ScopeNameCompiler : public PICStubCompiler
|
|||
|
||||
JS_ASSERT(masm.differenceBetween(failLabel, dbgJumpOffset) == SCOPENAME_JUMP_OFFSET);
|
||||
|
||||
JSC::ExecutablePool *ep = getExecPool(masm.size());
|
||||
if (!ep) {
|
||||
js_ReportOutOfMemory(f.cx);
|
||||
PICLinker buffer(cx, pic);
|
||||
if (!buffer.init(masm))
|
||||
return false;
|
||||
}
|
||||
|
||||
// :TODO: this can OOM
|
||||
JSC::LinkBuffer buffer(&masm, ep);
|
||||
|
||||
if (!pic.execPools.append(ep)) {
|
||||
ep->release();
|
||||
js_ReportOutOfMemory(f.cx);
|
||||
return false;
|
||||
}
|
||||
|
||||
buffer.link(failJump, pic.slowPathStart);
|
||||
buffer.link(done, pic.storeBack);
|
||||
|
@ -1765,7 +1713,7 @@ class ScopeNameCompiler : public PICStubCompiler
|
|||
bool generateCallStub()
|
||||
{
|
||||
Assembler masm;
|
||||
Vector<Jump, 8, ContextAllocPolicy> fails(f.cx);
|
||||
Vector<Jump, 8, ContextAllocPolicy> fails(cx);
|
||||
|
||||
/* For GETXPROP, the object is already in objReg. */
|
||||
if (pic.kind == ic::PICInfo::NAME)
|
||||
|
@ -1839,20 +1787,9 @@ class ScopeNameCompiler : public PICStubCompiler
|
|||
Label failLabel = masm.label();
|
||||
Jump failJump = masm.jump();
|
||||
|
||||
JSC::ExecutablePool *ep = getExecPool(masm.size());
|
||||
if (!ep) {
|
||||
js_ReportOutOfMemory(f.cx);
|
||||
PICLinker buffer(cx, pic);
|
||||
if (!buffer.init(masm))
|
||||
return false;
|
||||
}
|
||||
|
||||
// :TODO: this can OOM
|
||||
JSC::LinkBuffer buffer(&masm, ep);
|
||||
|
||||
if (!pic.execPools.append(ep)) {
|
||||
ep->release();
|
||||
js_ReportOutOfMemory(f.cx);
|
||||
return false;
|
||||
}
|
||||
|
||||
buffer.link(failJump, pic.slowPathStart);
|
||||
buffer.link(done, pic.storeBack);
|
||||
|
@ -1873,7 +1810,7 @@ class ScopeNameCompiler : public PICStubCompiler
|
|||
|
||||
bool updateForName()
|
||||
{
|
||||
if (!js_FindProperty(f.cx, ATOM_TO_JSID(atom), &obj, &holder, &prop))
|
||||
if (!js_FindProperty(cx, ATOM_TO_JSID(atom), &obj, &holder, &prop))
|
||||
return false;
|
||||
|
||||
return update();
|
||||
|
@ -1883,7 +1820,7 @@ class ScopeNameCompiler : public PICStubCompiler
|
|||
{
|
||||
obj = scopeChain;
|
||||
|
||||
if (!obj->lookupProperty(f.cx, ATOM_TO_JSID(atom), &holder, &prop))
|
||||
if (!obj->lookupProperty(cx, ATOM_TO_JSID(atom), &holder, &prop))
|
||||
return false;
|
||||
|
||||
return update();
|
||||
|
@ -1924,8 +1861,6 @@ class ScopeNameCompiler : public PICStubCompiler
|
|||
|
||||
bool retrieve(Value *vp)
|
||||
{
|
||||
JSContext *cx = f.cx;
|
||||
|
||||
if (prop && (!obj->isNative() || !holder->isNative())) {
|
||||
holder->dropProperty(cx, prop);
|
||||
if (!obj->getProperty(cx, ATOM_TO_JSID(atom), vp))
|
||||
|
@ -2001,7 +1936,7 @@ class BindNameCompiler : public PICStubCompiler
|
|||
bool generateStub(JSObject *obj)
|
||||
{
|
||||
Assembler masm;
|
||||
js::Vector<Jump, 8, ContextAllocPolicy> fails(f.cx);
|
||||
js::Vector<Jump, 8, ContextAllocPolicy> fails(cx);
|
||||
|
||||
/* Guard on the shape of the scope chain. */
|
||||
masm.loadPtr(Address(JSFrameReg, JSStackFrame::offsetOfScopeChain()), pic.objReg);
|
||||
|
@ -2039,20 +1974,9 @@ class BindNameCompiler : public PICStubCompiler
|
|||
|
||||
JS_ASSERT(masm.differenceBetween(failLabel, dbgStubJumpOffset) == BINDNAME_STUB_JUMP_OFFSET);
|
||||
|
||||
JSC::ExecutablePool *ep = getExecPool(masm.size());
|
||||
if (!ep) {
|
||||
js_ReportOutOfMemory(f.cx);
|
||||
PICLinker buffer(cx, pic);
|
||||
if (!buffer.init(masm))
|
||||
return false;
|
||||
}
|
||||
|
||||
// :TODO: this can OOM
|
||||
JSC::LinkBuffer buffer(&masm, ep);
|
||||
|
||||
if (!pic.execPools.append(ep)) {
|
||||
ep->release();
|
||||
js_ReportOutOfMemory(f.cx);
|
||||
return false;
|
||||
}
|
||||
|
||||
buffer.link(failJump, pic.slowPathStart);
|
||||
buffer.link(done, pic.storeBack);
|
||||
|
@ -2078,7 +2002,7 @@ class BindNameCompiler : public PICStubCompiler
|
|||
{
|
||||
JS_ASSERT(scopeChain->getParent());
|
||||
|
||||
JSObject *obj = js_FindIdentifierBase(f.cx, scopeChain, ATOM_TO_JSID(atom));
|
||||
JSObject *obj = js_FindIdentifierBase(cx, scopeChain, ATOM_TO_JSID(atom));
|
||||
if (!obj)
|
||||
return obj;
|
||||
|
||||
|
|
|
@ -199,12 +199,6 @@ StubCompiler::fixCrossJumps(uint8 *ncode, size_t offset, size_t total)
|
|||
slow.link(joins[i].from, fast.locationOf(joins[i].to));
|
||||
}
|
||||
|
||||
void
|
||||
StubCompiler::finalize(uint8 *ncode)
|
||||
{
|
||||
masm.finalize(ncode);
|
||||
}
|
||||
|
||||
JSC::MacroAssembler::Call
|
||||
StubCompiler::vpInc(JSOp op, uint32 depth)
|
||||
{
|
||||
|
|
|
@ -158,7 +158,6 @@ class StubCompiler
|
|||
|
||||
/* Finish all native code patching. */
|
||||
void fixCrossJumps(uint8 *ncode, size_t offset, size_t total);
|
||||
void finalize(uint8 *ncode);
|
||||
void jumpInScript(Jump j, jsbytecode *target);
|
||||
void crossJump(Jump j, Label l);
|
||||
|
||||
|
|
|
@ -100,8 +100,8 @@ TrampolineCompiler::compileTrampoline(Trampolines::TrampolinePtr *where, JSC::Ex
|
|||
return false;
|
||||
|
||||
JSC::LinkBuffer buffer(&masm, *pool);
|
||||
masm.finalize(buffer);
|
||||
uint8 *result = (uint8*)buffer.finalizeCodeAddendum().dataLocation();
|
||||
masm.finalize(result);
|
||||
*where = JS_DATA_TO_FUNC_PTR(Trampolines::TrampolinePtr, result + masm.distanceOf(entry));
|
||||
|
||||
return true;
|
||||
|
|
Загрузка…
Ссылка в новой задаче