зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset 6604b700492c (bug 863018) for suspicion of causing Windows mochitest b-c leaks.
CLOSED TREE
This commit is contained in:
Родитель
096bddd96f
Коммит
3b61162ed3
|
@ -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));
|
||||||
|
|
Загрузка…
Ссылка в новой задаче