Accelerate charCodeAt on ARM.
Review URL: http://codereview.chromium.org/402012 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3327 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
d55d3ce89a
commit
701c00f8b4
@ -3286,7 +3286,82 @@ void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) {
|
||||
void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) {
|
||||
VirtualFrame::SpilledScope spilled_scope;
|
||||
ASSERT(args->length() == 2);
|
||||
Comment(masm_, "[ GenerateFastCharCodeAt");
|
||||
|
||||
LoadAndSpill(args->at(0));
|
||||
LoadAndSpill(args->at(1));
|
||||
frame_->EmitPop(r0); // Index.
|
||||
frame_->EmitPop(r1); // String.
|
||||
|
||||
Label slow, end, not_a_flat_string, ascii_string, try_again_with_new_string;
|
||||
|
||||
__ tst(r1, Operand(kSmiTagMask));
|
||||
__ b(eq, &slow); // The 'string' was a Smi.
|
||||
|
||||
ASSERT(kSmiTag == 0);
|
||||
__ tst(r0, Operand(kSmiTagMask | 0x80000000u));
|
||||
__ b(ne, &slow); // The index was negative or not a Smi.
|
||||
|
||||
__ bind(&try_again_with_new_string);
|
||||
__ CompareObjectType(r1, r2, r2, FIRST_NONSTRING_TYPE);
|
||||
__ b(ge, &slow);
|
||||
|
||||
// Now r2 has the string type.
|
||||
__ ldr(r3, FieldMemOperand(r1, String::kLengthOffset));
|
||||
__ and_(r4, r2, Operand(kStringSizeMask));
|
||||
__ add(r4, r4, Operand(String::kLongLengthShift));
|
||||
__ mov(r3, Operand(r3, LSR, r4));
|
||||
// Now r3 has the length of the string. Compare with the index.
|
||||
__ cmp(r3, Operand(r0, LSR, kSmiTagSize));
|
||||
__ b(le, &slow);
|
||||
|
||||
// Here we know the index is in range. Check that string is sequential.
|
||||
ASSERT_EQ(0, kSeqStringTag);
|
||||
__ tst(r2, Operand(kStringRepresentationMask));
|
||||
__ b(ne, ¬_a_flat_string);
|
||||
|
||||
// Check whether it is an ASCII string.
|
||||
ASSERT_EQ(0, kTwoByteStringTag);
|
||||
__ tst(r2, Operand(kStringEncodingMask));
|
||||
__ b(ne, &ascii_string);
|
||||
|
||||
// 2-byte string. We can add without shifting since the Smi tag size is the
|
||||
// log2 of the number of bytes in a two-byte character.
|
||||
ASSERT_EQ(1, kSmiTagSize);
|
||||
ASSERT_EQ(1, kSmiShiftSize);
|
||||
__ add(r1, r1, Operand(r0));
|
||||
__ ldrh(r0, FieldMemOperand(r1, SeqTwoByteString::kHeaderSize));
|
||||
__ mov(r0, Operand(r0, LSL, kSmiTagSize));
|
||||
__ jmp(&end);
|
||||
|
||||
__ bind(&ascii_string);
|
||||
__ add(r1, r1, Operand(r0, LSR, kSmiTagSize));
|
||||
__ ldrb(r0, FieldMemOperand(r1, SeqAsciiString::kHeaderSize));
|
||||
__ mov(r0, Operand(r0, LSL, kSmiTagSize));
|
||||
__ jmp(&end);
|
||||
|
||||
__ bind(¬_a_flat_string);
|
||||
__ and_(r2, r2, Operand(kStringRepresentationMask));
|
||||
__ cmp(r2, Operand(kConsStringTag));
|
||||
__ b(ne, &slow);
|
||||
|
||||
// ConsString.
|
||||
// Check that the right hand side is the empty string (ie if this is really a
|
||||
// flat string in a cons string). If that is not the case we would rather go
|
||||
// to the runtime system now, to flatten the string.
|
||||
__ ldr(r2, FieldMemOperand(r1, ConsString::kSecondOffset));
|
||||
__ LoadRoot(r3, Heap::kEmptyStringRootIndex);
|
||||
__ cmp(r2, Operand(r3));
|
||||
__ b(ne, &slow);
|
||||
|
||||
// Get the first of the two strings.
|
||||
__ ldr(r1, FieldMemOperand(r1, ConsString::kFirstOffset));
|
||||
__ jmp(&try_again_with_new_string);
|
||||
|
||||
__ bind(&slow);
|
||||
__ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
|
||||
|
||||
__ bind(&end);
|
||||
frame_->EmitPush(r0);
|
||||
}
|
||||
|
||||
|
@ -3745,10 +3745,11 @@ void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) {
|
||||
__ movzxbl(temp.reg(), FieldOperand(temp.reg(), Map::kInstanceTypeOffset));
|
||||
|
||||
// We need special handling for non-flat strings.
|
||||
ASSERT(kSeqStringTag == 0);
|
||||
ASSERT_EQ(0, kSeqStringTag);
|
||||
__ testb(temp.reg(), Immediate(kStringRepresentationMask));
|
||||
__ j(not_zero, ¬_a_flat_string);
|
||||
// Check for 1-byte or 2-byte string.
|
||||
ASSERT_EQ(0, kTwoByteStringTag);
|
||||
__ testb(temp.reg(), Immediate(kStringEncodingMask));
|
||||
__ j(not_zero, &ascii_string);
|
||||
|
||||
|
@ -30,7 +30,7 @@
|
||||
*/
|
||||
|
||||
function Cons() {
|
||||
return "Te" + "st";
|
||||
return "Te" + "st testing 123";
|
||||
}
|
||||
|
||||
|
||||
@ -38,22 +38,22 @@ function Deep() {
|
||||
var a = "T";
|
||||
a += "e";
|
||||
a += "s";
|
||||
a += "t";
|
||||
a += "ting testing 123";
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
function Slice() {
|
||||
return "testing Testing".substring(8, 12);
|
||||
return "testing Testing testing 123456789012345".substring(8, 22);
|
||||
}
|
||||
|
||||
|
||||
function Flat() {
|
||||
return "Test";
|
||||
return "Testing testing 123";
|
||||
}
|
||||
|
||||
function Cons16() {
|
||||
return "Te" + "\u1234t";
|
||||
return "Te" + "\u1234t testing 123";
|
||||
}
|
||||
|
||||
|
||||
@ -61,18 +61,18 @@ function Deep16() {
|
||||
var a = "T";
|
||||
a += "e";
|
||||
a += "\u1234";
|
||||
a += "t";
|
||||
a += "ting testing 123";
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
function Slice16Beginning() {
|
||||
return "Te\u1234t test".substring(0, 4);
|
||||
return "Te\u1234t testing testing 123".substring(0, 14);
|
||||
}
|
||||
|
||||
|
||||
function Slice16Middle() {
|
||||
return "test Te\u1234t test".substring(5, 9);
|
||||
return "test Te\u1234t testing testing 123".substring(5, 19);
|
||||
}
|
||||
|
||||
|
||||
@ -82,7 +82,7 @@ function Slice16End() {
|
||||
|
||||
|
||||
function Flat16() {
|
||||
return "Te\u1234t";
|
||||
return "Te\u1234ting testing 123";
|
||||
}
|
||||
|
||||
|
||||
@ -108,32 +108,35 @@ function NotAString16() {
|
||||
|
||||
function TestStringType(generator, sixteen) {
|
||||
var g = generator;
|
||||
assertTrue(isNaN(g().charCodeAt(-1e19)));
|
||||
assertTrue(isNaN(g().charCodeAt(-0x80000001)));
|
||||
assertTrue(isNaN(g().charCodeAt(-0x80000000)));
|
||||
assertTrue(isNaN(g().charCodeAt(-0x40000000)));
|
||||
assertTrue(isNaN(g().charCodeAt(-1)));
|
||||
assertTrue(isNaN(g().charCodeAt(4)));
|
||||
assertTrue(isNaN(g().charCodeAt(5)));
|
||||
assertTrue(isNaN(g().charCodeAt(0x3fffffff)));
|
||||
assertTrue(isNaN(g().charCodeAt(0x7fffffff)));
|
||||
assertTrue(isNaN(g().charCodeAt(0x80000000)));
|
||||
assertTrue(isNaN(g().charCodeAt(1e9)));
|
||||
assertEquals(84, g().charCodeAt(0));
|
||||
assertEquals(84, g().charCodeAt("test"));
|
||||
assertEquals(84, g().charCodeAt(""));
|
||||
assertEquals(84, g().charCodeAt(null));
|
||||
assertEquals(84, g().charCodeAt(undefined));
|
||||
assertEquals(84, g().charCodeAt());
|
||||
assertEquals(84, g().charCodeAt(void 0));
|
||||
assertEquals(84, g().charCodeAt(false));
|
||||
assertEquals(101, g().charCodeAt(true));
|
||||
assertEquals(101, g().charCodeAt(1));
|
||||
assertEquals(sixteen ? 0x1234 : 115, g().charCodeAt(2));
|
||||
assertEquals(116, g().charCodeAt(3));
|
||||
assertEquals(101, g().charCodeAt(1.1));
|
||||
assertEquals(sixteen ? 0x1234 : 115, g().charCodeAt(2.1718));
|
||||
assertEquals(116, g().charCodeAt(3.14159));
|
||||
var len = g().toString().length;
|
||||
var t = sixteen ? "t" : "f"
|
||||
t += generator.name;
|
||||
assertTrue(isNaN(g().charCodeAt(-1e19)), 1 + t);
|
||||
assertTrue(isNaN(g().charCodeAt(-0x80000001)), 2 + t);
|
||||
assertTrue(isNaN(g().charCodeAt(-0x80000000)), 3 + t);
|
||||
assertTrue(isNaN(g().charCodeAt(-0x40000000)), 4 + t);
|
||||
assertTrue(isNaN(g().charCodeAt(-1)), 5 + t);
|
||||
assertTrue(isNaN(g().charCodeAt(len)), 6 + t);
|
||||
assertTrue(isNaN(g().charCodeAt(len + 1)), 7 + t);
|
||||
assertTrue(isNaN(g().charCodeAt(0x3fffffff)), 8 + t);
|
||||
assertTrue(isNaN(g().charCodeAt(0x7fffffff)), 9 + t);
|
||||
assertTrue(isNaN(g().charCodeAt(0x80000000)), 10 + t);
|
||||
assertTrue(isNaN(g().charCodeAt(1e9)), 11 + t);
|
||||
assertEquals(84, g().charCodeAt(0), 12 + t);
|
||||
assertEquals(84, g().charCodeAt("test"), 13 + t);
|
||||
assertEquals(84, g().charCodeAt(""), 14 + t);
|
||||
assertEquals(84, g().charCodeAt(null), 15 + t);
|
||||
assertEquals(84, g().charCodeAt(undefined), 16 + t);
|
||||
assertEquals(84, g().charCodeAt(), 17 + t);
|
||||
assertEquals(84, g().charCodeAt(void 0), 18 + t);
|
||||
assertEquals(84, g().charCodeAt(false), 19 + t);
|
||||
assertEquals(101, g().charCodeAt(true), 20 + t);
|
||||
assertEquals(101, g().charCodeAt(1), 21 + t);
|
||||
assertEquals(sixteen ? 0x1234 : 115, g().charCodeAt(2), 22 + t);
|
||||
assertEquals(116, g().charCodeAt(3), 23 + t);
|
||||
assertEquals(101, g().charCodeAt(1.1), 24 + t);
|
||||
assertEquals(sixteen ? 0x1234 : 115, g().charCodeAt(2.1718), 25 + t);
|
||||
assertEquals(116, g().charCodeAt(3.14159), 26 + t);
|
||||
}
|
||||
|
||||
|
||||
@ -157,10 +160,10 @@ function StupidThing() {
|
||||
this.charCodeAt = String.prototype.charCodeAt;
|
||||
}
|
||||
|
||||
assertEquals(52, new StupidThing().charCodeAt(0));
|
||||
assertEquals(50, new StupidThing().charCodeAt(1));
|
||||
assertTrue(isNaN(new StupidThing().charCodeAt(2)));
|
||||
assertTrue(isNaN(new StupidThing().charCodeAt(-1)));
|
||||
assertEquals(52, new StupidThing().charCodeAt(0), 27);
|
||||
assertEquals(50, new StupidThing().charCodeAt(1), 28);
|
||||
assertTrue(isNaN(new StupidThing().charCodeAt(2)), 29);
|
||||
assertTrue(isNaN(new StupidThing().charCodeAt(-1)), 30);
|
||||
|
||||
|
||||
// Medium (>255) and long (>65535) strings.
|
||||
@ -178,12 +181,12 @@ long += long + long + long; // 4096.
|
||||
long += long + long + long; // 16384.
|
||||
long += long + long + long; // 65536.
|
||||
|
||||
assertTrue(isNaN(medium.charCodeAt(-1)));
|
||||
assertEquals(49, medium.charCodeAt(0));
|
||||
assertEquals(56, medium.charCodeAt(255));
|
||||
assertTrue(isNaN(medium.charCodeAt(256)));
|
||||
assertTrue(isNaN(medium.charCodeAt(-1)), 31);
|
||||
assertEquals(49, medium.charCodeAt(0), 32);
|
||||
assertEquals(56, medium.charCodeAt(255), 33);
|
||||
assertTrue(isNaN(medium.charCodeAt(256)), 34);
|
||||
|
||||
assertTrue(isNaN(long.charCodeAt(-1)));
|
||||
assertEquals(49, long.charCodeAt(0));
|
||||
assertEquals(56, long.charCodeAt(65535));
|
||||
assertTrue(isNaN(long.charCodeAt(65536)));
|
||||
assertTrue(isNaN(long.charCodeAt(-1)), 35);
|
||||
assertEquals(49, long.charCodeAt(0), 36);
|
||||
assertEquals(56, long.charCodeAt(65535), 37);
|
||||
assertTrue(isNaN(long.charCodeAt(65536)), 38);
|
||||
|
Loading…
Reference in New Issue
Block a user