| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 2364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2375 | 2375 |
| 2376 void ArrayLengthStub::Generate(MacroAssembler* masm) { | 2376 void ArrayLengthStub::Generate(MacroAssembler* masm) { |
| 2377 Label miss; | 2377 Label miss; |
| 2378 Register receiver; | 2378 Register receiver; |
| 2379 if (kind() == Code::KEYED_LOAD_IC) { | 2379 if (kind() == Code::KEYED_LOAD_IC) { |
| 2380 // ----------- S t a t e ------------- | 2380 // ----------- S t a t e ------------- |
| 2381 // -- rax : key | 2381 // -- rax : key |
| 2382 // -- rdx : receiver | 2382 // -- rdx : receiver |
| 2383 // -- rsp[0] : return address | 2383 // -- rsp[0] : return address |
| 2384 // ----------------------------------- | 2384 // ----------------------------------- |
| 2385 __ Cmp(rax, masm->isolate()->factory()->length_symbol()); | 2385 __ Cmp(rax, masm->isolate()->factory()->length_string()); |
| 2386 receiver = rdx; | 2386 receiver = rdx; |
| 2387 } else { | 2387 } else { |
| 2388 ASSERT(kind() == Code::LOAD_IC); | 2388 ASSERT(kind() == Code::LOAD_IC); |
| 2389 // ----------- S t a t e ------------- | 2389 // ----------- S t a t e ------------- |
| 2390 // -- rax : receiver | 2390 // -- rax : receiver |
| 2391 // -- rcx : name | 2391 // -- rcx : name |
| 2392 // -- rsp[0] : return address | 2392 // -- rsp[0] : return address |
| 2393 // ----------------------------------- | 2393 // ----------------------------------- |
| 2394 receiver = rax; | 2394 receiver = rax; |
| 2395 } | 2395 } |
| 2396 | 2396 |
| 2397 StubCompiler::GenerateLoadArrayLength(masm, receiver, r8, &miss); | 2397 StubCompiler::GenerateLoadArrayLength(masm, receiver, r8, &miss); |
| 2398 __ bind(&miss); | 2398 __ bind(&miss); |
| 2399 StubCompiler::GenerateLoadMiss(masm, kind()); | 2399 StubCompiler::GenerateLoadMiss(masm, kind()); |
| 2400 } | 2400 } |
| 2401 | 2401 |
| 2402 | 2402 |
| 2403 void FunctionPrototypeStub::Generate(MacroAssembler* masm) { | 2403 void FunctionPrototypeStub::Generate(MacroAssembler* masm) { |
| 2404 Label miss; | 2404 Label miss; |
| 2405 Register receiver; | 2405 Register receiver; |
| 2406 if (kind() == Code::KEYED_LOAD_IC) { | 2406 if (kind() == Code::KEYED_LOAD_IC) { |
| 2407 // ----------- S t a t e ------------- | 2407 // ----------- S t a t e ------------- |
| 2408 // -- rax : key | 2408 // -- rax : key |
| 2409 // -- rdx : receiver | 2409 // -- rdx : receiver |
| 2410 // -- rsp[0] : return address | 2410 // -- rsp[0] : return address |
| 2411 // ----------------------------------- | 2411 // ----------------------------------- |
| 2412 __ Cmp(rax, masm->isolate()->factory()->prototype_symbol()); | 2412 __ Cmp(rax, masm->isolate()->factory()->prototype_string()); |
| 2413 receiver = rdx; | 2413 receiver = rdx; |
| 2414 } else { | 2414 } else { |
| 2415 ASSERT(kind() == Code::LOAD_IC); | 2415 ASSERT(kind() == Code::LOAD_IC); |
| 2416 // ----------- S t a t e ------------- | 2416 // ----------- S t a t e ------------- |
| 2417 // -- rax : receiver | 2417 // -- rax : receiver |
| 2418 // -- rcx : name | 2418 // -- rcx : name |
| 2419 // -- rsp[0] : return address | 2419 // -- rsp[0] : return address |
| 2420 // ----------------------------------- | 2420 // ----------------------------------- |
| 2421 receiver = rax; | 2421 receiver = rax; |
| 2422 } | 2422 } |
| 2423 | 2423 |
| 2424 StubCompiler::GenerateLoadFunctionPrototype(masm, receiver, r8, r9, &miss); | 2424 StubCompiler::GenerateLoadFunctionPrototype(masm, receiver, r8, r9, &miss); |
| 2425 __ bind(&miss); | 2425 __ bind(&miss); |
| 2426 StubCompiler::GenerateLoadMiss(masm, kind()); | 2426 StubCompiler::GenerateLoadMiss(masm, kind()); |
| 2427 } | 2427 } |
| 2428 | 2428 |
| 2429 | 2429 |
| 2430 void StringLengthStub::Generate(MacroAssembler* masm) { | 2430 void StringLengthStub::Generate(MacroAssembler* masm) { |
| 2431 Label miss; | 2431 Label miss; |
| 2432 Register receiver; | 2432 Register receiver; |
| 2433 if (kind() == Code::KEYED_LOAD_IC) { | 2433 if (kind() == Code::KEYED_LOAD_IC) { |
| 2434 // ----------- S t a t e ------------- | 2434 // ----------- S t a t e ------------- |
| 2435 // -- rax : key | 2435 // -- rax : key |
| 2436 // -- rdx : receiver | 2436 // -- rdx : receiver |
| 2437 // -- rsp[0] : return address | 2437 // -- rsp[0] : return address |
| 2438 // ----------------------------------- | 2438 // ----------------------------------- |
| 2439 __ Cmp(rax, masm->isolate()->factory()->length_symbol()); | 2439 __ Cmp(rax, masm->isolate()->factory()->length_string()); |
| 2440 receiver = rdx; | 2440 receiver = rdx; |
| 2441 } else { | 2441 } else { |
| 2442 ASSERT(kind() == Code::LOAD_IC); | 2442 ASSERT(kind() == Code::LOAD_IC); |
| 2443 // ----------- S t a t e ------------- | 2443 // ----------- S t a t e ------------- |
| 2444 // -- rax : receiver | 2444 // -- rax : receiver |
| 2445 // -- rcx : name | 2445 // -- rcx : name |
| 2446 // -- rsp[0] : return address | 2446 // -- rsp[0] : return address |
| 2447 // ----------------------------------- | 2447 // ----------------------------------- |
| 2448 receiver = rax; | 2448 receiver = rax; |
| 2449 } | 2449 } |
| (...skipping 17 matching lines...) Expand all Loading... |
| 2467 // (currently anything except for external arrays which means anything with | 2467 // (currently anything except for external arrays which means anything with |
| 2468 // elements of FixedArray type). Value must be a number, but only smis are | 2468 // elements of FixedArray type). Value must be a number, but only smis are |
| 2469 // accepted as the most common case. | 2469 // accepted as the most common case. |
| 2470 | 2470 |
| 2471 Label miss; | 2471 Label miss; |
| 2472 | 2472 |
| 2473 Register receiver = rdx; | 2473 Register receiver = rdx; |
| 2474 Register value = rax; | 2474 Register value = rax; |
| 2475 Register scratch = rbx; | 2475 Register scratch = rbx; |
| 2476 if (kind() == Code::KEYED_STORE_IC) { | 2476 if (kind() == Code::KEYED_STORE_IC) { |
| 2477 __ Cmp(rcx, masm->isolate()->factory()->length_symbol()); | 2477 __ Cmp(rcx, masm->isolate()->factory()->length_string()); |
| 2478 } | 2478 } |
| 2479 | 2479 |
| 2480 // Check that the receiver isn't a smi. | 2480 // Check that the receiver isn't a smi. |
| 2481 __ JumpIfSmi(receiver, &miss); | 2481 __ JumpIfSmi(receiver, &miss); |
| 2482 | 2482 |
| 2483 // Check that the object is a JS array. | 2483 // Check that the object is a JS array. |
| 2484 __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch); | 2484 __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch); |
| 2485 __ j(not_equal, &miss); | 2485 __ j(not_equal, &miss); |
| 2486 | 2486 |
| 2487 // Check that elements are FixedArray. | 2487 // Check that elements are FixedArray. |
| (...skipping 582 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3070 // String is sliced. | 3070 // String is sliced. |
| 3071 __ SmiToInteger32(r14, FieldOperand(rdi, SlicedString::kOffsetOffset)); | 3071 __ SmiToInteger32(r14, FieldOperand(rdi, SlicedString::kOffsetOffset)); |
| 3072 __ movq(rdi, FieldOperand(rdi, SlicedString::kParentOffset)); | 3072 __ movq(rdi, FieldOperand(rdi, SlicedString::kParentOffset)); |
| 3073 // r14: slice offset | 3073 // r14: slice offset |
| 3074 // r15: original subject string | 3074 // r15: original subject string |
| 3075 // rdi: parent string | 3075 // rdi: parent string |
| 3076 __ jmp(&check_encoding, Label::kNear); | 3076 __ jmp(&check_encoding, Label::kNear); |
| 3077 // String is a cons string, check whether it is flat. | 3077 // String is a cons string, check whether it is flat. |
| 3078 __ bind(&cons_string); | 3078 __ bind(&cons_string); |
| 3079 __ CompareRoot(FieldOperand(rdi, ConsString::kSecondOffset), | 3079 __ CompareRoot(FieldOperand(rdi, ConsString::kSecondOffset), |
| 3080 Heap::kEmptyStringRootIndex); | 3080 Heap::kempty_stringRootIndex); |
| 3081 __ j(not_equal, &runtime); | 3081 __ j(not_equal, &runtime); |
| 3082 __ movq(rdi, FieldOperand(rdi, ConsString::kFirstOffset)); | 3082 __ movq(rdi, FieldOperand(rdi, ConsString::kFirstOffset)); |
| 3083 // rdi: first part of cons string or parent of sliced string. | 3083 // rdi: first part of cons string or parent of sliced string. |
| 3084 // rbx: map of first part of cons string or map of parent of sliced string. | 3084 // rbx: map of first part of cons string or map of parent of sliced string. |
| 3085 // Is first part of cons or parent of slice a flat two byte string? | 3085 // Is first part of cons or parent of slice a flat two byte string? |
| 3086 __ bind(&check_encoding); | 3086 __ bind(&check_encoding); |
| 3087 __ movq(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); | 3087 __ movq(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); |
| 3088 __ testb(FieldOperand(rbx, Map::kInstanceTypeOffset), | 3088 __ testb(FieldOperand(rbx, Map::kInstanceTypeOffset), |
| 3089 Immediate(kStringRepresentationMask | kStringEncodingMask)); | 3089 Immediate(kStringRepresentationMask | kStringEncodingMask)); |
| 3090 STATIC_ASSERT((kSeqStringTag | kTwoByteStringTag) == 0); | 3090 STATIC_ASSERT((kSeqStringTag | kTwoByteStringTag) == 0); |
| (...skipping 478 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3569 CompareIC::State expected, | 3569 CompareIC::State expected, |
| 3570 Label* fail) { | 3570 Label* fail) { |
| 3571 Label ok; | 3571 Label ok; |
| 3572 if (expected == CompareIC::SMI) { | 3572 if (expected == CompareIC::SMI) { |
| 3573 __ JumpIfNotSmi(input, fail); | 3573 __ JumpIfNotSmi(input, fail); |
| 3574 } else if (expected == CompareIC::HEAP_NUMBER) { | 3574 } else if (expected == CompareIC::HEAP_NUMBER) { |
| 3575 __ JumpIfSmi(input, &ok); | 3575 __ JumpIfSmi(input, &ok); |
| 3576 __ CompareMap(input, masm->isolate()->factory()->heap_number_map(), NULL); | 3576 __ CompareMap(input, masm->isolate()->factory()->heap_number_map(), NULL); |
| 3577 __ j(not_equal, fail); | 3577 __ j(not_equal, fail); |
| 3578 } | 3578 } |
| 3579 // We could be strict about symbol/string here, but as long as | 3579 // We could be strict about internalized/non-internalized here, but as long as |
| 3580 // hydrogen doesn't care, the stub doesn't have to care either. | 3580 // hydrogen doesn't care, the stub doesn't have to care either. |
| 3581 __ bind(&ok); | 3581 __ bind(&ok); |
| 3582 } | 3582 } |
| 3583 | 3583 |
| 3584 | 3584 |
| 3585 static void BranchIfNonSymbol(MacroAssembler* masm, | 3585 static void BranchIfNotInternalizedString(MacroAssembler* masm, |
| 3586 Label* label, | 3586 Label* label, |
| 3587 Register object, | 3587 Register object, |
| 3588 Register scratch) { | 3588 Register scratch) { |
| 3589 __ JumpIfSmi(object, label); | 3589 __ JumpIfSmi(object, label); |
| 3590 __ movq(scratch, FieldOperand(object, HeapObject::kMapOffset)); | 3590 __ movq(scratch, FieldOperand(object, HeapObject::kMapOffset)); |
| 3591 __ movzxbq(scratch, | 3591 __ movzxbq(scratch, |
| 3592 FieldOperand(scratch, Map::kInstanceTypeOffset)); | 3592 FieldOperand(scratch, Map::kInstanceTypeOffset)); |
| 3593 // Ensure that no non-strings have the symbol bit set. | 3593 // Ensure that no non-strings have the internalized bit set. |
| 3594 STATIC_ASSERT(LAST_TYPE < kNotStringTag + kIsSymbolMask); | 3594 STATIC_ASSERT(LAST_TYPE < kNotStringTag + kIsInternalizedMask); |
| 3595 STATIC_ASSERT(kSymbolTag != 0); | 3595 STATIC_ASSERT(kInternalizedTag != 0); |
| 3596 __ testb(scratch, Immediate(kIsSymbolMask)); | 3596 __ testb(scratch, Immediate(kIsInternalizedMask)); |
| 3597 __ j(zero, label); | 3597 __ j(zero, label); |
| 3598 } | 3598 } |
| 3599 | 3599 |
| 3600 | 3600 |
| 3601 void ICCompareStub::GenerateGeneric(MacroAssembler* masm) { | 3601 void ICCompareStub::GenerateGeneric(MacroAssembler* masm) { |
| 3602 Label check_unequal_objects, done; | 3602 Label check_unequal_objects, done; |
| 3603 Condition cc = GetCondition(); | 3603 Condition cc = GetCondition(); |
| 3604 Factory* factory = masm->isolate()->factory(); | 3604 Factory* factory = masm->isolate()->factory(); |
| 3605 | 3605 |
| 3606 Label miss; | 3606 Label miss; |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3754 if (cc == less || cc == less_equal) { | 3754 if (cc == less || cc == less_equal) { |
| 3755 __ Set(rax, 1); | 3755 __ Set(rax, 1); |
| 3756 } else { | 3756 } else { |
| 3757 __ Set(rax, -1); | 3757 __ Set(rax, -1); |
| 3758 } | 3758 } |
| 3759 __ ret(0); | 3759 __ ret(0); |
| 3760 | 3760 |
| 3761 // The number comparison code did not provide a valid result. | 3761 // The number comparison code did not provide a valid result. |
| 3762 __ bind(&non_number_comparison); | 3762 __ bind(&non_number_comparison); |
| 3763 | 3763 |
| 3764 // Fast negative check for symbol-to-symbol equality. | 3764 // Fast negative check for internalized-to-internalized equality. |
| 3765 Label check_for_strings; | 3765 Label check_for_strings; |
| 3766 if (cc == equal) { | 3766 if (cc == equal) { |
| 3767 BranchIfNonSymbol(masm, &check_for_strings, rax, kScratchRegister); | 3767 BranchIfNotInternalizedString( |
| 3768 BranchIfNonSymbol(masm, &check_for_strings, rdx, kScratchRegister); | 3768 masm, &check_for_strings, rax, kScratchRegister); |
| 3769 BranchIfNotInternalizedString( |
| 3770 masm, &check_for_strings, rdx, kScratchRegister); |
| 3769 | 3771 |
| 3770 // We've already checked for object identity, so if both operands | 3772 // We've already checked for object identity, so if both operands are |
| 3771 // are symbols they aren't equal. Register eax (not rax) already holds a | 3773 // internalized strings they aren't equal. Register eax (not rax) already |
| 3772 // non-zero value, which indicates not equal, so just return. | 3774 // holds a non-zero value, which indicates not equal, so just return. |
| 3773 __ ret(0); | 3775 __ ret(0); |
| 3774 } | 3776 } |
| 3775 | 3777 |
| 3776 __ bind(&check_for_strings); | 3778 __ bind(&check_for_strings); |
| 3777 | 3779 |
| 3778 __ JumpIfNotBothSequentialAsciiStrings( | 3780 __ JumpIfNotBothSequentialAsciiStrings( |
| 3779 rdx, rax, rcx, rbx, &check_unequal_objects); | 3781 rdx, rax, rcx, rbx, &check_unequal_objects); |
| 3780 | 3782 |
| 3781 // Inline comparison of ASCII strings. | 3783 // Inline comparison of ASCII strings. |
| 3782 if (cc == equal) { | 3784 if (cc == equal) { |
| (...skipping 1063 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4846 __ movq(r8, FieldOperand(rax, HeapObject::kMapOffset)); | 4848 __ movq(r8, FieldOperand(rax, HeapObject::kMapOffset)); |
| 4847 __ movq(r9, FieldOperand(rdx, HeapObject::kMapOffset)); | 4849 __ movq(r9, FieldOperand(rdx, HeapObject::kMapOffset)); |
| 4848 } | 4850 } |
| 4849 // Get the instance types of the two strings as they will be needed soon. | 4851 // Get the instance types of the two strings as they will be needed soon. |
| 4850 __ movzxbl(r8, FieldOperand(r8, Map::kInstanceTypeOffset)); | 4852 __ movzxbl(r8, FieldOperand(r8, Map::kInstanceTypeOffset)); |
| 4851 __ movzxbl(r9, FieldOperand(r9, Map::kInstanceTypeOffset)); | 4853 __ movzxbl(r9, FieldOperand(r9, Map::kInstanceTypeOffset)); |
| 4852 | 4854 |
| 4853 // Look at the length of the result of adding the two strings. | 4855 // Look at the length of the result of adding the two strings. |
| 4854 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue / 2); | 4856 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue / 2); |
| 4855 __ SmiAdd(rbx, rbx, rcx); | 4857 __ SmiAdd(rbx, rbx, rcx); |
| 4856 // Use the symbol table when adding two one character strings, as it | 4858 // Use the string table when adding two one character strings, as it |
| 4857 // helps later optimizations to return a symbol here. | 4859 // helps later optimizations to return an internalized string here. |
| 4858 __ SmiCompare(rbx, Smi::FromInt(2)); | 4860 __ SmiCompare(rbx, Smi::FromInt(2)); |
| 4859 __ j(not_equal, &longer_than_two); | 4861 __ j(not_equal, &longer_than_two); |
| 4860 | 4862 |
| 4861 // Check that both strings are non-external ASCII strings. | 4863 // Check that both strings are non-external ASCII strings. |
| 4862 __ JumpIfBothInstanceTypesAreNotSequentialAscii(r8, r9, rbx, rcx, | 4864 __ JumpIfBothInstanceTypesAreNotSequentialAscii(r8, r9, rbx, rcx, |
| 4863 &call_runtime); | 4865 &call_runtime); |
| 4864 | 4866 |
| 4865 // Get the two characters forming the sub string. | 4867 // Get the two characters forming the sub string. |
| 4866 __ movzxbq(rbx, FieldOperand(rax, SeqOneByteString::kHeaderSize)); | 4868 __ movzxbq(rbx, FieldOperand(rax, SeqOneByteString::kHeaderSize)); |
| 4867 __ movzxbq(rcx, FieldOperand(rdx, SeqOneByteString::kHeaderSize)); | 4869 __ movzxbq(rcx, FieldOperand(rdx, SeqOneByteString::kHeaderSize)); |
| 4868 | 4870 |
| 4869 // Try to lookup two character string in symbol table. If it is not found | 4871 // Try to lookup two character string in string table. If it is not found |
| 4870 // just allocate a new one. | 4872 // just allocate a new one. |
| 4871 Label make_two_character_string, make_flat_ascii_string; | 4873 Label make_two_character_string, make_flat_ascii_string; |
| 4872 StringHelper::GenerateTwoCharacterSymbolTableProbe( | 4874 StringHelper::GenerateTwoCharacterStringTableProbe( |
| 4873 masm, rbx, rcx, r14, r11, rdi, r15, &make_two_character_string); | 4875 masm, rbx, rcx, r14, r11, rdi, r15, &make_two_character_string); |
| 4874 __ IncrementCounter(counters->string_add_native(), 1); | 4876 __ IncrementCounter(counters->string_add_native(), 1); |
| 4875 __ ret(2 * kPointerSize); | 4877 __ ret(2 * kPointerSize); |
| 4876 | 4878 |
| 4877 __ bind(&make_two_character_string); | 4879 __ bind(&make_two_character_string); |
| 4878 __ Set(rdi, 2); | 4880 __ Set(rdi, 2); |
| 4879 __ AllocateAsciiString(rax, rdi, r8, r9, r11, &call_runtime); | 4881 __ AllocateAsciiString(rax, rdi, r8, r9, r11, &call_runtime); |
| 4880 // rbx - first byte: first character | 4882 // rbx - first byte: first character |
| 4881 // rbx - second byte: *maybe* second character | 4883 // rbx - second byte: *maybe* second character |
| 4882 // Make sure that the second byte of rbx contains the second character. | 4884 // Make sure that the second byte of rbx contains the second character. |
| (...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5161 __ movb(kScratchRegister, Operand(src, 0)); | 5163 __ movb(kScratchRegister, Operand(src, 0)); |
| 5162 __ movb(Operand(dest, 0), kScratchRegister); | 5164 __ movb(Operand(dest, 0), kScratchRegister); |
| 5163 __ incq(src); | 5165 __ incq(src); |
| 5164 __ incq(dest); | 5166 __ incq(dest); |
| 5165 __ decl(count); | 5167 __ decl(count); |
| 5166 __ j(not_zero, &loop); | 5168 __ j(not_zero, &loop); |
| 5167 | 5169 |
| 5168 __ bind(&done); | 5170 __ bind(&done); |
| 5169 } | 5171 } |
| 5170 | 5172 |
| 5171 void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm, | 5173 void StringHelper::GenerateTwoCharacterStringTableProbe(MacroAssembler* masm, |
| 5172 Register c1, | 5174 Register c1, |
| 5173 Register c2, | 5175 Register c2, |
| 5174 Register scratch1, | 5176 Register scratch1, |
| 5175 Register scratch2, | 5177 Register scratch2, |
| 5176 Register scratch3, | 5178 Register scratch3, |
| 5177 Register scratch4, | 5179 Register scratch4, |
| 5178 Label* not_found) { | 5180 Label* not_found) { |
| 5179 // Register scratch3 is the general scratch register in this function. | 5181 // Register scratch3 is the general scratch register in this function. |
| 5180 Register scratch = scratch3; | 5182 Register scratch = scratch3; |
| 5181 | 5183 |
| 5182 // Make sure that both characters are not digits as such strings has a | 5184 // Make sure that both characters are not digits as such strings has a |
| 5183 // different hash algorithm. Don't try to look for these in the symbol table. | 5185 // different hash algorithm. Don't try to look for these in the string table. |
| 5184 Label not_array_index; | 5186 Label not_array_index; |
| 5185 __ leal(scratch, Operand(c1, -'0')); | 5187 __ leal(scratch, Operand(c1, -'0')); |
| 5186 __ cmpl(scratch, Immediate(static_cast<int>('9' - '0'))); | 5188 __ cmpl(scratch, Immediate(static_cast<int>('9' - '0'))); |
| 5187 __ j(above, ¬_array_index, Label::kNear); | 5189 __ j(above, ¬_array_index, Label::kNear); |
| 5188 __ leal(scratch, Operand(c2, -'0')); | 5190 __ leal(scratch, Operand(c2, -'0')); |
| 5189 __ cmpl(scratch, Immediate(static_cast<int>('9' - '0'))); | 5191 __ cmpl(scratch, Immediate(static_cast<int>('9' - '0'))); |
| 5190 __ j(below_equal, not_found); | 5192 __ j(below_equal, not_found); |
| 5191 | 5193 |
| 5192 __ bind(¬_array_index); | 5194 __ bind(¬_array_index); |
| 5193 // Calculate the two character string hash. | 5195 // Calculate the two character string hash. |
| 5194 Register hash = scratch1; | 5196 Register hash = scratch1; |
| 5195 GenerateHashInit(masm, hash, c1, scratch); | 5197 GenerateHashInit(masm, hash, c1, scratch); |
| 5196 GenerateHashAddCharacter(masm, hash, c2, scratch); | 5198 GenerateHashAddCharacter(masm, hash, c2, scratch); |
| 5197 GenerateHashGetHash(masm, hash, scratch); | 5199 GenerateHashGetHash(masm, hash, scratch); |
| 5198 | 5200 |
| 5199 // Collect the two characters in a register. | 5201 // Collect the two characters in a register. |
| 5200 Register chars = c1; | 5202 Register chars = c1; |
| 5201 __ shl(c2, Immediate(kBitsPerByte)); | 5203 __ shl(c2, Immediate(kBitsPerByte)); |
| 5202 __ orl(chars, c2); | 5204 __ orl(chars, c2); |
| 5203 | 5205 |
| 5204 // chars: two character string, char 1 in byte 0 and char 2 in byte 1. | 5206 // chars: two character string, char 1 in byte 0 and char 2 in byte 1. |
| 5205 // hash: hash of two character string. | 5207 // hash: hash of two character string. |
| 5206 | 5208 |
| 5207 // Load the symbol table. | 5209 // Load the string table. |
| 5208 Register symbol_table = c2; | 5210 Register string_table = c2; |
| 5209 __ LoadRoot(symbol_table, Heap::kSymbolTableRootIndex); | 5211 __ LoadRoot(string_table, Heap::kStringTableRootIndex); |
| 5210 | 5212 |
| 5211 // Calculate capacity mask from the symbol table capacity. | 5213 // Calculate capacity mask from the string table capacity. |
| 5212 Register mask = scratch2; | 5214 Register mask = scratch2; |
| 5213 __ SmiToInteger32(mask, | 5215 __ SmiToInteger32(mask, |
| 5214 FieldOperand(symbol_table, SymbolTable::kCapacityOffset)); | 5216 FieldOperand(string_table, StringTable::kCapacityOffset)); |
| 5215 __ decl(mask); | 5217 __ decl(mask); |
| 5216 | 5218 |
| 5217 Register map = scratch4; | 5219 Register map = scratch4; |
| 5218 | 5220 |
| 5219 // Registers | 5221 // Registers |
| 5220 // chars: two character string, char 1 in byte 0 and char 2 in byte 1. | 5222 // chars: two character string, char 1 in byte 0 and char 2 in byte 1. |
| 5221 // hash: hash of two character string (32-bit int) | 5223 // hash: hash of two character string (32-bit int) |
| 5222 // symbol_table: symbol table | 5224 // string_table: string table |
| 5223 // mask: capacity mask (32-bit int) | 5225 // mask: capacity mask (32-bit int) |
| 5224 // map: - | 5226 // map: - |
| 5225 // scratch: - | 5227 // scratch: - |
| 5226 | 5228 |
| 5227 // Perform a number of probes in the symbol table. | 5229 // Perform a number of probes in the string table. |
| 5228 static const int kProbes = 4; | 5230 static const int kProbes = 4; |
| 5229 Label found_in_symbol_table; | 5231 Label found_in_string_table; |
| 5230 Label next_probe[kProbes]; | 5232 Label next_probe[kProbes]; |
| 5231 Register candidate = scratch; // Scratch register contains candidate. | 5233 Register candidate = scratch; // Scratch register contains candidate. |
| 5232 for (int i = 0; i < kProbes; i++) { | 5234 for (int i = 0; i < kProbes; i++) { |
| 5233 // Calculate entry in symbol table. | 5235 // Calculate entry in string table. |
| 5234 __ movl(scratch, hash); | 5236 __ movl(scratch, hash); |
| 5235 if (i > 0) { | 5237 if (i > 0) { |
| 5236 __ addl(scratch, Immediate(SymbolTable::GetProbeOffset(i))); | 5238 __ addl(scratch, Immediate(StringTable::GetProbeOffset(i))); |
| 5237 } | 5239 } |
| 5238 __ andl(scratch, mask); | 5240 __ andl(scratch, mask); |
| 5239 | 5241 |
| 5240 // Load the entry from the symbol table. | 5242 // Load the entry from the string table. |
| 5241 STATIC_ASSERT(SymbolTable::kEntrySize == 1); | 5243 STATIC_ASSERT(StringTable::kEntrySize == 1); |
| 5242 __ movq(candidate, | 5244 __ movq(candidate, |
| 5243 FieldOperand(symbol_table, | 5245 FieldOperand(string_table, |
| 5244 scratch, | 5246 scratch, |
| 5245 times_pointer_size, | 5247 times_pointer_size, |
| 5246 SymbolTable::kElementsStartOffset)); | 5248 StringTable::kElementsStartOffset)); |
| 5247 | 5249 |
| 5248 // If entry is undefined no string with this hash can be found. | 5250 // If entry is undefined no string with this hash can be found. |
| 5249 Label is_string; | 5251 Label is_string; |
| 5250 __ CmpObjectType(candidate, ODDBALL_TYPE, map); | 5252 __ CmpObjectType(candidate, ODDBALL_TYPE, map); |
| 5251 __ j(not_equal, &is_string, Label::kNear); | 5253 __ j(not_equal, &is_string, Label::kNear); |
| 5252 | 5254 |
| 5253 __ CompareRoot(candidate, Heap::kUndefinedValueRootIndex); | 5255 __ CompareRoot(candidate, Heap::kUndefinedValueRootIndex); |
| 5254 __ j(equal, not_found); | 5256 __ j(equal, not_found); |
| 5255 // Must be the hole (deleted entry). | 5257 // Must be the hole (deleted entry). |
| 5256 if (FLAG_debug_code) { | 5258 if (FLAG_debug_code) { |
| 5257 __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); | 5259 __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); |
| 5258 __ cmpq(kScratchRegister, candidate); | 5260 __ cmpq(kScratchRegister, candidate); |
| 5259 __ Assert(equal, "oddball in symbol table is not undefined or the hole"); | 5261 __ Assert(equal, "oddball in string table is not undefined or the hole"); |
| 5260 } | 5262 } |
| 5261 __ jmp(&next_probe[i]); | 5263 __ jmp(&next_probe[i]); |
| 5262 | 5264 |
| 5263 __ bind(&is_string); | 5265 __ bind(&is_string); |
| 5264 | 5266 |
| 5265 // If length is not 2 the string is not a candidate. | 5267 // If length is not 2 the string is not a candidate. |
| 5266 __ SmiCompare(FieldOperand(candidate, String::kLengthOffset), | 5268 __ SmiCompare(FieldOperand(candidate, String::kLengthOffset), |
| 5267 Smi::FromInt(2)); | 5269 Smi::FromInt(2)); |
| 5268 __ j(not_equal, &next_probe[i]); | 5270 __ j(not_equal, &next_probe[i]); |
| 5269 | 5271 |
| 5270 // We use kScratchRegister as a temporary register in assumption that | 5272 // We use kScratchRegister as a temporary register in assumption that |
| 5271 // JumpIfInstanceTypeIsNotSequentialAscii does not use it implicitly | 5273 // JumpIfInstanceTypeIsNotSequentialAscii does not use it implicitly |
| 5272 Register temp = kScratchRegister; | 5274 Register temp = kScratchRegister; |
| 5273 | 5275 |
| 5274 // Check that the candidate is a non-external ASCII string. | 5276 // Check that the candidate is a non-external ASCII string. |
| 5275 __ movzxbl(temp, FieldOperand(map, Map::kInstanceTypeOffset)); | 5277 __ movzxbl(temp, FieldOperand(map, Map::kInstanceTypeOffset)); |
| 5276 __ JumpIfInstanceTypeIsNotSequentialAscii( | 5278 __ JumpIfInstanceTypeIsNotSequentialAscii( |
| 5277 temp, temp, &next_probe[i]); | 5279 temp, temp, &next_probe[i]); |
| 5278 | 5280 |
| 5279 // Check if the two characters match. | 5281 // Check if the two characters match. |
| 5280 __ movl(temp, FieldOperand(candidate, SeqOneByteString::kHeaderSize)); | 5282 __ movl(temp, FieldOperand(candidate, SeqOneByteString::kHeaderSize)); |
| 5281 __ andl(temp, Immediate(0x0000ffff)); | 5283 __ andl(temp, Immediate(0x0000ffff)); |
| 5282 __ cmpl(chars, temp); | 5284 __ cmpl(chars, temp); |
| 5283 __ j(equal, &found_in_symbol_table); | 5285 __ j(equal, &found_in_string_table); |
| 5284 __ bind(&next_probe[i]); | 5286 __ bind(&next_probe[i]); |
| 5285 } | 5287 } |
| 5286 | 5288 |
| 5287 // No matching 2 character string found by probing. | 5289 // No matching 2 character string found by probing. |
| 5288 __ jmp(not_found); | 5290 __ jmp(not_found); |
| 5289 | 5291 |
| 5290 // Scratch register contains result when we fall through to here. | 5292 // Scratch register contains result when we fall through to here. |
| 5291 Register result = candidate; | 5293 Register result = candidate; |
| 5292 __ bind(&found_in_symbol_table); | 5294 __ bind(&found_in_string_table); |
| 5293 if (!result.is(rax)) { | 5295 if (!result.is(rax)) { |
| 5294 __ movq(rax, result); | 5296 __ movq(rax, result); |
| 5295 } | 5297 } |
| 5296 } | 5298 } |
| 5297 | 5299 |
| 5298 | 5300 |
| 5299 void StringHelper::GenerateHashInit(MacroAssembler* masm, | 5301 void StringHelper::GenerateHashInit(MacroAssembler* masm, |
| 5300 Register hash, | 5302 Register hash, |
| 5301 Register character, | 5303 Register character, |
| 5302 Register scratch) { | 5304 Register scratch) { |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5408 STATIC_ASSERT(kIsIndirectStringMask == (kSlicedStringTag & kConsStringTag)); | 5410 STATIC_ASSERT(kIsIndirectStringMask == (kSlicedStringTag & kConsStringTag)); |
| 5409 STATIC_ASSERT(kIsIndirectStringMask != 0); | 5411 STATIC_ASSERT(kIsIndirectStringMask != 0); |
| 5410 __ testb(rbx, Immediate(kIsIndirectStringMask)); | 5412 __ testb(rbx, Immediate(kIsIndirectStringMask)); |
| 5411 __ j(zero, &seq_or_external_string, Label::kNear); | 5413 __ j(zero, &seq_or_external_string, Label::kNear); |
| 5412 | 5414 |
| 5413 __ testb(rbx, Immediate(kSlicedNotConsMask)); | 5415 __ testb(rbx, Immediate(kSlicedNotConsMask)); |
| 5414 __ j(not_zero, &sliced_string, Label::kNear); | 5416 __ j(not_zero, &sliced_string, Label::kNear); |
| 5415 // Cons string. Check whether it is flat, then fetch first part. | 5417 // Cons string. Check whether it is flat, then fetch first part. |
| 5416 // Flat cons strings have an empty second part. | 5418 // Flat cons strings have an empty second part. |
| 5417 __ CompareRoot(FieldOperand(rax, ConsString::kSecondOffset), | 5419 __ CompareRoot(FieldOperand(rax, ConsString::kSecondOffset), |
| 5418 Heap::kEmptyStringRootIndex); | 5420 Heap::kempty_stringRootIndex); |
| 5419 __ j(not_equal, &runtime); | 5421 __ j(not_equal, &runtime); |
| 5420 __ movq(rdi, FieldOperand(rax, ConsString::kFirstOffset)); | 5422 __ movq(rdi, FieldOperand(rax, ConsString::kFirstOffset)); |
| 5421 // Update instance type. | 5423 // Update instance type. |
| 5422 __ movq(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); | 5424 __ movq(rbx, FieldOperand(rdi, HeapObject::kMapOffset)); |
| 5423 __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); | 5425 __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); |
| 5424 __ jmp(&underlying_unpacked, Label::kNear); | 5426 __ jmp(&underlying_unpacked, Label::kNear); |
| 5425 | 5427 |
| 5426 __ bind(&sliced_string); | 5428 __ bind(&sliced_string); |
| 5427 // Sliced string. Fetch parent and correct start index by offset. | 5429 // Sliced string. Fetch parent and correct start index by offset. |
| 5428 __ addq(rdx, FieldOperand(rax, SlicedString::kOffsetOffset)); | 5430 __ addq(rdx, FieldOperand(rax, SlicedString::kOffsetOffset)); |
| (...skipping 415 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5844 if (Token::IsOrderedRelationalCompareOp(op_)) { | 5846 if (Token::IsOrderedRelationalCompareOp(op_)) { |
| 5845 __ Cmp(rdx, masm->isolate()->factory()->undefined_value()); | 5847 __ Cmp(rdx, masm->isolate()->factory()->undefined_value()); |
| 5846 __ j(equal, &unordered); | 5848 __ j(equal, &unordered); |
| 5847 } | 5849 } |
| 5848 | 5850 |
| 5849 __ bind(&miss); | 5851 __ bind(&miss); |
| 5850 GenerateMiss(masm); | 5852 GenerateMiss(masm); |
| 5851 } | 5853 } |
| 5852 | 5854 |
| 5853 | 5855 |
| 5854 void ICCompareStub::GenerateSymbols(MacroAssembler* masm) { | 5856 void ICCompareStub::GenerateInternalizedStrings(MacroAssembler* masm) { |
| 5855 ASSERT(state_ == CompareIC::SYMBOL); | 5857 ASSERT(state_ == CompareIC::INTERNALIZED_STRING); |
| 5856 ASSERT(GetCondition() == equal); | 5858 ASSERT(GetCondition() == equal); |
| 5857 | 5859 |
| 5858 // Registers containing left and right operands respectively. | 5860 // Registers containing left and right operands respectively. |
| 5859 Register left = rdx; | 5861 Register left = rdx; |
| 5860 Register right = rax; | 5862 Register right = rax; |
| 5861 Register tmp1 = rcx; | 5863 Register tmp1 = rcx; |
| 5862 Register tmp2 = rbx; | 5864 Register tmp2 = rbx; |
| 5863 | 5865 |
| 5864 // Check that both operands are heap objects. | 5866 // Check that both operands are heap objects. |
| 5865 Label miss; | 5867 Label miss; |
| 5866 Condition cond = masm->CheckEitherSmi(left, right, tmp1); | 5868 Condition cond = masm->CheckEitherSmi(left, right, tmp1); |
| 5867 __ j(cond, &miss, Label::kNear); | 5869 __ j(cond, &miss, Label::kNear); |
| 5868 | 5870 |
| 5869 // Check that both operands are symbols. | 5871 // Check that both operands are internalized strings. |
| 5870 __ movq(tmp1, FieldOperand(left, HeapObject::kMapOffset)); | 5872 __ movq(tmp1, FieldOperand(left, HeapObject::kMapOffset)); |
| 5871 __ movq(tmp2, FieldOperand(right, HeapObject::kMapOffset)); | 5873 __ movq(tmp2, FieldOperand(right, HeapObject::kMapOffset)); |
| 5872 __ movzxbq(tmp1, FieldOperand(tmp1, Map::kInstanceTypeOffset)); | 5874 __ movzxbq(tmp1, FieldOperand(tmp1, Map::kInstanceTypeOffset)); |
| 5873 __ movzxbq(tmp2, FieldOperand(tmp2, Map::kInstanceTypeOffset)); | 5875 __ movzxbq(tmp2, FieldOperand(tmp2, Map::kInstanceTypeOffset)); |
| 5874 STATIC_ASSERT(kSymbolTag != 0); | 5876 STATIC_ASSERT(kInternalizedTag != 0); |
| 5875 __ and_(tmp1, tmp2); | 5877 __ and_(tmp1, tmp2); |
| 5876 __ testb(tmp1, Immediate(kIsSymbolMask)); | 5878 __ testb(tmp1, Immediate(kIsInternalizedMask)); |
| 5877 __ j(zero, &miss, Label::kNear); | 5879 __ j(zero, &miss, Label::kNear); |
| 5878 | 5880 |
| 5879 // Symbols are compared by identity. | 5881 // Internalized strings are compared by identity. |
| 5880 Label done; | 5882 Label done; |
| 5881 __ cmpq(left, right); | 5883 __ cmpq(left, right); |
| 5882 // Make sure rax is non-zero. At this point input operands are | 5884 // Make sure rax is non-zero. At this point input operands are |
| 5883 // guaranteed to be non-zero. | 5885 // guaranteed to be non-zero. |
| 5884 ASSERT(right.is(rax)); | 5886 ASSERT(right.is(rax)); |
| 5885 __ j(not_equal, &done, Label::kNear); | 5887 __ j(not_equal, &done, Label::kNear); |
| 5886 STATIC_ASSERT(EQUAL == 0); | 5888 STATIC_ASSERT(EQUAL == 0); |
| 5887 STATIC_ASSERT(kSmiTag == 0); | 5889 STATIC_ASSERT(kSmiTag == 0); |
| 5888 __ Move(rax, Smi::FromInt(EQUAL)); | 5890 __ Move(rax, Smi::FromInt(EQUAL)); |
| 5889 __ bind(&done); | 5891 __ bind(&done); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5928 __ cmpq(left, right); | 5930 __ cmpq(left, right); |
| 5929 __ j(not_equal, ¬_same, Label::kNear); | 5931 __ j(not_equal, ¬_same, Label::kNear); |
| 5930 STATIC_ASSERT(EQUAL == 0); | 5932 STATIC_ASSERT(EQUAL == 0); |
| 5931 STATIC_ASSERT(kSmiTag == 0); | 5933 STATIC_ASSERT(kSmiTag == 0); |
| 5932 __ Move(rax, Smi::FromInt(EQUAL)); | 5934 __ Move(rax, Smi::FromInt(EQUAL)); |
| 5933 __ ret(0); | 5935 __ ret(0); |
| 5934 | 5936 |
| 5935 // Handle not identical strings. | 5937 // Handle not identical strings. |
| 5936 __ bind(¬_same); | 5938 __ bind(¬_same); |
| 5937 | 5939 |
| 5938 // Check that both strings are symbols. If they are, we're done | 5940 // Check that both strings are internalized strings. If they are, we're done |
| 5939 // because we already know they are not identical. | 5941 // because we already know they are not identical. |
| 5940 if (equality) { | 5942 if (equality) { |
| 5941 Label do_compare; | 5943 Label do_compare; |
| 5942 STATIC_ASSERT(kSymbolTag != 0); | 5944 STATIC_ASSERT(kInternalizedTag != 0); |
| 5943 __ and_(tmp1, tmp2); | 5945 __ and_(tmp1, tmp2); |
| 5944 __ testb(tmp1, Immediate(kIsSymbolMask)); | 5946 __ testb(tmp1, Immediate(kIsInternalizedMask)); |
| 5945 __ j(zero, &do_compare, Label::kNear); | 5947 __ j(zero, &do_compare, Label::kNear); |
| 5946 // Make sure rax is non-zero. At this point input operands are | 5948 // Make sure rax is non-zero. At this point input operands are |
| 5947 // guaranteed to be non-zero. | 5949 // guaranteed to be non-zero. |
| 5948 ASSERT(right.is(rax)); | 5950 ASSERT(right.is(rax)); |
| 5949 __ ret(0); | 5951 __ ret(0); |
| 5950 __ bind(&do_compare); | 5952 __ bind(&do_compare); |
| 5951 } | 5953 } |
| 5952 | 5954 |
| 5953 // Check that both strings are sequential ASCII. | 5955 // Check that both strings are sequential ASCII. |
| 5954 Label runtime; | 5956 Label runtime; |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6082 | 6084 |
| 6083 // Stop if found the property. | 6085 // Stop if found the property. |
| 6084 __ Cmp(entity_name, Handle<String>(name)); | 6086 __ Cmp(entity_name, Handle<String>(name)); |
| 6085 __ j(equal, miss); | 6087 __ j(equal, miss); |
| 6086 | 6088 |
| 6087 Label the_hole; | 6089 Label the_hole; |
| 6088 // Check for the hole and skip. | 6090 // Check for the hole and skip. |
| 6089 __ CompareRoot(entity_name, Heap::kTheHoleValueRootIndex); | 6091 __ CompareRoot(entity_name, Heap::kTheHoleValueRootIndex); |
| 6090 __ j(equal, &the_hole, Label::kNear); | 6092 __ j(equal, &the_hole, Label::kNear); |
| 6091 | 6093 |
| 6092 // Check if the entry name is not a symbol. | 6094 // Check if the entry name is not an internalized string. |
| 6093 __ movq(entity_name, FieldOperand(entity_name, HeapObject::kMapOffset)); | 6095 __ movq(entity_name, FieldOperand(entity_name, HeapObject::kMapOffset)); |
| 6094 __ testb(FieldOperand(entity_name, Map::kInstanceTypeOffset), | 6096 __ testb(FieldOperand(entity_name, Map::kInstanceTypeOffset), |
| 6095 Immediate(kIsSymbolMask)); | 6097 Immediate(kIsInternalizedMask)); |
| 6096 __ j(zero, miss); | 6098 __ j(zero, miss); |
| 6097 | 6099 |
| 6098 __ bind(&the_hole); | 6100 __ bind(&the_hole); |
| 6099 } | 6101 } |
| 6100 | 6102 |
| 6101 StringDictionaryLookupStub stub(properties, | 6103 StringDictionaryLookupStub stub(properties, |
| 6102 r0, | 6104 r0, |
| 6103 r0, | 6105 r0, |
| 6104 StringDictionaryLookupStub::NEGATIVE_LOOKUP); | 6106 StringDictionaryLookupStub::NEGATIVE_LOOKUP); |
| 6105 __ Push(Handle<Object>(name)); | 6107 __ Push(Handle<Object>(name)); |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6214 kElementsStartOffset - kHeapObjectTag)); | 6216 kElementsStartOffset - kHeapObjectTag)); |
| 6215 | 6217 |
| 6216 __ Cmp(scratch, masm->isolate()->factory()->undefined_value()); | 6218 __ Cmp(scratch, masm->isolate()->factory()->undefined_value()); |
| 6217 __ j(equal, ¬_in_dictionary); | 6219 __ j(equal, ¬_in_dictionary); |
| 6218 | 6220 |
| 6219 // Stop if found the property. | 6221 // Stop if found the property. |
| 6220 __ cmpq(scratch, Operand(rsp, 3 * kPointerSize)); | 6222 __ cmpq(scratch, Operand(rsp, 3 * kPointerSize)); |
| 6221 __ j(equal, &in_dictionary); | 6223 __ j(equal, &in_dictionary); |
| 6222 | 6224 |
| 6223 if (i != kTotalProbes - 1 && mode_ == NEGATIVE_LOOKUP) { | 6225 if (i != kTotalProbes - 1 && mode_ == NEGATIVE_LOOKUP) { |
| 6224 // If we hit a non symbol key during negative lookup | 6226 // If we hit a non internalized string key during negative lookup |
| 6225 // we have to bailout as this key might be equal to the | 6227 // we have to bailout as this key might be equal to the |
| 6226 // key we are looking for. | 6228 // key we are looking for. |
| 6227 | 6229 |
| 6228 // Check if the entry name is not a symbol. | 6230 // Check if the entry name is not an internalized string. |
| 6229 __ movq(scratch, FieldOperand(scratch, HeapObject::kMapOffset)); | 6231 __ movq(scratch, FieldOperand(scratch, HeapObject::kMapOffset)); |
| 6230 __ testb(FieldOperand(scratch, Map::kInstanceTypeOffset), | 6232 __ testb(FieldOperand(scratch, Map::kInstanceTypeOffset), |
| 6231 Immediate(kIsSymbolMask)); | 6233 Immediate(kIsInternalizedMask)); |
| 6232 __ j(zero, &maybe_in_dictionary); | 6234 __ j(zero, &maybe_in_dictionary); |
| 6233 } | 6235 } |
| 6234 } | 6236 } |
| 6235 | 6237 |
| 6236 __ bind(&maybe_in_dictionary); | 6238 __ bind(&maybe_in_dictionary); |
| 6237 // If we are doing negative lookup then probing failure should be | 6239 // If we are doing negative lookup then probing failure should be |
| 6238 // treated as a lookup success. For positive lookup probing failure | 6240 // treated as a lookup success. For positive lookup probing failure |
| 6239 // should be treated as lookup failure. | 6241 // should be treated as lookup failure. |
| 6240 if (mode_ == POSITIVE_LOOKUP) { | 6242 if (mode_ == POSITIVE_LOOKUP) { |
| 6241 __ movq(scratch, Immediate(0)); | 6243 __ movq(scratch, Immediate(0)); |
| (...skipping 470 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6712 #endif | 6714 #endif |
| 6713 | 6715 |
| 6714 __ Ret(); | 6716 __ Ret(); |
| 6715 } | 6717 } |
| 6716 | 6718 |
| 6717 #undef __ | 6719 #undef __ |
| 6718 | 6720 |
| 6719 } } // namespace v8::internal | 6721 } } // namespace v8::internal |
| 6720 | 6722 |
| 6721 #endif // V8_TARGET_ARCH_X64 | 6723 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |