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 |