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 3919 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3930 frame_->Push(&answer); | 3930 frame_->Push(&answer); |
3931 } | 3931 } |
3932 | 3932 |
3933 | 3933 |
3934 void CodeGenerator::GenerateStringCompare(ZoneList<Expression*>* args) { | 3934 void CodeGenerator::GenerateStringCompare(ZoneList<Expression*>* args) { |
3935 ASSERT_EQ(2, args->length()); | 3935 ASSERT_EQ(2, args->length()); |
3936 | 3936 |
3937 Load(args->at(0)); | 3937 Load(args->at(0)); |
3938 Load(args->at(1)); | 3938 Load(args->at(1)); |
3939 | 3939 |
3940 Result answer = frame_->CallRuntime(Runtime::kStringCompare, 2); | 3940 StringCompareStub stub; |
3941 Result answer = frame_->CallStub(&stub, 2); | |
3941 frame_->Push(&answer); | 3942 frame_->Push(&answer); |
3942 } | 3943 } |
3943 | 3944 |
3944 | 3945 |
3945 void CodeGenerator::GenerateClassOf(ZoneList<Expression*>* args) { | 3946 void CodeGenerator::GenerateClassOf(ZoneList<Expression*>* args) { |
3946 ASSERT(args->length() == 1); | 3947 ASSERT(args->length() == 1); |
3947 JumpTarget leave, null, function, non_function_constructor; | 3948 JumpTarget leave, null, function, non_function_constructor; |
3948 Load(args->at(0)); // Load the object. | 3949 Load(args->at(0)); // Load the object. |
3949 Result obj = frame_->Pop(); | 3950 Result obj = frame_->Pop(); |
3950 obj.ToRegister(); | 3951 obj.ToRegister(); |
(...skipping 2538 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6489 __ bind(&below_lbl); | 6490 __ bind(&below_lbl); |
6490 __ movq(rax, Immediate(-1)); | 6491 __ movq(rax, Immediate(-1)); |
6491 __ ret(2 * kPointerSize); | 6492 __ ret(2 * kPointerSize); |
6492 | 6493 |
6493 __ bind(&above_lbl); | 6494 __ bind(&above_lbl); |
6494 __ movq(rax, Immediate(1)); | 6495 __ movq(rax, Immediate(1)); |
6495 __ ret(2 * kPointerSize); // rax, rdx were pushed | 6496 __ ret(2 * kPointerSize); // rax, rdx were pushed |
6496 | 6497 |
6497 // Fast negative check for symbol-to-symbol equality. | 6498 // Fast negative check for symbol-to-symbol equality. |
6498 __ bind(&check_for_symbols); | 6499 __ bind(&check_for_symbols); |
6500 Label check_for_strings; | |
6499 if (cc_ == equal) { | 6501 if (cc_ == equal) { |
6500 BranchIfNonSymbol(masm, &call_builtin, rax, kScratchRegister); | 6502 BranchIfNonSymbol(masm, &check_for_strings, rax, kScratchRegister); |
6501 BranchIfNonSymbol(masm, &call_builtin, rdx, kScratchRegister); | 6503 BranchIfNonSymbol(masm, &check_for_strings, rdx, kScratchRegister); |
6502 | 6504 |
6503 // We've already checked for object identity, so if both operands | 6505 // We've already checked for object identity, so if both operands |
6504 // are symbols they aren't equal. Register eax (not rax) already holds a | 6506 // are symbols they aren't equal. Register eax (not rax) already holds a |
6505 // non-zero value, which indicates not equal, so just return. | 6507 // non-zero value, which indicates not equal, so just return. |
6506 __ ret(2 * kPointerSize); | 6508 __ ret(2 * kPointerSize); |
6507 } | 6509 } |
6508 | 6510 |
6511 __ bind(&check_for_strings); | |
6512 Condition either_smi = masm->CheckEitherSmi(rax, rdx); | |
6513 __ j(either_smi, &call_builtin); | |
6514 | |
6515 // Load instance type for both objects to check if they are flat | |
6516 // ASCII strings. | |
6517 __ movq(rcx, FieldOperand(rdx, HeapObject::kMapOffset)); | |
6518 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); | |
6519 __ movzxbl(rcx, FieldOperand(rcx, Map::kInstanceTypeOffset)); | |
6520 __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); | |
6521 | |
6522 Label non_ascii_flat; | |
6523 ASSERT(kNotStringTag != 0); | |
6524 const int kFlatAsciiStringMask = | |
6525 kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask; | |
6526 const int kFlatAsciiStringBits = | |
6527 kNotStringTag | kSeqStringTag | kAsciiStringTag; | |
6528 | |
6529 __ andl(rcx, Immediate(kFlatAsciiStringMask)); | |
6530 __ andl(rbx, Immediate(kFlatAsciiStringMask)); | |
6531 // Interleave the bits to check both rcx and rbx in one test. | |
6532 ASSERT_EQ(0, kFlatAsciiStringMask & (kFlatAsciiStringMask << 3)); | |
6533 __ lea(rcx, Operand(rcx, rbx, times_8, 0)); | |
6534 __ cmpl(rcx, Immediate(kFlatAsciiStringBits + (kFlatAsciiStringBits << 3))); | |
6535 __ j(not_equal, &call_builtin); | |
6536 | |
6537 // Inline comparison of ascii strings. | |
6538 StringCompareStub::GenerateCompareFlatAsciiStrings(masm, | |
6539 rdx, | |
6540 rax, | |
6541 rcx, | |
6542 rbx, | |
6543 rdi, | |
6544 r8); | |
6545 | |
6546 #ifdef DEBUG | |
6547 __ Abort("Unexpected fall-through from string comparison"); | |
6548 #endif | |
6549 | |
6509 __ bind(&call_builtin); | 6550 __ bind(&call_builtin); |
6510 // must swap argument order | 6551 // must swap argument order |
6511 __ pop(rcx); | 6552 __ pop(rcx); |
6512 __ pop(rdx); | 6553 __ pop(rdx); |
6513 __ pop(rax); | 6554 __ pop(rax); |
6514 __ push(rdx); | 6555 __ push(rdx); |
6515 __ push(rax); | 6556 __ push(rax); |
6516 | 6557 |
6517 // Figure out which native to call and setup the arguments. | 6558 // Figure out which native to call and setup the arguments. |
6518 Builtins::JavaScript builtin; | 6559 Builtins::JavaScript builtin; |
(...skipping 1601 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
8120 __ movzxwl(kScratchRegister, Operand(src, 0)); | 8161 __ movzxwl(kScratchRegister, Operand(src, 0)); |
8121 __ movw(Operand(dest, 0), kScratchRegister); | 8162 __ movw(Operand(dest, 0), kScratchRegister); |
8122 __ addq(src, Immediate(2)); | 8163 __ addq(src, Immediate(2)); |
8123 __ addq(dest, Immediate(2)); | 8164 __ addq(dest, Immediate(2)); |
8124 } | 8165 } |
8125 __ subl(count, Immediate(1)); | 8166 __ subl(count, Immediate(1)); |
8126 __ j(not_zero, &loop); | 8167 __ j(not_zero, &loop); |
8127 } | 8168 } |
8128 | 8169 |
8129 | 8170 |
8171 | |
8172 void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm, | |
8173 Register left, | |
8174 Register right, | |
8175 Register scratch1, | |
8176 Register scratch2, | |
8177 Register scratch3, | |
8178 Register scratch4) { | |
8179 // Ensure that you can always subtract a string length from a non-negative | |
8180 // number (e.g. another length). | |
8181 ASSERT(String::kMaxLength < 0x7fffffff); | |
8182 | |
8183 // Find minimum length and length difference. | |
8184 __ movl(scratch1, FieldOperand(left, String::kLengthOffset)); | |
8185 __ movl(scratch4, scratch1); | |
8186 __ subl(scratch4, FieldOperand(right, String::kLengthOffset)); | |
8187 // Register scratch4 now holds left.length - right.length. | |
8188 const Register length_difference = scratch4; | |
8189 Label left_shorter; | |
8190 __ j(less, &left_shorter); | |
8191 // The right string isn't longer that the left one. | |
8192 // Get the right string's length by subtracting the (non-negative) difference | |
8193 // from the left string's length. | |
8194 __ subl(scratch1, length_difference); | |
8195 __ bind(&left_shorter); | |
8196 // Register scratch1 now holds Min(left.length, right.length). | |
8197 const Register min_length = scratch1; | |
8198 | |
8199 Label compare_lengths; | |
8200 // If min-length is zero, go directly to comparing lengths. | |
8201 __ testl(min_length, min_length); | |
8202 __ j(zero, &compare_lengths); | |
8203 | |
8204 // Registers scratch2 and scratch3 are free. | |
8205 Label result_not_equal; | |
8206 Label loop; | |
8207 { | |
8208 // Check characters 0 .. min_length - 1 in a loop. | |
8209 // Use scratch3 as loop index, min_length as limit and scratch2 | |
8210 // for computation. | |
8211 const Register index = scratch3; | |
8212 __ movl(index, Immediate(0)); // Index into strings. | |
8213 __ bind(&loop); | |
8214 // Compare characters. | |
8215 // TODO(lrn): Could we load more than one character at a time? | |
8216 __ movb(scratch2, FieldOperand(left, | |
8217 index, | |
8218 times_1, | |
8219 SeqAsciiString::kHeaderSize)); | |
8220 // Increment index and use -1 modifier on next load to give | |
8221 // the previous load extra time to complete. | |
8222 __ addl(index, Immediate(1)); | |
8223 __ cmpb(scratch2, FieldOperand(right, | |
8224 index, | |
8225 times_1, | |
8226 SeqAsciiString::kHeaderSize - 1)); | |
8227 __ j(not_equal, &result_not_equal); | |
8228 __ cmpl(index, min_length); | |
8229 __ j(not_equal, &loop); | |
8230 } | |
8231 // Completed loop without finding different characters. | |
8232 // Compare lengths (precomputed). | |
8233 __ bind(&compare_lengths); | |
8234 __ testl(length_difference, length_difference); | |
8235 __ j(not_zero, &result_not_equal); | |
8236 | |
8237 // Result is EQUAL. | |
8238 __ Move(rax, Smi::FromInt(EQUAL)); | |
8239 __ IncrementCounter(&Counters::string_compare_native, 1); | |
8240 __ ret(2 * kPointerSize); | |
8241 | |
8242 Label result_greater; | |
8243 __ bind(&result_not_equal); | |
8244 // Unequal comparison of left to right, either character or length. | |
8245 __ j(greater, &result_greater); | |
8246 | |
8247 // Result is LESS. | |
8248 __ Move(rax, Smi::FromInt(LESS)); | |
8249 __ IncrementCounter(&Counters::string_compare_native, 1); | |
8250 __ ret(2 * kPointerSize); | |
8251 | |
8252 // Result is GREATER. | |
8253 __ bind(&result_greater); | |
8254 __ Move(rax, Smi::FromInt(GREATER)); | |
8255 __ IncrementCounter(&Counters::string_compare_native, 1); | |
8256 __ ret(2 * kPointerSize); | |
8257 } | |
8258 | |
8259 | |
8260 void StringCompareStub::Generate(MacroAssembler* masm) { | |
8261 Label runtime; | |
8262 | |
8263 // Stack frame on entry. | |
8264 // rsp[0]: return address | |
8265 // rsp[8]: right string | |
8266 // rsp[16]: left string | |
8267 | |
8268 __ movq(rdx, Operand(rsp, 2 * kPointerSize)); // left | |
8269 __ movq(rax, Operand(rsp, 1 * kPointerSize)); // right | |
8270 | |
8271 Label not_same; | |
8272 __ cmpq(rdx, rax); | |
8273 __ j(not_equal, ¬_same); | |
8274 __ Move(rax, Smi::FromInt(0)); | |
Søren Thygesen Gjesse
2010/01/18 09:58:01
0 -> EQUAL.
Lasse Reichstein
2010/01/18 10:33:02
Fixed
| |
8275 __ IncrementCounter(&Counters::string_compare_native, 1); | |
8276 __ ret(2 * kPointerSize); | |
8277 | |
8278 __ bind(¬_same); | |
8279 | |
8280 // Check that both objects are not smis. | |
8281 Condition either_smi = masm->CheckEitherSmi(rax, rdx); | |
8282 __ j(either_smi, &runtime); | |
8283 | |
8284 // Load instance type for both strings. | |
8285 __ movq(rcx, FieldOperand(rdx, HeapObject::kMapOffset)); | |
8286 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); | |
8287 __ movzxbl(rcx, FieldOperand(rcx, Map::kInstanceTypeOffset)); | |
8288 __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); | |
8289 | |
8290 // Check that both are flat ascii strings. | |
8291 Label non_ascii_flat; | |
8292 ASSERT(kNotStringTag != 0); | |
8293 const int kFlatAsciiStringMask = | |
8294 kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask; | |
8295 const int kFlatAsciiStringBits = | |
8296 kNotStringTag | kSeqStringTag | kAsciiStringTag; | |
8297 | |
8298 __ andl(rcx, Immediate(kFlatAsciiStringMask)); | |
8299 __ andl(rbx, Immediate(kFlatAsciiStringMask)); | |
8300 // Interleave the bits to check both rcx and rbx in one test. | |
8301 ASSERT_EQ(0, kFlatAsciiStringMask & (kFlatAsciiStringMask << 3)); | |
8302 __ lea(rcx, Operand(rcx, rbx, times_8, 0)); | |
8303 __ cmpl(rcx, Immediate(kFlatAsciiStringBits + (kFlatAsciiStringBits << 3))); | |
8304 __ j(not_equal, &non_ascii_flat); | |
8305 | |
8306 // Inline comparison of ascii strings. | |
8307 GenerateCompareFlatAsciiStrings(masm, rdx, rax, rcx, rbx, rdi, r8); | |
8308 | |
8309 __ bind(&non_ascii_flat); | |
8310 | |
8311 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) | |
8312 // tagged as a small integer. | |
8313 __ bind(&runtime); | |
8314 __ TailCallRuntime(ExternalReference(Runtime::kStringCompare), 2, 1); | |
8315 } | |
8316 | |
8130 #undef __ | 8317 #undef __ |
8131 | 8318 |
8132 #define __ masm. | 8319 #define __ masm. |
8133 | 8320 |
8134 #ifdef _WIN64 | 8321 #ifdef _WIN64 |
8135 typedef double (*ModuloFunction)(double, double); | 8322 typedef double (*ModuloFunction)(double, double); |
8136 // Define custom fmod implementation. | 8323 // Define custom fmod implementation. |
8137 ModuloFunction CreateModuloFunction() { | 8324 ModuloFunction CreateModuloFunction() { |
8138 size_t actual_size; | 8325 size_t actual_size; |
8139 byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize, | 8326 byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize, |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
8213 __ ret(0); | 8400 __ ret(0); |
8214 | 8401 |
8215 CodeDesc desc; | 8402 CodeDesc desc; |
8216 masm.GetCode(&desc); | 8403 masm.GetCode(&desc); |
8217 // Call the function from C++. | 8404 // Call the function from C++. |
8218 return FUNCTION_CAST<ModuloFunction>(buffer); | 8405 return FUNCTION_CAST<ModuloFunction>(buffer); |
8219 } | 8406 } |
8220 | 8407 |
8221 #endif | 8408 #endif |
8222 | 8409 |
8410 | |
8223 #undef __ | 8411 #undef __ |
8224 | 8412 |
8225 } } // namespace v8::internal | 8413 } } // namespace v8::internal |
OLD | NEW |