Backed out changeset 6604b700492c (bug 863018) for suspicion of causing Windows mochitest b-c leaks.

CLOSED TREE
This commit is contained in:
Ryan VanderMeulen 2013-04-26 12:03:03 -04:00
Родитель 096bddd96f
Коммит 3b61162ed3
16 изменённых файлов: 28 добавлений и 233 удалений

Просмотреть файл

@ -3548,152 +3548,52 @@ CodeGenerator::visitConcat(LConcat *lir)
Register rhs = ToRegister(lir->rhs()); Register rhs = ToRegister(lir->rhs());
Register output = ToRegister(lir->output()); Register output = ToRegister(lir->output());
Register temp = ToRegister(lir->temp());
JS_ASSERT(lhs == CallTempReg0);
JS_ASSERT(rhs == CallTempReg1);
JS_ASSERT(ToRegister(lir->temp1()) == CallTempReg2);
JS_ASSERT(ToRegister(lir->temp2()) == CallTempReg3);
JS_ASSERT(ToRegister(lir->temp3()) == CallTempReg4);
JS_ASSERT(ToRegister(lir->temp4()) == CallTempReg5);
JS_ASSERT(output == CallTempReg6);
OutOfLineCode *ool = oolCallVM(ConcatStringsInfo, lir, (ArgList(), lhs, rhs), OutOfLineCode *ool = oolCallVM(ConcatStringsInfo, lir, (ArgList(), lhs, rhs),
StoreRegisterTo(output)); StoreRegisterTo(output));
if (!ool) if (!ool)
return false; return false;
IonCode *stringConcatStub = gen->ionCompartment()->stringConcatStub(); Label done;
masm.call(stringConcatStub);
masm.branchTestPtr(Assembler::Zero, output, output, ool->entry());
masm.bind(ool->rejoin());
return true;
}
static void
CopyStringChars(MacroAssembler &masm, Register to, Register from, Register len, Register scratch)
{
// Copy |len| jschars from |from| to |to|. Assumes len > 0 (checked below in
// debug builds), and when done |to| must point to the next available char.
#ifdef DEBUG
Label ok;
masm.branch32(Assembler::GreaterThan, len, Imm32(0), &ok);
masm.breakpoint();
masm.bind(&ok);
#endif
JS_STATIC_ASSERT(sizeof(jschar) == 2);
Label start;
masm.bind(&start);
masm.load16ZeroExtend(Address(from, 0), scratch);
masm.store16(scratch, Address(to, 0));
masm.addPtr(Imm32(2), from);
masm.addPtr(Imm32(2), to);
masm.sub32(Imm32(1), len);
masm.j(Assembler::NonZero, &start);
}
IonCode *
IonCompartment::generateStringConcatStub(JSContext *cx)
{
MacroAssembler masm(cx);
Register lhs = CallTempReg0;
Register rhs = CallTempReg1;
Register temp1 = CallTempReg2;
Register temp2 = CallTempReg3;
Register temp3 = CallTempReg4;
Register temp4 = CallTempReg5;
Register output = CallTempReg6;
Label failure;
// If lhs is empty, return rhs. // If lhs is empty, return rhs.
Label leftEmpty; Label leftEmpty;
masm.loadStringLength(lhs, temp1); masm.loadStringLength(lhs, temp);
masm.branchTest32(Assembler::Zero, temp1, temp1, &leftEmpty); masm.branchTest32(Assembler::Zero, temp, temp, &leftEmpty);
// If rhs is empty, return lhs. // If rhs is empty, return lhs.
Label rightEmpty; Label rightEmpty;
masm.loadStringLength(rhs, temp2); masm.loadStringLength(rhs, output);
masm.branchTest32(Assembler::Zero, temp2, temp2, &rightEmpty); masm.branchTest32(Assembler::Zero, output, output, &rightEmpty);
masm.add32(temp1, temp2); // Ensure total length <= JSString::MAX_LENGTH.
masm.add32(output, temp);
// Check if we can use a JSShortString. masm.branch32(Assembler::Above, temp, Imm32(JSString::MAX_LENGTH), ool->entry());
Label isShort;
masm.branch32(Assembler::BelowOrEqual, temp2, Imm32(JSShortString::MAX_SHORT_LENGTH),
&isShort);
// Ensure result length <= JSString::MAX_LENGTH.
masm.branch32(Assembler::Above, temp1, Imm32(JSString::MAX_LENGTH), &failure);
// Allocate a new rope. // Allocate a new rope.
masm.newGCString(output, &failure); masm.newGCString(output, ool->entry());
// Store lengthAndFlags. // Store lengthAndFlags.
JS_STATIC_ASSERT(JSString::ROPE_FLAGS == 0); JS_STATIC_ASSERT(JSString::ROPE_FLAGS == 0);
masm.lshiftPtr(Imm32(JSString::LENGTH_SHIFT), temp2); masm.lshiftPtr(Imm32(JSString::LENGTH_SHIFT), temp);
masm.storePtr(temp2, Address(output, JSString::offsetOfLengthAndFlags())); masm.storePtr(temp, Address(output, JSString::offsetOfLengthAndFlags()));
// Store left and right nodes. // Store left and right nodes.
masm.storePtr(lhs, Address(output, JSRope::offsetOfLeft())); masm.storePtr(lhs, Address(output, JSRope::offsetOfLeft()));
masm.storePtr(rhs, Address(output, JSRope::offsetOfRight())); masm.storePtr(rhs, Address(output, JSRope::offsetOfRight()));
masm.ret(); masm.jump(&done);
masm.bind(&leftEmpty); masm.bind(&leftEmpty);
masm.mov(rhs, output); masm.mov(rhs, output);
masm.ret(); masm.jump(&done);
masm.bind(&rightEmpty); masm.bind(&rightEmpty);
masm.mov(lhs, output); masm.mov(lhs, output);
masm.ret();
masm.bind(&isShort); masm.bind(&done);
masm.bind(ool->rejoin());
// State: lhs length in temp1, result length in temp2. return true;
// Ensure both strings are linear (flags != 0).
JS_STATIC_ASSERT(JSString::ROPE_FLAGS == 0);
masm.branchTestPtr(Assembler::Zero, Address(lhs, JSString::offsetOfLengthAndFlags()),
Imm32(JSString::FLAGS_MASK), &failure);
masm.branchTestPtr(Assembler::Zero, Address(rhs, JSString::offsetOfLengthAndFlags()),
Imm32(JSString::FLAGS_MASK), &failure);
// Allocate a JSShortString.
masm.newGCShortString(output, &failure);
// Set lengthAndFlags.
masm.lshiftPtr(Imm32(JSString::LENGTH_SHIFT), temp2);
masm.orPtr(Imm32(JSString::FIXED_FLAGS), temp2);
masm.storePtr(temp2, Address(output, JSString::offsetOfLengthAndFlags()));
// Set chars pointer, keep in temp2 for copy loop below.
masm.computeEffectiveAddress(Address(output, JSShortString::offsetOfInlineStorage()), temp2);
masm.storePtr(temp2, Address(output, JSShortString::offsetOfChars()));
// Copy lhs chars. Temp1 still holds the lhs length. Note that this
// advances temp2 to point to the next char.
masm.loadPtr(Address(lhs, JSString::offsetOfChars()), temp3);
CopyStringChars(masm, temp2, temp3, temp1, temp4);
// Copy rhs chars.
masm.loadPtr(Address(rhs, JSString::offsetOfChars()), temp3);
masm.loadStringLength(rhs, temp1);
CopyStringChars(masm, temp2, temp3, temp1, temp4);
// Null-terminate.
masm.store16(Imm32(0), Address(temp2, 0));
masm.ret();
masm.bind(&failure);
masm.movePtr(ImmWord((void *)NULL), output);
masm.ret();
Linker linker(masm);
return linker.newCode(cx, JSC::OTHER_CODE);
} }
typedef bool (*CharCodeAtFn)(JSContext *, HandleString, int32_t, uint32_t *); typedef bool (*CharCodeAtFn)(JSContext *, HandleString, int32_t, uint32_t *);

Просмотреть файл

@ -183,6 +183,9 @@ IonRuntime::initialize(JSContext *cx)
{ {
AutoEnterAtomsCompartment ac(cx); AutoEnterAtomsCompartment ac(cx);
if (!cx->compartment->ensureIonCompartmentExists(cx))
return false;
IonContext ictx(cx, NULL); IonContext ictx(cx, NULL);
AutoFlushCache afc("IonRuntime::initialize"); AutoFlushCache afc("IonRuntime::initialize");
@ -190,9 +193,6 @@ IonRuntime::initialize(JSContext *cx)
if (!execAlloc_) if (!execAlloc_)
return false; return false;
if (!cx->compartment->ensureIonCompartmentExists(cx))
return false;
functionWrappers_ = cx->new_<VMWrapperMap>(cx); functionWrappers_ = cx->new_<VMWrapperMap>(cx);
if (!functionWrappers_ || !functionWrappers_->init()) if (!functionWrappers_ || !functionWrappers_->init())
return false; return false;
@ -284,8 +284,7 @@ IonRuntime::freeOsrTempData()
IonCompartment::IonCompartment(IonRuntime *rt) IonCompartment::IonCompartment(IonRuntime *rt)
: rt(rt), : rt(rt),
stubCodes_(NULL), stubCodes_(NULL),
baselineCallReturnAddr_(NULL), baselineCallReturnAddr_(NULL)
stringConcatStub_(NULL)
{ {
} }
@ -301,11 +300,6 @@ IonCompartment::initialize(JSContext *cx)
stubCodes_ = cx->new_<ICStubCodeMap>(cx); stubCodes_ = cx->new_<ICStubCodeMap>(cx);
if (!stubCodes_ || !stubCodes_->init()) if (!stubCodes_ || !stubCodes_->init())
return false; return false;
stringConcatStub_ = generateStringConcatStub(cx);
if (!stringConcatStub_)
return false;
return true; return true;
} }
@ -360,8 +354,6 @@ IonCompartment::mark(JSTracer *trc, JSCompartment *compartment)
// Free temporary OSR buffer. // Free temporary OSR buffer.
rt->freeOsrTempData(); rt->freeOsrTempData();
MarkIonCodeRoot(trc, &stringConcatStub_, "stringConcatStub");
} }
void void

Просмотреть файл

@ -197,13 +197,6 @@ class IonCompartment
// Allocated space for optimized baseline stubs. // Allocated space for optimized baseline stubs.
OptimizedICStubSpace optimizedStubSpace_; OptimizedICStubSpace optimizedStubSpace_;
// Stub to concatenate two strings inline. Note that it can't be
// stored in IonRuntime because masm.newGCString bakes in
// zone-specific pointers.
IonCode *stringConcatStub_;
IonCode *generateStringConcatStub(JSContext *cx);
public: public:
IonCode *getVMWrapper(const VMFunction &f); IonCode *getVMWrapper(const VMFunction &f);
@ -291,10 +284,6 @@ class IonCompartment
return rt->debugTrapHandler(cx); return rt->debugTrapHandler(cx);
} }
IonCode *stringConcatStub() {
return stringConcatStub_;
}
AutoFlushCache *flusher() { AutoFlushCache *flusher() {
return rt->flusher(); return rt->flusher();
} }

Просмотреть файл

@ -463,12 +463,6 @@ MacroAssembler::newGCString(const Register &result, Label *fail)
newGCThing(result, js::gc::FINALIZE_STRING, fail); newGCThing(result, js::gc::FINALIZE_STRING, fail);
} }
void
MacroAssembler::newGCShortString(const Register &result, Label *fail)
{
newGCThing(result, js::gc::FINALIZE_SHORT_STRING, fail);
}
void void
MacroAssembler::parNewGCThing(const Register &result, MacroAssembler::parNewGCThing(const Register &result,
const Register &threadContextReg, const Register &threadContextReg,

Просмотреть файл

@ -580,7 +580,6 @@ class MacroAssembler : public MacroAssemblerSpecific
void newGCThing(const Register &result, gc::AllocKind allocKind, Label *fail); void newGCThing(const Register &result, gc::AllocKind allocKind, Label *fail);
void newGCThing(const Register &result, JSObject *templateObject, Label *fail); void newGCThing(const Register &result, JSObject *templateObject, Label *fail);
void newGCString(const Register &result, Label *fail); void newGCString(const Register &result, Label *fail);
void newGCShortString(const Register &result, Label *fail);
void parNewGCThing(const Register &result, void parNewGCThing(const Register &result,
const Register &threadContextReg, const Register &threadContextReg,

Просмотреть файл

@ -2243,19 +2243,15 @@ class LBinaryV : public LCallInstructionHelper<BOX_PIECES, 2 * BOX_PIECES, 0>
}; };
// Adds two string, returning a string. // Adds two string, returning a string.
class LConcat : public LInstructionHelper<1, 2, 4> class LConcat : public LInstructionHelper<1, 2, 1>
{ {
public: public:
LIR_HEADER(Concat) LIR_HEADER(Concat)
LConcat(const LAllocation &lhs, const LAllocation &rhs, const LDefinition &temp1, LConcat(const LAllocation &lhs, const LAllocation &rhs, const LDefinition &temp) {
const LDefinition &temp2, const LDefinition &temp3, const LDefinition &temp4) {
setOperand(0, lhs); setOperand(0, lhs);
setOperand(1, rhs); setOperand(1, rhs);
setTemp(0, temp1); setTemp(0, temp);
setTemp(1, temp2);
setTemp(2, temp3);
setTemp(3, temp4);
} }
const LAllocation *lhs() { const LAllocation *lhs() {
@ -2264,18 +2260,9 @@ class LConcat : public LInstructionHelper<1, 2, 4>
const LAllocation *rhs() { const LAllocation *rhs() {
return this->getOperand(1); return this->getOperand(1);
} }
const LDefinition *temp1() { const LDefinition *temp() {
return this->getTemp(0); return this->getTemp(0);
} }
const LDefinition *temp2() {
return this->getTemp(1);
}
const LDefinition *temp3() {
return this->getTemp(2);
}
const LDefinition *temp4() {
return this->getTemp(3);
}
}; };
// Get uint16 character code from a string. // Get uint16 character code from a string.

Просмотреть файл

@ -1307,13 +1307,8 @@ LIRGenerator::visitConcat(MConcat *ins)
JS_ASSERT(rhs->type() == MIRType_String); JS_ASSERT(rhs->type() == MIRType_String);
JS_ASSERT(ins->type() == MIRType_String); JS_ASSERT(ins->type() == MIRType_String);
LConcat *lir = new LConcat(useFixed(lhs, CallTempReg0), LConcat *lir = new LConcat(useRegister(lhs), useRegister(rhs), temp());
useFixed(rhs, CallTempReg1), if (!define(lir, ins))
tempFixed(CallTempReg2),
tempFixed(CallTempReg3),
tempFixed(CallTempReg4),
tempFixed(CallTempReg5));
if (!defineFixed(lir, ins, LAllocation(AnyRegister(CallTempReg6))))
return false; return false;
return assignSafepoint(lir, ins); return assignSafepoint(lir, ins);
} }

Просмотреть файл

@ -55,7 +55,7 @@ static const Register CallTempReg2 = r7;
static const Register CallTempReg3 = r8; static const Register CallTempReg3 = r8;
static const Register CallTempReg4 = r0; static const Register CallTempReg4 = r0;
static const Register CallTempReg5 = r1; static const Register CallTempReg5 = r1;
static const Register CallTempReg6 = r2;
static const Register IntArgReg0 = r0; static const Register IntArgReg0 = r0;
static const Register IntArgReg1 = r1; static const Register IntArgReg1 = r1;

Просмотреть файл

@ -853,9 +853,6 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM
void branchTestPtr(Condition cond, const Register &lhs, const Imm32 rhs, Label *label) { void branchTestPtr(Condition cond, const Register &lhs, const Imm32 rhs, Label *label) {
branchTest32(cond, lhs, rhs, label); branchTest32(cond, lhs, rhs, label);
} }
void branchTestPtr(Condition cond, const Address &lhs, Imm32 imm, Label *label) {
branchTest32(cond, lhs, imm, label);
}
void branchPtr(Condition cond, Register lhs, Register rhs, Label *label) { void branchPtr(Condition cond, Register lhs, Register rhs, Label *label) {
branch32(cond, lhs, rhs, label); branch32(cond, lhs, rhs, label);
} }

Просмотреть файл

@ -82,7 +82,6 @@ static const Register CallTempReg2 = rbx;
static const Register CallTempReg3 = rcx; static const Register CallTempReg3 = rcx;
static const Register CallTempReg4 = rsi; static const Register CallTempReg4 = rsi;
static const Register CallTempReg5 = rdx; static const Register CallTempReg5 = rdx;
static const Register CallTempReg6 = rbp;
// Different argument registers for WIN64 // Different argument registers for WIN64
#if defined(_WIN64) #if defined(_WIN64)
@ -627,19 +626,6 @@ class Assembler : public AssemblerX86Shared
void testq(const Register &lhs, const Register &rhs) { void testq(const Register &lhs, const Register &rhs) {
masm.testq_rr(rhs.code(), lhs.code()); masm.testq_rr(rhs.code(), lhs.code());
} }
void testq(const Operand &lhs, Imm32 rhs) {
switch (lhs.kind()) {
case Operand::REG:
masm.testq_i32r(rhs.value, lhs.reg());
break;
case Operand::REG_DISP:
masm.testq_i32m(rhs.value, lhs.disp(), lhs.base());
break;
default:
JS_NOT_REACHED("unexpected operand kind");
break;
}
}
void jmp(void *target, Relocation::Kind reloc = Relocation::HARDCODED) { void jmp(void *target, Relocation::Kind reloc = Relocation::HARDCODED) {
JmpSrc src = masm.jmp(); JmpSrc src = masm.jmp();

Просмотреть файл

@ -510,10 +510,6 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
testq(lhs, imm); testq(lhs, imm);
j(cond, label); j(cond, label);
} }
void branchTestPtr(Condition cond, const Address &lhs, Imm32 imm, Label *label) {
testq(Operand(lhs), imm);
j(cond, label);
}
void decBranchPtr(Condition cond, const Register &lhs, Imm32 imm, Label *label) { void decBranchPtr(Condition cond, const Register &lhs, Imm32 imm, Label *label) {
subPtr(imm, lhs); subPtr(imm, lhs);
j(cond, label); j(cond, label);

Просмотреть файл

@ -54,7 +54,6 @@ static const Register CallTempReg2 = ebx;
static const Register CallTempReg3 = ecx; static const Register CallTempReg3 = ecx;
static const Register CallTempReg4 = esi; static const Register CallTempReg4 = esi;
static const Register CallTempReg5 = edx; static const Register CallTempReg5 = edx;
static const Register CallTempReg6 = ebp;
// We have no arg regs, so our NonArgRegs are just our CallTempReg* // We have no arg regs, so our NonArgRegs are just our CallTempReg*
static const Register CallTempNonArgRegs[] = { edi, eax, ebx, ecx, esi, edx }; static const Register CallTempNonArgRegs[] = { edi, eax, ebx, ecx, esi, edx };

Просмотреть файл

@ -544,10 +544,6 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared
testl(lhs, imm); testl(lhs, imm);
j(cond, label); j(cond, label);
} }
void branchTestPtr(Condition cond, const Address &lhs, Imm32 imm, Label *label) {
testl(Operand(lhs), imm);
j(cond, label);
}
void decBranchPtr(Condition cond, const Register &lhs, Imm32 imm, Label *label) { void decBranchPtr(Condition cond, const Register &lhs, Imm32 imm, Label *label) {
subPtr(imm, lhs); subPtr(imm, lhs);
j(cond, label); j(cond, label);

Просмотреть файл

@ -1,13 +0,0 @@
function f() {
var res = 0;
for (var i=0; i<100; i++) {
var s = "test" + i;
res += s.length;
assertEq(s[0], "t");
assertEq(s[3], "t");
if (i > 90)
assertEq(s[4], "9");
}
return res;
}
assertEq(f(), 590);

Просмотреть файл

@ -319,24 +319,6 @@ js::ConcatStrings(JSContext *cx,
if (!JSString::validateLength(cxIfCanGC, wholeLength)) if (!JSString::validateLength(cxIfCanGC, wholeLength))
return NULL; return NULL;
if (JSShortString::lengthFits(wholeLength)) {
JSShortString *str = js_NewGCShortString<allowGC>(cx);
if (!str)
return NULL;
const jschar *leftChars = left->getChars(cx);
if (!leftChars)
return NULL;
const jschar *rightChars = right->getChars(cx);
if (!rightChars)
return NULL;
jschar *buf = str->init(wholeLength);
PodCopy(buf, leftChars, leftLen);
PodCopy(buf + leftLen, rightChars, rightLen);
buf[wholeLength] = 0;
return str;
}
return JSRope::new_<allowGC>(cx, left, right, wholeLength); return JSRope::new_<allowGC>(cx, left, right, wholeLength);
} }

Просмотреть файл

@ -677,10 +677,6 @@ class JSInlineString : public JSFlatString
static bool lengthFits(size_t length) { static bool lengthFits(size_t length) {
return length <= MAX_INLINE_LENGTH; return length <= MAX_INLINE_LENGTH;
} }
static size_t offsetOfInlineStorage() {
return offsetof(JSInlineString, d.inlineStorage);
}
}; };
JS_STATIC_ASSERT(sizeof(JSInlineString) == sizeof(JSString)); JS_STATIC_ASSERT(sizeof(JSInlineString) == sizeof(JSString));