Chromium Code Reviews| OLD | NEW | 
|---|---|
| 1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 the V8 project authors. All rights reserved. | 
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without | 
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are | 
| 4 // met: | 4 // met: | 
| 5 // | 5 // | 
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright | 
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. | 
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above | 
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following | 
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided | 
| (...skipping 3924 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3935 } | 3935 } | 
| 3936 | 3936 | 
| 3937 | 3937 | 
| 3938 void CodeGenerator::GenerateSubString(ZoneList<Expression*>* args) { | 3938 void CodeGenerator::GenerateSubString(ZoneList<Expression*>* args) { | 
| 3939 ASSERT_EQ(3, args->length()); | 3939 ASSERT_EQ(3, args->length()); | 
| 3940 | 3940 | 
| 3941 Load(args->at(0)); | 3941 Load(args->at(0)); | 
| 3942 Load(args->at(1)); | 3942 Load(args->at(1)); | 
| 3943 Load(args->at(2)); | 3943 Load(args->at(2)); | 
| 3944 | 3944 | 
| 3945 Result answer = frame_->CallRuntime(Runtime::kSubString, 3); | 3945 SubStringStub stub; | 
| 3946 Result answer = frame_->CallStub(&stub, 3); | |
| 3946 frame_->Push(&answer); | 3947 frame_->Push(&answer); | 
| 3947 } | 3948 } | 
| 3948 | 3949 | 
| 3949 | 3950 | 
| 3950 void CodeGenerator::GenerateStringCompare(ZoneList<Expression*>* args) { | 3951 void CodeGenerator::GenerateStringCompare(ZoneList<Expression*>* args) { | 
| 3951 ASSERT_EQ(2, args->length()); | 3952 ASSERT_EQ(2, args->length()); | 
| 3952 | 3953 | 
| 3953 Load(args->at(0)); | 3954 Load(args->at(0)); | 
| 3954 Load(args->at(1)); | 3955 Load(args->at(1)); | 
| 3955 | 3956 | 
| (...skipping 4175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8131 __ movq(rax, rbx); | 8132 __ movq(rax, rbx); | 
| 8132 __ IncrementCounter(&Counters::string_add_native, 1); | 8133 __ IncrementCounter(&Counters::string_add_native, 1); | 
| 8133 __ ret(2 * kPointerSize); | 8134 __ ret(2 * kPointerSize); | 
| 8134 | 8135 | 
| 8135 // Just jump to runtime to add the two strings. | 8136 // Just jump to runtime to add the two strings. | 
| 8136 __ bind(&string_add_runtime); | 8137 __ bind(&string_add_runtime); | 
| 8137 __ TailCallRuntime(ExternalReference(Runtime::kStringAdd), 2, 1); | 8138 __ TailCallRuntime(ExternalReference(Runtime::kStringAdd), 2, 1); | 
| 8138 } | 8139 } | 
| 8139 | 8140 | 
| 8140 | 8141 | 
| 8141 void StringAddStub::GenerateCopyCharacters(MacroAssembler* masm, | 8142 void StringStubBase::GenerateCopyCharacters(MacroAssembler* masm, | 
| 8142 Register dest, | 8143 Register dest, | 
| 8143 Register src, | 8144 Register src, | 
| 8144 Register count, | 8145 Register count, | 
| 8145 bool ascii) { | 8146 bool ascii) { | 
| 8146 Label loop; | 8147 Label loop; | 
| 8147 __ bind(&loop); | 8148 __ bind(&loop); | 
| 8148 // This loop just copies one character at a time, as it is only used for very | 8149 // This loop just copies one character at a time, as it is only used for very | 
| 8149 // short strings. | 8150 // short strings. | 
| 8150 if (ascii) { | 8151 if (ascii) { | 
| 8151 __ movb(kScratchRegister, Operand(src, 0)); | 8152 __ movb(kScratchRegister, Operand(src, 0)); | 
| 8152 __ movb(Operand(dest, 0), kScratchRegister); | 8153 __ movb(Operand(dest, 0), kScratchRegister); | 
| 8153 __ addq(src, Immediate(1)); | 8154 __ addq(src, Immediate(1)); | 
| 8154 __ addq(dest, Immediate(1)); | 8155 __ addq(dest, Immediate(1)); | 
| 8155 } else { | 8156 } else { | 
| 8156 __ movzxwl(kScratchRegister, Operand(src, 0)); | 8157 __ movzxwl(kScratchRegister, Operand(src, 0)); | 
| 8157 __ movw(Operand(dest, 0), kScratchRegister); | 8158 __ movw(Operand(dest, 0), kScratchRegister); | 
| 8158 __ addq(src, Immediate(2)); | 8159 __ addq(src, Immediate(2)); | 
| 8159 __ addq(dest, Immediate(2)); | 8160 __ addq(dest, Immediate(2)); | 
| 8160 } | 8161 } | 
| 8161 __ subl(count, Immediate(1)); | 8162 __ subl(count, Immediate(1)); | 
| 8162 __ j(not_zero, &loop); | 8163 __ j(not_zero, &loop); | 
| 8163 } | 8164 } | 
| 8164 | 8165 | 
| 8165 | 8166 | 
| 8167 void StringStubBase::GenerateCopyCharactersREP(MacroAssembler* masm, | |
| 8168 Register dest, | |
| 8169 Register src, | |
| 8170 Register count, | |
| 8171 bool ascii) { | |
| 8172 // Copy characters using rep movs of doublewords. Align destination on 4 byte | |
| 8173 // boundary before starting rep movs. Copy remaining characters after running | |
| 8174 // rep movs. | |
| 8175 ASSERT(dest.is(rdi)); // rep movs destination | |
| 8176 ASSERT(src.is(rsi)); // rep movs source | |
| 8177 ASSERT(count.is(rcx)); // rep movs count | |
| 8178 | |
| 8179 // Nothing to do for zero characters. | |
| 8180 Label done; | |
| 8181 __ testq(count, count); | |
| 8182 __ j(zero, &done); | |
| 8183 | |
| 8184 // Make count the number of bytes to copy. | |
| 8185 if (!ascii) { | |
| 
 
Søren Thygesen Gjesse
2010/01/25 08:31:33
ASSERT(kShortSize == 2);
 
Lasse Reichstein
2010/01/25 08:47:20
It's not really the size of short ints that matter
 
 | |
| 8186 __ addq(count, count); | |
| 8187 } | |
| 8188 | |
| 8189 // Don't enter the rep movs if there are less than 4 bytes to copy. | |
| 8190 Label last_bytes; | |
| 8191 __ testq(count, Immediate(~3)); | |
| 8192 __ j(zero, &last_bytes); | |
| 8193 | |
| 8194 // Copy from edi to esi using rep movs instruction. | |
| 8195 __ movq(kScratchRegister, count); | |
| 8196 __ sar(count, Immediate(2)); // Number of doublewords to copy. | |
| 8197 __ repmovsl(); | |
| 
 
Søren Thygesen Gjesse
2010/01/25 08:31:33
It is not better to use repmovsq?
 
Lasse Reichstein
2010/01/25 08:47:20
Probably, since we expect long strings, the tine s
 
 | |
| 8198 | |
| 8199 // Find number of bytes left. | |
| 8200 __ movq(count, kScratchRegister); | |
| 8201 __ and_(count, Immediate(3)); | |
| 8202 | |
| 8203 // Check if there are more bytes to copy. | |
| 8204 __ bind(&last_bytes); | |
| 8205 __ testq(count, count); | |
| 8206 __ j(zero, &done); | |
| 8207 | |
| 8208 // Copy remaining characters. | |
| 8209 Label loop; | |
| 8210 __ bind(&loop); | |
| 8211 __ movb(kScratchRegister, Operand(src, 0)); | |
| 8212 __ movb(Operand(dest, 0), kScratchRegister); | |
| 8213 __ addq(src, Immediate(1)); | |
| 8214 __ addq(dest, Immediate(1)); | |
| 8215 __ subq(count, Immediate(1)); | |
| 8216 __ j(not_zero, &loop); | |
| 8217 | |
| 8218 __ bind(&done); | |
| 8219 } | |
| 8220 | |
| 8221 | |
| 8222 void SubStringStub::Generate(MacroAssembler* masm) { | |
| 8223 Label runtime; | |
| 8224 | |
| 8225 // Stack frame on entry. | |
| 8226 // rsp[0]: return address | |
| 8227 // rsp[8]: to | |
| 8228 // rsp[16]: from | |
| 8229 // rsp[24]: string | |
| 8230 | |
| 8231 const int kToOffset = 1 * kPointerSize; | |
| 8232 const int kFromOffset = 2 * kPointerSize; | |
| 8233 const int kStringOffset = 3 * kPointerSize; | |
| 
 
Søren Thygesen Gjesse
2010/01/25 08:31:33
Now that you have these constants, why not add
 
Lasse Reichstein
2010/01/25 08:47:20
Done.
 
 | |
| 8234 | |
| 8235 // Make sure first argument is a string. | |
| 8236 __ movq(rax, Operand(rsp, kStringOffset)); | |
| 8237 ASSERT_EQ(0, kSmiTag); | |
| 8238 __ testl(rax, Immediate(kSmiTagMask)); | |
| 8239 __ j(zero, &runtime); | |
| 8240 Condition is_string = masm->IsObjectStringType(rax, rbx, rbx); | |
| 8241 __ j(NegateCondition(is_string), &runtime); | |
| 8242 | |
| 8243 // rax: string | |
| 8244 // rbx: instance type | |
| 8245 // Calculate length of sub string using the smi values. | |
| 8246 __ movq(rcx, Operand(rsp, kToOffset)); | |
| 8247 __ movq(rdx, Operand(rsp, kFromOffset)); | |
| 8248 __ JumpIfNotBothPositiveSmi(rcx, rdx, &runtime); | |
| 8249 | |
| 8250 __ SmiSub(rcx, rcx, rdx, NULL); // Overflow doesn't happen. | |
| 8251 __ j(negative, &runtime); | |
| 8252 // Handle sub-strings of length 2 and less in the runtime system. | |
| 8253 __ SmiToInteger32(rcx, rcx); | |
| 8254 __ cmpl(rcx, Immediate(2)); | |
| 8255 __ j(below_equal, &runtime); | |
| 8256 | |
| 8257 // rax: string | |
| 8258 // rbx: instance type | |
| 8259 // rcx: result string length | |
| 8260 // Check for flat ascii string | |
| 8261 Label non_ascii_flat; | |
| 8262 __ and_(rbx, Immediate(kStringRepresentationMask | kStringEncodingMask)); | |
| 8263 __ cmpb(rbx, Immediate(kSeqStringTag | kAsciiStringTag)); | |
| 8264 __ j(not_equal, &non_ascii_flat); | |
| 8265 | |
| 8266 // Allocate the result. | |
| 8267 __ AllocateAsciiString(rax, rcx, rbx, rdx, rdi, &runtime); | |
| 8268 | |
| 8269 // rax: result string | |
| 8270 // rcx: result string length | |
| 8271 __ movq(rdx, rsi); // esi used by following code. | |
| 8272 // Locate first character of result. | |
| 8273 __ lea(rdi, FieldOperand(rax, SeqAsciiString::kHeaderSize)); | |
| 8274 // Load string argument and locate character of sub string start. | |
| 8275 __ movq(rsi, Operand(rsp, kStringOffset)); | |
| 8276 __ movq(rbx, Operand(rsp, kFromOffset)); | |
| 8277 { | |
| 8278 SmiIndex smi_as_index = masm->SmiToIndex(rbx, rbx, times_1); | |
| 8279 __ lea(rsi, Operand(rsi, smi_as_index.reg, smi_as_index.scale, | |
| 
 
Søren Thygesen Gjesse
2010/01/25 08:31:33
Perhaps use FieldOperand, and remove " - kHeapObje
 
 | |
| 8280 SeqAsciiString::kHeaderSize - kHeapObjectTag)); | |
| 8281 } | |
| 8282 | |
| 8283 // rax: result string | |
| 8284 // rcx: result length | |
| 8285 // rdx: original value of rsi | |
| 8286 // rdi: first character of result | |
| 8287 // rsi: character of sub string start | |
| 8288 GenerateCopyCharactersREP(masm, rdi, rsi, rcx, true); | |
| 8289 __ movq(rsi, rdx); // Restore rsi. | |
| 8290 __ IncrementCounter(&Counters::sub_string_native, 1); | |
| 8291 __ ret(3 * kPointerSize); | |
| 8292 | |
| 8293 __ bind(&non_ascii_flat); | |
| 8294 // rax: string | |
| 8295 // rbx: instance type & kStringRepresentationMask | kStringEncodingMask | |
| 8296 // rcx: result string length | |
| 8297 // Check for sequential two byte string | |
| 8298 __ cmpb(rbx, Immediate(kSeqStringTag | kTwoByteStringTag)); | |
| 8299 __ j(not_equal, &runtime); | |
| 8300 | |
| 8301 // Allocate the result. | |
| 8302 __ AllocateTwoByteString(rax, rcx, rbx, rdx, rdi, &runtime); | |
| 8303 | |
| 8304 // rax: result string | |
| 8305 // rcx: result string length | |
| 8306 __ movq(rdx, rsi); // esi used by following code. | |
| 8307 // Locate first character of result. | |
| 8308 __ lea(rdi, FieldOperand(rax, SeqTwoByteString::kHeaderSize)); | |
| 8309 // Load string argument and locate character of sub string start. | |
| 8310 __ movq(rsi, Operand(rsp, kStringOffset)); | |
| 8311 __ movq(rbx, Operand(rsp, kFromOffset)); | |
| 8312 { | |
| 8313 SmiIndex smi_as_index = masm->SmiToIndex(rbx, rbx, times_2); | |
| 8314 __ lea(rsi, Operand(rsi, smi_as_index.reg, smi_as_index.scale, | |
| 
 
Søren Thygesen Gjesse
2010/01/25 08:31:33
Operand -> FieldOperand?
 
 | |
| 8315 SeqAsciiString::kHeaderSize - kHeapObjectTag)); | |
| 8316 } | |
| 8317 | |
| 8318 // rax: result string | |
| 8319 // rcx: result length | |
| 8320 // rdx: original value of rsi | |
| 8321 // rdi: first character of result | |
| 8322 // rsi: character of sub string start | |
| 8323 GenerateCopyCharactersREP(masm, rdi, rsi, rcx, false); | |
| 8324 __ movq(rsi, rdx); // Restore esi. | |
| 8325 __ IncrementCounter(&Counters::sub_string_native, 1); | |
| 8326 __ ret(3 * kPointerSize); | |
| 8327 | |
| 8328 // Just jump to runtime to create the sub string. | |
| 8329 __ bind(&runtime); | |
| 8330 __ TailCallRuntime(ExternalReference(Runtime::kSubString), 3, 1); | |
| 8331 } | |
| 8332 | |
| 8166 | 8333 | 
| 8167 void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm, | 8334 void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm, | 
| 8168 Register left, | 8335 Register left, | 
| 8169 Register right, | 8336 Register right, | 
| 8170 Register scratch1, | 8337 Register scratch1, | 
| 8171 Register scratch2, | 8338 Register scratch2, | 
| 8172 Register scratch3, | 8339 Register scratch3, | 
| 8173 Register scratch4) { | 8340 Register scratch4) { | 
| 8174 // Ensure that you can always subtract a string length from a non-negative | 8341 // Ensure that you can always subtract a string length from a non-negative | 
| 8175 // number (e.g. another length). | 8342 // number (e.g. another length). | 
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8373 // Call the function from C++. | 8540 // Call the function from C++. | 
| 8374 return FUNCTION_CAST<ModuloFunction>(buffer); | 8541 return FUNCTION_CAST<ModuloFunction>(buffer); | 
| 8375 } | 8542 } | 
| 8376 | 8543 | 
| 8377 #endif | 8544 #endif | 
| 8378 | 8545 | 
| 8379 | 8546 | 
| 8380 #undef __ | 8547 #undef __ | 
| 8381 | 8548 | 
| 8382 } } // namespace v8::internal | 8549 } } // namespace v8::internal | 
| OLD | NEW |