mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-07 20:17:37 +00:00
Backed out 2 changesets (bug 969012) for gc bustage
Backed out changeset 01f27ad85b1b (bug 969012) Backed out changeset f844291b895b (bug 969012)
This commit is contained in:
parent
f048271843
commit
43d93ff145
@ -1,60 +0,0 @@
|
||||
function testClosureCreationAndInvocation() {
|
||||
var a = 'foobar';
|
||||
function makeaddv(vvvv) {
|
||||
var z = -4 * vvvv;
|
||||
var y = -3 * vvvv;
|
||||
var x = -2 * vvvv;
|
||||
var w = -1 * vvvv;
|
||||
var v = 0 * vvvv;
|
||||
var u = 1 * vvvv;
|
||||
var t = 2 * vvvv;
|
||||
var s = 3 * vvvv;
|
||||
var r = 4 * vvvv;
|
||||
var q = 5 * vvvv;
|
||||
var p = 6 * vvvv;
|
||||
var o = 7 * vvvv;
|
||||
var n = 8 * vvvv;
|
||||
var m = 9 * vvvv;
|
||||
var l = 10 * vvvv;
|
||||
var k = 11 * vvvv;
|
||||
var j = 12 * vvvv;
|
||||
var i = 13 * vvvv;
|
||||
var h = 14 * vvvv;
|
||||
var g = 15 * vvvv;
|
||||
var f = 16 * vvvv;
|
||||
var e = 17 * vvvv;
|
||||
var d = 18 * vvvv;
|
||||
var c = 19 * vvvv;
|
||||
var b = 20 * vvvv;
|
||||
var a = 21 * vvvv;
|
||||
return function (x) {
|
||||
switch (x) {
|
||||
case 0: return a; case 1: return b;
|
||||
case 2: return c; case 3: return d;
|
||||
case 4: return e; case 5: return f;
|
||||
case 6: return g; case 7: return h;
|
||||
case 8: return i; case 9: return j;
|
||||
case 10: return k; case 11: return l;
|
||||
case 12: return m; case 13: return n;
|
||||
case 14: return o; case 15: return p;
|
||||
case 16: return q; case 17: return r;
|
||||
case 18: return s; case 19: return t;
|
||||
case 20: return u; case 21: return v;
|
||||
case 22: return w; case 23: return x;
|
||||
case 24: return y; case 25: return z;
|
||||
}
|
||||
};
|
||||
}
|
||||
var a = Array();
|
||||
for (var i = 0; i < 26; ++i) {
|
||||
a.push(makeaddv(Math.random()));
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
var a = testClosureCreationAndInvocation();
|
||||
for (var i = 0; i < 26; ++i) {
|
||||
print(a[i](i));
|
||||
}
|
||||
|
||||
|
@ -1,83 +0,0 @@
|
||||
function testx() {
|
||||
function compareArray(aExpected, aActual) {}
|
||||
for (var i = 0; i < expected.length; i++) {}
|
||||
var supportsArrayIndexGettersOnArrays = undefined;
|
||||
function fnSupportsArrayIndexGettersOnArrays() {}
|
||||
var supportsArrayIndexGettersOnObjects = undefined;
|
||||
function fnSupportsArrayIndexGettersOnObjects() {}
|
||||
function ConvertToFileUrl(pathStr) {
|
||||
}
|
||||
function fnExists() {}
|
||||
var __globalObject = Function("return this;")();
|
||||
function fnGlobalObject() {}
|
||||
function fnSupportsStrict() {
|
||||
eval('with ({}) {}');
|
||||
}
|
||||
function dataPropertyAttributesAreCorrect(obj, configurable) {}
|
||||
function accessorPropertyAttributesAreCorrect(obj, configurable) {}
|
||||
var NotEarlyErrorString = "NotEarlyError";
|
||||
var EarlyErrorRePat = "^((?!" + NotEarlyErrorString + ").)*$";
|
||||
var NotEarlyError = new Error(NotEarlyErrorString);
|
||||
function Test262Error(message) {};
|
||||
function testFailed(message) {}
|
||||
function testPrint(message) {}
|
||||
function $PRINT(message) {}
|
||||
function $INCLUDE(message) { }
|
||||
function $ERROR(message) {}
|
||||
function $FAIL(message) {}
|
||||
function getPrecision(num) {}
|
||||
var prec;
|
||||
function isEqual(num1, num2) {}
|
||||
function ToInteger(p) {}
|
||||
var HoursPerDay = 24;
|
||||
var MinutesPerHour = 60;
|
||||
var SecondsPerMinute = 60;
|
||||
var msPerDay = 86400000;
|
||||
var msPerSecond = 1000;
|
||||
var msPerMinute = 60000;
|
||||
var msPerHour = 3600000;
|
||||
var date_1899_end = -2208988800001;
|
||||
var date_1900_start = -2208988800000;
|
||||
var date_1969_end = -1;
|
||||
var date_1970_start = 0;
|
||||
var date_1999_end = 946684799999;
|
||||
var date_2000_start = 946684800000;
|
||||
var date_2099_end = 4102444799999;
|
||||
var date_2100_start = 4102444800000;
|
||||
var $LocalTZ,
|
||||
$DST_start_month,
|
||||
$DST_start_sunday,
|
||||
$DST_start_hour,
|
||||
$DST_start_minutes,
|
||||
$DST_end_month,
|
||||
$DST_end_sunday,
|
||||
$DST_end_hour,
|
||||
$DST_end_minutes;
|
||||
function Day(t) {}
|
||||
function TimeWithinDay(t) {}
|
||||
function DaysInYear(y){}
|
||||
function DayFromYear(y) {}
|
||||
function TimeFromYear(y){}
|
||||
function YearFromTime(t) {}
|
||||
function InLeapYear(t){}
|
||||
function DayWithinYear(t) {}
|
||||
function MonthFromTime(t){}
|
||||
function DateFromTime(t) {}
|
||||
function WeekDay(t) {}
|
||||
var LocalTZA = $LocalTZ*msPerHour;
|
||||
function DaysInMonth(m, leap) {}
|
||||
function GetSundayInMonth(t, m, count){}
|
||||
function DaylightSavingTA(t) {}
|
||||
function LocalTime(t){}
|
||||
function UTC(t) {}
|
||||
function HourFromTime(t){}
|
||||
function MinFromTime(t){}
|
||||
function SecFromTime(t){}
|
||||
function msFromTime(t){}
|
||||
function MakeTime(hour, min, sec, ms){}
|
||||
function MakeDay(year, month, date) {}
|
||||
function MakeDate( day, time ) {}
|
||||
function TimeClip(time) {}
|
||||
function ConstructDate(year, month, date, hours, minutes, seconds, ms){}
|
||||
function runTestCase(testcase) {}
|
||||
} testx();
|
@ -3,6 +3,15 @@ load(libdir + "parallelarray-helpers.js");
|
||||
function testClosureCreationAndInvocation() {
|
||||
var a = range(0, 64);
|
||||
function makeaddv(v) {
|
||||
var u = 1;
|
||||
var t = 2;
|
||||
var s = 3;
|
||||
var r = 4;
|
||||
var q = 5;
|
||||
var p = 6;
|
||||
var o = 7;
|
||||
var n = 8;
|
||||
var m = 9;
|
||||
var l = 10;
|
||||
var k = 11;
|
||||
var j = 12;
|
||||
@ -25,6 +34,11 @@ function testClosureCreationAndInvocation() {
|
||||
case 6: return g; case 7: return h;
|
||||
case 8: return i; case 9: return j;
|
||||
case 10: return k; case 11: return l;
|
||||
case 12: return m; case 13: return n;
|
||||
case 14: return o; case 15: return p;
|
||||
case 16: return q; case 17: return r;
|
||||
case 18: return s; case 19: return t;
|
||||
case 20: return u;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -3,6 +3,15 @@ load(libdir + "parallelarray-helpers.js");
|
||||
function testClosureCreationAndInvocation() {
|
||||
var a = range(0, 64);
|
||||
function makeaddv(v) {
|
||||
var u = 1;
|
||||
var t = 2;
|
||||
var s = 3;
|
||||
var r = 4;
|
||||
var q = 5;
|
||||
var p = 6;
|
||||
var o = 7;
|
||||
var n = 8;
|
||||
var m = 9;
|
||||
var l = 10;
|
||||
var k = 11;
|
||||
var j = 12;
|
||||
@ -23,6 +32,11 @@ function testClosureCreationAndInvocation() {
|
||||
case 6: return g; case 7: return h;
|
||||
case 8: return i; case 9: return j;
|
||||
case 10: return k; case 11: return l;
|
||||
case 12: return m; case 13: return n;
|
||||
case 14: return o; case 15: return p;
|
||||
case 16: return q; case 17: return r;
|
||||
case 18: return s; case 19: return t;
|
||||
case 20: return u;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
@ -1044,7 +1044,8 @@ CodeGenerator::visitLambda(LLambda *lir)
|
||||
|
||||
JS_ASSERT(!info.singletonType);
|
||||
|
||||
masm.createGCObject(output, tempReg, info.fun, gc::DefaultHeap, ool->entry());
|
||||
masm.newGCThing(output, tempReg, info.fun, ool->entry(), gc::DefaultHeap);
|
||||
masm.initGCThing(output, tempReg, info.fun);
|
||||
|
||||
emitLambdaInit(output, scopeChain, info);
|
||||
|
||||
@ -1080,7 +1081,8 @@ CodeGenerator::visitLambdaArrow(LLambdaArrow *lir)
|
||||
return true;
|
||||
}
|
||||
|
||||
masm.createGCObject(output, tempReg, info.fun, gc::DefaultHeap, ool->entry());
|
||||
masm.newGCThing(output, tempReg, info.fun, ool->entry(), gc::DefaultHeap);
|
||||
masm.initGCThing(output, tempReg, info.fun);
|
||||
|
||||
emitLambdaInit(output, scopeChain, info);
|
||||
|
||||
@ -3504,6 +3506,28 @@ CodeGenerator::visitNewDerivedTypedObject(LNewDerivedTypedObject *lir)
|
||||
return callVM(CreateDerivedTypedObjInfo, lir);
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGenerator::visitNewSlots(LNewSlots *lir)
|
||||
{
|
||||
Register temp1 = ToRegister(lir->temp1());
|
||||
Register temp2 = ToRegister(lir->temp2());
|
||||
Register temp3 = ToRegister(lir->temp3());
|
||||
Register output = ToRegister(lir->output());
|
||||
|
||||
masm.mov(ImmPtr(GetIonContext()->runtime), temp1);
|
||||
masm.mov(ImmWord(lir->mir()->nslots()), temp2);
|
||||
|
||||
masm.setupUnalignedABICall(2, temp3);
|
||||
masm.passABIArg(temp1);
|
||||
masm.passABIArg(temp2);
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, NewSlots));
|
||||
|
||||
if (!bailoutTestPtr(Assembler::Zero, output, output, lir->snapshot()))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CodeGenerator::visitAtan2D(LAtan2D *lir)
|
||||
{
|
||||
Register temp = ToRegister(lir->temp());
|
||||
@ -3552,7 +3576,8 @@ CodeGenerator::visitNewArray(LNewArray *lir)
|
||||
if (!addOutOfLineCode(ool))
|
||||
return false;
|
||||
|
||||
masm.createGCObject(objReg, tempReg, templateObject, lir->mir()->initialHeap(), ool->entry());
|
||||
masm.newGCThing(objReg, tempReg, templateObject, ool->entry(), lir->mir()->initialHeap());
|
||||
masm.initGCThing(objReg, tempReg, templateObject);
|
||||
|
||||
masm.bind(ool->rejoin());
|
||||
return true;
|
||||
@ -3638,7 +3663,8 @@ CodeGenerator::visitNewObject(LNewObject *lir)
|
||||
if (!addOutOfLineCode(ool))
|
||||
return false;
|
||||
|
||||
masm.createGCObject(objReg, tempReg, templateObject, lir->mir()->initialHeap(), ool->entry());
|
||||
masm.newGCThing(objReg, tempReg, templateObject, ool->entry(), lir->mir()->initialHeap());
|
||||
masm.initGCThing(objReg, tempReg, templateObject);
|
||||
|
||||
masm.bind(ool->rejoin());
|
||||
return true;
|
||||
@ -3673,13 +3699,13 @@ CodeGenerator::visitNewDeclEnvObject(LNewDeclEnvObject *lir)
|
||||
if (!ool)
|
||||
return false;
|
||||
|
||||
masm.createGCObject(objReg, tempReg, templateObj, gc::DefaultHeap, ool->entry());
|
||||
|
||||
masm.newGCThing(objReg, tempReg, templateObj, ool->entry(), gc::DefaultHeap);
|
||||
masm.initGCThing(objReg, tempReg, templateObj);
|
||||
masm.bind(ool->rejoin());
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef JSObject *(*NewCallObjectFn)(JSContext *, HandleShape, HandleTypeObject);
|
||||
typedef JSObject *(*NewCallObjectFn)(JSContext *, HandleShape, HandleTypeObject, HeapSlot *);
|
||||
static const VMFunction NewCallObjectInfo =
|
||||
FunctionInfo<NewCallObjectFn>(NewCallObject);
|
||||
|
||||
@ -3691,21 +3717,44 @@ CodeGenerator::visitNewCallObject(LNewCallObject *lir)
|
||||
|
||||
JSObject *templateObj = lir->mir()->templateObject();
|
||||
|
||||
OutOfLineCode *ool = oolCallVM(NewCallObjectInfo, lir,
|
||||
(ArgList(), ImmGCPtr(templateObj->lastProperty()),
|
||||
ImmGCPtr(templateObj->type())),
|
||||
StoreRegisterTo(objReg));
|
||||
OutOfLineCode *ool;
|
||||
if (lir->slots()->isRegister()) {
|
||||
ool = oolCallVM(NewCallObjectInfo, lir,
|
||||
(ArgList(), ImmGCPtr(templateObj->lastProperty()),
|
||||
ImmGCPtr(templateObj->type()),
|
||||
ToRegister(lir->slots())),
|
||||
StoreRegisterTo(objReg));
|
||||
} else {
|
||||
ool = oolCallVM(NewCallObjectInfo, lir,
|
||||
(ArgList(), ImmGCPtr(templateObj->lastProperty()),
|
||||
ImmGCPtr(templateObj->type()),
|
||||
ImmPtr(nullptr)),
|
||||
StoreRegisterTo(objReg));
|
||||
}
|
||||
if (!ool)
|
||||
return false;
|
||||
|
||||
// Inline call object creation, using the OOL path only for tricky cases.
|
||||
masm.createGCObject(objReg, tempReg, templateObj, gc::DefaultHeap, ool->entry());
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
if (templateObj->hasDynamicSlots()) {
|
||||
// Slot initialization is unbarriered in this case, so we must either
|
||||
// allocate in the nursery or bail if that is not possible.
|
||||
masm.jump(ool->entry());
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
// Inline call object creation, using the OOL path only for tricky cases.
|
||||
masm.newGCThing(objReg, tempReg, templateObj, ool->entry(), gc::DefaultHeap);
|
||||
masm.initGCThing(objReg, tempReg, templateObj);
|
||||
}
|
||||
|
||||
if (lir->slots()->isRegister())
|
||||
masm.storePtr(ToRegister(lir->slots()), Address(objReg, JSObject::offsetOfSlots()));
|
||||
|
||||
masm.bind(ool->rejoin());
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef JSObject *(*NewSingletonCallObjectFn)(JSContext *, HandleShape);
|
||||
typedef JSObject *(*NewSingletonCallObjectFn)(JSContext *, HandleShape, HeapSlot *);
|
||||
static const VMFunction NewSingletonCallObjectInfo =
|
||||
FunctionInfo<NewSingletonCallObjectFn>(NewSingletonCallObject);
|
||||
|
||||
@ -3717,9 +3766,17 @@ CodeGenerator::visitNewSingletonCallObject(LNewSingletonCallObject *lir)
|
||||
JSObject *templateObj = lir->mir()->templateObject();
|
||||
|
||||
OutOfLineCode *ool;
|
||||
ool = oolCallVM(NewSingletonCallObjectInfo, lir,
|
||||
(ArgList(), ImmGCPtr(templateObj->lastProperty())),
|
||||
StoreRegisterTo(objReg));
|
||||
if (lir->slots()->isRegister()) {
|
||||
ool = oolCallVM(NewSingletonCallObjectInfo, lir,
|
||||
(ArgList(), ImmGCPtr(templateObj->lastProperty()),
|
||||
ToRegister(lir->slots())),
|
||||
StoreRegisterTo(objReg));
|
||||
} else {
|
||||
ool = oolCallVM(NewSingletonCallObjectInfo, lir,
|
||||
(ArgList(), ImmGCPtr(templateObj->lastProperty()),
|
||||
ImmPtr(nullptr)),
|
||||
StoreRegisterTo(objReg));
|
||||
}
|
||||
if (!ool)
|
||||
return false;
|
||||
|
||||
@ -3742,6 +3799,17 @@ CodeGenerator::visitNewCallObjectPar(LNewCallObjectPar *lir)
|
||||
JSObject *templateObj = lir->mir()->templateObj();
|
||||
|
||||
emitAllocateGCThingPar(lir, resultReg, cxReg, tempReg1, tempReg2, templateObj);
|
||||
|
||||
// NB: !lir->slots()->isRegister() implies that there is no slots
|
||||
// array at all, and the memory is already zeroed when copying
|
||||
// from the template object
|
||||
|
||||
if (lir->slots()->isRegister()) {
|
||||
Register slotsReg = ToRegister(lir->slots());
|
||||
JS_ASSERT(slotsReg != resultReg);
|
||||
masm.storePtr(slotsReg, Address(resultReg, JSObject::offsetOfSlots()));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -3800,7 +3868,8 @@ CodeGenerator::visitNewStringObject(LNewStringObject *lir)
|
||||
if (!ool)
|
||||
return false;
|
||||
|
||||
masm.createGCObject(output, temp, templateObj, gc::DefaultHeap, ool->entry());
|
||||
masm.newGCThing(output, temp, templateObj, ool->entry(), gc::DefaultHeap);
|
||||
masm.initGCThing(output, temp, templateObj);
|
||||
|
||||
masm.loadStringLength(input, temp);
|
||||
|
||||
@ -4045,7 +4114,7 @@ CodeGenerator::visitCreateThisWithTemplate(LCreateThisWithTemplate *lir)
|
||||
return false;
|
||||
|
||||
// Allocate. If the FreeList is empty, call to VM, which may GC.
|
||||
masm.newGCThing(objReg, tempReg, templateObject, lir->mir()->initialHeap(), ool->entry());
|
||||
masm.newGCThing(objReg, tempReg, templateObject, ool->entry(), lir->mir()->initialHeap());
|
||||
|
||||
// Initialize based on the templateObject.
|
||||
masm.bind(ool->rejoin());
|
||||
@ -5174,70 +5243,6 @@ JitCompartment::generateStringConcatStub(JSContext *cx, ExecutionMode mode)
|
||||
return code;
|
||||
}
|
||||
|
||||
JitCode *
|
||||
JitRuntime::generateMallocStub(JSContext *cx)
|
||||
{
|
||||
const Register regReturn = CallTempReg0;
|
||||
const Register regNBytes = CallTempReg0;
|
||||
const Register regRuntime = CallTempReg1;
|
||||
const Register regTemp = CallTempReg1;
|
||||
|
||||
MacroAssembler masm(cx);
|
||||
|
||||
RegisterSet regs = RegisterSet::Volatile();
|
||||
regs.takeUnchecked(regNBytes);
|
||||
masm.PushRegsInMask(regs);
|
||||
|
||||
masm.setupUnalignedABICall(2, regTemp);
|
||||
masm.movePtr(ImmPtr(cx->runtime()), regRuntime);
|
||||
masm.passABIArg(regRuntime);
|
||||
masm.passABIArg(regNBytes);
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, MallocWrapper));
|
||||
masm.storeCallResult(regReturn);
|
||||
|
||||
masm.PopRegsInMask(regs);
|
||||
masm.ret();
|
||||
|
||||
Linker linker(masm);
|
||||
JitCode *code = linker.newCode<NoGC>(cx, JSC::OTHER_CODE);
|
||||
|
||||
#ifdef JS_ION_PERF
|
||||
writePerfSpewerJitCodeProfile(code, "MallocStub");
|
||||
#endif
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
JitCode *
|
||||
JitRuntime::generateFreeStub(JSContext *cx)
|
||||
{
|
||||
const Register regSlots = CallTempReg0;
|
||||
const Register regTemp = CallTempReg1;
|
||||
|
||||
MacroAssembler masm(cx);
|
||||
|
||||
RegisterSet regs = RegisterSet::Volatile();
|
||||
regs.takeUnchecked(regSlots);
|
||||
masm.PushRegsInMask(regs);
|
||||
|
||||
masm.setupUnalignedABICall(1, regTemp);
|
||||
masm.passABIArg(regSlots);
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, js_free));
|
||||
|
||||
masm.PopRegsInMask(regs);
|
||||
|
||||
masm.ret();
|
||||
|
||||
Linker linker(masm);
|
||||
JitCode *code = linker.newCode<NoGC>(cx, JSC::OTHER_CODE);
|
||||
|
||||
#ifdef JS_ION_PERF
|
||||
writePerfSpewerJitCodeProfile(code, "FreeStub");
|
||||
#endif
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
typedef bool (*CharCodeAtFn)(JSContext *, HandleString, int32_t, uint32_t *);
|
||||
static const VMFunction CharCodeAtInfo = FunctionInfo<CharCodeAtFn>(jit::CharCodeAt);
|
||||
|
||||
@ -5909,7 +5914,9 @@ CodeGenerator::visitArrayConcat(LArrayConcat *lir)
|
||||
masm.branch32(Assembler::NotEqual, Address(temp1, ObjectElements::offsetOfLength()), temp2, &fail);
|
||||
|
||||
// Try to allocate an object.
|
||||
masm.createGCObject(temp1, temp2, lir->mir()->templateObj(), lir->mir()->initialHeap(), &fail);
|
||||
JSObject *templateObj = lir->mir()->templateObj();
|
||||
masm.newGCThing(temp1, temp2, templateObj, &fail, lir->mir()->initialHeap());
|
||||
masm.initGCThing(temp1, temp2, templateObj);
|
||||
masm.jump(&call);
|
||||
{
|
||||
masm.bind(&fail);
|
||||
@ -6280,7 +6287,8 @@ CodeGenerator::visitRest(LRest *lir)
|
||||
JSObject *templateObject = lir->mir()->templateObject();
|
||||
|
||||
Label joinAlloc, failAlloc;
|
||||
masm.createGCObject(temp2, temp0, templateObject, gc::DefaultHeap, &failAlloc);
|
||||
masm.newGCThing(temp2, temp0, templateObject, &failAlloc, gc::DefaultHeap);
|
||||
masm.initGCThing(temp2, temp0, templateObject);
|
||||
masm.jump(&joinAlloc);
|
||||
{
|
||||
masm.bind(&failAlloc);
|
||||
|
@ -135,6 +135,7 @@ class CodeGenerator : public CodeGeneratorSpecific
|
||||
bool visitCallDirectEvalV(LCallDirectEvalV *lir);
|
||||
bool visitDoubleToInt32(LDoubleToInt32 *lir);
|
||||
bool visitFloat32ToInt32(LFloat32ToInt32 *lir);
|
||||
bool visitNewSlots(LNewSlots *lir);
|
||||
bool visitNewArrayCallVM(LNewArray *lir);
|
||||
bool visitNewArray(LNewArray *lir);
|
||||
bool visitOutOfLineNewArray(OutOfLineNewArray *ool);
|
||||
|
@ -270,16 +270,6 @@ JitRuntime::initialize(JSContext *cx)
|
||||
if (!shapePreBarrier_)
|
||||
return false;
|
||||
|
||||
IonSpew(IonSpew_Codegen, "# Emitting malloc stub");
|
||||
mallocStub_ = generateMallocStub(cx);
|
||||
if (!mallocStub_)
|
||||
return false;
|
||||
|
||||
IonSpew(IonSpew_Codegen, "# Emitting free stub");
|
||||
freeStub_ = generateFreeStub(cx);
|
||||
if (!freeStub_)
|
||||
return false;
|
||||
|
||||
IonSpew(IonSpew_Codegen, "# Emitting VM function wrappers");
|
||||
for (VMFunction *fun = VMFunction::functions; fun; fun = fun->next) {
|
||||
if (!generateVMWrapper(cx, *fun))
|
||||
|
@ -4738,13 +4738,27 @@ IonBuilder::createCallObject(MDefinition *callee, MDefinition *scope)
|
||||
// creation.
|
||||
CallObject *templateObj = inspector->templateCallObject();
|
||||
|
||||
// Allocate the object. Run-once scripts need a singleton type, so always do
|
||||
// a VM call in such cases.
|
||||
MNullaryInstruction *callObj;
|
||||
// If the CallObject needs dynamic slots, allocate those now.
|
||||
MInstruction *slots;
|
||||
if (templateObj->hasDynamicSlots()) {
|
||||
size_t nslots = JSObject::dynamicSlotsCount(templateObj->numFixedSlots(),
|
||||
templateObj->lastProperty()->slotSpan(templateObj->getClass()),
|
||||
templateObj->getClass());
|
||||
slots = MNewSlots::New(alloc(), nslots);
|
||||
} else {
|
||||
slots = MConstant::New(alloc(), NullValue());
|
||||
}
|
||||
current->add(slots);
|
||||
|
||||
// Allocate the actual object. It is important that no intervening
|
||||
// instructions could potentially bailout, thus leaking the dynamic slots
|
||||
// pointer. Run-once scripts need a singleton type, so always do a VM call
|
||||
// in such cases.
|
||||
MUnaryInstruction *callObj;
|
||||
if (script()->treatAsRunOnce())
|
||||
callObj = MNewRunOnceCallObject::New(alloc(), templateObj);
|
||||
callObj = MNewRunOnceCallObject::New(alloc(), templateObj, slots);
|
||||
else
|
||||
callObj = MNewCallObject::New(alloc(), templateObj);
|
||||
callObj = MNewCallObject::New(alloc(), templateObj, slots);
|
||||
current->add(callObj);
|
||||
|
||||
// Initialize the object's reserved slots. No post barrier is needed here,
|
||||
@ -4753,20 +4767,14 @@ IonBuilder::createCallObject(MDefinition *callee, MDefinition *scope)
|
||||
current->add(MStoreFixedSlot::New(alloc(), callObj, CallObject::calleeSlot(), callee));
|
||||
|
||||
// Initialize argument slots.
|
||||
MSlots *slots = nullptr;
|
||||
for (AliasedFormalIter i(script()); i; i++) {
|
||||
unsigned slot = i.scopeSlot();
|
||||
unsigned formal = i.frameIndex();
|
||||
MDefinition *param = current->getSlot(info().argSlotUnchecked(formal));
|
||||
if (slot >= templateObj->numFixedSlots()) {
|
||||
if (!slots) {
|
||||
slots = MSlots::New(alloc(), callObj);
|
||||
current->add(slots);
|
||||
}
|
||||
if (slot >= templateObj->numFixedSlots())
|
||||
current->add(MStoreSlot::New(alloc(), slots, slot - templateObj->numFixedSlots(), param));
|
||||
} else {
|
||||
else
|
||||
current->add(MStoreFixedSlot::New(alloc(), callObj, slot, param));
|
||||
}
|
||||
}
|
||||
|
||||
return callObj;
|
||||
@ -7740,10 +7748,6 @@ IonBuilder::setElemTryTypedStatic(bool *emitted, MDefinition *object,
|
||||
return true;
|
||||
|
||||
TypedArrayObject *tarr = &tarrObj->as<TypedArrayObject>();
|
||||
|
||||
if (gc::IsInsideNursery(tarr->runtimeFromMainThread(), tarr->viewData()))
|
||||
return true;
|
||||
|
||||
ArrayBufferView::ViewType viewType = (ArrayBufferView::ViewType) tarr->type();
|
||||
|
||||
MDefinition *ptr = convertShiftToMaskForStaticTypedArray(index, viewType);
|
||||
|
@ -425,11 +425,14 @@ template void MacroAssembler::loadFromTypedArray(int arrayType, const Address &s
|
||||
template void MacroAssembler::loadFromTypedArray(int arrayType, const BaseIndex &src, const ValueOperand &dest,
|
||||
bool allowDouble, Register temp, Label *fail);
|
||||
|
||||
// Inlined version of gc::CheckAllocatorState that checks the bare essentials
|
||||
// and bails for anything that cannot be handled with our jit allocators.
|
||||
void
|
||||
MacroAssembler::checkAllocatorState(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.
|
||||
|
||||
int thingSize = int(gc::Arena::thingSize(allocKind));
|
||||
|
||||
#ifdef JS_GC_ZEAL
|
||||
// Don't execute the inline path if gcZeal is active.
|
||||
branch32(Assembler::NotEqual,
|
||||
@ -441,68 +444,29 @@ MacroAssembler::checkAllocatorState(Label *fail)
|
||||
// as the metadata to use for the object may vary between executions of the op.
|
||||
if (GetIonContext()->compartment->hasObjectMetadataCallback())
|
||||
jump(fail);
|
||||
}
|
||||
|
||||
// Inline version of ShouldNurseryAllocate.
|
||||
bool
|
||||
MacroAssembler::shouldNurseryAllocate(gc::AllocKind allocKind, gc::InitialHeap initialHeap)
|
||||
{
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
// Note that Ion elides barriers on writes to objects known to be in the
|
||||
// nursery, so any allocation that can be made into the nursery must be made
|
||||
// into the nursery, even if the nursery is disabled. At runtime these will
|
||||
// take the out-of-line path, which is required to insert a barrier for the
|
||||
// initializing writes.
|
||||
return IsNurseryAllocable(allocKind) && initialHeap != gc::TenuredHeap;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Inline version of Nursery::allocateObject.
|
||||
void
|
||||
MacroAssembler::nurseryAllocate(Register result, Register slots, gc::AllocKind allocKind,
|
||||
size_t nDynamicSlots, gc::InitialHeap initialHeap, Label *fail)
|
||||
{
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
JS_ASSERT(IsNurseryAllocable(allocKind));
|
||||
JS_ASSERT(initialHeap != gc::TenuredHeap);
|
||||
|
||||
// We still need to allocate in the nursery, per the comment in
|
||||
// shouldNurseryAllocate; however, we need to insert into hugeSlots, so
|
||||
// bail to do the nursery allocation in the interpreter.
|
||||
if (nDynamicSlots >= Nursery::MaxNurserySlots) {
|
||||
jump(fail);
|
||||
// Always use nursery allocation if it is possible to do so. The jit
|
||||
// assumes a nursery pointer is returned to avoid barriers.
|
||||
if (allocKind <= gc::FINALIZE_OBJECT_LAST && initialHeap != gc::TenuredHeap) {
|
||||
// Inline Nursery::allocate. No explicit check for nursery.isEnabled()
|
||||
// is needed, as the comparison with the nursery's end will always fail
|
||||
// in such cases.
|
||||
const Nursery &nursery = GetIonContext()->runtime->gcNursery();
|
||||
loadPtr(AbsoluteAddress(nursery.addressOfPosition()), result);
|
||||
computeEffectiveAddress(Address(result, thingSize), temp);
|
||||
branchPtr(Assembler::BelowOrEqual, AbsoluteAddress(nursery.addressOfCurrentEnd()), temp, fail);
|
||||
storePtr(temp, AbsoluteAddress(nursery.addressOfPosition()));
|
||||
return;
|
||||
}
|
||||
|
||||
// No explicit check for nursery.isEnabled() is needed, as the comparison
|
||||
// with the nursery's end will always fail in such cases.
|
||||
const Nursery &nursery = GetIonContext()->runtime->gcNursery();
|
||||
Register temp = slots;
|
||||
int thingSize = int(gc::Arena::thingSize(allocKind));
|
||||
int totalSize = thingSize + nDynamicSlots * sizeof(HeapSlot);
|
||||
loadPtr(AbsoluteAddress(nursery.addressOfPosition()), result);
|
||||
computeEffectiveAddress(Address(result, totalSize), temp);
|
||||
branchPtr(Assembler::BelowOrEqual, AbsoluteAddress(nursery.addressOfCurrentEnd()), temp, fail);
|
||||
storePtr(temp, AbsoluteAddress(nursery.addressOfPosition()));
|
||||
|
||||
if (nDynamicSlots)
|
||||
computeEffectiveAddress(Address(result, thingSize), slots);
|
||||
#endif // JSGC_GENERATIONAL
|
||||
}
|
||||
|
||||
// Inlined version of FreeSpan::allocate.
|
||||
void
|
||||
MacroAssembler::freeSpanAllocate(Register result, Register temp, gc::AllocKind allocKind, Label *fail)
|
||||
{
|
||||
CompileZone *zone = GetIonContext()->compartment->zone();
|
||||
int thingSize = int(gc::Arena::thingSize(allocKind));
|
||||
|
||||
// Load FreeSpan::first of |zone|'s freeLists for |allocKind|. If there is
|
||||
// no room remaining in the span, we bail to finish the allocation. The
|
||||
// interpreter will call |refillFreeLists|, setting up a new FreeSpan so
|
||||
// that we can continue allocating in the jit.
|
||||
// Inline FreeSpan::allocate.
|
||||
// There is always exactly one FreeSpan per allocKind per JSCompartment.
|
||||
// If a FreeSpan is replaced, its members are updated in the freeLists table,
|
||||
// which the code below always re-reads.
|
||||
loadPtr(AbsoluteAddress(zone->addressOfFreeListFirst(allocKind)), result);
|
||||
branchPtr(Assembler::BelowOrEqual, AbsoluteAddress(zone->addressOfFreeListLast(allocKind)), result, fail);
|
||||
computeEffectiveAddress(Address(result, thingSize), temp);
|
||||
@ -510,118 +474,25 @@ MacroAssembler::freeSpanAllocate(Register result, Register temp, gc::AllocKind a
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::callMallocStub(size_t nbytes, Register result, Label *fail)
|
||||
{
|
||||
// This register must match the one in JitRuntime::generateMallocStub.
|
||||
const Register regNBytes = CallTempReg0;
|
||||
|
||||
JS_ASSERT(nbytes > 0);
|
||||
JS_ASSERT(nbytes <= INT32_MAX);
|
||||
|
||||
if (regNBytes != result)
|
||||
push(regNBytes);
|
||||
move32(Imm32(nbytes), regNBytes);
|
||||
call(GetIonContext()->runtime->jitRuntime()->mallocStub());
|
||||
if (regNBytes != result) {
|
||||
movePtr(regNBytes, result);
|
||||
pop(regNBytes);
|
||||
}
|
||||
branchTest32(Assembler::Zero, result, result, fail);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::callFreeStub(Register slots)
|
||||
{
|
||||
// This register must match the one in JitRuntime::generateFreeStub.
|
||||
const Register regSlots = CallTempReg0;
|
||||
|
||||
push(regSlots);
|
||||
movePtr(slots, regSlots);
|
||||
call(GetIonContext()->runtime->jitRuntime()->freeStub());
|
||||
pop(regSlots);
|
||||
}
|
||||
|
||||
// Inlined equivalent of gc::AllocateObject, without failure case handling.
|
||||
void
|
||||
MacroAssembler::allocateObject(Register result, Register slots, gc::AllocKind allocKind,
|
||||
uint32_t nDynamicSlots, gc::InitialHeap initialHeap, Label *fail)
|
||||
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);
|
||||
|
||||
checkAllocatorState(fail);
|
||||
|
||||
if (shouldNurseryAllocate(allocKind, initialHeap))
|
||||
return nurseryAllocate(result, slots, allocKind, nDynamicSlots, initialHeap, fail);
|
||||
|
||||
if (!nDynamicSlots)
|
||||
return freeSpanAllocate(result, slots, allocKind, fail);
|
||||
|
||||
callMallocStub(nDynamicSlots * sizeof(HeapValue), slots, fail);
|
||||
|
||||
Label failAlloc;
|
||||
Label success;
|
||||
|
||||
push(slots);
|
||||
freeSpanAllocate(result, slots, allocKind, &failAlloc);
|
||||
pop(slots);
|
||||
jump(&success);
|
||||
|
||||
bind(&failAlloc);
|
||||
pop(slots);
|
||||
callFreeStub(slots);
|
||||
jump(fail);
|
||||
|
||||
bind(&success);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::newGCThing(Register result, Register temp, JSObject *templateObj,
|
||||
gc::InitialHeap initialHeap, Label *fail)
|
||||
{
|
||||
// This method does not initialize the object: if external slots get
|
||||
// allocated into |temp|, there is no easy way for us to ensure the caller
|
||||
// frees them. Instead just assert this case does not happen.
|
||||
JS_ASSERT(!templateObj->numDynamicSlots());
|
||||
|
||||
gc::AllocKind allocKind = templateObj->tenuredGetAllocKind();
|
||||
JS_ASSERT(allocKind >= gc::FINALIZE_OBJECT0 && allocKind <= gc::FINALIZE_OBJECT_LAST);
|
||||
|
||||
allocateObject(result, temp, allocKind, templateObj->numDynamicSlots(), initialHeap, fail);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::createGCObject(Register obj, Register temp, JSObject *templateObj,
|
||||
gc::InitialHeap initialHeap, Label *fail)
|
||||
{
|
||||
uint32_t nDynamicSlots = templateObj->numDynamicSlots();
|
||||
gc::AllocKind allocKind = templateObj->tenuredGetAllocKind();
|
||||
JS_ASSERT(allocKind >= gc::FINALIZE_OBJECT0 && allocKind <= gc::FINALIZE_OBJECT_LAST);
|
||||
|
||||
allocateObject(obj, temp, allocKind, nDynamicSlots, initialHeap, fail);
|
||||
initGCThing(obj, temp, templateObj);
|
||||
}
|
||||
|
||||
|
||||
// Inlined equivalent of gc::AllocateNonObject, without failure case handling.
|
||||
// Non-object allocation does not need to worry about slots, so can take a
|
||||
// simpler path.
|
||||
void
|
||||
MacroAssembler::allocateNonObject(Register result, Register temp, gc::AllocKind allocKind, Label *fail)
|
||||
{
|
||||
checkAllocatorState(fail);
|
||||
freeSpanAllocate(result, temp, allocKind, fail);
|
||||
newGCThing(result, temp, allocKind, fail, initialHeap);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::newGCString(Register result, Register temp, Label *fail)
|
||||
{
|
||||
allocateNonObject(result, temp, js::gc::FINALIZE_STRING, fail);
|
||||
newGCThing(result, temp, js::gc::FINALIZE_STRING, fail);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::newGCFatInlineString(Register result, Register temp, Label *fail)
|
||||
{
|
||||
allocateNonObject(result, temp, js::gc::FINALIZE_FAT_INLINE_STRING, fail);
|
||||
newGCThing(result, temp, js::gc::FINALIZE_FAT_INLINE_STRING, fail);
|
||||
}
|
||||
|
||||
void
|
||||
@ -677,7 +548,6 @@ MacroAssembler::newGCThingPar(Register result, Register cx, Register tempReg1, R
|
||||
{
|
||||
gc::AllocKind allocKind = templateObject->tenuredGetAllocKind();
|
||||
JS_ASSERT(allocKind >= gc::FINALIZE_OBJECT0 && allocKind <= gc::FINALIZE_OBJECT_LAST);
|
||||
JS_ASSERT(!templateObject->numDynamicSlots());
|
||||
|
||||
newGCThingPar(result, cx, tempReg1, tempReg2, allocKind, fail);
|
||||
}
|
||||
@ -697,7 +567,7 @@ MacroAssembler::newGCFatInlineStringPar(Register result, Register cx, Register t
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::copySlotsFromTemplate(Register obj, const JSObject *templateObj,
|
||||
MacroAssembler::copySlotsFromTemplate(Register obj, Register temp, const JSObject *templateObj,
|
||||
uint32_t start, uint32_t end)
|
||||
{
|
||||
uint32_t nfixed = Min(templateObj->numFixedSlots(), end);
|
||||
@ -706,26 +576,27 @@ MacroAssembler::copySlotsFromTemplate(Register obj, const JSObject *templateObj,
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::fillSlotsWithUndefined(Address base, Register temp, uint32_t start, uint32_t end)
|
||||
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);
|
||||
|
||||
Address addr = base;
|
||||
move32(Imm32(jv.s.payload.i32), temp);
|
||||
for (unsigned i = start; i < end; ++i, addr.offset += sizeof(HeapValue))
|
||||
store32(temp, ToPayload(addr));
|
||||
mov(ImmWord(jv.s.tag), temp);
|
||||
for (unsigned i = start; i < nfixed; i++)
|
||||
store32(temp, ToType(Address(obj, JSObject::getFixedSlotOffset(i))));
|
||||
|
||||
addr = base;
|
||||
move32(Imm32(jv.s.tag), temp);
|
||||
for (unsigned i = start; i < end; ++i, addr.offset += sizeof(HeapValue))
|
||||
store32(temp, ToType(addr));
|
||||
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);
|
||||
for (uint32_t i = start; i < end; ++i, base.offset += sizeof(HeapValue))
|
||||
storePtr(temp, base);
|
||||
uint32_t nfixed = Min(templateObj->numFixedSlots(), end);
|
||||
for (unsigned i = start; i < nfixed; i++)
|
||||
storePtr(temp, Address(obj, JSObject::getFixedSlotOffset(i)));
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -742,7 +613,7 @@ FindStartOfUndefinedSlots(JSObject *templateObj, uint32_t nslots)
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::initGCSlots(Register obj, Register slots, JSObject *templateObj)
|
||||
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.
|
||||
@ -750,9 +621,6 @@ MacroAssembler::initGCSlots(Register obj, Register slots, JSObject *templateObj)
|
||||
if (nslots == 0)
|
||||
return;
|
||||
|
||||
uint32_t nfixed = templateObj->numFixedSlots();
|
||||
uint32_t ndynamic = templateObj->numDynamicSlots();
|
||||
|
||||
// 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
|
||||
@ -761,41 +629,22 @@ MacroAssembler::initGCSlots(Register obj, Register slots, JSObject *templateObj)
|
||||
// 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);
|
||||
JS_ASSERT(startOfUndefined <= nfixed); // Reserved slots must be fixed.
|
||||
|
||||
// Copy over any preserved reserved slots.
|
||||
copySlotsFromTemplate(obj, templateObj, 0, startOfUndefined);
|
||||
|
||||
// Fill the rest of the fixed slots with undefined.
|
||||
fillSlotsWithUndefined(Address(obj, JSObject::getFixedSlotOffset(startOfUndefined)), slots,
|
||||
startOfUndefined, nfixed);
|
||||
|
||||
if (ndynamic) {
|
||||
// We are short one register to do this elegantly. Borrow the obj
|
||||
// register briefly for our slots base address.
|
||||
push(obj);
|
||||
loadPtr(Address(obj, JSObject::offsetOfSlots()), obj);
|
||||
fillSlotsWithUndefined(Address(obj, 0), slots, 0, ndynamic);
|
||||
pop(obj);
|
||||
}
|
||||
copySlotsFromTemplate(obj, temp, templateObj, 0, startOfUndefined);
|
||||
fillSlotsWithUndefined(obj, temp, templateObj, startOfUndefined, nslots);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::initGCThing(Register obj, Register slots, JSObject *templateObj)
|
||||
MacroAssembler::initGCThing(Register obj, Register temp, JSObject *templateObj)
|
||||
{
|
||||
// Fast initialization of an empty object returned by allocateObject().
|
||||
// Fast initialization of an empty object returned by NewGCThing().
|
||||
|
||||
JS_ASSERT(!templateObj->hasDynamicElements());
|
||||
|
||||
storePtr(ImmGCPtr(templateObj->lastProperty()), Address(obj, JSObject::offsetOfShape()));
|
||||
storePtr(ImmGCPtr(templateObj->type()), Address(obj, JSObject::offsetOfType()));
|
||||
if (templateObj->hasDynamicSlots())
|
||||
storePtr(slots, Address(obj, JSObject::offsetOfSlots()));
|
||||
else
|
||||
storePtr(ImmPtr(nullptr), Address(obj, JSObject::offsetOfSlots()));
|
||||
storePtr(ImmPtr(nullptr), Address(obj, JSObject::offsetOfSlots()));
|
||||
|
||||
if (templateObj->is<ArrayObject>()) {
|
||||
Register temp = slots;
|
||||
JS_ASSERT(!templateObj->getDenseInitializedLength());
|
||||
|
||||
int elementsOffset = JSObject::offsetOfFixedElements();
|
||||
@ -818,7 +667,7 @@ MacroAssembler::initGCThing(Register obj, Register slots, JSObject *templateObj)
|
||||
} else {
|
||||
storePtr(ImmPtr(emptyObjectElements), Address(obj, JSObject::offsetOfElements()));
|
||||
|
||||
initGCSlots(obj, slots, templateObj);
|
||||
initGCSlots(obj, temp, templateObj);
|
||||
|
||||
if (templateObj->hasPrivate()) {
|
||||
uint32_t nfixed = templateObj->numFixedSlots();
|
||||
|
@ -790,30 +790,10 @@ class MacroAssembler : public MacroAssemblerSpecific
|
||||
void branchEqualTypeIfNeeded(MIRType type, MDefinition *maybeDef, Register tag, Label *label);
|
||||
|
||||
// Inline allocation.
|
||||
private:
|
||||
void checkAllocatorState(Label *fail);
|
||||
bool shouldNurseryAllocate(gc::AllocKind allocKind, gc::InitialHeap initialHeap);
|
||||
void nurseryAllocate(Register result, Register slots, gc::AllocKind allocKind,
|
||||
size_t nDynamicSlots, gc::InitialHeap initialHeap, Label *fail);
|
||||
void freeSpanAllocate(Register result, Register temp, gc::AllocKind allocKind, Label *fail);
|
||||
void allocateObject(Register result, Register slots, gc::AllocKind allocKind,
|
||||
uint32_t nDynamicSlots, gc::InitialHeap initialHeap, Label *fail);
|
||||
void allocateNonObject(Register result, Register temp, gc::AllocKind allocKind, Label *fail);
|
||||
void copySlotsFromTemplate(Register obj, const JSObject *templateObj,
|
||||
uint32_t start, uint32_t end);
|
||||
void fillSlotsWithUndefined(Address addr, Register temp, uint32_t start, uint32_t end);
|
||||
void initGCSlots(Register obj, Register temp, JSObject *templateObj);
|
||||
|
||||
public:
|
||||
void callMallocStub(size_t nbytes, Register result, Label *fail);
|
||||
void callFreeStub(Register slots);
|
||||
void createGCObject(Register result, Register temp, JSObject *templateObj,
|
||||
gc::InitialHeap initialHeap, Label *fail);
|
||||
|
||||
void newGCThing(Register result, Register temp, JSObject *templateObj,
|
||||
gc::InitialHeap initialHeap, Label *fail);
|
||||
void initGCThing(Register obj, Register temp, JSObject *templateObj);
|
||||
|
||||
void newGCThing(Register result, Register temp, gc::AllocKind allocKind, Label *fail,
|
||||
gc::InitialHeap initialHeap = gc::DefaultHeap);
|
||||
void newGCThing(Register result, Register temp, JSObject *templateObject, Label *fail,
|
||||
gc::InitialHeap initialHeap);
|
||||
void newGCString(Register result, Register temp, Label *fail);
|
||||
void newGCFatInlineString(Register result, Register temp, Label *fail);
|
||||
|
||||
@ -826,6 +806,12 @@ class MacroAssembler : public MacroAssemblerSpecific
|
||||
void newGCFatInlineStringPar(Register result, Register cx, Register tempReg1, Register tempReg2,
|
||||
Label *fail);
|
||||
|
||||
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.
|
||||
|
@ -186,10 +186,6 @@ class JitRuntime
|
||||
JitCode *valuePreBarrier_;
|
||||
JitCode *shapePreBarrier_;
|
||||
|
||||
// Thunk to call malloc/free.
|
||||
JitCode *mallocStub_;
|
||||
JitCode *freeStub_;
|
||||
|
||||
// Thunk used by the debugger for breakpoint and step mode.
|
||||
JitCode *debugTrapHandler_;
|
||||
|
||||
@ -243,8 +239,6 @@ class JitRuntime
|
||||
JitCode *generateBailoutHandler(JSContext *cx);
|
||||
JitCode *generateInvalidator(JSContext *cx);
|
||||
JitCode *generatePreBarrier(JSContext *cx, MIRType type);
|
||||
JitCode *generateMallocStub(JSContext *cx);
|
||||
JitCode *generateFreeStub(JSContext *cx);
|
||||
JitCode *generateDebugTrapHandler(JSContext *cx);
|
||||
JitCode *generateForkJoinGetSliceStub(JSContext *cx);
|
||||
JitCode *generateBaselineDebugModeOSRHandler(JSContext *cx, uint32_t *noFrameRegPopOffsetOut);
|
||||
@ -361,14 +355,6 @@ class JitRuntime
|
||||
return shapePreBarrier_;
|
||||
}
|
||||
|
||||
JitCode *mallocStub() const {
|
||||
return mallocStub_;
|
||||
}
|
||||
|
||||
JitCode *freeStub() const {
|
||||
return freeStub_;
|
||||
}
|
||||
|
||||
bool ensureForkJoinGetSliceStubExists(JSContext *cx);
|
||||
JitCode *forkJoinGetSliceStub() const {
|
||||
return forkJoinGetSliceStub_;
|
||||
|
@ -302,6 +302,32 @@ class LGoto : public LControlInstructionHelper<1, 0, 0>
|
||||
}
|
||||
};
|
||||
|
||||
class LNewSlots : public LCallInstructionHelper<1, 0, 3>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(NewSlots)
|
||||
|
||||
LNewSlots(const LDefinition &temp1, const LDefinition &temp2, const LDefinition &temp3) {
|
||||
setTemp(0, temp1);
|
||||
setTemp(1, temp2);
|
||||
setTemp(2, temp3);
|
||||
}
|
||||
|
||||
const LDefinition *temp1() {
|
||||
return getTemp(0);
|
||||
}
|
||||
const LDefinition *temp2() {
|
||||
return getTemp(1);
|
||||
}
|
||||
const LDefinition *temp3() {
|
||||
return getTemp(2);
|
||||
}
|
||||
|
||||
MNewSlots *mir() const {
|
||||
return mir_->toNewSlots();
|
||||
}
|
||||
};
|
||||
|
||||
class LNewArray : public LInstructionHelper<1, 0, 1>
|
||||
{
|
||||
public:
|
||||
@ -438,19 +464,22 @@ class LNewDeclEnvObject : public LInstructionHelper<1, 0, 1>
|
||||
}
|
||||
};
|
||||
|
||||
// Allocates a new CallObject.
|
||||
// Allocates a new CallObject. The inputs are:
|
||||
// slots: either a reg representing a HeapSlot *, or a placeholder
|
||||
// meaning that no slots pointer is needed.
|
||||
//
|
||||
// This instruction generates two possible instruction sets:
|
||||
// (1) If the call object is extensible, this is a callVM to create the
|
||||
// call object.
|
||||
// (2) Otherwise, an inline allocation of the call object is attempted.
|
||||
//
|
||||
class LNewCallObject : public LInstructionHelper<1, 0, 1>
|
||||
class LNewCallObject : public LInstructionHelper<1, 1, 1>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(NewCallObject)
|
||||
|
||||
LNewCallObject(const LDefinition &temp) {
|
||||
LNewCallObject(const LAllocation &slots, const LDefinition &temp) {
|
||||
setOperand(0, slots);
|
||||
setTemp(0, temp);
|
||||
}
|
||||
|
||||
@ -458,42 +487,46 @@ class LNewCallObject : public LInstructionHelper<1, 0, 1>
|
||||
return getTemp(0);
|
||||
}
|
||||
|
||||
const LAllocation *slots() {
|
||||
return getOperand(0);
|
||||
}
|
||||
|
||||
MNewCallObject *mir() const {
|
||||
return mir_->toNewCallObject();
|
||||
}
|
||||
};
|
||||
|
||||
// Allocates a new CallObject with singleton type.
|
||||
// Allocates a new CallObject with singleton type through an out-of-line VM
|
||||
// call. The inputs are:
|
||||
// slots: either a reg representing a HeapSlot *, or a placeholder
|
||||
// meaning that no slots pointer is needed.
|
||||
//
|
||||
// This instruction generates two possible instruction sets:
|
||||
// (1) If the call object is extensible, this is a callVM to create the
|
||||
// call object.
|
||||
// (2) Otherwise, an inline allocation of the call object is attempted.
|
||||
//
|
||||
class LNewSingletonCallObject : public LInstructionHelper<1, 0, 1>
|
||||
class LNewSingletonCallObject : public LInstructionHelper<1, 1, 0>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(NewSingletonCallObject)
|
||||
|
||||
LNewSingletonCallObject(const LDefinition &temp) {
|
||||
setTemp(0, temp);
|
||||
LNewSingletonCallObject(const LAllocation &slots) {
|
||||
setOperand(0, slots);
|
||||
}
|
||||
|
||||
const LDefinition *temp() {
|
||||
return getTemp(0);
|
||||
const LAllocation *slots() {
|
||||
return getOperand(0);
|
||||
}
|
||||
|
||||
MNewCallObjectBase *mir() const {
|
||||
MNewCallObjectBase * mir() const {
|
||||
MOZ_ASSERT(mir_->isNewCallObject() || mir_->isNewRunOnceCallObject());
|
||||
return static_cast<MNewCallObjectBase *>(mir_);
|
||||
}
|
||||
};
|
||||
|
||||
class LNewCallObjectPar : public LInstructionHelper<1, 1, 2>
|
||||
class LNewCallObjectPar : public LInstructionHelper<1, 2, 2>
|
||||
{
|
||||
LNewCallObjectPar(const LAllocation &cx, const LDefinition &temp1, const LDefinition &temp2) {
|
||||
LNewCallObjectPar(const LAllocation &cx, const LAllocation &slots,
|
||||
const LDefinition &temp1, const LDefinition &temp2)
|
||||
{
|
||||
setOperand(0, cx);
|
||||
setOperand(1, slots);
|
||||
setTemp(0, temp1);
|
||||
setTemp(1, temp2);
|
||||
}
|
||||
@ -501,16 +534,37 @@ class LNewCallObjectPar : public LInstructionHelper<1, 1, 2>
|
||||
public:
|
||||
LIR_HEADER(NewCallObjectPar);
|
||||
|
||||
static LNewCallObjectPar *New(TempAllocator &alloc, const LAllocation &cx,
|
||||
const LDefinition &temp1, const LDefinition &temp2)
|
||||
static LNewCallObjectPar *NewWithSlots(TempAllocator &alloc,
|
||||
const LAllocation &cx, const LAllocation &slots,
|
||||
const LDefinition &temp1, const LDefinition &temp2)
|
||||
{
|
||||
return new(alloc) LNewCallObjectPar(cx, temp1, temp2);
|
||||
return new(alloc) LNewCallObjectPar(cx, slots, temp1, temp2);
|
||||
}
|
||||
|
||||
static LNewCallObjectPar *NewSansSlots(TempAllocator &alloc,
|
||||
const LAllocation &cx,
|
||||
const LDefinition &temp1, const LDefinition &temp2)
|
||||
{
|
||||
LAllocation slots = LConstantIndex::Bogus();
|
||||
return new(alloc) LNewCallObjectPar(cx, slots, temp1, temp2);
|
||||
}
|
||||
|
||||
const LAllocation *forkJoinContext() {
|
||||
return getOperand(0);
|
||||
}
|
||||
|
||||
const LAllocation *slots() {
|
||||
return getOperand(1);
|
||||
}
|
||||
|
||||
const bool hasDynamicSlots() {
|
||||
// TO INVESTIGATE: Felix tried using isRegister() method here,
|
||||
// but for useFixed(_, CallTempN), isRegister() is false (and
|
||||
// isUse() is true). So for now ignore that and try to match
|
||||
// the LConstantIndex::Bogus() generated above instead.
|
||||
return slots() && ! slots()->isConstant();
|
||||
}
|
||||
|
||||
const MNewCallObjectPar *mir() const {
|
||||
return mir_->toNewCallObjectPar();
|
||||
}
|
||||
|
@ -26,6 +26,7 @@
|
||||
_(NewArray) \
|
||||
_(ArraySplice) \
|
||||
_(NewObject) \
|
||||
_(NewSlots) \
|
||||
_(NewDeclEnvObject) \
|
||||
_(NewCallObject) \
|
||||
_(NewSingletonCallObject) \
|
||||
|
@ -158,6 +158,17 @@ LIRGenerator::visitDefFun(MDefFun *ins)
|
||||
return add(lir, ins) && assignSafepoint(lir, ins);
|
||||
}
|
||||
|
||||
bool
|
||||
LIRGenerator::visitNewSlots(MNewSlots *ins)
|
||||
{
|
||||
// No safepoint needed, since we don't pass a cx.
|
||||
LNewSlots *lir = new(alloc()) LNewSlots(tempFixed(CallTempReg0), tempFixed(CallTempReg1),
|
||||
tempFixed(CallTempReg2));
|
||||
if (!assignSnapshot(lir))
|
||||
return false;
|
||||
return defineReturn(lir, ins);
|
||||
}
|
||||
|
||||
bool
|
||||
LIRGenerator::visitNewArray(MNewArray *ins)
|
||||
{
|
||||
@ -182,14 +193,20 @@ LIRGenerator::visitNewDeclEnvObject(MNewDeclEnvObject *ins)
|
||||
bool
|
||||
LIRGenerator::visitNewCallObject(MNewCallObject *ins)
|
||||
{
|
||||
LAllocation slots;
|
||||
if (ins->slots()->type() == MIRType_Slots)
|
||||
slots = useRegister(ins->slots());
|
||||
else
|
||||
slots = LConstantIndex::Bogus();
|
||||
|
||||
LInstruction *lir;
|
||||
if (ins->templateObject()->hasSingletonType()) {
|
||||
LNewSingletonCallObject *singletonLir = new(alloc()) LNewSingletonCallObject(temp());
|
||||
LNewSingletonCallObject *singletonLir = new(alloc()) LNewSingletonCallObject(slots);
|
||||
if (!define(singletonLir, ins))
|
||||
return false;
|
||||
lir = singletonLir;
|
||||
} else {
|
||||
LNewCallObject *normalLir = new(alloc()) LNewCallObject(temp());
|
||||
LNewCallObject *normalLir = new(alloc()) LNewCallObject(slots, temp());
|
||||
if (!define(normalLir, ins))
|
||||
return false;
|
||||
lir = normalLir;
|
||||
@ -204,7 +221,13 @@ LIRGenerator::visitNewCallObject(MNewCallObject *ins)
|
||||
bool
|
||||
LIRGenerator::visitNewRunOnceCallObject(MNewRunOnceCallObject *ins)
|
||||
{
|
||||
LNewSingletonCallObject *lir = new(alloc()) LNewSingletonCallObject(temp());
|
||||
LAllocation slots;
|
||||
if (ins->slots()->type() == MIRType_Slots)
|
||||
slots = useRegister(ins->slots());
|
||||
else
|
||||
slots = LConstantIndex::Bogus();
|
||||
|
||||
LNewSingletonCallObject *lir = new(alloc()) LNewSingletonCallObject(slots);
|
||||
if (!define(lir, ins))
|
||||
return false;
|
||||
|
||||
@ -228,7 +251,17 @@ bool
|
||||
LIRGenerator::visitNewCallObjectPar(MNewCallObjectPar *ins)
|
||||
{
|
||||
const LAllocation &parThreadContext = useRegister(ins->forkJoinContext());
|
||||
LNewCallObjectPar *lir = LNewCallObjectPar::New(alloc(), parThreadContext, temp(), temp());
|
||||
const LDefinition &temp1 = temp();
|
||||
const LDefinition &temp2 = temp();
|
||||
|
||||
LNewCallObjectPar *lir;
|
||||
if (ins->slots()->type() == MIRType_Slots) {
|
||||
const LAllocation &slots = useRegister(ins->slots());
|
||||
lir = LNewCallObjectPar::NewWithSlots(alloc(), parThreadContext, slots, temp1, temp2);
|
||||
} else {
|
||||
lir = LNewCallObjectPar::NewSansSlots(alloc(), parThreadContext, temp1, temp2);
|
||||
}
|
||||
|
||||
return define(lir, ins);
|
||||
}
|
||||
|
||||
|
@ -68,6 +68,7 @@ class LIRGenerator : public LIRGeneratorSpecific
|
||||
bool visitCallee(MCallee *callee);
|
||||
bool visitGoto(MGoto *ins);
|
||||
bool visitTableSwitch(MTableSwitch *tableswitch);
|
||||
bool visitNewSlots(MNewSlots *ins);
|
||||
bool visitNewArray(MNewArray *ins);
|
||||
bool visitNewObject(MNewObject *ins);
|
||||
bool visitNewDeclEnvObject(MNewDeclEnvObject *ins);
|
||||
|
@ -9319,6 +9319,33 @@ class MPostWriteBarrier : public MBinaryInstruction, public ObjectPolicy<0>
|
||||
#endif
|
||||
};
|
||||
|
||||
class MNewSlots : public MNullaryInstruction
|
||||
{
|
||||
unsigned nslots_;
|
||||
|
||||
MNewSlots(unsigned nslots)
|
||||
: nslots_(nslots)
|
||||
{
|
||||
setResultType(MIRType_Slots);
|
||||
}
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(NewSlots)
|
||||
|
||||
static MNewSlots *New(TempAllocator &alloc, unsigned nslots) {
|
||||
return new(alloc) MNewSlots(nslots);
|
||||
}
|
||||
unsigned nslots() const {
|
||||
return nslots_;
|
||||
}
|
||||
AliasSet getAliasSet() const {
|
||||
return AliasSet::None();
|
||||
}
|
||||
bool possiblyCalls() const {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class MNewDeclEnvObject : public MNullaryInstruction
|
||||
{
|
||||
CompilerRootObject templateObj_;
|
||||
@ -9345,19 +9372,22 @@ class MNewDeclEnvObject : public MNullaryInstruction
|
||||
}
|
||||
};
|
||||
|
||||
class MNewCallObjectBase : public MNullaryInstruction
|
||||
class MNewCallObjectBase : public MUnaryInstruction
|
||||
{
|
||||
CompilerRootObject templateObj_;
|
||||
|
||||
protected:
|
||||
MNewCallObjectBase(JSObject *templateObj)
|
||||
: MNullaryInstruction(),
|
||||
MNewCallObjectBase(JSObject *templateObj, MDefinition *slots)
|
||||
: MUnaryInstruction(slots),
|
||||
templateObj_(templateObj)
|
||||
{
|
||||
setResultType(MIRType_Object);
|
||||
}
|
||||
|
||||
public:
|
||||
MDefinition *slots() {
|
||||
return getOperand(0);
|
||||
}
|
||||
JSObject *templateObject() {
|
||||
return templateObj_;
|
||||
}
|
||||
@ -9371,14 +9401,14 @@ class MNewCallObject : public MNewCallObjectBase
|
||||
public:
|
||||
INSTRUCTION_HEADER(NewCallObject)
|
||||
|
||||
MNewCallObject(JSObject *templateObj)
|
||||
: MNewCallObjectBase(templateObj)
|
||||
MNewCallObject(JSObject *templateObj, MDefinition *slots)
|
||||
: MNewCallObjectBase(templateObj, slots)
|
||||
{}
|
||||
|
||||
static MNewCallObject *
|
||||
New(TempAllocator &alloc, JSObject *templateObj)
|
||||
New(TempAllocator &alloc, JSObject *templateObj, MDefinition *slots)
|
||||
{
|
||||
return new(alloc) MNewCallObject(templateObj);
|
||||
return new(alloc) MNewCallObject(templateObj, slots);
|
||||
}
|
||||
};
|
||||
|
||||
@ -9387,23 +9417,23 @@ class MNewRunOnceCallObject : public MNewCallObjectBase
|
||||
public:
|
||||
INSTRUCTION_HEADER(NewRunOnceCallObject)
|
||||
|
||||
MNewRunOnceCallObject(JSObject *templateObj)
|
||||
: MNewCallObjectBase(templateObj)
|
||||
MNewRunOnceCallObject(JSObject *templateObj, MDefinition *slots)
|
||||
: MNewCallObjectBase(templateObj, slots)
|
||||
{}
|
||||
|
||||
static MNewRunOnceCallObject *
|
||||
New(TempAllocator &alloc, JSObject *templateObj)
|
||||
New(TempAllocator &alloc, JSObject *templateObj, MDefinition *slots)
|
||||
{
|
||||
return new(alloc) MNewRunOnceCallObject(templateObj);
|
||||
return new(alloc) MNewRunOnceCallObject(templateObj, slots);
|
||||
}
|
||||
};
|
||||
|
||||
class MNewCallObjectPar : public MUnaryInstruction
|
||||
class MNewCallObjectPar : public MBinaryInstruction
|
||||
{
|
||||
CompilerRootObject templateObj_;
|
||||
|
||||
MNewCallObjectPar(MDefinition *cx, JSObject *templateObj)
|
||||
: MUnaryInstruction(cx),
|
||||
MNewCallObjectPar(MDefinition *cx, JSObject *templateObj, MDefinition *slots)
|
||||
: MBinaryInstruction(cx, slots),
|
||||
templateObj_(templateObj)
|
||||
{
|
||||
setResultType(MIRType_Object);
|
||||
@ -9413,13 +9443,17 @@ class MNewCallObjectPar : public MUnaryInstruction
|
||||
INSTRUCTION_HEADER(NewCallObjectPar);
|
||||
|
||||
static MNewCallObjectPar *New(TempAllocator &alloc, MDefinition *cx, MNewCallObjectBase *callObj) {
|
||||
return new(alloc) MNewCallObjectPar(cx, callObj->templateObject());
|
||||
return new(alloc) MNewCallObjectPar(cx, callObj->templateObject(), callObj->slots());
|
||||
}
|
||||
|
||||
MDefinition *forkJoinContext() const {
|
||||
return getOperand(0);
|
||||
}
|
||||
|
||||
MDefinition *slots() const {
|
||||
return getOperand(1);
|
||||
}
|
||||
|
||||
JSObject *templateObj() const {
|
||||
return templateObj_;
|
||||
}
|
||||
|
@ -87,6 +87,7 @@ namespace jit {
|
||||
_(ToInt32) \
|
||||
_(TruncateToInt32) \
|
||||
_(ToString) \
|
||||
_(NewSlots) \
|
||||
_(NewArray) \
|
||||
_(NewObject) \
|
||||
_(NewDeclEnvObject) \
|
||||
|
@ -181,6 +181,7 @@ class ParallelSafetyVisitor : public MInstructionVisitor
|
||||
SAFE_OP(TruncateToInt32)
|
||||
SAFE_OP(MaybeToDoubleElement)
|
||||
CUSTOM_OP(ToString)
|
||||
SAFE_OP(NewSlots)
|
||||
CUSTOM_OP(NewArray)
|
||||
CUSTOM_OP(NewObject)
|
||||
CUSTOM_OP(NewCallObject)
|
||||
@ -532,10 +533,6 @@ ParallelSafetyVisitor::visitCreateThisWithTemplate(MCreateThisWithTemplate *ins)
|
||||
bool
|
||||
ParallelSafetyVisitor::visitNewCallObject(MNewCallObject *ins)
|
||||
{
|
||||
if (ins->templateObject()->hasDynamicSlots()) {
|
||||
SpewMIR(ins, "call with dynamic slots");
|
||||
return markUnsafe();
|
||||
}
|
||||
replace(ins, MNewCallObjectPar::New(alloc(), ForkJoinContext(), ins));
|
||||
return true;
|
||||
}
|
||||
@ -543,10 +540,6 @@ ParallelSafetyVisitor::visitNewCallObject(MNewCallObject *ins)
|
||||
bool
|
||||
ParallelSafetyVisitor::visitNewRunOnceCallObject(MNewRunOnceCallObject *ins)
|
||||
{
|
||||
if (ins->templateObject()->hasDynamicSlots()) {
|
||||
SpewMIR(ins, "call with dynamic slots");
|
||||
return markUnsafe();
|
||||
}
|
||||
replace(ins, MNewCallObjectPar::New(alloc(), ForkJoinContext(), ins));
|
||||
return true;
|
||||
}
|
||||
@ -675,6 +668,11 @@ ParallelSafetyVisitor::insertWriteGuard(MInstruction *writeInstruction,
|
||||
object = valueBeingWritten->toSlots()->object();
|
||||
break;
|
||||
|
||||
case MDefinition::Op_NewSlots:
|
||||
// Values produced by new slots will ALWAYS be
|
||||
// thread-local.
|
||||
return true;
|
||||
|
||||
default:
|
||||
SpewMIR(writeInstruction, "cannot insert write guard for %s",
|
||||
valueBeingWritten->opName());
|
||||
|
@ -525,16 +525,25 @@ InterruptCheck(JSContext *cx)
|
||||
return CheckForInterrupt(cx);
|
||||
}
|
||||
|
||||
void *
|
||||
MallocWrapper(JSRuntime *rt, size_t nbytes)
|
||||
HeapSlot *
|
||||
NewSlots(JSRuntime *rt, unsigned nslots)
|
||||
{
|
||||
return rt->pod_malloc<uint8_t>(nbytes);
|
||||
JS_STATIC_ASSERT(sizeof(Value) == sizeof(HeapSlot));
|
||||
|
||||
Value *slots = reinterpret_cast<Value *>(rt->malloc_(nslots * sizeof(Value)));
|
||||
if (!slots)
|
||||
return nullptr;
|
||||
|
||||
for (unsigned i = 0; i < nslots; i++)
|
||||
slots[i] = UndefinedValue();
|
||||
|
||||
return reinterpret_cast<HeapSlot *>(slots);
|
||||
}
|
||||
|
||||
JSObject *
|
||||
NewCallObject(JSContext *cx, HandleShape shape, HandleTypeObject type)
|
||||
NewCallObject(JSContext *cx, HandleShape shape, HandleTypeObject type, HeapSlot *slots)
|
||||
{
|
||||
JSObject *obj = CallObject::create(cx, shape, type);
|
||||
JSObject *obj = CallObject::create(cx, shape, type, slots);
|
||||
if (!obj)
|
||||
return nullptr;
|
||||
|
||||
@ -550,9 +559,9 @@ NewCallObject(JSContext *cx, HandleShape shape, HandleTypeObject type)
|
||||
}
|
||||
|
||||
JSObject *
|
||||
NewSingletonCallObject(JSContext *cx, HandleShape shape)
|
||||
NewSingletonCallObject(JSContext *cx, HandleShape shape, HeapSlot *slots)
|
||||
{
|
||||
JSObject *obj = CallObject::createSingleton(cx, shape);
|
||||
JSObject *obj = CallObject::createSingleton(cx, shape, slots);
|
||||
if (!obj)
|
||||
return nullptr;
|
||||
|
||||
|
@ -619,9 +619,9 @@ bool SetProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, Handl
|
||||
|
||||
bool InterruptCheck(JSContext *cx);
|
||||
|
||||
void *MallocWrapper(JSRuntime *rt, size_t nbytes);
|
||||
JSObject *NewCallObject(JSContext *cx, HandleShape shape, HandleTypeObject type);
|
||||
JSObject *NewSingletonCallObject(JSContext *cx, HandleShape shape);
|
||||
HeapSlot *NewSlots(JSRuntime *rt, unsigned nslots);
|
||||
JSObject *NewCallObject(JSContext *cx, HandleShape shape, HandleTypeObject type, HeapSlot *slots);
|
||||
JSObject *NewSingletonCallObject(JSContext *cx, HandleShape shape, HeapSlot *slots);
|
||||
JSObject *NewStringObject(JSContext *cx, HandleString str);
|
||||
|
||||
bool SPSEnter(JSContext *cx, HandleScript script);
|
||||
|
@ -245,10 +245,8 @@ struct AssemblerBuffer
|
||||
// Break the instruction stream so we can go back and edit it at this point
|
||||
void perforate() {
|
||||
Slice *tmp = newSlice(LifoAlloc_);
|
||||
if (!tmp) {
|
||||
if (!tmp)
|
||||
m_oom = true;
|
||||
return;
|
||||
}
|
||||
bufferSize += tail->size();
|
||||
tail->setNext(tmp);
|
||||
tail = tmp;
|
||||
|
@ -236,7 +236,8 @@ class JSObject : public js::ObjectImpl
|
||||
js::gc::AllocKind kind,
|
||||
js::gc::InitialHeap heap,
|
||||
js::HandleShape shape,
|
||||
js::HandleTypeObject type);
|
||||
js::HandleTypeObject type,
|
||||
js::HeapSlot *extantSlots = nullptr);
|
||||
|
||||
/* Make an array object with the specified initial state. */
|
||||
static inline js::ArrayObject *createArray(js::ExclusiveContext *cx,
|
||||
|
@ -486,8 +486,14 @@ JSObject::isVarObj()
|
||||
|
||||
/* static */ inline JSObject *
|
||||
JSObject::create(js::ExclusiveContext *cx, js::gc::AllocKind kind, js::gc::InitialHeap heap,
|
||||
js::HandleShape shape, js::HandleTypeObject type)
|
||||
js::HandleShape shape, js::HandleTypeObject type,
|
||||
js::HeapSlot *extantSlots /* = nullptr */)
|
||||
{
|
||||
/*
|
||||
* Callers must use dynamicSlotsCount to size the initial slot array of the
|
||||
* object. We can't check the allocated capacity of the dynamic slots, but
|
||||
* make sure their presence is consistent with the shape.
|
||||
*/
|
||||
JS_ASSERT(shape && type);
|
||||
JS_ASSERT(type->clasp() == shape->getObjectClass());
|
||||
JS_ASSERT(type->clasp() != &js::ArrayObject::class_);
|
||||
@ -495,9 +501,13 @@ JSObject::create(js::ExclusiveContext *cx, js::gc::AllocKind kind, js::gc::Initi
|
||||
js::gc::GetGCKindSlots(kind, type->clasp()) == shape->numFixedSlots());
|
||||
JS_ASSERT_IF(type->clasp()->flags & JSCLASS_BACKGROUND_FINALIZE, IsBackgroundFinalized(kind));
|
||||
JS_ASSERT_IF(type->clasp()->finalize, heap == js::gc::TenuredHeap);
|
||||
JS_ASSERT_IF(extantSlots, dynamicSlotsCount(shape->numFixedSlots(), shape->slotSpan(),
|
||||
type->clasp()));
|
||||
|
||||
const js::Class *clasp = type->clasp();
|
||||
size_t nDynamicSlots = dynamicSlotsCount(shape->numFixedSlots(), shape->slotSpan(), clasp);
|
||||
size_t nDynamicSlots = 0;
|
||||
if (!extantSlots)
|
||||
nDynamicSlots = dynamicSlotsCount(shape->numFixedSlots(), shape->slotSpan(), clasp);
|
||||
|
||||
JSObject *obj = js::NewGCObject<js::CanGC>(cx, kind, nDynamicSlots, heap);
|
||||
if (!obj)
|
||||
@ -505,7 +515,13 @@ JSObject::create(js::ExclusiveContext *cx, js::gc::AllocKind kind, js::gc::Initi
|
||||
|
||||
obj->shape_.init(shape);
|
||||
obj->type_.init(type);
|
||||
// Note: slots are created and assigned internally by NewGCObject.
|
||||
if (extantSlots) {
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
if (cx->isJSContext())
|
||||
cx->asJSContext()->runtime()->gc.nursery.notifyInitialSlots(obj, extantSlots);
|
||||
#endif
|
||||
obj->slots = extantSlots;
|
||||
}
|
||||
obj->elements = js::emptyObjectElements;
|
||||
|
||||
if (clasp->hasPrivate())
|
||||
|
@ -137,7 +137,7 @@ ScopeObject::setEnclosingScope(HandleObject obj)
|
||||
}
|
||||
|
||||
CallObject *
|
||||
CallObject::create(JSContext *cx, HandleShape shape, HandleTypeObject type)
|
||||
CallObject::create(JSContext *cx, HandleShape shape, HandleTypeObject type, HeapSlot *slots)
|
||||
{
|
||||
MOZ_ASSERT(!type->singleton(),
|
||||
"passed a singleton type to create() (use createSingleton() "
|
||||
@ -146,7 +146,7 @@ CallObject::create(JSContext *cx, HandleShape shape, HandleTypeObject type)
|
||||
MOZ_ASSERT(CanBeFinalizedInBackground(kind, &CallObject::class_));
|
||||
kind = gc::GetBackgroundAllocKind(kind);
|
||||
|
||||
JSObject *obj = JSObject::create(cx, kind, gc::DefaultHeap, shape, type);
|
||||
JSObject *obj = JSObject::create(cx, kind, gc::DefaultHeap, shape, type, slots);
|
||||
if (!obj)
|
||||
return nullptr;
|
||||
|
||||
@ -154,7 +154,7 @@ CallObject::create(JSContext *cx, HandleShape shape, HandleTypeObject type)
|
||||
}
|
||||
|
||||
CallObject *
|
||||
CallObject::createSingleton(JSContext *cx, HandleShape shape)
|
||||
CallObject::createSingleton(JSContext *cx, HandleShape shape, HeapSlot *slots)
|
||||
{
|
||||
gc::AllocKind kind = gc::GetGCObjectKind(shape->numFixedSlots());
|
||||
MOZ_ASSERT(CanBeFinalizedInBackground(kind, &CallObject::class_));
|
||||
@ -163,7 +163,7 @@ CallObject::createSingleton(JSContext *cx, HandleShape shape)
|
||||
RootedTypeObject type(cx, cx->getSingletonType(&class_, nullptr));
|
||||
if (!type)
|
||||
return nullptr;
|
||||
RootedObject obj(cx, JSObject::create(cx, kind, gc::TenuredHeap, shape, type));
|
||||
RootedObject obj(cx, JSObject::create(cx, kind, gc::TenuredHeap, shape, type, slots));
|
||||
if (!obj)
|
||||
return nullptr;
|
||||
|
||||
|
@ -238,18 +238,20 @@ class CallObject : public ScopeObject
|
||||
/* These functions are internal and are exposed only for JITs. */
|
||||
|
||||
/*
|
||||
* Construct a bare-bones call object given a shape and a non-singleton
|
||||
* type. The call object must be further initialized to be usable.
|
||||
* Construct a bare-bones call object given a shape, a non-singleton type,
|
||||
* and slots pointer. The call object must be further initialized to be
|
||||
* usable.
|
||||
*/
|
||||
static CallObject *
|
||||
create(JSContext *cx, HandleShape shape, HandleTypeObject type);
|
||||
create(JSContext *cx, HandleShape shape, HandleTypeObject type, HeapSlot *slots);
|
||||
|
||||
/*
|
||||
* Construct a bare-bones call object given a shape and make it have
|
||||
* singleton type. The call object must be initialized to be usable.
|
||||
* Construct a bare-bones call object given a shape and slots pointer, and
|
||||
* make it have singleton type. The call object must be initialized to be
|
||||
* usable.
|
||||
*/
|
||||
static CallObject *
|
||||
createSingleton(JSContext *cx, HandleShape shape);
|
||||
createSingleton(JSContext *cx, HandleShape shape, HeapSlot *slots);
|
||||
|
||||
static CallObject *
|
||||
createTemplateObject(JSContext *cx, HandleScript script, gc::InitialHeap heap);
|
||||
|
Loading…
Reference in New Issue
Block a user