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 |