зеркало из https://github.com/mozilla/gecko-dev.git
Bug 969012 - Use a second register for object allocation; r=jandem
--HG-- extra : rebase_source : 2cbc07d17ed3cf84fbc2590745a4c22a62ee573c
This commit is contained in:
Родитель
17f4a32d8b
Коммит
944db060be
|
@ -964,6 +964,7 @@ CodeGenerator::visitLambda(LLambda *lir)
|
|||
{
|
||||
Register scopeChain = ToRegister(lir->scopeChain());
|
||||
Register output = ToRegister(lir->output());
|
||||
Register tempReg = ToRegister(lir->temp());
|
||||
const LambdaFunctionInfo &info = lir->mir()->info();
|
||||
|
||||
OutOfLineCode *ool = oolCallVM(LambdaInfo, lir, (ArgList(), ImmGCPtr(info.fun), scopeChain),
|
||||
|
@ -973,8 +974,8 @@ CodeGenerator::visitLambda(LLambda *lir)
|
|||
|
||||
JS_ASSERT(!info.singletonType);
|
||||
|
||||
masm.newGCThing(output, info.fun, ool->entry(), gc::DefaultHeap);
|
||||
masm.initGCThing(output, info.fun);
|
||||
masm.newGCThing(output, tempReg, info.fun, ool->entry(), gc::DefaultHeap);
|
||||
masm.initGCThing(output, tempReg, info.fun);
|
||||
|
||||
emitLambdaInit(output, scopeChain, info);
|
||||
|
||||
|
@ -983,7 +984,7 @@ CodeGenerator::visitLambda(LLambda *lir)
|
|||
}
|
||||
|
||||
void
|
||||
CodeGenerator::emitLambdaInit(const Register &output, const Register &scopeChain,
|
||||
CodeGenerator::emitLambdaInit(Register output, Register scopeChain,
|
||||
const LambdaFunctionInfo &info)
|
||||
{
|
||||
// Initialize nargs and flags. We do this with a single uint32 to avoid
|
||||
|
@ -3396,6 +3397,7 @@ CodeGenerator::visitNewArray(LNewArray *lir)
|
|||
{
|
||||
JS_ASSERT(gen->info().executionMode() == SequentialExecution);
|
||||
Register objReg = ToRegister(lir->output());
|
||||
Register tempReg = ToRegister(lir->temp());
|
||||
JSObject *templateObject = lir->mir()->templateObject();
|
||||
DebugOnly<uint32_t> count = lir->mir()->count();
|
||||
|
||||
|
@ -3408,8 +3410,8 @@ CodeGenerator::visitNewArray(LNewArray *lir)
|
|||
if (!addOutOfLineCode(ool))
|
||||
return false;
|
||||
|
||||
masm.newGCThing(objReg, templateObject, ool->entry(), lir->mir()->initialHeap());
|
||||
masm.initGCThing(objReg, templateObject);
|
||||
masm.newGCThing(objReg, tempReg, templateObject, ool->entry(), lir->mir()->initialHeap());
|
||||
masm.initGCThing(objReg, tempReg, templateObject);
|
||||
|
||||
masm.bind(ool->rejoin());
|
||||
return true;
|
||||
|
@ -3485,6 +3487,7 @@ CodeGenerator::visitNewObject(LNewObject *lir)
|
|||
{
|
||||
JS_ASSERT(gen->info().executionMode() == SequentialExecution);
|
||||
Register objReg = ToRegister(lir->output());
|
||||
Register tempReg = ToRegister(lir->temp());
|
||||
JSObject *templateObject = lir->mir()->templateObject();
|
||||
|
||||
if (lir->mir()->shouldUseVM())
|
||||
|
@ -3494,8 +3497,8 @@ CodeGenerator::visitNewObject(LNewObject *lir)
|
|||
if (!addOutOfLineCode(ool))
|
||||
return false;
|
||||
|
||||
masm.newGCThing(objReg, templateObject, ool->entry(), lir->mir()->initialHeap());
|
||||
masm.initGCThing(objReg, templateObject);
|
||||
masm.newGCThing(objReg, tempReg, templateObject, ool->entry(), lir->mir()->initialHeap());
|
||||
masm.initGCThing(objReg, tempReg, templateObject);
|
||||
|
||||
masm.bind(ool->rejoin());
|
||||
return true;
|
||||
|
@ -3517,7 +3520,8 @@ static const VMFunction NewDeclEnvObjectInfo =
|
|||
bool
|
||||
CodeGenerator::visitNewDeclEnvObject(LNewDeclEnvObject *lir)
|
||||
{
|
||||
Register obj = ToRegister(lir->output());
|
||||
Register objReg = ToRegister(lir->output());
|
||||
Register tempReg = ToRegister(lir->temp());
|
||||
JSObject *templateObj = lir->mir()->templateObj();
|
||||
CompileInfo &info = lir->mir()->block()->info();
|
||||
|
||||
|
@ -3525,12 +3529,12 @@ CodeGenerator::visitNewDeclEnvObject(LNewDeclEnvObject *lir)
|
|||
OutOfLineCode *ool = oolCallVM(NewDeclEnvObjectInfo, lir,
|
||||
(ArgList(), ImmGCPtr(info.funMaybeLazy()),
|
||||
Imm32(gc::DefaultHeap)),
|
||||
StoreRegisterTo(obj));
|
||||
StoreRegisterTo(objReg));
|
||||
if (!ool)
|
||||
return false;
|
||||
|
||||
masm.newGCThing(obj, templateObj, ool->entry(), gc::DefaultHeap);
|
||||
masm.initGCThing(obj, templateObj);
|
||||
masm.newGCThing(objReg, tempReg, templateObj, ool->entry(), gc::DefaultHeap);
|
||||
masm.initGCThing(objReg, tempReg, templateObj);
|
||||
masm.bind(ool->rejoin());
|
||||
return true;
|
||||
}
|
||||
|
@ -3543,7 +3547,8 @@ static const VMFunction NewCallObjectInfo =
|
|||
bool
|
||||
CodeGenerator::visitNewCallObject(LNewCallObject *lir)
|
||||
{
|
||||
Register obj = ToRegister(lir->output());
|
||||
Register objReg = ToRegister(lir->output());
|
||||
Register tempReg = ToRegister(lir->temp());
|
||||
|
||||
JSObject *templateObj = lir->mir()->templateObject();
|
||||
|
||||
|
@ -3555,14 +3560,14 @@ CodeGenerator::visitNewCallObject(LNewCallObject *lir)
|
|||
ImmGCPtr(templateObj->lastProperty()),
|
||||
ImmGCPtr(templateObj->hasSingletonType() ? nullptr : templateObj->type()),
|
||||
ToRegister(lir->slots())),
|
||||
StoreRegisterTo(obj));
|
||||
StoreRegisterTo(objReg));
|
||||
} else {
|
||||
ool = oolCallVM(NewCallObjectInfo, lir,
|
||||
(ArgList(), ImmGCPtr(lir->mir()->block()->info().script()),
|
||||
ImmGCPtr(templateObj->lastProperty()),
|
||||
ImmGCPtr(templateObj->hasSingletonType() ? nullptr : templateObj->type()),
|
||||
ImmPtr(nullptr)),
|
||||
StoreRegisterTo(obj));
|
||||
StoreRegisterTo(objReg));
|
||||
}
|
||||
if (!ool)
|
||||
return false;
|
||||
|
@ -3571,11 +3576,11 @@ CodeGenerator::visitNewCallObject(LNewCallObject *lir)
|
|||
// Objects can only be given singleton types in VM calls.
|
||||
masm.jump(ool->entry());
|
||||
} else {
|
||||
masm.newGCThing(obj, templateObj, ool->entry(), gc::DefaultHeap);
|
||||
masm.initGCThing(obj, templateObj);
|
||||
masm.newGCThing(objReg, tempReg, templateObj, ool->entry(), gc::DefaultHeap);
|
||||
masm.initGCThing(objReg, tempReg, templateObj);
|
||||
|
||||
if (lir->slots()->isRegister())
|
||||
masm.storePtr(ToRegister(lir->slots()), Address(obj, JSObject::offsetOfSlots()));
|
||||
masm.storePtr(ToRegister(lir->slots()), Address(objReg, JSObject::offsetOfSlots()));
|
||||
}
|
||||
|
||||
masm.bind(ool->rejoin());
|
||||
|
@ -3661,8 +3666,8 @@ CodeGenerator::visitNewStringObject(LNewStringObject *lir)
|
|||
if (!ool)
|
||||
return false;
|
||||
|
||||
masm.newGCThing(output, templateObj, ool->entry(), gc::DefaultHeap);
|
||||
masm.initGCThing(output, templateObj);
|
||||
masm.newGCThing(output, temp, templateObj, ool->entry(), gc::DefaultHeap);
|
||||
masm.initGCThing(output, temp, templateObj);
|
||||
|
||||
masm.loadStringLength(input, temp);
|
||||
|
||||
|
@ -3704,9 +3709,8 @@ public:
|
|||
};
|
||||
|
||||
bool
|
||||
CodeGenerator::emitAllocateGCThingPar(LInstruction *lir, const Register &objReg,
|
||||
const Register &cxReg, const Register &tempReg1,
|
||||
const Register &tempReg2, JSObject *templateObj)
|
||||
CodeGenerator::emitAllocateGCThingPar(LInstruction *lir, Register objReg, Register cxReg,
|
||||
Register tempReg1, Register tempReg2, JSObject *templateObj)
|
||||
{
|
||||
gc::AllocKind allocKind = templateObj->tenuredGetAllocKind();
|
||||
OutOfLineNewGCThingPar *ool = new(alloc()) OutOfLineNewGCThingPar(lir, allocKind, objReg, cxReg);
|
||||
|
@ -3715,7 +3719,7 @@ CodeGenerator::emitAllocateGCThingPar(LInstruction *lir, const Register &objReg,
|
|||
|
||||
masm.newGCThingPar(objReg, cxReg, tempReg1, tempReg2, templateObj, ool->entry());
|
||||
masm.bind(ool->rejoin());
|
||||
masm.initGCThing(objReg, templateObj);
|
||||
masm.initGCThing(objReg, tempReg1, templateObj);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -3899,6 +3903,7 @@ CodeGenerator::visitCreateThisWithTemplate(LCreateThisWithTemplate *lir)
|
|||
gc::AllocKind allocKind = templateObject->tenuredGetAllocKind();
|
||||
gc::InitialHeap initialHeap = lir->mir()->initialHeap();
|
||||
Register objReg = ToRegister(lir->output());
|
||||
Register tempReg = ToRegister(lir->temp());
|
||||
|
||||
OutOfLineCode *ool = oolCallVM(NewGCObjectInfo, lir,
|
||||
(ArgList(), Imm32(allocKind), Imm32(initialHeap)),
|
||||
|
@ -3907,11 +3912,11 @@ CodeGenerator::visitCreateThisWithTemplate(LCreateThisWithTemplate *lir)
|
|||
return false;
|
||||
|
||||
// Allocate. If the FreeList is empty, call to VM, which may GC.
|
||||
masm.newGCThing(objReg, templateObject, ool->entry(), lir->mir()->initialHeap());
|
||||
masm.newGCThing(objReg, tempReg, templateObject, ool->entry(), lir->mir()->initialHeap());
|
||||
|
||||
// Initialize based on the templateObject.
|
||||
masm.bind(ool->rejoin());
|
||||
masm.initGCThing(objReg, templateObject);
|
||||
masm.initGCThing(objReg, tempReg, templateObject);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -4865,7 +4870,7 @@ JitCompartment::generateStringConcatStub(JSContext *cx, ExecutionMode mode)
|
|||
// Allocate a new rope.
|
||||
switch (mode) {
|
||||
case SequentialExecution:
|
||||
masm.newGCString(output, &failure);
|
||||
masm.newGCString(output, temp3, &failure);
|
||||
break;
|
||||
case ParallelExecution:
|
||||
masm.push(temp1);
|
||||
|
@ -4910,7 +4915,7 @@ JitCompartment::generateStringConcatStub(JSContext *cx, ExecutionMode mode)
|
|||
// Allocate a JSShortString.
|
||||
switch (mode) {
|
||||
case SequentialExecution:
|
||||
masm.newGCShortString(output, &failure);
|
||||
masm.newGCShortString(output, temp3, &failure);
|
||||
break;
|
||||
case ParallelExecution:
|
||||
masm.push(temp1);
|
||||
|
@ -5630,8 +5635,8 @@ CodeGenerator::visitArrayConcat(LArrayConcat *lir)
|
|||
|
||||
// Try to allocate an object.
|
||||
JSObject *templateObj = lir->mir()->templateObj();
|
||||
masm.newGCThing(temp1, templateObj, &fail, lir->mir()->initialHeap());
|
||||
masm.initGCThing(temp1, templateObj);
|
||||
masm.newGCThing(temp1, temp2, templateObj, &fail, lir->mir()->initialHeap());
|
||||
masm.initGCThing(temp1, temp2, templateObj);
|
||||
masm.jump(&call);
|
||||
{
|
||||
masm.bind(&fail);
|
||||
|
@ -6002,8 +6007,8 @@ CodeGenerator::visitRest(LRest *lir)
|
|||
JSObject *templateObject = lir->mir()->templateObject();
|
||||
|
||||
Label joinAlloc, failAlloc;
|
||||
masm.newGCThing(temp2, templateObject, &failAlloc, gc::DefaultHeap);
|
||||
masm.initGCThing(temp2, templateObject);
|
||||
masm.newGCThing(temp2, temp0, templateObject, &failAlloc, gc::DefaultHeap);
|
||||
masm.initGCThing(temp2, temp0, templateObject);
|
||||
masm.jump(&joinAlloc);
|
||||
{
|
||||
masm.bind(&failAlloc);
|
||||
|
|
|
@ -366,13 +366,13 @@ class CodeGenerator : public CodeGeneratorSpecific
|
|||
|
||||
bool generateBranchV(const ValueOperand &value, Label *ifTrue, Label *ifFalse, FloatRegister fr);
|
||||
|
||||
bool emitAllocateGCThingPar(LInstruction *lir, const Register &objReg, const Register &cxReg,
|
||||
const Register &tempReg1, const Register &tempReg2,
|
||||
bool emitAllocateGCThingPar(LInstruction *lir, Register objReg, Register cxReg,
|
||||
Register tempReg1, Register tempReg2,
|
||||
JSObject *templateObj);
|
||||
|
||||
bool emitCallToUncompiledScriptPar(LInstruction *lir, Register calleeReg);
|
||||
|
||||
void emitLambdaInit(const Register &resultReg, const Register &scopeChainReg,
|
||||
void emitLambdaInit(Register resultReg, Register scopeChainReg,
|
||||
const LambdaFunctionInfo &info);
|
||||
|
||||
bool emitFilterArgumentsOrEval(LInstruction *lir, Register string, Register temp1,
|
||||
|
|
|
@ -7928,7 +7928,7 @@ IonBuilder::jsop_rest()
|
|||
|
||||
// Unroll the argument copy loop. We don't need to do any bounds or hole
|
||||
// checking here.
|
||||
MConstant *index;
|
||||
MConstant *index = nullptr;
|
||||
for (unsigned i = numFormals; i < numActuals; i++) {
|
||||
index = MConstant::New(alloc(), Int32Value(i - numFormals));
|
||||
current->add(index);
|
||||
|
|
|
@ -361,7 +361,7 @@ MacroAssembler::branchNurseryPtr(Condition cond, const Address &ptr1, const ImmM
|
|||
}
|
||||
|
||||
void
|
||||
MacroAssembler::moveNurseryPtr(const ImmMaybeNurseryPtr &ptr, const Register ®)
|
||||
MacroAssembler::moveNurseryPtr(const ImmMaybeNurseryPtr &ptr, Register reg)
|
||||
{
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
if (ptr.value && gc::IsInsideNursery(GetIonContext()->cx->runtime(), (void *)ptr.value))
|
||||
|
@ -634,7 +634,7 @@ MacroAssembler::clampDoubleToUint8(FloatRegister input, Register output)
|
|||
}
|
||||
|
||||
void
|
||||
MacroAssembler::newGCThing(const Register &result, gc::AllocKind allocKind, Label *fail,
|
||||
MacroAssembler::newGCThing(Register result, Register temp, gc::AllocKind allocKind, Label *fail,
|
||||
gc::InitialHeap initialHeap /* = gc::DefaultHeap */)
|
||||
{
|
||||
// Inlined equivalent of js::gc::NewGCThing() without failure case handling.
|
||||
|
@ -662,10 +662,9 @@ MacroAssembler::newGCThing(const Register &result, gc::AllocKind allocKind, Labe
|
|||
// in such cases.
|
||||
const Nursery &nursery = GetIonContext()->runtime->gcNursery();
|
||||
loadPtr(AbsoluteAddress(nursery.addressOfPosition()), result);
|
||||
addPtr(Imm32(thingSize), result);
|
||||
branchPtr(Assembler::BelowOrEqual, AbsoluteAddress(nursery.addressOfCurrentEnd()), result, fail);
|
||||
storePtr(result, AbsoluteAddress(nursery.addressOfPosition()));
|
||||
subPtr(Imm32(thingSize), result);
|
||||
computeEffectiveAddress(Address(result, thingSize), temp);
|
||||
branchPtr(Assembler::BelowOrEqual, AbsoluteAddress(nursery.addressOfCurrentEnd()), temp, fail);
|
||||
storePtr(temp, AbsoluteAddress(nursery.addressOfPosition()));
|
||||
return;
|
||||
}
|
||||
#endif // JSGC_GENERATIONAL
|
||||
|
@ -678,37 +677,34 @@ MacroAssembler::newGCThing(const Register &result, gc::AllocKind allocKind, Labe
|
|||
// which the code below always re-reads.
|
||||
loadPtr(AbsoluteAddress(zone->addressOfFreeListFirst(allocKind)), result);
|
||||
branchPtr(Assembler::BelowOrEqual, AbsoluteAddress(zone->addressOfFreeListLast(allocKind)), result, fail);
|
||||
|
||||
addPtr(Imm32(thingSize), result);
|
||||
storePtr(result, AbsoluteAddress(zone->addressOfFreeListFirst(allocKind)));
|
||||
subPtr(Imm32(thingSize), result);
|
||||
computeEffectiveAddress(Address(result, thingSize), temp);
|
||||
storePtr(temp, AbsoluteAddress(zone->addressOfFreeListFirst(allocKind)));
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::newGCThing(const Register &result, JSObject *templateObject,
|
||||
Label *fail, gc::InitialHeap initialHeap)
|
||||
MacroAssembler::newGCThing(Register result, Register temp, JSObject *templateObject, Label *fail,
|
||||
gc::InitialHeap initialHeap)
|
||||
{
|
||||
gc::AllocKind allocKind = templateObject->tenuredGetAllocKind();
|
||||
JS_ASSERT(allocKind >= gc::FINALIZE_OBJECT0 && allocKind <= gc::FINALIZE_OBJECT_LAST);
|
||||
|
||||
newGCThing(result, allocKind, fail, initialHeap);
|
||||
newGCThing(result, temp, allocKind, fail, initialHeap);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::newGCString(const Register &result, Label *fail)
|
||||
MacroAssembler::newGCString(Register result, Register temp, Label *fail)
|
||||
{
|
||||
newGCThing(result, js::gc::FINALIZE_STRING, fail);
|
||||
newGCThing(result, temp, js::gc::FINALIZE_STRING, fail);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::newGCShortString(const Register &result, Label *fail)
|
||||
MacroAssembler::newGCShortString(Register result, Register temp, Label *fail)
|
||||
{
|
||||
newGCThing(result, js::gc::FINALIZE_SHORT_STRING, fail);
|
||||
newGCThing(result, temp, js::gc::FINALIZE_SHORT_STRING, fail);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::newGCThingPar(const Register &result, const Register &cx,
|
||||
const Register &tempReg1, const Register &tempReg2,
|
||||
MacroAssembler::newGCThingPar(Register result, Register cx, Register tempReg1, Register tempReg2,
|
||||
gc::AllocKind allocKind, Label *fail)
|
||||
{
|
||||
// Similar to ::newGCThing(), except that it allocates from a custom
|
||||
|
@ -755,8 +751,7 @@ MacroAssembler::newGCThingPar(const Register &result, const Register &cx,
|
|||
}
|
||||
|
||||
void
|
||||
MacroAssembler::newGCThingPar(const Register &result, const Register &cx,
|
||||
const Register &tempReg1, const Register &tempReg2,
|
||||
MacroAssembler::newGCThingPar(Register result, Register cx, Register tempReg1, Register tempReg2,
|
||||
JSObject *templateObject, Label *fail)
|
||||
{
|
||||
gc::AllocKind allocKind = templateObject->tenuredGetAllocKind();
|
||||
|
@ -766,69 +761,127 @@ MacroAssembler::newGCThingPar(const Register &result, const Register &cx,
|
|||
}
|
||||
|
||||
void
|
||||
MacroAssembler::newGCStringPar(const Register &result, const Register &cx,
|
||||
const Register &tempReg1, const Register &tempReg2,
|
||||
MacroAssembler::newGCStringPar(Register result, Register cx, Register tempReg1, Register tempReg2,
|
||||
Label *fail)
|
||||
{
|
||||
newGCThingPar(result, cx, tempReg1, tempReg2, js::gc::FINALIZE_STRING, fail);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::newGCShortStringPar(const Register &result, const Register &cx,
|
||||
const Register &tempReg1, const Register &tempReg2,
|
||||
Label *fail)
|
||||
MacroAssembler::newGCShortStringPar(Register result, Register cx, Register tempReg1,
|
||||
Register tempReg2, Label *fail)
|
||||
{
|
||||
newGCThingPar(result, cx, tempReg1, tempReg2, js::gc::FINALIZE_SHORT_STRING, fail);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::initGCThing(const Register &obj, JSObject *templateObject)
|
||||
MacroAssembler::copySlotsFromTemplate(Register obj, Register temp, const JSObject *templateObj,
|
||||
uint32_t start, uint32_t end)
|
||||
{
|
||||
uint32_t nfixed = Min(templateObj->numFixedSlots(), end);
|
||||
for (unsigned i = start; i < nfixed; i++)
|
||||
storeValue(templateObj->getFixedSlot(i), Address(obj, JSObject::getFixedSlotOffset(i)));
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::fillSlotsWithUndefined(Register obj, Register temp, const JSObject *templateObj,
|
||||
uint32_t start, uint32_t end)
|
||||
{
|
||||
#ifdef JS_NUNBOX32
|
||||
// We only have a single spare register, so do the initialization as two
|
||||
// strided writes of the tag and body.
|
||||
jsval_layout jv = JSVAL_TO_IMPL(UndefinedValue());
|
||||
uint32_t nfixed = Min(templateObj->numFixedSlots(), end);
|
||||
|
||||
mov(ImmWord(jv.s.tag), temp);
|
||||
for (unsigned i = start; i < nfixed; i++)
|
||||
store32(temp, ToType(Address(obj, JSObject::getFixedSlotOffset(i))));
|
||||
|
||||
mov(ImmWord(jv.s.payload.i32), temp);
|
||||
for (unsigned i = start; i < nfixed; i++)
|
||||
store32(temp, ToPayload(Address(obj, JSObject::getFixedSlotOffset(i))));
|
||||
#else
|
||||
moveValue(UndefinedValue(), temp);
|
||||
uint32_t nfixed = Min(templateObj->numFixedSlots(), end);
|
||||
for (unsigned i = start; i < nfixed; i++)
|
||||
storePtr(temp, Address(obj, JSObject::getFixedSlotOffset(i)));
|
||||
#endif
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
FindStartOfUndefinedSlots(JSObject *templateObj, uint32_t nslots)
|
||||
{
|
||||
JS_ASSERT(nslots == templateObj->lastProperty()->slotSpan(templateObj->getClass()));
|
||||
JS_ASSERT(nslots > 0);
|
||||
for (uint32_t first = nslots; first != 0; --first) {
|
||||
if (templateObj->getSlot(first - 1) != UndefinedValue())
|
||||
return first;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::initGCSlots(Register obj, Register temp, JSObject *templateObj)
|
||||
{
|
||||
// Slots of non-array objects are required to be initialized.
|
||||
// Use the values currently in the template object.
|
||||
uint32_t nslots = templateObj->lastProperty()->slotSpan(templateObj->getClass());
|
||||
if (nslots == 0)
|
||||
return;
|
||||
|
||||
// Attempt to group slot writes such that we minimize the amount of
|
||||
// duplicated data we need to embed in code and load into registers. In
|
||||
// general, most template object slots will be undefined except for any
|
||||
// reserved slots. Since reserved slots come first, we split the object
|
||||
// logically into independent non-UndefinedValue writes to the head and
|
||||
// duplicated writes of UndefinedValue to the tail. For the majority of
|
||||
// objects, the "tail" will be the entire slot range.
|
||||
uint32_t startOfUndefined = FindStartOfUndefinedSlots(templateObj, nslots);
|
||||
copySlotsFromTemplate(obj, temp, templateObj, 0, startOfUndefined);
|
||||
fillSlotsWithUndefined(obj, temp, templateObj, startOfUndefined, nslots);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::initGCThing(Register obj, Register temp, JSObject *templateObj)
|
||||
{
|
||||
// Fast initialization of an empty object returned by NewGCThing().
|
||||
|
||||
JS_ASSERT(!templateObject->hasDynamicElements());
|
||||
JS_ASSERT(!templateObj->hasDynamicElements());
|
||||
|
||||
storePtr(ImmGCPtr(templateObject->lastProperty()), Address(obj, JSObject::offsetOfShape()));
|
||||
storePtr(ImmGCPtr(templateObject->type()), Address(obj, JSObject::offsetOfType()));
|
||||
storePtr(ImmGCPtr(templateObj->lastProperty()), Address(obj, JSObject::offsetOfShape()));
|
||||
storePtr(ImmGCPtr(templateObj->type()), Address(obj, JSObject::offsetOfType()));
|
||||
storePtr(ImmPtr(nullptr), Address(obj, JSObject::offsetOfSlots()));
|
||||
|
||||
if (templateObject->is<ArrayObject>()) {
|
||||
JS_ASSERT(!templateObject->getDenseInitializedLength());
|
||||
if (templateObj->is<ArrayObject>()) {
|
||||
JS_ASSERT(!templateObj->getDenseInitializedLength());
|
||||
|
||||
int elementsOffset = JSObject::offsetOfFixedElements();
|
||||
|
||||
addPtr(Imm32(elementsOffset), obj);
|
||||
storePtr(obj, Address(obj, -elementsOffset + JSObject::offsetOfElements()));
|
||||
addPtr(Imm32(-elementsOffset), obj);
|
||||
computeEffectiveAddress(Address(obj, elementsOffset), temp);
|
||||
storePtr(temp, Address(obj, JSObject::offsetOfElements()));
|
||||
|
||||
// Fill in the elements header.
|
||||
store32(Imm32(templateObject->getDenseCapacity()),
|
||||
store32(Imm32(templateObj->getDenseCapacity()),
|
||||
Address(obj, elementsOffset + ObjectElements::offsetOfCapacity()));
|
||||
store32(Imm32(templateObject->getDenseInitializedLength()),
|
||||
store32(Imm32(templateObj->getDenseInitializedLength()),
|
||||
Address(obj, elementsOffset + ObjectElements::offsetOfInitializedLength()));
|
||||
store32(Imm32(templateObject->as<ArrayObject>().length()),
|
||||
store32(Imm32(templateObj->as<ArrayObject>().length()),
|
||||
Address(obj, elementsOffset + ObjectElements::offsetOfLength()));
|
||||
store32(Imm32(templateObject->shouldConvertDoubleElements()
|
||||
store32(Imm32(templateObj->shouldConvertDoubleElements()
|
||||
? ObjectElements::CONVERT_DOUBLE_ELEMENTS
|
||||
: 0),
|
||||
Address(obj, elementsOffset + ObjectElements::offsetOfFlags()));
|
||||
JS_ASSERT(!templateObj->hasPrivate());
|
||||
} else {
|
||||
storePtr(ImmPtr(emptyObjectElements), Address(obj, JSObject::offsetOfElements()));
|
||||
|
||||
// Fixed slots of non-array objects are required to be initialized.
|
||||
// Use the values currently in the template object.
|
||||
size_t nslots = Min(templateObject->numFixedSlots(),
|
||||
templateObject->lastProperty()->slotSpan(templateObject->getClass()));
|
||||
for (unsigned i = 0; i < nslots; i++) {
|
||||
storeValue(templateObject->getFixedSlot(i),
|
||||
Address(obj, JSObject::getFixedSlotOffset(i)));
|
||||
}
|
||||
}
|
||||
initGCSlots(obj, temp, templateObj);
|
||||
|
||||
if (templateObject->hasPrivate()) {
|
||||
uint32_t nfixed = templateObject->numFixedSlots();
|
||||
storePtr(ImmPtr(templateObject->getPrivate()),
|
||||
Address(obj, JSObject::getPrivateDataOffset(nfixed)));
|
||||
if (templateObj->hasPrivate()) {
|
||||
uint32_t nfixed = templateObj->numFixedSlots();
|
||||
storePtr(ImmPtr(templateObj->getPrivate()),
|
||||
Address(obj, JSObject::getPrivateDataOffset(nfixed)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -870,7 +923,7 @@ MacroAssembler::compareStrings(JSOp op, Register left, Register right, Register
|
|||
}
|
||||
|
||||
void
|
||||
MacroAssembler::checkInterruptFlagPar(const Register &tempReg, Label *fail)
|
||||
MacroAssembler::checkInterruptFlagPar(Register tempReg, Label *fail)
|
||||
{
|
||||
#ifdef JS_THREADSAFE
|
||||
movePtr(ImmPtr(GetIonContext()->runtime->addressOfInterruptPar()), tempReg);
|
||||
|
@ -1819,7 +1872,7 @@ MacroAssembler::branchIfNotInterpretedConstructor(Register fun, Register scratch
|
|||
}
|
||||
|
||||
void
|
||||
MacroAssembler::branchEqualTypeIfNeeded(MIRType type, MDefinition *maybeDef, const Register &tag,
|
||||
MacroAssembler::branchEqualTypeIfNeeded(MIRType type, MDefinition *maybeDef, Register tag,
|
||||
Label *label)
|
||||
{
|
||||
if (!maybeDef || maybeDef->mightBeType(type)) {
|
||||
|
|
|
@ -352,13 +352,13 @@ class MacroAssembler : public MacroAssemblerSpecific
|
|||
}
|
||||
|
||||
// Branches to |label| if |reg| is false. |reg| should be a C++ bool.
|
||||
void branchIfFalseBool(const Register ®, Label *label) {
|
||||
void branchIfFalseBool(Register reg, Label *label) {
|
||||
// Note that C++ bool is only 1 byte, so ignore the higher-order bits.
|
||||
branchTest32(Assembler::Zero, reg, Imm32(0xFF), label);
|
||||
}
|
||||
|
||||
// Branches to |label| if |reg| is true. |reg| should be a C++ bool.
|
||||
void branchIfTrueBool(const Register ®, Label *label) {
|
||||
void branchIfTrueBool(Register reg, Label *label) {
|
||||
// Note that C++ bool is only 1 byte, so ignore the higher-order bits.
|
||||
branchTest32(Assembler::NonZero, reg, Imm32(0xFF), label);
|
||||
}
|
||||
|
@ -381,10 +381,10 @@ class MacroAssembler : public MacroAssemblerSpecific
|
|||
loadPtr(Address(worker, ThreadPoolWorker::offsetOfSliceBounds()), dest);
|
||||
}
|
||||
|
||||
void loadJSContext(const Register &dest) {
|
||||
void loadJSContext(Register dest) {
|
||||
loadPtr(AbsoluteAddress(GetIonContext()->runtime->addressOfJSContext()), dest);
|
||||
}
|
||||
void loadJitActivation(const Register &dest) {
|
||||
void loadJitActivation(Register dest) {
|
||||
loadPtr(AbsoluteAddress(GetIonContext()->runtime->addressOfActivation()), dest);
|
||||
}
|
||||
|
||||
|
@ -634,7 +634,7 @@ class MacroAssembler : public MacroAssemblerSpecific
|
|||
branch32(cond, length, Imm32(key.constant()), label);
|
||||
}
|
||||
|
||||
void branchTestNeedsBarrier(Condition cond, const Register &scratch, Label *label) {
|
||||
void branchTestNeedsBarrier(Condition cond, Register scratch, Label *label) {
|
||||
JS_ASSERT(cond == Zero || cond == NonZero);
|
||||
CompileZone *zone = GetIonContext()->compartment->zone();
|
||||
movePtr(ImmPtr(zone->addressOfNeedsBarrier()), scratch);
|
||||
|
@ -690,7 +690,7 @@ class MacroAssembler : public MacroAssemblerSpecific
|
|||
|
||||
void branchNurseryPtr(Condition cond, const Address &ptr1, const ImmMaybeNurseryPtr &ptr2,
|
||||
Label *label);
|
||||
void moveNurseryPtr(const ImmMaybeNurseryPtr &ptr, const Register ®);
|
||||
void moveNurseryPtr(const ImmMaybeNurseryPtr &ptr, Register reg);
|
||||
|
||||
void canonicalizeDouble(FloatRegister reg) {
|
||||
Label notNaN;
|
||||
|
@ -783,30 +783,31 @@ class MacroAssembler : public MacroAssemblerSpecific
|
|||
|
||||
// Emit type case branch on tag matching if the type tag in the definition
|
||||
// might actually be that type.
|
||||
void branchEqualTypeIfNeeded(MIRType type, MDefinition *maybeDef, const Register &tag,
|
||||
Label *label);
|
||||
void branchEqualTypeIfNeeded(MIRType type, MDefinition *maybeDef, Register tag, Label *label);
|
||||
|
||||
// Inline allocation.
|
||||
void newGCThing(const Register &result, gc::AllocKind allocKind, Label *fail,
|
||||
void newGCThing(Register result, Register temp, gc::AllocKind allocKind, Label *fail,
|
||||
gc::InitialHeap initialHeap = gc::DefaultHeap);
|
||||
void newGCThing(const Register &result, JSObject *templateObject, Label *fail,
|
||||
void newGCThing(Register result, Register temp, JSObject *templateObject, Label *fail,
|
||||
gc::InitialHeap initialHeap);
|
||||
void newGCString(const Register &result, Label *fail);
|
||||
void newGCShortString(const Register &result, Label *fail);
|
||||
void newGCString(Register result, Register temp, Label *fail);
|
||||
void newGCShortString(Register result, Register temp, Label *fail);
|
||||
|
||||
void newGCThingPar(const Register &result, const Register &cx,
|
||||
const Register &tempReg1, const Register &tempReg2,
|
||||
void newGCThingPar(Register result, Register cx, Register tempReg1, Register tempReg2,
|
||||
gc::AllocKind allocKind, Label *fail);
|
||||
void newGCThingPar(const Register &result, const Register &cx,
|
||||
const Register &tempReg1, const Register &tempReg2,
|
||||
void newGCThingPar(Register result, Register cx, Register tempReg1, Register tempReg2,
|
||||
JSObject *templateObject, Label *fail);
|
||||
void newGCStringPar(const Register &result, const Register &cx,
|
||||
const Register &tempReg1, const Register &tempReg2,
|
||||
void newGCStringPar(Register result, Register cx, Register tempReg1, Register tempReg2,
|
||||
Label *fail);
|
||||
void newGCShortStringPar(const Register &result, const Register &cx,
|
||||
const Register &tempReg1, const Register &tempReg2,
|
||||
void newGCShortStringPar(Register result, Register cx, Register tempReg1, Register tempReg2,
|
||||
Label *fail);
|
||||
void initGCThing(const Register &obj, JSObject *templateObject);
|
||||
|
||||
void copySlotsFromTemplate(Register obj, Register temp, const JSObject *templateObj,
|
||||
uint32_t start, uint32_t end);
|
||||
void fillSlotsWithUndefined(Register obj, Register temp, const JSObject *templateObj,
|
||||
uint32_t start, uint32_t end);
|
||||
void initGCSlots(Register obj, Register temp, JSObject *templateObj);
|
||||
void initGCThing(Register obj, Register temp, JSObject *templateObj);
|
||||
|
||||
// Compares two strings for equality based on the JSOP.
|
||||
// This checks for identical pointers, atoms and length and fails for everything else.
|
||||
|
@ -815,7 +816,7 @@ class MacroAssembler : public MacroAssemblerSpecific
|
|||
|
||||
// Checks the flags that signal that parallel code may need to interrupt or
|
||||
// abort. Branches to fail in that case.
|
||||
void checkInterruptFlagPar(const Register &tempReg, Label *fail);
|
||||
void checkInterruptFlagPar(Register tempReg, Label *fail);
|
||||
|
||||
// If the JitCode that created this assembler needs to transition into the VM,
|
||||
// we want to store the JitCode on the stack in order to mark it during a GC.
|
||||
|
@ -903,7 +904,7 @@ class MacroAssembler : public MacroAssemblerSpecific
|
|||
}
|
||||
|
||||
// see above comment for what is returned
|
||||
uint32_t callIon(const Register &callee) {
|
||||
uint32_t callIon(Register callee) {
|
||||
leaveSPSFrame();
|
||||
MacroAssemblerSpecific::callIon(callee);
|
||||
uint32_t ret = currentOffset();
|
||||
|
|
|
@ -328,29 +328,45 @@ class LNewSlots : public LCallInstructionHelper<1, 0, 3>
|
|||
}
|
||||
};
|
||||
|
||||
class LNewArray : public LInstructionHelper<1, 0, 0>
|
||||
class LNewArray : public LInstructionHelper<1, 0, 1>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(NewArray)
|
||||
|
||||
LNewArray(const LDefinition &temp) {
|
||||
setTemp(0, temp);
|
||||
}
|
||||
|
||||
const char *extraName() const {
|
||||
return mir()->shouldUseVM() ? "VMCall" : nullptr;
|
||||
}
|
||||
|
||||
const LDefinition *temp() {
|
||||
return getTemp(0);
|
||||
}
|
||||
|
||||
MNewArray *mir() const {
|
||||
return mir_->toNewArray();
|
||||
}
|
||||
};
|
||||
|
||||
class LNewObject : public LInstructionHelper<1, 0, 0>
|
||||
class LNewObject : public LInstructionHelper<1, 0, 1>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(NewObject)
|
||||
|
||||
LNewObject(const LDefinition &temp) {
|
||||
setTemp(0, temp);
|
||||
}
|
||||
|
||||
const char *extraName() const {
|
||||
return mir()->shouldUseVM() ? "VMCall" : nullptr;
|
||||
}
|
||||
|
||||
const LDefinition *temp() {
|
||||
return getTemp(0);
|
||||
}
|
||||
|
||||
MNewObject *mir() const {
|
||||
return mir_->toNewObject();
|
||||
}
|
||||
|
@ -430,11 +446,19 @@ class LNewDenseArrayPar : public LCallInstructionHelper<1, 2, 3>
|
|||
// (1) An inline allocation of the call object is attempted.
|
||||
// (2) Otherwise, a callVM create a new object.
|
||||
//
|
||||
class LNewDeclEnvObject : public LInstructionHelper<1, 0, 0>
|
||||
class LNewDeclEnvObject : public LInstructionHelper<1, 0, 1>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(NewDeclEnvObject);
|
||||
|
||||
LNewDeclEnvObject(const LDefinition &temp) {
|
||||
setTemp(0, temp);
|
||||
}
|
||||
|
||||
const LDefinition *temp() {
|
||||
return getTemp(0);
|
||||
}
|
||||
|
||||
MNewDeclEnvObject *mir() const {
|
||||
return mir_->toNewDeclEnvObject();
|
||||
}
|
||||
|
@ -449,13 +473,18 @@ class LNewDeclEnvObject : public LInstructionHelper<1, 0, 0>
|
|||
// call object.
|
||||
// (2) Otherwise, an inline allocation of the call object is attempted.
|
||||
//
|
||||
class LNewCallObject : public LInstructionHelper<1, 1, 0>
|
||||
class LNewCallObject : public LInstructionHelper<1, 1, 1>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(NewCallObject)
|
||||
|
||||
LNewCallObject(const LAllocation &slots) {
|
||||
LNewCallObject(const LAllocation &slots, const LDefinition &temp) {
|
||||
setOperand(0, slots);
|
||||
setTemp(0, temp);
|
||||
}
|
||||
|
||||
const LDefinition *temp() {
|
||||
return getTemp(0);
|
||||
}
|
||||
|
||||
const LAllocation *slots() {
|
||||
|
@ -883,17 +912,22 @@ class LCreateThisWithProto : public LCallInstructionHelper<1, 2, 0>
|
|||
|
||||
// Allocate an object for |new| on the caller-side.
|
||||
// Always performs object initialization with a fast path.
|
||||
class LCreateThisWithTemplate : public LInstructionHelper<1, 0, 0>
|
||||
class LCreateThisWithTemplate : public LInstructionHelper<1, 0, 1>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(CreateThisWithTemplate)
|
||||
|
||||
LCreateThisWithTemplate()
|
||||
{ }
|
||||
LCreateThisWithTemplate(const LDefinition &temp) {
|
||||
setTemp(0, temp);
|
||||
}
|
||||
|
||||
MCreateThisWithTemplate *mir() const {
|
||||
return mir_->toCreateThisWithTemplate();
|
||||
}
|
||||
|
||||
const LDefinition *temp() {
|
||||
return getTemp(0);
|
||||
}
|
||||
};
|
||||
|
||||
// Allocate a new arguments object for the frame.
|
||||
|
@ -3396,17 +3430,21 @@ class LLambdaForSingleton : public LCallInstructionHelper<1, 1, 0>
|
|||
}
|
||||
};
|
||||
|
||||
class LLambda : public LInstructionHelper<1, 1, 0>
|
||||
class LLambda : public LInstructionHelper<1, 1, 1>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(Lambda)
|
||||
|
||||
LLambda(const LAllocation &scopeChain) {
|
||||
LLambda(const LAllocation &scopeChain, const LDefinition &temp) {
|
||||
setOperand(0, scopeChain);
|
||||
setTemp(0, temp);
|
||||
}
|
||||
const LAllocation *scopeChain() {
|
||||
return getOperand(0);
|
||||
}
|
||||
const LDefinition *temp() {
|
||||
return getTemp(0);
|
||||
}
|
||||
const MLambda *mir() const {
|
||||
return mir_->toLambda();
|
||||
}
|
||||
|
|
|
@ -174,21 +174,21 @@ LIRGenerator::visitNewSlots(MNewSlots *ins)
|
|||
bool
|
||||
LIRGenerator::visitNewArray(MNewArray *ins)
|
||||
{
|
||||
LNewArray *lir = new(alloc()) LNewArray();
|
||||
LNewArray *lir = new(alloc()) LNewArray(temp());
|
||||
return define(lir, ins) && assignSafepoint(lir, ins);
|
||||
}
|
||||
|
||||
bool
|
||||
LIRGenerator::visitNewObject(MNewObject *ins)
|
||||
{
|
||||
LNewObject *lir = new(alloc()) LNewObject();
|
||||
LNewObject *lir = new(alloc()) LNewObject(temp());
|
||||
return define(lir, ins) && assignSafepoint(lir, ins);
|
||||
}
|
||||
|
||||
bool
|
||||
LIRGenerator::visitNewDeclEnvObject(MNewDeclEnvObject *ins)
|
||||
{
|
||||
LNewDeclEnvObject *lir = new(alloc()) LNewDeclEnvObject();
|
||||
LNewDeclEnvObject *lir = new(alloc()) LNewDeclEnvObject(temp());
|
||||
return define(lir, ins) && assignSafepoint(lir, ins);
|
||||
}
|
||||
|
||||
|
@ -201,7 +201,7 @@ LIRGenerator::visitNewCallObject(MNewCallObject *ins)
|
|||
else
|
||||
slots = LConstantIndex::Bogus();
|
||||
|
||||
LNewCallObject *lir = new(alloc()) LNewCallObject(slots);
|
||||
LNewCallObject *lir = new(alloc()) LNewCallObject(slots, temp());
|
||||
if (!define(lir, ins))
|
||||
return false;
|
||||
|
||||
|
@ -311,7 +311,7 @@ LIRGenerator::visitInitPropGetterSetter(MInitPropGetterSetter *ins)
|
|||
bool
|
||||
LIRGenerator::visitCreateThisWithTemplate(MCreateThisWithTemplate *ins)
|
||||
{
|
||||
LCreateThisWithTemplate *lir = new(alloc()) LCreateThisWithTemplate();
|
||||
LCreateThisWithTemplate *lir = new(alloc()) LCreateThisWithTemplate(temp());
|
||||
return define(lir, ins) && assignSafepoint(lir, ins);
|
||||
}
|
||||
|
||||
|
@ -2026,7 +2026,7 @@ LIRGenerator::visitLambda(MLambda *ins)
|
|||
return defineReturn(lir, ins) && assignSafepoint(lir, ins);
|
||||
}
|
||||
|
||||
LLambda *lir = new(alloc()) LLambda(useRegister(ins->scopeChain()));
|
||||
LLambda *lir = new(alloc()) LLambda(useRegister(ins->scopeChain()), temp());
|
||||
return define(lir, ins) && assignSafepoint(lir, ins);
|
||||
}
|
||||
|
||||
|
|
|
@ -2531,14 +2531,6 @@ MacroAssemblerARMCompat::branchFloat(DoubleCondition cond, const FloatRegister &
|
|||
ma_b(label, ConditionFromDoubleCondition(cond));
|
||||
}
|
||||
|
||||
// higher level tag testing code
|
||||
Operand ToPayload(Operand base) {
|
||||
return Operand(Register::FromCode(base.base()), base.disp());
|
||||
}
|
||||
Operand ToType(Operand base) {
|
||||
return Operand(Register::FromCode(base.base()), base.disp() + sizeof(void *));
|
||||
}
|
||||
|
||||
Assembler::Condition
|
||||
MacroAssemblerARMCompat::testInt32(Assembler::Condition cond, const ValueOperand &value)
|
||||
{
|
||||
|
|
|
@ -35,6 +35,20 @@ class MacroAssemblerARM : public Assembler
|
|||
// baseline IC stubs rely on lr holding the return address.
|
||||
Register secondScratchReg_;
|
||||
|
||||
// higher level tag testing code
|
||||
Operand ToPayload(Operand base) {
|
||||
return Operand(Register::FromCode(base.base()), base.disp());
|
||||
}
|
||||
Address ToPayload(Address base) {
|
||||
return ToPayload(Operand(base)).toAddress();
|
||||
}
|
||||
Operand ToType(Operand base) {
|
||||
return Operand(Register::FromCode(base.base()), base.disp() + sizeof(void *));
|
||||
}
|
||||
Address ToType(Address base) {
|
||||
return ToType(Operand(base)).toAddress();
|
||||
}
|
||||
|
||||
public:
|
||||
MacroAssemblerARM()
|
||||
: secondScratchReg_(lr)
|
||||
|
|
|
@ -91,6 +91,9 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared
|
|||
Operand ToPayload(Operand base) {
|
||||
return base;
|
||||
}
|
||||
Address ToPayload(Address base) {
|
||||
return base;
|
||||
}
|
||||
Operand ToType(Operand base) {
|
||||
switch (base.kind()) {
|
||||
case Operand::MEM_REG_DISP:
|
||||
|
@ -104,6 +107,9 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared
|
|||
MOZ_ASSUME_UNREACHABLE("unexpected operand kind");
|
||||
}
|
||||
}
|
||||
Address ToType(Address base) {
|
||||
return ToType(Operand(base)).toAddress();
|
||||
}
|
||||
void moveValue(const Value &val, Register type, Register data) {
|
||||
jsval_layout jv = JSVAL_TO_IMPL(val);
|
||||
movl(Imm32(jv.s.tag), type);
|
||||
|
|
Загрузка…
Ссылка в новой задаче