Bug 1016379 - Implement charAt, charCodeAt, str[index] for Latin1 strings. r=luke

This commit is contained in:
Jan de Mooij 2014-05-31 10:44:32 +02:00
parent 2929deb6c1
commit d1f1ef3fa6
6 changed files with 84 additions and 11 deletions

View File

@ -0,0 +1,47 @@
function testCharCodeAt() {
var s = toLatin1("abcdefghijklm1234567891000");
for (var i=0; i<10; i++)
assertEq(s.charCodeAt(i), 97 + i);
var rope = s + toLatin1("blah");
assertEq(rope.charCodeAt(s.length + 3), 104);
rope = s + "Foo987";
assertEq(rope.charCodeAt(s.length + 4), 56);
rope = "twoByte\u0580" + s;
assertEq(rope.charCodeAt(7), 0x580);
assertEq(rope.charCodeAt(14), 103);
}
testCharCodeAt();
function testCharAt() {
var s = toLatin1("abcdefghijklm100000002345");
assertEq(s.charAt(0), "a");
assertEq(s.charAt(s.length-1), "5");
assertEq(s.charAt(s.length), "");
var rope = s + toLatin1("abcZYX");
assertEq(rope.charAt(s.length + 3), "Z");
rope = s + "Foo987";
assertEq(rope.charAt(s.length + 4), "8");
rope = "twoByte\u0580" + s;
assertEq(rope.charAt(7), "\u0580");
assertEq(rope.charAt(14), "g");
}
testCharAt();
function testIndex(s) {
assertEq(s[0], "a");
assertEq(s[s.length-1], "6");
rope = "twoByte\u0512" + s
assertEq(rope[7], "\u0512");
}
var s = toLatin1("abcdefghijklm123456");
testIndex(s);
testIndex(s);
testIndex(s);

View File

@ -4425,8 +4425,7 @@ ICGetElem_String::Compiler::generateStubCode(MacroAssembler &masm)
key, &failure);
// Get char code.
masm.loadStringChars(str, scratchReg);
masm.load16ZeroExtend(BaseIndex(scratchReg, key, TimesTwo, 0), scratchReg);
masm.loadStringChar(str, key, scratchReg);
// Check if char code >= UNIT_STATIC_LIMIT.
masm.branch32(Assembler::AboveOrEqual, scratchReg, Imm32(StaticStrings::UNIT_STATIC_LIMIT),

View File

@ -5487,9 +5487,7 @@ CodeGenerator::visitCharCodeAt(LCharCodeAt *lir)
return false;
masm.branchIfRope(str, ool->entry());
masm.loadStringChars(str, output);
masm.load16ZeroExtend(BaseIndex(output, index, TimesTwo, 0), output);
masm.loadStringChar(str, index, output);
masm.bind(ool->rejoin());
return true;

View File

@ -881,6 +881,26 @@ MacroAssembler::loadStringChars(Register str, Register dest)
bind(&done);
}
void
MacroAssembler::loadStringChar(Register str, Register index, Register output)
{
MOZ_ASSERT(str != output);
MOZ_ASSERT(index != output);
loadStringChars(str, output);
Label isLatin1, done;
branchTest32(Assembler::NonZero, Address(str, JSString::offsetOfFlags()),
Imm32(JSString::LATIN1_CHARS_BIT), &isLatin1);
load16ZeroExtend(BaseIndex(output, index, TimesTwo), output);
jump(&done);
bind(&isLatin1);
load8ZeroExtend(BaseIndex(output, index, TimesOne), output);
bind(&done);
}
void
MacroAssembler::checkInterruptFlagPar(Register tempReg, Label *fail)
{

View File

@ -381,6 +381,7 @@ class MacroAssembler : public MacroAssemblerSpecific
}
void loadStringChars(Register str, Register dest);
void loadStringChar(Register str, Register index, Register output);
void branchIfRope(Register str, Label *label) {
Address flags(str, JSString::offsetOfFlags());

View File

@ -19,6 +19,7 @@
#include "gc/Marking.h"
#include "gc/Rooting.h"
#include "js/CharacterEncoding.h"
#include "js/GCAPI.h"
#include "js/RootingAPI.h"
class JSDependentString;
@ -637,6 +638,13 @@ class JSLinearString : public JSString
return JS::TwoByteChars(chars(), length());
}
jschar latin1OrTwoByteChar(size_t index) const {
MOZ_ASSERT(JSString::isLinear());
MOZ_ASSERT(index < length());
JS::AutoCheckCannotGC nogc;
return hasLatin1Chars() ? latin1Chars(nogc)[index] : twoByteChars(nogc)[index];
}
/* Temporary, unsafe helper function for bug 998392. Don't use for anything else. */
void debugUnsafeConvertToLatin1();
};
@ -1157,23 +1165,23 @@ JSString::getChar(js::ExclusiveContext *cx, size_t index, jschar *code)
* test.charCodeAt(x + 1)
* }
*/
const jschar *chars;
JSString *str;
if (isRope()) {
JSRope *rope = &asRope();
if (uint32_t(index) < rope->leftChild()->length()) {
chars = rope->leftChild()->getChars(cx);
str = rope->leftChild();
} else {
chars = rope->rightChild()->getChars(cx);
str = rope->rightChild();
index -= rope->leftChild()->length();
}
} else {
chars = getChars(cx);
str = this;
}
if (!chars)
if (!str->ensureLinear(cx))
return false;
*code = chars[index];
*code = str->asLinear().latin1OrTwoByteChar(index);
return true;
}