Decouple JSContext from Ion backend, bug 774253. r=dvander

This commit is contained in:
Brian Hackett 2012-08-01 13:23:30 -06:00
parent 004b0b22cc
commit 6c4d57b26e
25 changed files with 316 additions and 255 deletions

View File

@ -207,8 +207,7 @@ CodeGenerator::visitIntToString(LIntToString *lir)
bool
CodeGenerator::visitRegExp(LRegExp *lir)
{
GlobalObject *global = &gen->info().script()->global();
RootedObject proto(gen->cx, global->getOrCreateRegExpPrototype(gen->cx));
JSObject *proto = lir->mir()->getRegExpPrototype();
typedef JSObject *(*pf)(JSContext *, JSObject *, JSObject *);
static const VMFunction CloneRegExpObjectInfo = FunctionInfo<pf>(CloneRegExpObject);
@ -234,7 +233,7 @@ CodeGenerator::visitLambda(LLambda *lir)
{
Register scopeChain = ToRegister(lir->scopeChain());
Register output = ToRegister(lir->output());
RootedFunction fun(gen->cx, lir->mir()->fun());
JSFunction *fun = lir->mir()->fun();
typedef JSObject *(*pf)(JSContext *, HandleFunction, HandleObject);
static const VMFunction Info = FunctionInfo<pf>(js::Lambda);
@ -244,23 +243,11 @@ CodeGenerator::visitLambda(LLambda *lir)
if (!ool)
return false;
JS_ASSERT(gen->cx->compartment == fun->compartment());
JS_ASSERT(gen->compartment == fun->compartment());
JS_ASSERT(!fun->hasSingletonType());
// Because of compartment-per-global and compile'n'go, the Function prototype,
// first non-scope object on the scope chain, and global object, are all
// invariant. We can thus use CloneFunctionObject with the global object to get
// a bogus clone and use that as our template object.
RootedObject parent(gen->cx, &fun->global());
RootedFunction clone(gen->cx, CloneFunctionObject(gen->cx, fun, parent));
if (!clone)
return false;
JS_ASSERT(clone->getAllocKind() != JSFunction::ExtendedFinalizeKind);
JS_ASSERT(clone->isInterpreted());
masm.newGCThing(gen->cx, output, clone, ool->entry());
masm.initGCThing(gen->cx, output, clone);
masm.newGCThing(output, fun, ool->entry());
masm.initGCThing(output, fun);
// Initialize nargs and flags. We do this with a single uint32 to avoid
// 16-bit writes.
@ -276,9 +263,9 @@ CodeGenerator::visitLambda(LLambda *lir)
JS_STATIC_ASSERT(offsetof(JSFunction, flags) == offsetof(JSFunction, nargs) + 2);
masm.store32(Imm32(u.word), Address(output, offsetof(JSFunction, nargs)));
masm.storePtr(ImmGCPtr(clone->script()), Address(output, JSFunction::offsetOfNativeOrScript()));
masm.storePtr(ImmGCPtr(fun->script()), Address(output, JSFunction::offsetOfNativeOrScript()));
masm.storePtr(scopeChain, Address(output, JSFunction::offsetOfEnvironment()));
masm.storePtr(ImmGCPtr(clone->atom), Address(output, offsetof(JSFunction, atom)));
masm.storePtr(ImmGCPtr(fun->atom), Address(output, offsetof(JSFunction, atom)));
masm.bind(ool->rejoin());
return true;
@ -619,7 +606,8 @@ CodeGenerator::visitCallGeneric(LCallGeneric *call)
if (call->hasSingleTarget() &&
call->getSingleTarget()->script()->ion == ION_DISABLED_SCRIPT)
{
emitCallInvokeFunction(call, unusedStack);
if (!emitCallInvokeFunction(call, unusedStack))
return false;
if (call->mir()->isConstructing()) {
Label notPrimitive;
@ -652,7 +640,7 @@ CodeGenerator::visitCallGeneric(LCallGeneric *call)
masm.movePtr(Address(objreg, offsetof(JSScript, ion)), objreg);
// Guard that the IonScript has been compiled.
masm.branchPtr(Assembler::BelowOrEqual, objreg, ImmWord(ION_DISABLED_SCRIPT), &invoke);
masm.branchPtr(Assembler::BelowOrEqual, objreg, ImmWord(ION_COMPILING_SCRIPT), &invoke);
// Nestle %esp up to the argument vector.
masm.freeStack(unusedStack);
@ -691,7 +679,7 @@ CodeGenerator::visitCallGeneric(LCallGeneric *call)
// Hardcode the address of the argumentsRectifier code.
IonCompartment *ion = gen->ionCompartment();
IonCode *argumentsRectifier = ion->getArgumentsRectifier(gen->cx);
IonCode *argumentsRectifier = ion->getArgumentsRectifier(GetIonContext()->cx);
if (!argumentsRectifier)
return false;
@ -721,7 +709,8 @@ CodeGenerator::visitCallGeneric(LCallGeneric *call)
// Handle uncompiled or native functions.
masm.bind(&invoke);
emitCallInvokeFunction(call, unusedStack);
if (!emitCallInvokeFunction(call, unusedStack))
return false;
masm.bind(&end);
@ -885,7 +874,8 @@ CodeGenerator::visitApplyArgsGeneric(LApplyArgsGeneric *apply)
(!apply->getSingleTarget()->isInterpreted() ||
apply->getSingleTarget()->script()->ion == ION_DISABLED_SCRIPT))
{
emitCallInvokeFunction(apply, copyreg);
if (!emitCallInvokeFunction(apply, copyreg))
return false;
emitPopArguments(apply, copyreg);
return true;
}
@ -910,7 +900,7 @@ CodeGenerator::visitApplyArgsGeneric(LApplyArgsGeneric *apply)
masm.movePtr(Address(objreg, offsetof(JSScript, ion)), objreg);
// Guard that the IonScript has been compiled.
masm.branchPtr(Assembler::BelowOrEqual, objreg, ImmWord(ION_DISABLED_SCRIPT), &invoke);
masm.branchPtr(Assembler::BelowOrEqual, objreg, ImmWord(ION_COMPILING_SCRIPT), &invoke);
// Call with an Ion frame or a rectifier frame.
{
@ -951,7 +941,7 @@ CodeGenerator::visitApplyArgsGeneric(LApplyArgsGeneric *apply)
// Hardcode the address of the argumentsRectifier code.
IonCompartment *ion = gen->ionCompartment();
IonCode *argumentsRectifier = ion->getArgumentsRectifier(gen->cx);
IonCode *argumentsRectifier = ion->getArgumentsRectifier(GetIonContext()->cx);
if (!argumentsRectifier)
return false;
@ -982,7 +972,8 @@ CodeGenerator::visitApplyArgsGeneric(LApplyArgsGeneric *apply)
// Handle uncompiled or native functions.
{
masm.bind(&invoke);
emitCallInvokeFunction(apply, copyreg);
if (!emitCallInvokeFunction(apply, copyreg))
return false;
}
// Pop arguments and continue.
@ -1068,7 +1059,7 @@ CodeGenerator::visitCheckOverRecursed(LCheckOverRecursed *lir)
// Ion may legally place frames very close to the limit. Calling additional
// C functions may then violate the limit without any checking.
JSRuntime *rt = gen->cx->runtime;
JSRuntime *rt = gen->compartment->rt;
Register limitReg = ToRegister(lir->limitTemp());
// Since Ion frames exist on the C stack, the stack limit may be
@ -1184,7 +1175,10 @@ CodeGenerator::visitNewArrayCallVM(LNewArray *lir)
JS_ASSERT(!lir->isCall());
saveLive(lir);
pushArg(ImmGCPtr(lir->mir()->type()));
JSObject *templateObject = lir->mir()->templateObject();
types::TypeObject *type = templateObject->hasSingletonType() ? NULL : templateObject->type();
pushArg(ImmGCPtr(type));
pushArg(Imm32(lir->mir()->count()));
if (!callVM(NewInitArrayInfo, lir))
@ -1206,7 +1200,7 @@ CodeGenerator::visitNewSlots(LNewSlots *lir)
Register temp3 = ToRegister(lir->temp3());
Register output = ToRegister(lir->output());
masm.mov(ImmWord(gen->cx->runtime), temp1);
masm.mov(ImmWord(gen->compartment->rt), temp1);
masm.mov(Imm32(lir->mir()->nslots()), temp2);
masm.setupUnalignedABICall(2, temp3);
@ -1225,7 +1219,7 @@ bool
CodeGenerator::visitNewArray(LNewArray *lir)
{
Register objReg = ToRegister(lir->output());
types::TypeObject *typeObj = lir->mir()->type();
JSObject *templateObject = lir->mir()->templateObject();
uint32 count = lir->mir()->count();
JS_ASSERT(count < JSObject::NELEMENTS_LIMIT);
@ -1238,20 +1232,15 @@ CodeGenerator::visitNewArray(LNewArray *lir)
// but only when data doesn't fit the available array slots.
bool allocating = lir->mir()->isAllocating() && count > maxArraySlots;
if (!gen->cx->typeInferenceEnabled() || !typeObj || allocating)
if (templateObject->hasSingletonType() || allocating)
return visitNewArrayCallVM(lir);
OutOfLineNewArray *ool = new OutOfLineNewArray(lir);
if (!addOutOfLineCode(ool))
return false;
RootedObject templateObject(gen->cx, NewDenseUnallocatedArray(gen->cx, count));
if (!templateObject)
return false;
templateObject->setType(typeObj);
masm.newGCThing(gen->cx, objReg, templateObject, ool->entry());
masm.initGCThing(gen->cx, objReg, templateObject);
masm.newGCThing(objReg, templateObject, ool->entry());
masm.initGCThing(objReg, templateObject);
masm.bind(ool->rejoin());
return true;
@ -1290,14 +1279,13 @@ CodeGenerator::visitNewObjectVMCall(LNewObject *lir)
{
Register objReg = ToRegister(lir->output());
typedef JSObject *(*pf)(JSContext *, HandleObject, types::TypeObject *);
typedef JSObject *(*pf)(JSContext *, HandleObject);
static const VMFunction Info = FunctionInfo<pf>(NewInitObject);
JS_ASSERT(!lir->isCall());
saveLive(lir);
pushArg(ImmGCPtr(lir->mir()->type()));
pushArg(ImmGCPtr(lir->mir()->baseObj()));
pushArg(ImmGCPtr(lir->mir()->templateObject()));
if (!callVM(Info, lir))
return false;
@ -1313,26 +1301,17 @@ CodeGenerator::visitNewObject(LNewObject *lir)
{
Register objReg = ToRegister(lir->output());
RootedObject baseObj(gen->cx, lir->mir()->baseObj());
types::TypeObject *typeObj = lir->mir()->type();
JSObject *templateObject = lir->mir()->templateObject();
if (!gen->cx->typeInferenceEnabled() || !typeObj ||
!baseObj || baseObj->hasDynamicSlots())
{
if (templateObject->hasSingletonType() || templateObject->hasDynamicSlots())
return visitNewObjectVMCall(lir);
}
OutOfLineNewObject *ool = new OutOfLineNewObject(lir);
if (!addOutOfLineCode(ool))
return false;
RootedObject templateObject(gen->cx, CopyInitializerObject(gen->cx, baseObj));
if (!templateObject)
return false;
templateObject->setType(typeObj);
masm.newGCThing(gen->cx, objReg, templateObject, ool->entry());
masm.initGCThing(gen->cx, objReg, templateObject);
masm.newGCThing(objReg, templateObject, ool->entry());
masm.initGCThing(objReg, templateObject);
masm.bind(ool->rejoin());
return true;
@ -1355,8 +1334,9 @@ CodeGenerator::visitNewCallObject(LNewCallObject *lir)
typedef JSObject *(*pf)(JSContext *, HandleShape, HandleTypeObject, HeapSlot *, HandleObject);
static const VMFunction NewCallObjectInfo = FunctionInfo<pf>(NewCallObject);
RootedObject global(gen->cx, gen->cx->compartment->maybeGlobal());
RootedObject templateObj(gen->cx, lir->mir()->templateObj());
JSObject *templateObj = lir->mir()->templateObj();
JSObject *global = &templateObj->global();
if (lir->isCall()) {
pushArg(ImmGCPtr(global));
if (lir->slots()->isRegister())
@ -1388,8 +1368,8 @@ CodeGenerator::visitNewCallObject(LNewCallObject *lir)
if (!ool)
return false;
masm.newGCThing(gen->cx, obj, templateObj, ool->entry());
masm.initGCThing(gen->cx, obj, templateObj);
masm.newGCThing(obj, templateObj, ool->entry());
masm.initGCThing(obj, templateObj);
if (lir->slots()->isRegister())
masm.storePtr(ToRegister(lir->slots()), Address(obj, JSObject::offsetOfSlots()));
@ -1417,7 +1397,7 @@ CodeGenerator::visitCreateThis(LCreateThis *lir)
{
JS_ASSERT(lir->mir()->hasTemplateObject());
RootedObject templateObject(gen->cx, lir->mir()->getTemplateObject());
JSObject *templateObject = lir->mir()->getTemplateObject();
gc::AllocKind allocKind = templateObject->getAllocKind();
int thingSize = (int)gc::Arena::thingSize(allocKind);
Register objReg = ToRegister(lir->output());
@ -1432,11 +1412,11 @@ CodeGenerator::visitCreateThis(LCreateThis *lir)
return false;
// Allocate. If the FreeList is empty, call to VM, which may GC.
masm.newGCThing(gen->cx, objReg, templateObject, ool->entry());
masm.newGCThing(objReg, templateObject, ool->entry());
// Initialize based on the templateObject.
masm.bind(ool->rejoin());
masm.initGCThing(gen->cx, objReg, templateObject);
masm.initGCThing(objReg, templateObject);
return true;
}
@ -1596,7 +1576,7 @@ CodeGenerator::visitMathFunctionD(LMathFunctionD *ins)
FloatRegister input = ToFloatRegister(ins->input());
JS_ASSERT(ToFloatRegister(ins->output()) == ReturnFloatReg);
MathCache *mathCache = gen->cx->runtime->getMathCache(gen->cx);
MathCache *mathCache = ins->mir()->cache();
masm.setupUnalignedABICall(2, temp);
masm.movePtr(ImmWord(mathCache), temp);
@ -1928,7 +1908,7 @@ CodeGenerator::visitFromCharCode(LFromCharCode *lir)
masm.jump(ool->entry());
masm.bind(&fast);
masm.movePtr(ImmWord(&gen->cx->runtime->staticStrings.unitStaticTable), output);
masm.movePtr(ImmWord(&gen->compartment->rt->staticStrings.unitStaticTable), output);
masm.loadPtr(BaseIndex(output, code, ScalePointer), output);
masm.bind(ool->rejoin());
return true;
@ -2441,7 +2421,7 @@ CodeGenerator::visitIteratorStart(LIteratorStart *lir)
JS_ASSERT(flags == JSITER_ENUMERATE);
// Fetch the most recent iterator and ensure it's not NULL.
masm.loadPtr(AbsoluteAddress(&gen->cx->runtime->nativeIterCache.last), output);
masm.loadPtr(AbsoluteAddress(&gen->compartment->rt->nativeIterCache.last), output);
masm.branchTestPtr(Assembler::Zero, output, output, ool->entry());
// Load NativeIterator.
@ -2634,7 +2614,7 @@ CodeGenerator::visitGetArgument(LGetArgument *lir)
bool
CodeGenerator::generate()
{
JSContext *cx = gen->cx;
JSContext *cx = GetIonContext()->cx;
unsigned slots = graph.localSlotCount() +
(graph.argumentSlotCount() * sizeof(Value) / STACK_SLOT_SIZE);
@ -3019,11 +2999,11 @@ CodeGenerator::visitOutOfLineCacheGetProperty(OutOfLineCache *ool)
// and which atom property it should get
// Note: because all registers are saved, the output register should be
// a def register, else the result will be overriden by restoreLive(ins)
RootedPropertyName name(gen->cx);
PropertyName *name = NULL;
switch (ins->op()) {
case LInstruction::LOp_InstanceOfO:
case LInstruction::LOp_InstanceOfV:
name = GetIonContext()->cx->runtime->atomState.classPrototypeAtom;
name = gen->compartment->rt->atomState.classPrototypeAtom;
objReg = ToRegister(ins->getTemp(1));
output = TypedOrValueRegister(MIRType_Object, ToAnyRegister(ins->getDef(0)));
break;
@ -3320,7 +3300,7 @@ CodeGenerator::visitTypeOfV(LTypeOfV *lir)
if (!addOutOfLineCode(ool))
return false;
PropertyName **typeAtoms = gen->cx->runtime->atomState.typeAtoms;
PropertyName **typeAtoms = gen->compartment->rt->atomState.typeAtoms;
// Jump to the OOL path if the value is an object. Objects are complicated
// since they may have a typeof hook.
@ -3792,15 +3772,10 @@ CodeGenerator::emitInstanceOf(LInstruction *ins, Register rhs)
bool
CodeGenerator::visitProfilingEnter(LProfilingEnter *lir)
{
SPSProfiler *profiler = &gen->cx->runtime->spsProfiler;
SPSProfiler *profiler = &gen->compartment->rt->spsProfiler;
JS_ASSERT(profiler->enabled());
// This could be a push for an inline script, so we can't always use
// gen->info().script() blindly.
JSScript *script = lir->script();
const char *string = profiler->profileString(gen->cx, script, script->function());
if (string == NULL)
return false;
const char *string = lir->profileString();
Register size = ToRegister(lir->temp1()->output());
Register base = ToRegister(lir->temp2()->output());
@ -3832,7 +3807,7 @@ CodeGenerator::visitProfilingEnter(LProfilingEnter *lir)
bool
CodeGenerator::visitProfilingExit(LProfilingExit *exit)
{
SPSProfiler *profiler = &gen->cx->runtime->spsProfiler;
SPSProfiler *profiler = &gen->compartment->rt->spsProfiler;
JS_ASSERT(profiler->enabled());
Register temp = ToRegister(exit->temp());
masm.movePtr(ImmWord(profiler->sizePointer()), temp);

View File

@ -8,6 +8,7 @@
#include "Ion.h"
#include "IonAnalysis.h"
#include "IonBuilder.h"
#include "IonLinker.h"
#include "IonSpewer.h"
#include "LIR.h"
#include "AliasAnalysis.h"
@ -35,6 +36,7 @@
#include "vm/Stack-inl.h"
#include "ion/IonFrames-inl.h"
#include "ion/CompilerRoot.h"
#include "methodjit/Retcon.h"
using namespace js;
using namespace js::ion;
@ -86,8 +88,9 @@ ion::GetIonContext()
return CurrentIonContext();
}
IonContext::IonContext(JSContext *cx, TempAllocator *temp)
IonContext::IonContext(JSContext *cx, JSCompartment *compartment, TempAllocator *temp)
: cx(cx),
compartment(compartment),
temp(temp),
prev_(CurrentIonContext()),
assemblerCount_(0)
@ -849,12 +852,12 @@ static bool
IonCompile(JSContext *cx, JSScript *script, JSFunction *fun, jsbytecode *osrPc, bool constructing)
{
TempAllocator temp(&cx->tempLifoAlloc());
IonContext ictx(cx, &temp);
IonContext ictx(cx, cx->compartment, &temp);
if (!cx->compartment->ensureIonCompartmentExists(cx))
return false;
MIRGraph graph(temp);
MIRGraph graph(&temp);
CompileInfo *info = cx->tempLifoAlloc().new_<CompileInfo>(script, fun, osrPc, constructing);
if (!info)
return false;
@ -869,7 +872,7 @@ IonCompile(JSContext *cx, JSScript *script, JSFunction *fun, jsbytecode *osrPc,
enterCompiler.init(script, false, 0);
AutoCompilerRoots roots(script->compartment()->rt);
IonBuilder builder(cx, temp, graph, &oracle, *info);
IonBuilder builder(cx, &temp, &graph, &oracle, info);
if (!Compiler(builder, graph)) {
IonSpew(IonSpew_Abort, "IM Compilation failed.");
return false;
@ -1144,7 +1147,7 @@ EnterIon(JSContext *cx, StackFrame *fp, void *jitcode)
Value result = Int32Value(numActualArgs);
{
AssertCompartmentUnchanged pcc(cx);
IonContext ictx(cx, NULL);
IonContext ictx(cx, cx->compartment, NULL);
IonActivation activation(cx, fp);
JSAutoResolveFlags rf(cx, RESOLVE_INFER);

View File

@ -176,14 +176,16 @@ enum MethodStatus
// An Ion context is needed to enter into either an Ion method or an instance
// of the Ion compiler. It points to a temporary allocator and the active
// JSContext.
// JSContext, either of which may be NULL, and the active compartment, which
// will not be NULL.
class IonContext
{
public:
IonContext(JSContext *cx, TempAllocator *temp);
IonContext(JSContext *cx, JSCompartment *compartment, TempAllocator *temp);
~IonContext();
JSContext *cx;
JSCompartment *compartment;
TempAllocator *temp;
int getNextAssemblerId() {
return assemblerCount_++;

View File

@ -17,26 +17,6 @@
namespace js {
namespace ion {
class IonAllocPolicy
{
public:
void *malloc_(size_t bytes) {
JSContext *cx = GetIonContext()->cx;
return cx->tempLifoAlloc().alloc(bytes);
}
void *realloc_(void *p, size_t oldBytes, size_t bytes) {
void *n = malloc_(bytes);
if (!n)
return n;
memcpy(n, p, Min(oldBytes, bytes));
return n;
}
void free_(void *p) {
}
void reportAllocOverflow() const {
}
};
class TempAllocator
{
LifoAlloc *lifoAlloc_;
@ -68,6 +48,11 @@ class TempAllocator
return p;
}
LifoAlloc *lifoAlloc()
{
return lifoAlloc_;
}
bool ensureBallast() {
// Most infallible Ion allocations are small, so we use a ballast of
// ~16K for now.
@ -75,6 +60,25 @@ class TempAllocator
}
};
class IonAllocPolicy
{
public:
void *malloc_(size_t bytes) {
return GetIonContext()->temp->allocate(bytes);
}
void *realloc_(void *p, size_t oldBytes, size_t bytes) {
void *n = malloc_(bytes);
if (!n)
return n;
memcpy(n, p, Min(oldBytes, bytes));
return n;
}
void free_(void *p) {
}
void reportAllocOverflow() const {
}
};
class AutoIonContextAlloc
{
TempAllocator tempAlloc_;

View File

@ -23,10 +23,11 @@
using namespace js;
using namespace js::ion;
IonBuilder::IonBuilder(JSContext *cx, TempAllocator &temp, MIRGraph &graph, TypeOracle *oracle,
CompileInfo &info, size_t inliningDepth, uint32 loopDepth)
: MIRGenerator(cx, temp, graph, info),
script(info.script()),
IonBuilder::IonBuilder(JSContext *cx, TempAllocator *temp, MIRGraph *graph,
TypeOracle *oracle, CompileInfo *info, size_t inliningDepth, uint32 loopDepth)
: MIRGenerator(cx->compartment, temp, graph, info),
script(info->script()),
cx(cx),
loopDepth_(loopDepth),
callerResumePoint_(NULL),
callerBuilder_(NULL),
@ -35,7 +36,14 @@ IonBuilder::IonBuilder(JSContext *cx, TempAllocator &temp, MIRGraph &graph, Type
failedBoundsCheck_(script->failedBoundsCheck),
lazyArguments_(NULL)
{
pc = info.startPC();
pc = info->startPC();
}
void
IonBuilder::clearForBackEnd()
{
cx = NULL;
oracle = NULL;
}
bool
@ -279,8 +287,13 @@ IonBuilder::build()
// Emit the start instruction, so we can begin real instructions.
current->makeStart(MStart::New(MStart::StartType_Default));
if (instrumentedProfiling())
current->add(MProfilingEnter::New(script));
if (instrumentedProfiling()) {
SPSProfiler *profiler = &cx->runtime->spsProfiler;
const char *string = profiler->profileString(cx, script, script->function());
if (!string)
return false;
current->add(MProfilingEnter::New(string));
}
// Parameters have been checked to correspond to the typeset, now we unbox
// what we can in an infallible manner.
@ -393,8 +406,13 @@ IonBuilder::buildInline(IonBuilder *callerBuilder, MResumePoint *callerResumePoi
current->setCallerResumePoint(callerResumePoint);
// Flag the entry into an inlined function with a special MStart block
if (instrumentedProfiling())
current->add(MProfilingEnter::New(script));
if (instrumentedProfiling()) {
SPSProfiler *profiler = &cx->runtime->spsProfiler;
const char *string = profiler->profileString(cx, script, script->function());
if (!string)
return false;
current->add(MProfilingEnter::New(string));
}
// Connect the entrance block to the last block in the caller's graph.
MBasicBlock *predecessor = callerBuilder->current;
@ -1165,7 +1183,7 @@ IonBuilder::processIfEnd(CFGState &state)
}
current = state.branch.ifFalse;
graph_.moveBlockToEnd(current);
graph().moveBlockToEnd(current);
pc = current->pc();
return ControlStatus_Joined;
}
@ -1180,7 +1198,7 @@ IonBuilder::processIfElseTrueEnd(CFGState &state)
state.stopAt = state.branch.falseEnd;
pc = state.branch.ifFalse->pc();
current = state.branch.ifFalse;
graph_.moveBlockToEnd(current);
graph().moveBlockToEnd(current);
return ControlStatus_Jumped;
}
@ -1230,7 +1248,7 @@ IonBuilder::processBrokenLoop(CFGState &state)
// A broken loop is not a real loop (it has no header or backedge), so
// reset the loop depth.
for (MBasicBlockIterator i(graph_.begin(state.loop.entry)); i != graph_.end(); i++) {
for (MBasicBlockIterator i(graph().begin(state.loop.entry)); i != graph().end(); i++) {
if (i->loopDepth() > loopDepth_)
i->setLoopDepth(i->loopDepth() - 1);
}
@ -1241,7 +1259,7 @@ IonBuilder::processBrokenLoop(CFGState &state)
current = state.loop.successor;
if (current) {
JS_ASSERT(current->loopDepth() == loopDepth_);
graph_.moveBlockToEnd(current);
graph().moveBlockToEnd(current);
}
// Join the breaks together and continue parsing.
@ -1285,7 +1303,7 @@ IonBuilder::finishLoop(CFGState &state, MBasicBlock *successor)
if (!state.loop.entry->setBackedge(current))
return ControlStatus_Error;
if (successor) {
graph_.moveBlockToEnd(successor);
graph().moveBlockToEnd(successor);
successor->inheritPhis(state.loop.entry);
}
@ -1542,7 +1560,7 @@ IonBuilder::processNextTableSwitchCase(CFGState &state)
successor->addPredecessor(current);
// Insert successor after the current block, to maintain RPO.
graph_.moveBlockToEnd(successor);
graph().moveBlockToEnd(successor);
}
// If this is the last successor the block should stop at the end of the tableswitch
@ -1617,7 +1635,7 @@ IonBuilder::processNextLookupSwitchCase(CFGState &state)
}
// Move next body block to end to maintain RPO.
graph_.moveBlockToEnd(successor);
graph().moveBlockToEnd(successor);
// If this is the last successor the block should stop at the end of the lookupswitch
// Else it should stop at the start of the next successor
@ -1676,7 +1694,7 @@ IonBuilder::processAndOrEnd(CFGState &state)
return ControlStatus_Error;
current = state.branch.ifFalse;
graph_.moveBlockToEnd(current);
graph().moveBlockToEnd(current);
pc = current->pc();
return ControlStatus_Joined;
}
@ -2156,7 +2174,7 @@ IonBuilder::tableSwitch(JSOp op, jssrcnote *sn)
}
// Move defaultcase to the end, to maintain RPO.
graph_.moveBlockToEnd(defaultcase);
graph().moveBlockToEnd(defaultcase);
JS_ASSERT(tableswitch->numCases() == (uint32)(high - low + 1));
JS_ASSERT(tableswitch->numSuccessors() > 0);
@ -2370,7 +2388,7 @@ IonBuilder::lookupSwitch(JSOp op, jssrcnote *sn)
for (size_t i = 0; i < bodyBlocks.length(); i++) {
(*state.lookupswitch.bodies)[i] = bodyBlocks[i];
}
graph_.moveBlockToEnd(bodyBlocks[0]);
graph().moveBlockToEnd(bodyBlocks[0]);
// Create control flow info
ControlFlowInfo switchinfo(cfgStack_.length(), exitpc);
@ -2805,7 +2823,8 @@ IonBuilder::jsop_call_inline(HandleFunction callee, uint32 argc, bool constructi
if (!oracle.init(cx, callee->script()))
return false;
IonBuilder inlineBuilder(cx, temp(), graph(), &oracle, *info, inliningDepth + 1, loopDepth_);
IonBuilder inlineBuilder(cx, &temp(), &graph(), &oracle,
info, inliningDepth + 1, loopDepth_);
// Create |this| on the caller-side for inlined constructors.
MDefinition *thisDefn = NULL;
@ -3244,7 +3263,7 @@ IonBuilder::inlineScriptedCall(AutoObjectVector &targets, uint32 argc, bool cons
MConstant *constFun = disp->getFunctionConstant(i);
RootedFunction target(cx, constFun->value().toObject().toFunction());
MBasicBlock *block = disp->getSuccessor(i);
graph_.moveBlockToEnd(block);
graph().moveBlockToEnd(block);
current = block;
if (!jsop_call_inline(target, argc, constructing, constFun, bottom, retvalDefns))
@ -3255,9 +3274,9 @@ IonBuilder::inlineScriptedCall(AutoObjectVector &targets, uint32 argc, bool cons
// a fallback case to consider. Move the fallback blocks to the end of the graph
// and link them to the bottom block.
if (disp->inlinePropertyTable()) {
graph_.moveBlockToEnd(disp->fallbackPrepBlock());
graph_.moveBlockToEnd(disp->fallbackMidBlock());
graph_.moveBlockToEnd(disp->fallbackEndBlock());
graph().moveBlockToEnd(disp->fallbackPrepBlock());
graph().moveBlockToEnd(disp->fallbackMidBlock());
graph().moveBlockToEnd(disp->fallbackEndBlock());
// Link the end fallback block to bottom.
MBasicBlock *fallbackEndBlock = disp->fallbackEndBlock();
@ -3270,7 +3289,7 @@ IonBuilder::inlineScriptedCall(AutoObjectVector &targets, uint32 argc, bool cons
}
}
graph_.moveBlockToEnd(bottom);
graph().moveBlockToEnd(bottom);
bottom->inheritSlots(top);
@ -3803,19 +3822,36 @@ IonBuilder::jsop_compare(JSOp op)
return true;
}
JSObject *
IonBuilder::getNewArrayTemplateObject(uint32 count)
{
JSObject *templateObject = NewDenseUnallocatedArray(cx, count);
if (!templateObject)
return NULL;
if (types::UseNewTypeForInitializer(cx, script, pc, JSProto_Array)) {
if (!templateObject->setSingletonType(cx))
return NULL;
} else {
types::TypeObject *type = types::TypeScript::InitObject(cx, script, pc, JSProto_Array);
if (!type)
return NULL;
templateObject->setType(type);
}
return templateObject;
}
bool
IonBuilder::jsop_newarray(uint32 count)
{
JS_ASSERT(script->hasGlobal());
types::TypeObject *type = NULL;
if (!types::UseNewTypeForInitializer(cx, script, pc, JSProto_Array)) {
type = types::TypeScript::InitObject(cx, script, pc, JSProto_Array);
if (!type)
return false;
}
JSObject *templateObject = getNewArrayTemplateObject(count);
if (!templateObject)
return false;
MNewArray *ins = new MNewArray(count, type, MNewArray::NewArray_Allocating);
MNewArray *ins = new MNewArray(count, templateObject, MNewArray::NewArray_Allocating);
current->add(ins);
current->push(ins);
@ -3829,14 +3865,29 @@ IonBuilder::jsop_newobject(HandleObject baseObj)
// Don't bake in the TypeObject for non-CNG scripts.
JS_ASSERT(script->hasGlobal());
types::TypeObject *type = NULL;
if (!types::UseNewTypeForInitializer(cx, script, pc, JSProto_Object)) {
type = types::TypeScript::InitObject(cx, script, pc, JSProto_Object);
if (!type)
return false;
JSObject *templateObject;
if (baseObj) {
templateObject = CopyInitializerObject(cx, baseObj);
} else {
gc::AllocKind kind = GuessObjectGCKind(0);
templateObject = NewBuiltinClassInstance(cx, &ObjectClass, kind);
}
MNewObject *ins = MNewObject::New(baseObj, type);
if (!templateObject)
return false;
if (types::UseNewTypeForInitializer(cx, script, pc, JSProto_Object)) {
if (!templateObject->setSingletonType(cx))
return false;
} else {
types::TypeObject *type = types::TypeScript::InitObject(cx, script, pc, JSProto_Object);
if (!type)
return false;
templateObject->setType(type);
}
MNewObject *ins = MNewObject::New(templateObject);
current->add(ins);
current->push(ins);
@ -3886,27 +3937,28 @@ IonBuilder::jsop_initprop(HandlePropertyName name)
MDefinition *value = current->pop();
MDefinition *obj = current->peek(-1);
RootedObject baseObj(cx, obj->toNewObject()->baseObj());
RootedObject templateObject(cx, obj->toNewObject()->templateObject());
if (!oracle->propertyWriteCanSpecialize(script, pc)) {
// This should only happen for a few names like __proto__.
return abort("INITPROP Monitored initprop");
}
// JSOP_NEWINIT becomes an MNewObject without a known base.
if (!baseObj) {
RootedObject holder(cx);
RootedShape shape(cx);
RootedId id(cx, NameToId(name));
bool res = LookupPropertyWithFlags(cx, templateObject, id,
JSRESOLVE_QUALIFIED, &holder, &shape);
if (!res)
return false;
if (!shape || holder != templateObject) {
// JSOP_NEWINIT becomes an MNewObject without preconfigured properties.
MInitProp *init = MInitProp::New(obj, name, value);
current->add(init);
return resumeAfter(init);
}
RootedObject holder(cx);
RootedShape shape(cx);
RootedId id(cx, NameToId(name));
DebugOnly<bool> res = LookupPropertyWithFlags(cx, baseObj, id,
JSRESOLVE_QUALIFIED, &holder, &shape);
JS_ASSERT(res && shape && holder == baseObj);
bool needsBarrier = true;
TypeOracle::BinaryTypes b = oracle->binaryTypes(script, pc);
if (b.lhsTypes &&
@ -3916,7 +3968,7 @@ IonBuilder::jsop_initprop(HandlePropertyName name)
needsBarrier = false;
}
if (baseObj->isFixedSlot(shape->slot())) {
if (templateObject->isFixedSlot(shape->slot())) {
MStoreFixedSlot *store = MStoreFixedSlot::New(obj, shape->slot(), value);
if (needsBarrier)
store->setNeedsBarrier();
@ -3928,7 +3980,7 @@ IonBuilder::jsop_initprop(HandlePropertyName name)
MSlots *slots = MSlots::New(obj);
current->add(slots);
MStoreSlot *store = MStoreSlot::New(slots, baseObj->dynamicSlotIndex(shape->slot()), value);
MStoreSlot *store = MStoreSlot::New(slots, templateObject->dynamicSlotIndex(shape->slot()), value);
if (needsBarrier)
store->setNeedsBarrier();
@ -3967,7 +4019,7 @@ IonBuilder::newBlockAfter(MBasicBlock *at, MBasicBlock *predecessor, jsbytecode
MBasicBlock *block = MBasicBlock::New(graph(), info(), predecessor, pc, MBasicBlock::NORMAL);
if (!block)
return NULL;
graph_.insertBlockAfter(at, block);
graph().insertBlockAfter(at, block);
return block;
}
@ -3987,7 +4039,7 @@ IonBuilder::newOsrPreheader(MBasicBlock *predecessor, jsbytecode *loopEntry)
// Create two blocks: one for the OSR entry with no predecessors, one for
// the preheader, which has the OSR entry block as a predecessor. The
// OSR block is always the second block (with id 1).
MBasicBlock *osrBlock = newBlockAfter(*graph_.begin(), loopEntry);
MBasicBlock *osrBlock = newBlockAfter(*graph().begin(), loopEntry);
MBasicBlock *preheader = newBlock(predecessor, loopEntry);
if (!osrBlock || !preheader)
return NULL;
@ -5705,7 +5757,11 @@ IonBuilder::jsop_delprop(JSAtom *atom)
bool
IonBuilder::jsop_regexp(RegExpObject *reobj)
{
MRegExp *ins = MRegExp::New(reobj, MRegExp::MustClone);
JSObject *prototype = script->global().getOrCreateRegExpPrototype(cx);
if (!prototype)
return false;
MRegExp *ins = MRegExp::New(reobj, prototype, MRegExp::MustClone);
current->add(ins);
current->push(ins);

View File

@ -159,8 +159,8 @@ class IonBuilder : public MIRGenerator
static int CmpSuccessors(const void *a, const void *b);
public:
IonBuilder(JSContext *cx, TempAllocator &temp, MIRGraph &graph, TypeOracle *oracle,
CompileInfo &info, size_t inliningDepth = 0, uint32 loopDepth = 0);
IonBuilder(JSContext *cx, TempAllocator *temp, MIRGraph *graph,
TypeOracle *oracle, CompileInfo *info, size_t inliningDepth = 0, uint32 loopDepth = 0);
bool build();
bool buildInline(IonBuilder *callerBuilder, MResumePoint *callerResumePoint,
@ -284,6 +284,8 @@ class IonBuilder : public MIRGenerator
MInstruction *addBoundsCheck(MDefinition *index, MDefinition *length);
JSObject *getNewArrayTemplateObject(uint32 count);
bool invalidatedIdempotentCache();
bool loadSlot(MDefinition *obj, Shape *shape, MIRType rvalType);
@ -423,7 +425,11 @@ class IonBuilder : public MIRGenerator
// A builder is inextricably tied to a particular script.
JSScript * const script;
void clearForBackEnd();
private:
JSContext *cx;
jsbytecode *pc;
MBasicBlock *current;
uint32 loopDepth_;

View File

@ -338,8 +338,8 @@ MacroAssembler::clampDoubleToUint8(FloatRegister input, Register output)
}
void
MacroAssembler::newGCThing(JSContext *cx, const Register &result,
HandleObject templateObject, Label *fail)
MacroAssembler::newGCThing(const Register &result,
JSObject *templateObject, Label *fail)
{
// Inlined equivalent of js::gc::NewGCThing() without failure case handling.
@ -347,12 +347,13 @@ MacroAssembler::newGCThing(JSContext *cx, const Register &result,
JS_ASSERT(allocKind >= gc::FINALIZE_OBJECT0 && allocKind <= gc::FINALIZE_OBJECT_LAST);
int thingSize = (int)gc::Arena::thingSize(allocKind);
JS_ASSERT(cx->typeInferenceEnabled());
JS_ASSERT(!templateObject->hasDynamicElements());
JSCompartment *compartment = GetIonContext()->compartment;
#ifdef JS_GC_ZEAL
// Don't execute the inline path if gcZeal is active.
movePtr(ImmWord(cx->runtime), result);
movePtr(ImmWord(compartment->rt), result);
loadPtr(Address(result, offsetof(JSRuntime, gcZeal_)), result);
branch32(Assembler::NotEqual, result, Imm32(0), fail);
#endif
@ -362,7 +363,7 @@ MacroAssembler::newGCThing(JSContext *cx, const Register &result,
// If a FreeSpan is replaced, its members are updated in the freeLists table,
// which the code below always re-reads.
gc::FreeSpan *list = const_cast<gc::FreeSpan *>
(cx->compartment->arenas.getFreeList(allocKind));
(compartment->arenas.getFreeList(allocKind));
loadPtr(AbsoluteAddress(&list->first), result);
branchPtr(Assembler::BelowOrEqual, AbsoluteAddress(&list->last), result, fail);
@ -372,7 +373,7 @@ MacroAssembler::newGCThing(JSContext *cx, const Register &result,
}
void
MacroAssembler::initGCThing(JSContext *cx, const Register &obj, HandleObject templateObject)
MacroAssembler::initGCThing(const Register &obj, JSObject *templateObject)
{
// Fast initialization of an empty object returned by NewGCThing().

View File

@ -73,7 +73,7 @@ class MacroAssembler : public MacroAssemblerSpecific
: autoRooter_(cx, thisFromCtor()),
enoughMemory_(true)
{
ionContext_.construct(cx, (js::ion::TempAllocator *)NULL);
ionContext_.construct(cx, cx->compartment, (js::ion::TempAllocator *)NULL);
alloc_.construct(cx);
#ifdef JS_CPU_ARM
m_buffer.id = GetIonContext()->getNextAssemblerId();
@ -406,8 +406,8 @@ class MacroAssembler : public MacroAssemblerSpecific
void clampDoubleToUint8(FloatRegister input, Register output);
// Inline allocation.
void newGCThing(JSContext *cx, const Register &result, HandleObject templateObject, Label *fail);
void initGCThing(JSContext *cx, const Register &obj, HandleObject templateObject);
void newGCThing(const Register &result, JSObject *templateObject, Label *fail);
void initGCThing(const Register &obj, JSObject *templateObject);
// If the IonCode that created this assembler needs to transition into the VM,
// we want to store the IonCode on the stack in order to mark it during a GC.

View File

@ -2862,8 +2862,8 @@ class LProfilingEnter : public LInstructionHelper<0, 0, 2>
return getTemp(1);
}
JSScript *script() const {
return mir_->toProfilingEnter()->script();
const char *profileString() const {
return mir_->toProfilingEnter()->profileString();
}
};

View File

@ -146,7 +146,11 @@ IonBuilder::inlineMathFunction(MMathFunction::Function function, uint32 argc, bo
if (!discardCall(argc, argv, current))
return InliningStatus_Error;
MMathFunction *ins = MMathFunction::New(argv[1], function);
MathCache *cache = cx->runtime->getMathCache(cx);
if (!cache)
return InliningStatus_Error;
MMathFunction *ins = MMathFunction::New(argv[1], function, cache);
current->add(ins);
current->push(ins);
return InliningStatus_Inlined;
@ -179,8 +183,11 @@ IonBuilder::inlineArray(uint32 argc, bool constructing)
if (!discardCall(argc, argv, current))
return InliningStatus_Error;
types::TypeObject *type = types::TypeScript::InitObject(cx, script, pc, JSProto_Array);
MNewArray *ins = new MNewArray(initLength, type, MNewArray::NewArray_Unallocating);
JSObject *templateObject = getNewArrayTemplateObject(initLength);
if (!templateObject)
return InliningStatus_Error;
MNewArray *ins = new MNewArray(initLength, templateObject, MNewArray::NewArray_Unallocating);
current->add(ins);
current->push(ins);

View File

@ -763,7 +763,7 @@ MMod::foldsTo(bool useValueNumbers)
if (MDefinition *folded = EvaluateConstantOperands(this))
return folded;
JSRuntime *rt = GetIonContext()->cx->runtime;
JSRuntime *rt = GetIonContext()->compartment->rt;
double NaN = rt->NaNValue.toDouble();
double Inf = rt->positiveInfinityValue.toDouble();
@ -1078,8 +1078,8 @@ MTypeOf::foldsTo(bool useValueNumbers)
return this;
}
JSContext *cx = GetIonContext()->cx;
return MConstant::New(StringValue(cx->runtime->atomState.typeAtoms[type]));
JSRuntime *rt = GetIonContext()->compartment->rt;
return MConstant::New(StringValue(rt->atomState.typeAtoms[type]));
}
MBitAnd *
@ -1196,11 +1196,8 @@ MToDouble::foldsTo(bool useValueNumbers)
{
if (input()->isConstant()) {
const Value &v = input()->toConstant()->value();
if (v.isPrimitive()) {
double out;
DebugOnly<bool> ok = ToNumber(GetIonContext()->cx, v, &out);
JS_ASSERT(ok);
if (v.isNumber()) {
double out = v.toNumber();
return MConstant::New(DoubleValue(out));
}
}

View File

@ -948,17 +948,17 @@ class MNewArray : public MNullaryInstruction
private:
// Number of space to allocate for the array.
uint32 count_;
// Type of the object.
HeapPtr<types::TypeObject> type_;
// Template for the created object.
HeapPtr<JSObject> templateObject_;
// Allocate space at initialization or not
AllocatingBehaviour allocating_;
public:
INSTRUCTION_HEADER(NewArray);
MNewArray(uint32 count, types::TypeObject *type, AllocatingBehaviour allocating)
MNewArray(uint32 count, JSObject *templateObject, AllocatingBehaviour allocating)
: count_(count),
type_(type),
templateObject_(templateObject),
allocating_(allocating)
{
setResultType(MIRType_Object);
@ -968,8 +968,8 @@ class MNewArray : public MNullaryInstruction
return count_;
}
types::TypeObject *type() const {
return type_;
JSObject *templateObject() const {
return templateObject_;
}
bool isAllocating() const {
@ -990,11 +990,11 @@ class MNewArray : public MNullaryInstruction
class MNewObject : public MNullaryInstruction
{
CompilerRootObject baseObj_;
HeapPtr<types::TypeObject> type_;
// Template for the created object.
HeapPtr<JSObject> templateObject_;
MNewObject(HandleObject baseObj, types::TypeObject *type)
: baseObj_(baseObj),
type_(type)
MNewObject(JSObject *templateObject)
: templateObject_(templateObject)
{
setResultType(MIRType_Object);
}
@ -1002,15 +1002,12 @@ class MNewObject : public MNullaryInstruction
public:
INSTRUCTION_HEADER(NewObject);
static MNewObject *New(HandleObject baseObj, types::TypeObject *type) {
return new MNewObject(baseObj, type);
static MNewObject *New(JSObject *templateObject) {
return new MNewObject(templateObject);
}
JSObject *baseObj() const {
return baseObj_;
}
types::TypeObject *type() const {
return type_;
JSObject *templateObject() const {
return templateObject_;
}
};
@ -2281,9 +2278,10 @@ class MMathFunction
private:
Function function_;
MathCache *cache_;
MMathFunction(MDefinition *input, Function function)
: MUnaryInstruction(input), function_(function)
MMathFunction(MDefinition *input, Function function, MathCache *cache)
: MUnaryInstruction(input), function_(function), cache_(cache)
{
setResultType(MIRType_Double);
setMovable();
@ -2291,12 +2289,15 @@ class MMathFunction
public:
INSTRUCTION_HEADER(MathFunction);
static MMathFunction *New(MDefinition *input, Function function) {
return new MMathFunction(input, function);
static MMathFunction *New(MDefinition *input, Function function, MathCache *cache) {
return new MMathFunction(input, function, cache);
}
Function function() const {
return function_;
}
MathCache *cache() const {
return cache_;
}
MDefinition *input() const {
return getOperand(0);
}
@ -2886,10 +2887,12 @@ class MRegExp : public MNullaryInstruction
private:
HeapPtr<RegExpObject> source_;
HeapPtr<JSObject> prototype_;
CloneBehavior shouldClone_;
MRegExp(RegExpObject *source, CloneBehavior shouldClone)
MRegExp(RegExpObject *source, JSObject *prototype, CloneBehavior shouldClone)
: source_(source),
prototype_(prototype),
shouldClone_(shouldClone)
{
setResultType(MIRType_Object);
@ -2903,13 +2906,16 @@ class MRegExp : public MNullaryInstruction
public:
INSTRUCTION_HEADER(RegExp)
static MRegExp *New(RegExpObject *source, CloneBehavior shouldClone) {
return new MRegExp(source, shouldClone);
static MRegExp *New(RegExpObject *source, JSObject *prototype, CloneBehavior shouldClone) {
return new MRegExp(source, prototype, shouldClone);
}
const HeapPtr<RegExpObject> &source() const {
return source_;
}
JSObject *getRegExpPrototype() const {
return prototype_;
}
CloneBehavior shouldClone() const {
return shouldClone_;
}
@ -5154,22 +5160,22 @@ class MNewCallObject : public MUnaryInstruction
// ones)
class MProfilingEnter : public MNullaryInstruction
{
JSScript *script_;
const char *string_;
MProfilingEnter(JSScript *script) : script_(script) {
JS_ASSERT(script != NULL);
MProfilingEnter(const char *string) : string_(string) {
JS_ASSERT(string != NULL);
setGuard();
}
public:
INSTRUCTION_HEADER(ProfilingEnter);
static MProfilingEnter *New(JSScript *script) {
return new MProfilingEnter(script);
static MProfilingEnter *New(const char *string) {
return new MProfilingEnter(string);
}
JSScript *script() {
return script_;
const char *profileString() {
return string_;
}
AliasSet getAliasSet() const {

View File

@ -28,22 +28,22 @@ class MStart;
class MIRGenerator
{
public:
MIRGenerator(JSContext *cx, TempAllocator &temp, MIRGraph &graph, CompileInfo &info);
MIRGenerator(JSCompartment *compartment, TempAllocator *temp, MIRGraph *graph, CompileInfo *info);
TempAllocator &temp() {
return temp_;
return *temp_;
}
MIRGraph &graph() {
return graph_;
return *graph_;
}
bool ensureBallast() {
return temp().ensureBallast();
}
IonCompartment *ionCompartment() const {
return cx->compartment->ionCompartment();
return compartment->ionCompartment();
}
CompileInfo &info() {
return info_;
return *info_;
}
template <typename T>
@ -61,14 +61,14 @@ class MIRGenerator
}
public:
JSContext *cx;
JSCompartment *compartment;
protected:
CompileInfo &info_;
TempAllocator &temp_;
CompileInfo *info_;
TempAllocator *temp_;
JSFunction *fun_;
uint32 nslots_;
MIRGraph &graph_;
MIRGraph *graph_;
bool error_;
};

View File

@ -16,8 +16,9 @@
using namespace js;
using namespace js::ion;
MIRGenerator::MIRGenerator(JSContext *cx, TempAllocator &temp, MIRGraph &graph, CompileInfo &info)
: cx(cx),
MIRGenerator::MIRGenerator(JSCompartment *compartment,
TempAllocator *temp, MIRGraph *graph, CompileInfo *info)
: compartment(compartment),
info_(info),
temp_(temp),
graph_(graph),

View File

@ -454,7 +454,7 @@ typedef Vector<MBasicBlock *, 1, IonAllocPolicy> MIRGraphExits;
class MIRGraph
{
InlineList<MBasicBlock> blocks_;
TempAllocator &alloc_;
TempAllocator *alloc_;
MIRGraphExits *exitAccumulator_;
uint32 blockIdGen_;
uint32 idGen_;
@ -465,7 +465,7 @@ class MIRGraph
#endif
public:
MIRGraph(TempAllocator &alloc)
MIRGraph(TempAllocator *alloc)
: alloc_(alloc),
exitAccumulator_(NULL),
blockIdGen_(0),
@ -479,7 +479,7 @@ class MIRGraph
template <typename T>
T * allocate(size_t count = 1) {
return reinterpret_cast<T *>(alloc_.allocate(sizeof(T) * count));
return reinterpret_cast<T *>(alloc_->allocate(sizeof(T) * count));
}
void addBlock(MBasicBlock *block);

View File

@ -250,28 +250,20 @@ NewInitArray(JSContext *cx, uint32_t count, types::TypeObject *type)
}
JSObject*
NewInitObject(JSContext *cx, HandleObject baseObj, types::TypeObject *type)
NewInitObject(JSContext *cx, HandleObject templateObject)
{
RootedObject obj(cx);
if (baseObj) {
// JSOP_NEWOBJECT
obj = CopyInitializerObject(cx, baseObj);
} else {
// JSOP_NEWINIT
gc::AllocKind kind = GuessObjectGCKind(0);
obj = NewBuiltinClassInstance(cx, &ObjectClass, kind);
}
RootedObject obj(cx, CopyInitializerObject(cx, templateObject));
if (!obj)
return NULL;
if (!type) {
if (templateObject->hasSingletonType()) {
if (!obj->setSingletonType(cx))
return NULL;
types::TypeScript::Monitor(cx, ObjectValue(*obj));
} else {
obj->setType(type);
obj->setType(templateObject->type());
}
return obj;

View File

@ -424,7 +424,7 @@ bool IteratorMore(JSContext *cx, HandleObject obj, JSBool *res);
// Allocation functions for JSOP_NEWARRAY and JSOP_NEWOBJECT
JSObject *NewInitArray(JSContext *cx, uint32_t count, types::TypeObject *type);
JSObject *NewInitObject(JSContext *cx, HandleObject baseObj, types::TypeObject *type);
JSObject *NewInitObject(JSContext *cx, HandleObject templateObject);
bool ArrayPopDense(JSContext *cx, JSObject *obj, Value *rval);
bool ArrayPushDense(JSContext *cx, JSObject *obj, const Value &v, uint32_t *length);

View File

@ -176,8 +176,9 @@ CodeGeneratorARM::generateOutOfLineCode()
// Push the frame size, so the handler can recover the IonScript.
masm.ma_mov(Imm32(frameSize()), lr);
IonCompartment *ion = gen->cx->compartment->ionCompartment();
IonCode *handler = ion->getGenericBailoutHandler(gen->cx);
JSContext *cx = GetIonContext()->cx;
IonCompartment *ion = cx->compartment->ionCompartment();
IonCode *handler = ion->getGenericBailoutHandler(cx);
if (!handler)
return false;
masm.branch(handler);
@ -1409,7 +1410,7 @@ CodeGeneratorARM::visitInterruptCheck(LInterruptCheck *lir)
if (!ool)
return false;
void *interrupt = (void*)&gen->cx->runtime->interrupt;
void *interrupt = (void*)&gen->compartment->rt->interrupt;
masm.load32(AbsoluteAddress(interrupt), lr);
masm.ma_cmp(lr, Imm32(0));
masm.ma_b(ool->entry(), Assembler::NonZero);
@ -1430,9 +1431,12 @@ CodeGeneratorARM::generateInvalidateEpilogue()
// Push the return address of the point that we bailed out at onto the stack
masm.Push(lr);
JSContext *cx = GetIonContext()->cx;
// Push the Ion script onto the stack (when we determine what that pointer is).
invalidateEpilogueData_ = masm.pushWithPatch(ImmWord(uintptr_t(-1)));
IonCode *thunk = gen->cx->compartment->ionCompartment()->getOrCreateInvalidationThunk(gen->cx);
IonCode *thunk = cx->compartment->ionCompartment()->getOrCreateInvalidationThunk(cx);
if (!thunk)
return false;

View File

@ -201,7 +201,7 @@ CodeGeneratorShared::encode(LSnapshot *snapshot)
DebugOnly<jsbytecode *> bailPC = pc;
if (mir->mode() == MResumePoint::ResumeAfter)
bailPC = GetNextPc(pc);
JS_ASSERT(exprStack == js_ReconstructStackDepth(gen->cx, script, bailPC));
JS_ASSERT(exprStack == js_ReconstructStackDepth(GetIonContext()->cx, script, bailPC));
#ifdef TRACK_SNAPSHOTS
LInstruction *ins = instruction();
@ -360,8 +360,9 @@ CodeGeneratorShared::callVM(const VMFunction &fun, LInstruction *ins, const Regi
#endif
// Generate the wrapper of the VM function.
IonCompartment *ion = gen->cx->compartment->ionCompartment();
IonCode *wrapper = ion->generateVMWrapper(gen->cx, fun);
JSContext *cx = GetIonContext()->cx;
IonCompartment *ion = cx->compartment->ionCompartment();
IonCode *wrapper = ion->generateVMWrapper(cx, fun);
if (!wrapper)
return false;

View File

@ -293,8 +293,9 @@ CodeGeneratorX86Shared::generateOutOfLineCode()
// Push the frame size, so the handler can recover the IonScript.
masm.push(Imm32(frameSize()));
IonCompartment *ion = gen->cx->compartment->ionCompartment();
IonCode *handler = ion->getGenericBailoutHandler(gen->cx);
JSContext *cx = GetIonContext()->cx;
IonCompartment *ion = cx->compartment->ionCompartment();
IonCode *handler = ion->getGenericBailoutHandler(cx);
if (!handler)
return false;
@ -1248,9 +1249,11 @@ CodeGeneratorX86Shared::generateInvalidateEpilogue()
masm.bind(&invalidate_);
JSContext *cx = GetIonContext()->cx;
// Push the Ion script onto the stack (when we determine what that pointer is).
invalidateEpilogueData_ = masm.pushWithPatch(ImmWord(uintptr_t(-1)));
IonCode *thunk = gen->cx->compartment->ionCompartment()->getOrCreateInvalidationThunk(gen->cx);
IonCode *thunk = cx->compartment->ionCompartment()->getOrCreateInvalidationThunk(cx);
if (!thunk)
return false;

View File

@ -304,7 +304,7 @@ CodeGeneratorX64::visitInterruptCheck(LInterruptCheck *lir)
if (!ool)
return false;
void *interrupt = (void*)&gen->cx->runtime->interrupt;
void *interrupt = (void*)&gen->compartment->rt->interrupt;
masm.movq(ImmWord(interrupt), ScratchReg);
masm.cmpl(Operand(ScratchReg, 0), Imm32(0));
masm.j(Assembler::NonZero, ool->entry());

View File

@ -298,7 +298,7 @@ CodeGeneratorX86::visitInterruptCheck(LInterruptCheck *lir)
if (!ool)
return false;
void *interrupt = (void*)&gen->cx->runtime->interrupt;
void *interrupt = (void*)&gen->compartment->rt->interrupt;
masm.cmpl(Operand(interrupt), Imm32(0));
masm.j(Assembler::NonZero, ool->entry());
masm.bind(ool->rejoin());

View File

@ -12,6 +12,8 @@
#include "ion/IonFrames.h"
#include "ion/MoveResolver.h"
#include "jscompartment.h"
namespace js {
namespace ion {
@ -707,8 +709,8 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared
// Save an exit frame (which must be aligned to the stack pointer) to
// ThreadData::ionTop.
void linkExitFrame() {
JSContext *cx = GetIonContext()->cx;
movl(StackPointer, Operand(&cx->runtime->ionTop));
JSCompartment *compartment = GetIonContext()->compartment;
movl(StackPointer, Operand(&compartment->rt->ionTop));
}
void callWithExitFrame(IonCode *target, Register dynStack) {

View File

@ -26,6 +26,7 @@ namespace ion {
}
# define ION_DISABLED_SCRIPT ((js::ion::IonScript *)0x1)
# define ION_COMPILING_SCRIPT ((js::ion::IonScript *)0x2)
struct Shape;

View File

@ -1029,7 +1029,7 @@ mjit::EnterMethodJIT(JSContext *cx, StackFrame *fp, void *code, Value *stackLimi
JSBool ok;
{
AssertCompartmentUnchanged pcc(cx);
ion::IonContext ictx(cx, NULL);
ion::IonContext ictx(cx, cx->compartment, NULL);
ion::IonActivation activation(cx, NULL);
JSAutoResolveFlags rf(cx, RESOLVE_INFER);