OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 #include "src/code-stub-assembler.h" | 4 #include "src/code-stub-assembler.h" |
5 #include "src/code-factory.h" | 5 #include "src/code-factory.h" |
6 #include "src/frames-inl.h" | 6 #include "src/frames-inl.h" |
7 #include "src/frames.h" | 7 #include "src/frames.h" |
8 | 8 |
9 namespace v8 { | 9 namespace v8 { |
10 namespace internal { | 10 namespace internal { |
(...skipping 2872 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2883 STATIC_ASSERT(JS_GLOBAL_OBJECT_TYPE <= LAST_SPECIAL_RECEIVER_TYPE); | 2883 STATIC_ASSERT(JS_GLOBAL_OBJECT_TYPE <= LAST_SPECIAL_RECEIVER_TYPE); |
2884 return Int32LessThanOrEqual(instance_type, | 2884 return Int32LessThanOrEqual(instance_type, |
2885 Int32Constant(LAST_SPECIAL_RECEIVER_TYPE)); | 2885 Int32Constant(LAST_SPECIAL_RECEIVER_TYPE)); |
2886 } | 2886 } |
2887 | 2887 |
2888 Node* CodeStubAssembler::IsStringInstanceType(Node* instance_type) { | 2888 Node* CodeStubAssembler::IsStringInstanceType(Node* instance_type) { |
2889 STATIC_ASSERT(INTERNALIZED_STRING_TYPE == FIRST_TYPE); | 2889 STATIC_ASSERT(INTERNALIZED_STRING_TYPE == FIRST_TYPE); |
2890 return Int32LessThan(instance_type, Int32Constant(FIRST_NONSTRING_TYPE)); | 2890 return Int32LessThan(instance_type, Int32Constant(FIRST_NONSTRING_TYPE)); |
2891 } | 2891 } |
2892 | 2892 |
| 2893 Node* CodeStubAssembler::IsOneByteStringInstanceType(Node* instance_type) { |
| 2894 CSA_ASSERT(this, IsStringInstanceType(instance_type)); |
| 2895 return Word32Equal( |
| 2896 Word32And(instance_type, Int32Constant(kStringEncodingMask)), |
| 2897 Int32Constant(kOneByteStringTag)); |
| 2898 } |
| 2899 |
| 2900 Node* CodeStubAssembler::IsSequentialStringInstanceType(Node* instance_type) { |
| 2901 CSA_ASSERT(this, IsStringInstanceType(instance_type)); |
| 2902 return Word32Equal( |
| 2903 Word32And(instance_type, Int32Constant(kStringRepresentationMask)), |
| 2904 Int32Constant(kSeqStringTag)); |
| 2905 } |
| 2906 |
2893 Node* CodeStubAssembler::IsJSReceiverInstanceType(Node* instance_type) { | 2907 Node* CodeStubAssembler::IsJSReceiverInstanceType(Node* instance_type) { |
2894 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); | 2908 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); |
2895 return Int32GreaterThanOrEqual(instance_type, | 2909 return Int32GreaterThanOrEqual(instance_type, |
2896 Int32Constant(FIRST_JS_RECEIVER_TYPE)); | 2910 Int32Constant(FIRST_JS_RECEIVER_TYPE)); |
2897 } | 2911 } |
2898 | 2912 |
2899 Node* CodeStubAssembler::IsJSReceiver(Node* object) { | 2913 Node* CodeStubAssembler::IsJSReceiver(Node* object) { |
2900 STATIC_ASSERT(LAST_JS_OBJECT_TYPE == LAST_TYPE); | 2914 STATIC_ASSERT(LAST_JS_OBJECT_TYPE == LAST_TYPE); |
2901 return IsJSReceiverInstanceType(LoadInstanceType(object)); | 2915 return IsJSReceiverInstanceType(LoadInstanceType(object)); |
2902 } | 2916 } |
(...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3248 // given character range using CopyStringCharacters. | 3262 // given character range using CopyStringCharacters. |
3249 // |from_string| must be a sequential string. |from_index| and | 3263 // |from_string| must be a sequential string. |from_index| and |
3250 // |character_count| must be Smis s.t. | 3264 // |character_count| must be Smis s.t. |
3251 // 0 <= |from_index| <= |from_index| + |character_count| < from_string.length. | 3265 // 0 <= |from_index| <= |from_index| + |character_count| < from_string.length. |
3252 Node* AllocAndCopyStringCharacters(CodeStubAssembler* a, Node* context, | 3266 Node* AllocAndCopyStringCharacters(CodeStubAssembler* a, Node* context, |
3253 Node* from, Node* from_instance_type, | 3267 Node* from, Node* from_instance_type, |
3254 Node* from_index, Node* character_count) { | 3268 Node* from_index, Node* character_count) { |
3255 typedef CodeStubAssembler::Label Label; | 3269 typedef CodeStubAssembler::Label Label; |
3256 typedef CodeStubAssembler::Variable Variable; | 3270 typedef CodeStubAssembler::Variable Variable; |
3257 | 3271 |
3258 Label end(a), two_byte_sequential(a); | 3272 Label end(a), one_byte_sequential(a), two_byte_sequential(a); |
3259 Variable var_result(a, MachineRepresentation::kTagged); | 3273 Variable var_result(a, MachineRepresentation::kTagged); |
3260 | 3274 |
3261 Node* const smi_zero = a->SmiConstant(Smi::kZero); | 3275 Node* const smi_zero = a->SmiConstant(Smi::kZero); |
3262 | 3276 |
3263 STATIC_ASSERT((kOneByteStringTag & kStringEncodingMask) != 0); | 3277 a->Branch(a->IsOneByteStringInstanceType(from_instance_type), |
3264 a->GotoIf(a->Word32Equal(a->Word32And(from_instance_type, | 3278 &one_byte_sequential, &two_byte_sequential); |
3265 a->Int32Constant(kStringEncodingMask)), | |
3266 a->Int32Constant(0)), | |
3267 &two_byte_sequential); | |
3268 | 3279 |
3269 // The subject string is a sequential one-byte string. | 3280 // The subject string is a sequential one-byte string. |
| 3281 a->Bind(&one_byte_sequential); |
3270 { | 3282 { |
3271 Node* result = | 3283 Node* result = |
3272 a->AllocateSeqOneByteString(context, a->SmiToWord(character_count)); | 3284 a->AllocateSeqOneByteString(context, a->SmiToWord(character_count)); |
3273 a->CopyStringCharacters(from, result, from_index, smi_zero, character_count, | 3285 a->CopyStringCharacters(from, result, from_index, smi_zero, character_count, |
3274 String::ONE_BYTE_ENCODING, | 3286 String::ONE_BYTE_ENCODING, |
3275 String::ONE_BYTE_ENCODING, | 3287 String::ONE_BYTE_ENCODING, |
3276 CodeStubAssembler::SMI_PARAMETERS); | 3288 CodeStubAssembler::SMI_PARAMETERS); |
3277 var_result.Bind(result); | 3289 var_result.Bind(result); |
3278 | 3290 |
3279 a->Goto(&end); | 3291 a->Goto(&end); |
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3544 Node* const instance_type) { | 3556 Node* const instance_type) { |
3545 CSA_ASSERT(a, a->IsStringInstanceType(instance_type)); | 3557 CSA_ASSERT(a, a->IsStringInstanceType(instance_type)); |
3546 STATIC_ASSERT(kShortExternalStringTag != 0); | 3558 STATIC_ASSERT(kShortExternalStringTag != 0); |
3547 return a->Word32NotEqual( | 3559 return a->Word32NotEqual( |
3548 a->Word32And(instance_type, a->Int32Constant(kShortExternalStringMask)), | 3560 a->Word32And(instance_type, a->Int32Constant(kShortExternalStringMask)), |
3549 a->Int32Constant(0)); | 3561 a->Int32Constant(0)); |
3550 } | 3562 } |
3551 | 3563 |
3552 } // namespace | 3564 } // namespace |
3553 | 3565 |
| 3566 void CodeStubAssembler::TryUnpackString(Variable* var_string, |
| 3567 Variable* var_offset, |
| 3568 Variable* var_instance_type, |
| 3569 Label* if_bailout) { |
| 3570 DCHECK_EQ(var_string->rep(), MachineType::PointerRepresentation()); |
| 3571 DCHECK_EQ(var_offset->rep(), MachineType::PointerRepresentation()); |
| 3572 DCHECK_EQ(var_instance_type->rep(), MachineRepresentation::kWord32); |
| 3573 CSA_ASSERT(this, IsString(var_string->value())); |
| 3574 |
| 3575 Label out(this); |
| 3576 |
| 3577 VariableList vars({var_string, var_offset, var_instance_type}, zone()); |
| 3578 Label dispatch(this, vars); |
| 3579 Label if_isdirect(this); |
| 3580 Label if_iscons(this, Label::kDeferred); |
| 3581 Label if_isexternal(this, Label::kDeferred); |
| 3582 Label if_issliced(this, Label::kDeferred); |
| 3583 Label if_isthin(this, Label::kDeferred); |
| 3584 |
| 3585 Goto(&dispatch); |
| 3586 |
| 3587 // Dispatch based on string representation. |
| 3588 Bind(&dispatch); |
| 3589 { |
| 3590 int32_t values[] = { |
| 3591 kSeqStringTag, kConsStringTag, kExternalStringTag, |
| 3592 kSlicedStringTag, kThinStringTag, |
| 3593 }; |
| 3594 Label* labels[] = { |
| 3595 &if_isdirect, &if_iscons, &if_isexternal, &if_issliced, &if_isthin, |
| 3596 }; |
| 3597 STATIC_ASSERT(arraysize(values) == arraysize(labels)); |
| 3598 |
| 3599 Node* const representation = Word32And( |
| 3600 var_instance_type->value(), Int32Constant(kStringRepresentationMask)); |
| 3601 Switch(representation, if_bailout, values, labels, arraysize(values)); |
| 3602 } |
| 3603 |
| 3604 // Cons string. Check whether it is flat, then fetch first part. |
| 3605 // Flat cons strings have an empty second part. |
| 3606 Bind(&if_iscons); |
| 3607 { |
| 3608 Node* const string = var_string->value(); |
| 3609 GotoIfNot(IsEmptyString(LoadObjectField(string, ConsString::kSecondOffset)), |
| 3610 if_bailout); |
| 3611 |
| 3612 Node* const lhs = LoadObjectField(string, ConsString::kFirstOffset); |
| 3613 var_string->Bind(BitcastTaggedToWord(lhs)); |
| 3614 var_instance_type->Bind(LoadInstanceType(lhs)); |
| 3615 |
| 3616 Goto(&dispatch); |
| 3617 } |
| 3618 |
| 3619 // Sliced string. Fetch parent and correct start index by offset. |
| 3620 Bind(&if_issliced); |
| 3621 { |
| 3622 Node* const string = var_string->value(); |
| 3623 Node* const sliced_offset = |
| 3624 LoadObjectField(string, SlicedString::kOffsetOffset); |
| 3625 var_offset->Bind(IntPtrAdd(var_offset->value(), SmiUntag(sliced_offset))); |
| 3626 |
| 3627 Node* const parent = LoadObjectField(string, SlicedString::kParentOffset); |
| 3628 var_string->Bind(BitcastTaggedToWord(parent)); |
| 3629 var_instance_type->Bind(LoadInstanceType(parent)); |
| 3630 |
| 3631 Goto(&dispatch); |
| 3632 } |
| 3633 |
| 3634 // Thin string. Fetch the actual string. |
| 3635 Bind(&if_isthin); |
| 3636 { |
| 3637 Node* const string = var_string->value(); |
| 3638 Node* const actual_string = |
| 3639 LoadObjectField(string, ThinString::kActualOffset); |
| 3640 Node* const actual_instance_type = LoadInstanceType(actual_string); |
| 3641 |
| 3642 var_string->Bind(BitcastTaggedToWord(actual_string)); |
| 3643 var_instance_type->Bind(actual_instance_type); |
| 3644 |
| 3645 Goto(&dispatch); |
| 3646 } |
| 3647 |
| 3648 // External string. |
| 3649 Bind(&if_isexternal); |
| 3650 { |
| 3651 Node* const string = var_string->value(); |
| 3652 Node* const faked_seq_string = |
| 3653 TryDerefExternalString(string, var_instance_type->value(), if_bailout); |
| 3654 |
| 3655 STATIC_ASSERT(kSeqStringTag == 0x0); |
| 3656 Node* const faked_seq_instance_type = Word32Xor( |
| 3657 var_instance_type->value(), Int32Constant(kExternalStringTag)); |
| 3658 CSA_ASSERT(this, IsSequentialStringInstanceType(faked_seq_instance_type)); |
| 3659 |
| 3660 var_string->Bind(faked_seq_string); |
| 3661 var_instance_type->Bind(faked_seq_instance_type); |
| 3662 |
| 3663 Goto(&if_isdirect); |
| 3664 } |
| 3665 |
| 3666 Bind(&if_isdirect); |
| 3667 } |
| 3668 |
3554 Node* CodeStubAssembler::TryDerefExternalString(Node* const string, | 3669 Node* CodeStubAssembler::TryDerefExternalString(Node* const string, |
3555 Node* const instance_type, | 3670 Node* const instance_type, |
3556 Label* if_bailout) { | 3671 Label* if_bailout) { |
3557 Label out(this); | 3672 Label out(this); |
3558 | 3673 |
3559 USE(IsExternalStringInstanceType); | 3674 USE(IsExternalStringInstanceType); |
3560 CSA_ASSERT(this, IsExternalStringInstanceType(this, instance_type)); | 3675 CSA_ASSERT(this, IsExternalStringInstanceType(this, instance_type)); |
3561 GotoIf(IsShortExternalStringInstanceType(this, instance_type), if_bailout); | 3676 GotoIf(IsShortExternalStringInstanceType(this, instance_type), if_bailout); |
3562 | 3677 |
3563 // Move the pointer so that offset-wise, it looks like a sequential string. | 3678 // Move the pointer so that offset-wise, it looks like a sequential string. |
(...skipping 2047 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5611 // This method is used for binary op and compare feedback. These | 5726 // This method is used for binary op and compare feedback. These |
5612 // vector nodes are initialized with a smi 0, so we can simply OR | 5727 // vector nodes are initialized with a smi 0, so we can simply OR |
5613 // our new feedback in place. | 5728 // our new feedback in place. |
5614 Node* previous_feedback = LoadFixedArrayElement(feedback_vector, slot_id); | 5729 Node* previous_feedback = LoadFixedArrayElement(feedback_vector, slot_id); |
5615 Node* combined_feedback = SmiOr(previous_feedback, feedback); | 5730 Node* combined_feedback = SmiOr(previous_feedback, feedback); |
5616 StoreFixedArrayElement(feedback_vector, slot_id, combined_feedback, | 5731 StoreFixedArrayElement(feedback_vector, slot_id, combined_feedback, |
5617 SKIP_WRITE_BARRIER); | 5732 SKIP_WRITE_BARRIER); |
5618 } | 5733 } |
5619 | 5734 |
5620 Node* CodeStubAssembler::LoadReceiverMap(Node* receiver) { | 5735 Node* CodeStubAssembler::LoadReceiverMap(Node* receiver) { |
5621 Variable var_receiver_map(this, MachineRepresentation::kTagged); | 5736 return Select(TaggedIsSmi(receiver), |
5622 Label load_smi_map(this, Label::kDeferred), load_receiver_map(this), | 5737 [=] { return LoadRoot(Heap::kHeapNumberMapRootIndex); }, |
5623 if_result(this); | 5738 [=] { return LoadMap(receiver); }, |
5624 | 5739 MachineRepresentation::kTagged); |
5625 Branch(TaggedIsSmi(receiver), &load_smi_map, &load_receiver_map); | |
5626 Bind(&load_smi_map); | |
5627 { | |
5628 var_receiver_map.Bind(LoadRoot(Heap::kHeapNumberMapRootIndex)); | |
5629 Goto(&if_result); | |
5630 } | |
5631 Bind(&load_receiver_map); | |
5632 { | |
5633 var_receiver_map.Bind(LoadMap(receiver)); | |
5634 Goto(&if_result); | |
5635 } | |
5636 Bind(&if_result); | |
5637 return var_receiver_map.value(); | |
5638 } | 5740 } |
5639 | 5741 |
5640 Node* CodeStubAssembler::TryToIntptr(Node* key, Label* miss) { | 5742 Node* CodeStubAssembler::TryToIntptr(Node* key, Label* miss) { |
5641 Variable var_intptr_key(this, MachineType::PointerRepresentation()); | 5743 Variable var_intptr_key(this, MachineType::PointerRepresentation()); |
5642 Label done(this, &var_intptr_key), key_is_smi(this); | 5744 Label done(this, &var_intptr_key), key_is_smi(this); |
5643 GotoIf(TaggedIsSmi(key), &key_is_smi); | 5745 GotoIf(TaggedIsSmi(key), &key_is_smi); |
5644 // Try to convert a heap number to a Smi. | 5746 // Try to convert a heap number to a Smi. |
5645 GotoIfNot(IsHeapNumberMap(LoadMap(key)), miss); | 5747 GotoIfNot(IsHeapNumberMap(LoadMap(key)), miss); |
5646 { | 5748 { |
5647 Node* value = LoadHeapNumberValue(key); | 5749 Node* value = LoadHeapNumberValue(key); |
(...skipping 2697 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8345 formatted.c_str(), TENURED); | 8447 formatted.c_str(), TENURED); |
8346 CallRuntime(Runtime::kGlobalPrint, NoContextConstant(), | 8448 CallRuntime(Runtime::kGlobalPrint, NoContextConstant(), |
8347 HeapConstant(string)); | 8449 HeapConstant(string)); |
8348 } | 8450 } |
8349 CallRuntime(Runtime::kDebugPrint, NoContextConstant(), tagged_value); | 8451 CallRuntime(Runtime::kDebugPrint, NoContextConstant(), tagged_value); |
8350 #endif | 8452 #endif |
8351 } | 8453 } |
8352 | 8454 |
8353 } // namespace internal | 8455 } // namespace internal |
8354 } // namespace v8 | 8456 } // namespace v8 |
OLD | NEW |