Chromium Code Reviews| 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 2880 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2891 STATIC_ASSERT(JS_GLOBAL_OBJECT_TYPE <= LAST_SPECIAL_RECEIVER_TYPE); | 2891 STATIC_ASSERT(JS_GLOBAL_OBJECT_TYPE <= LAST_SPECIAL_RECEIVER_TYPE); |
| 2892 return Int32LessThanOrEqual(instance_type, | 2892 return Int32LessThanOrEqual(instance_type, |
| 2893 Int32Constant(LAST_SPECIAL_RECEIVER_TYPE)); | 2893 Int32Constant(LAST_SPECIAL_RECEIVER_TYPE)); |
| 2894 } | 2894 } |
| 2895 | 2895 |
| 2896 Node* CodeStubAssembler::IsStringInstanceType(Node* instance_type) { | 2896 Node* CodeStubAssembler::IsStringInstanceType(Node* instance_type) { |
| 2897 STATIC_ASSERT(INTERNALIZED_STRING_TYPE == FIRST_TYPE); | 2897 STATIC_ASSERT(INTERNALIZED_STRING_TYPE == FIRST_TYPE); |
| 2898 return Int32LessThan(instance_type, Int32Constant(FIRST_NONSTRING_TYPE)); | 2898 return Int32LessThan(instance_type, Int32Constant(FIRST_NONSTRING_TYPE)); |
| 2899 } | 2899 } |
| 2900 | 2900 |
| 2901 Node* CodeStubAssembler::IsOneByteStringInstanceType(Node* instance_type) { | |
| 2902 CSA_ASSERT(this, IsStringInstanceType(instance_type)); | |
| 2903 return Word32Equal( | |
| 2904 Word32And(instance_type, Int32Constant(kStringEncodingMask)), | |
| 2905 Int32Constant(kOneByteStringTag)); | |
| 2906 } | |
| 2907 | |
| 2908 Node* CodeStubAssembler::IsSequentialStringInstanceType(Node* instance_type) { | |
| 2909 CSA_ASSERT(this, IsStringInstanceType(instance_type)); | |
| 2910 return Word32Equal( | |
| 2911 Word32And(instance_type, Int32Constant(kStringRepresentationMask)), | |
| 2912 Int32Constant(kSeqStringTag)); | |
| 2913 } | |
| 2914 | |
| 2901 Node* CodeStubAssembler::IsJSReceiverInstanceType(Node* instance_type) { | 2915 Node* CodeStubAssembler::IsJSReceiverInstanceType(Node* instance_type) { |
| 2902 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); | 2916 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); |
| 2903 return Int32GreaterThanOrEqual(instance_type, | 2917 return Int32GreaterThanOrEqual(instance_type, |
| 2904 Int32Constant(FIRST_JS_RECEIVER_TYPE)); | 2918 Int32Constant(FIRST_JS_RECEIVER_TYPE)); |
| 2905 } | 2919 } |
| 2906 | 2920 |
| 2907 Node* CodeStubAssembler::IsJSReceiver(Node* object) { | 2921 Node* CodeStubAssembler::IsJSReceiver(Node* object) { |
| 2908 STATIC_ASSERT(LAST_JS_OBJECT_TYPE == LAST_TYPE); | 2922 STATIC_ASSERT(LAST_JS_OBJECT_TYPE == LAST_TYPE); |
| 2909 return IsJSReceiverInstanceType(LoadInstanceType(object)); | 2923 return IsJSReceiverInstanceType(LoadInstanceType(object)); |
| 2910 } | 2924 } |
| (...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3252 // given character range using CopyStringCharacters. | 3266 // given character range using CopyStringCharacters. |
| 3253 // |from_string| must be a sequential string. |from_index| and | 3267 // |from_string| must be a sequential string. |from_index| and |
| 3254 // |character_count| must be Smis s.t. | 3268 // |character_count| must be Smis s.t. |
| 3255 // 0 <= |from_index| <= |from_index| + |character_count| < from_string.length. | 3269 // 0 <= |from_index| <= |from_index| + |character_count| < from_string.length. |
| 3256 Node* AllocAndCopyStringCharacters(CodeStubAssembler* a, Node* context, | 3270 Node* AllocAndCopyStringCharacters(CodeStubAssembler* a, Node* context, |
| 3257 Node* from, Node* from_instance_type, | 3271 Node* from, Node* from_instance_type, |
| 3258 Node* from_index, Node* character_count) { | 3272 Node* from_index, Node* character_count) { |
| 3259 typedef CodeStubAssembler::Label Label; | 3273 typedef CodeStubAssembler::Label Label; |
| 3260 typedef CodeStubAssembler::Variable Variable; | 3274 typedef CodeStubAssembler::Variable Variable; |
| 3261 | 3275 |
| 3262 Label end(a), two_byte_sequential(a); | 3276 Label end(a), one_byte_sequential(a), two_byte_sequential(a); |
| 3263 Variable var_result(a, MachineRepresentation::kTagged); | 3277 Variable var_result(a, MachineRepresentation::kTagged); |
| 3264 | 3278 |
| 3265 Node* const smi_zero = a->SmiConstant(Smi::kZero); | 3279 Node* const smi_zero = a->SmiConstant(Smi::kZero); |
| 3266 | 3280 |
| 3267 STATIC_ASSERT((kOneByteStringTag & kStringEncodingMask) != 0); | 3281 a->Branch(a->IsOneByteStringInstanceType(from_instance_type), |
|
jgruber
2017/03/13 12:27:37
Drive-by simplification.
| |
| 3268 a->GotoIf(a->Word32Equal(a->Word32And(from_instance_type, | 3282 &one_byte_sequential, &two_byte_sequential); |
| 3269 a->Int32Constant(kStringEncodingMask)), | |
| 3270 a->Int32Constant(0)), | |
| 3271 &two_byte_sequential); | |
| 3272 | 3283 |
| 3273 // The subject string is a sequential one-byte string. | 3284 // The subject string is a sequential one-byte string. |
| 3285 a->Bind(&one_byte_sequential); | |
| 3274 { | 3286 { |
| 3275 Node* result = | 3287 Node* result = |
| 3276 a->AllocateSeqOneByteString(context, a->SmiToWord(character_count)); | 3288 a->AllocateSeqOneByteString(context, a->SmiToWord(character_count)); |
| 3277 a->CopyStringCharacters(from, result, from_index, smi_zero, character_count, | 3289 a->CopyStringCharacters(from, result, from_index, smi_zero, character_count, |
| 3278 String::ONE_BYTE_ENCODING, | 3290 String::ONE_BYTE_ENCODING, |
| 3279 String::ONE_BYTE_ENCODING, | 3291 String::ONE_BYTE_ENCODING, |
| 3280 CodeStubAssembler::SMI_PARAMETERS); | 3292 CodeStubAssembler::SMI_PARAMETERS); |
| 3281 var_result.Bind(result); | 3293 var_result.Bind(result); |
| 3282 | 3294 |
| 3283 a->Goto(&end); | 3295 a->Goto(&end); |
| (...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3548 Node* const instance_type) { | 3560 Node* const instance_type) { |
| 3549 CSA_ASSERT(a, a->IsStringInstanceType(instance_type)); | 3561 CSA_ASSERT(a, a->IsStringInstanceType(instance_type)); |
| 3550 STATIC_ASSERT(kShortExternalStringTag != 0); | 3562 STATIC_ASSERT(kShortExternalStringTag != 0); |
| 3551 return a->Word32NotEqual( | 3563 return a->Word32NotEqual( |
| 3552 a->Word32And(instance_type, a->Int32Constant(kShortExternalStringMask)), | 3564 a->Word32And(instance_type, a->Int32Constant(kShortExternalStringMask)), |
| 3553 a->Int32Constant(0)); | 3565 a->Int32Constant(0)); |
| 3554 } | 3566 } |
| 3555 | 3567 |
| 3556 } // namespace | 3568 } // namespace |
| 3557 | 3569 |
| 3570 void CodeStubAssembler::TryUnpackString(Variable* var_string, | |
|
jgruber
2017/03/13 12:27:37
String unpacking is getting messy, planning on ref
| |
| 3571 Variable* var_offset, | |
| 3572 Variable* var_instance_type, | |
| 3573 Label* if_bailout) { | |
| 3574 DCHECK_EQ(var_string->rep(), MachineType::PointerRepresentation()); | |
| 3575 DCHECK_EQ(var_offset->rep(), MachineType::PointerRepresentation()); | |
| 3576 DCHECK_EQ(var_instance_type->rep(), MachineRepresentation::kWord32); | |
| 3577 CSA_ASSERT(this, IsString(var_string->value())); | |
| 3578 | |
| 3579 Label out(this); | |
| 3580 | |
| 3581 VariableList vars({var_string, var_offset, var_instance_type}, zone()); | |
| 3582 Label dispatch(this, vars); | |
| 3583 Label if_isdirect(this); | |
| 3584 Label if_iscons(this, Label::kDeferred); | |
| 3585 Label if_isexternal(this, Label::kDeferred); | |
| 3586 Label if_issliced(this, Label::kDeferred); | |
| 3587 Label if_isthin(this, Label::kDeferred); | |
| 3588 | |
| 3589 Goto(&dispatch); | |
| 3590 | |
| 3591 // Dispatch based on string representation. | |
| 3592 Bind(&dispatch); | |
| 3593 { | |
| 3594 int32_t values[] = { | |
| 3595 kSeqStringTag, kConsStringTag, kExternalStringTag, | |
| 3596 kSlicedStringTag, kThinStringTag, | |
| 3597 }; | |
| 3598 Label* labels[] = { | |
| 3599 &if_isdirect, &if_iscons, &if_isexternal, &if_issliced, &if_isthin, | |
| 3600 }; | |
| 3601 STATIC_ASSERT(arraysize(values) == arraysize(labels)); | |
| 3602 | |
| 3603 Node* const representation = Word32And( | |
| 3604 var_instance_type->value(), Int32Constant(kStringRepresentationMask)); | |
| 3605 Switch(representation, if_bailout, values, labels, arraysize(values)); | |
| 3606 } | |
| 3607 | |
| 3608 // Cons string. Check whether it is flat, then fetch first part. | |
| 3609 // Flat cons strings have an empty second part. | |
| 3610 Bind(&if_iscons); | |
| 3611 { | |
| 3612 Node* const string = var_string->value(); | |
| 3613 GotoIfNot(IsEmptyString(LoadObjectField(string, ConsString::kSecondOffset)), | |
| 3614 if_bailout); | |
| 3615 | |
| 3616 Node* const lhs = LoadObjectField(string, ConsString::kFirstOffset); | |
| 3617 var_string->Bind(BitcastTaggedToWord(lhs)); | |
| 3618 var_instance_type->Bind(LoadInstanceType(lhs)); | |
| 3619 | |
| 3620 Goto(&dispatch); | |
| 3621 } | |
| 3622 | |
| 3623 // Sliced string. Fetch parent and correct start index by offset. | |
| 3624 Bind(&if_issliced); | |
| 3625 { | |
| 3626 Node* const string = var_string->value(); | |
| 3627 Node* const sliced_offset = | |
| 3628 LoadObjectField(string, SlicedString::kOffsetOffset); | |
| 3629 var_offset->Bind(IntPtrAdd(var_offset->value(), SmiUntag(sliced_offset))); | |
| 3630 | |
| 3631 Node* const parent = LoadObjectField(string, SlicedString::kParentOffset); | |
| 3632 var_string->Bind(BitcastTaggedToWord(parent)); | |
| 3633 var_instance_type->Bind(LoadInstanceType(parent)); | |
| 3634 | |
| 3635 Goto(&dispatch); | |
| 3636 } | |
| 3637 | |
| 3638 // Thin string. Fetch the actual string. | |
| 3639 Bind(&if_isthin); | |
| 3640 { | |
| 3641 Node* const string = var_string->value(); | |
| 3642 Node* const actual_string = | |
| 3643 LoadObjectField(string, ThinString::kActualOffset); | |
| 3644 Node* const actual_instance_type = LoadInstanceType(actual_string); | |
| 3645 CSA_ASSERT(this, IsSequentialStringInstanceType(actual_instance_type)); | |
| 3646 | |
| 3647 var_string->Bind(BitcastTaggedToWord(actual_string)); | |
| 3648 var_instance_type->Bind(actual_instance_type); | |
| 3649 | |
| 3650 Goto(&if_isdirect); | |
| 3651 } | |
| 3652 | |
| 3653 // External string. | |
| 3654 Bind(&if_isexternal); | |
| 3655 { | |
| 3656 Node* const string = var_string->value(); | |
| 3657 Node* const faked_seq_string = | |
| 3658 TryDerefExternalString(string, var_instance_type->value(), if_bailout); | |
| 3659 | |
| 3660 STATIC_ASSERT(kSeqStringTag == 0x0); | |
| 3661 Node* const faked_seq_instance_type = Word32Xor( | |
| 3662 var_instance_type->value(), Int32Constant(kExternalStringTag)); | |
| 3663 CSA_ASSERT(this, IsSequentialStringInstanceType(faked_seq_instance_type)); | |
| 3664 | |
| 3665 var_string->Bind(faked_seq_string); | |
| 3666 var_instance_type->Bind(faked_seq_instance_type); | |
| 3667 | |
| 3668 Goto(&if_isdirect); | |
| 3669 } | |
| 3670 | |
| 3671 Bind(&if_isdirect); | |
| 3672 } | |
| 3673 | |
| 3558 Node* CodeStubAssembler::TryDerefExternalString(Node* const string, | 3674 Node* CodeStubAssembler::TryDerefExternalString(Node* const string, |
| 3559 Node* const instance_type, | 3675 Node* const instance_type, |
| 3560 Label* if_bailout) { | 3676 Label* if_bailout) { |
| 3561 Label out(this); | 3677 Label out(this); |
| 3562 | 3678 |
| 3563 USE(IsExternalStringInstanceType); | 3679 USE(IsExternalStringInstanceType); |
| 3564 CSA_ASSERT(this, IsExternalStringInstanceType(this, instance_type)); | 3680 CSA_ASSERT(this, IsExternalStringInstanceType(this, instance_type)); |
| 3565 GotoIf(IsShortExternalStringInstanceType(this, instance_type), if_bailout); | 3681 GotoIf(IsShortExternalStringInstanceType(this, instance_type), if_bailout); |
| 3566 | 3682 |
| 3567 // Move the pointer so that offset-wise, it looks like a sequential string. | 3683 // Move the pointer so that offset-wise, it looks like a sequential string. |
| (...skipping 2018 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5586 // This method is used for binary op and compare feedback. These | 5702 // This method is used for binary op and compare feedback. These |
| 5587 // vector nodes are initialized with a smi 0, so we can simply OR | 5703 // vector nodes are initialized with a smi 0, so we can simply OR |
| 5588 // our new feedback in place. | 5704 // our new feedback in place. |
| 5589 Node* previous_feedback = LoadFixedArrayElement(feedback_vector, slot_id); | 5705 Node* previous_feedback = LoadFixedArrayElement(feedback_vector, slot_id); |
| 5590 Node* combined_feedback = SmiOr(previous_feedback, feedback); | 5706 Node* combined_feedback = SmiOr(previous_feedback, feedback); |
| 5591 StoreFixedArrayElement(feedback_vector, slot_id, combined_feedback, | 5707 StoreFixedArrayElement(feedback_vector, slot_id, combined_feedback, |
| 5592 SKIP_WRITE_BARRIER); | 5708 SKIP_WRITE_BARRIER); |
| 5593 } | 5709 } |
| 5594 | 5710 |
| 5595 Node* CodeStubAssembler::LoadReceiverMap(Node* receiver) { | 5711 Node* CodeStubAssembler::LoadReceiverMap(Node* receiver) { |
| 5596 Variable var_receiver_map(this, MachineRepresentation::kTagged); | 5712 return Select(TaggedIsSmi(receiver), |
|
jgruber
2017/03/13 12:27:37
Drive-by simplification.
| |
| 5597 Label load_smi_map(this, Label::kDeferred), load_receiver_map(this), | 5713 [=] { return LoadRoot(Heap::kHeapNumberMapRootIndex); }, |
| 5598 if_result(this); | 5714 [=] { return LoadMap(receiver); }, |
| 5599 | 5715 MachineRepresentation::kTagged); |
| 5600 Branch(TaggedIsSmi(receiver), &load_smi_map, &load_receiver_map); | |
| 5601 Bind(&load_smi_map); | |
| 5602 { | |
| 5603 var_receiver_map.Bind(LoadRoot(Heap::kHeapNumberMapRootIndex)); | |
| 5604 Goto(&if_result); | |
| 5605 } | |
| 5606 Bind(&load_receiver_map); | |
| 5607 { | |
| 5608 var_receiver_map.Bind(LoadMap(receiver)); | |
| 5609 Goto(&if_result); | |
| 5610 } | |
| 5611 Bind(&if_result); | |
| 5612 return var_receiver_map.value(); | |
| 5613 } | 5716 } |
| 5614 | 5717 |
| 5615 Node* CodeStubAssembler::TryToIntptr(Node* key, Label* miss) { | 5718 Node* CodeStubAssembler::TryToIntptr(Node* key, Label* miss) { |
| 5616 Variable var_intptr_key(this, MachineType::PointerRepresentation()); | 5719 Variable var_intptr_key(this, MachineType::PointerRepresentation()); |
| 5617 Label done(this, &var_intptr_key), key_is_smi(this); | 5720 Label done(this, &var_intptr_key), key_is_smi(this); |
| 5618 GotoIf(TaggedIsSmi(key), &key_is_smi); | 5721 GotoIf(TaggedIsSmi(key), &key_is_smi); |
| 5619 // Try to convert a heap number to a Smi. | 5722 // Try to convert a heap number to a Smi. |
| 5620 GotoIfNot(IsHeapNumberMap(LoadMap(key)), miss); | 5723 GotoIfNot(IsHeapNumberMap(LoadMap(key)), miss); |
| 5621 { | 5724 { |
| 5622 Node* value = LoadHeapNumberValue(key); | 5725 Node* value = LoadHeapNumberValue(key); |
| (...skipping 2697 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8320 formatted.c_str(), TENURED); | 8423 formatted.c_str(), TENURED); |
| 8321 CallRuntime(Runtime::kGlobalPrint, NoContextConstant(), | 8424 CallRuntime(Runtime::kGlobalPrint, NoContextConstant(), |
| 8322 HeapConstant(string)); | 8425 HeapConstant(string)); |
| 8323 } | 8426 } |
| 8324 CallRuntime(Runtime::kDebugPrint, NoContextConstant(), tagged_value); | 8427 CallRuntime(Runtime::kDebugPrint, NoContextConstant(), tagged_value); |
| 8325 #endif | 8428 #endif |
| 8326 } | 8429 } |
| 8327 | 8430 |
| 8328 } // namespace internal | 8431 } // namespace internal |
| 8329 } // namespace v8 | 8432 } // namespace v8 |
| OLD | NEW |