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 #include "src/ic/handler-configuration.h" | 8 #include "src/ic/handler-configuration.h" |
9 #include "src/ic/stub-cache.h" | 9 #include "src/ic/stub-cache.h" |
10 | 10 |
(...skipping 2055 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2066 Bind(&next_iter); | 2066 Bind(&next_iter); |
2067 Node* compare = WordNotEqual(from_offset, limit_offset); | 2067 Node* compare = WordNotEqual(from_offset, limit_offset); |
2068 Branch(compare, &decrement, &done); | 2068 Branch(compare, &decrement, &done); |
2069 } | 2069 } |
2070 | 2070 |
2071 Bind(&done); | 2071 Bind(&done); |
2072 IncrementCounter(isolate()->counters()->inlined_copied_elements(), 1); | 2072 IncrementCounter(isolate()->counters()->inlined_copied_elements(), 1); |
2073 Comment("] CopyFixedArrayElements"); | 2073 Comment("] CopyFixedArrayElements"); |
2074 } | 2074 } |
2075 | 2075 |
2076 void CodeStubAssembler::CopyStringCharacters(compiler::Node* from_string, | 2076 void CodeStubAssembler::CopyStringCharacters( |
2077 compiler::Node* to_string, | 2077 compiler::Node* from_string, compiler::Node* to_string, |
2078 compiler::Node* from_index, | 2078 compiler::Node* from_index, compiler::Node* to_index, |
2079 compiler::Node* to_index, | 2079 compiler::Node* character_count, String::Encoding from_encoding, |
2080 compiler::Node* character_count, | 2080 String::Encoding to_encoding, ParameterMode mode) { |
2081 String::Encoding encoding, | 2081 bool from_one_byte = from_encoding == String::ONE_BYTE_ENCODING; |
2082 ParameterMode mode) { | 2082 bool to_one_byte = to_encoding == String::ONE_BYTE_ENCODING; |
2083 bool one_byte = encoding == String::ONE_BYTE_ENCODING; | 2083 DCHECK_IMPLIES(to_one_byte, from_one_byte); |
2084 Comment(one_byte ? "CopyStringCharacters ONE_BYTE_ENCODING" | 2084 Comment("CopyStringCharacters %s -> %s", |
2085 : "CopyStringCharacters TWO_BYTE_ENCODING"); | 2085 from_one_byte ? "ONE_BYTE_ENCODING" : "TWO_BYTE_ENCODING", |
| 2086 to_one_byte ? "ONE_BYTE_ENCODING" : "TWO_BYTE_ENCODING"); |
2086 | 2087 |
2087 ElementsKind kind = one_byte ? UINT8_ELEMENTS : UINT16_ELEMENTS; | 2088 ElementsKind from_kind = from_one_byte ? UINT8_ELEMENTS : UINT16_ELEMENTS; |
2088 int header_size = (one_byte ? SeqOneByteString::kHeaderSize | 2089 ElementsKind to_kind = to_one_byte ? UINT8_ELEMENTS : UINT16_ELEMENTS; |
2089 : SeqTwoByteString::kHeaderSize) - | 2090 STATIC_ASSERT(SeqOneByteString::kHeaderSize == SeqTwoByteString::kHeaderSize); |
2090 kHeapObjectTag; | 2091 int header_size = SeqOneByteString::kHeaderSize - kHeapObjectTag; |
2091 Node* from_offset = ElementOffsetFromIndex(from_index, kind, mode); | 2092 Node* from_offset = |
2092 Node* to_offset = ElementOffsetFromIndex(to_index, kind, mode); | 2093 ElementOffsetFromIndex(from_index, from_kind, mode, header_size); |
2093 Node* byte_count = ElementOffsetFromIndex(character_count, kind, mode); | 2094 Node* to_offset = |
| 2095 ElementOffsetFromIndex(to_index, to_kind, mode, header_size); |
| 2096 Node* byte_count = ElementOffsetFromIndex(character_count, from_kind, mode); |
2094 Node* limit_offset = IntPtrAddFoldConstants(from_offset, byte_count); | 2097 Node* limit_offset = IntPtrAddFoldConstants(from_offset, byte_count); |
2095 | 2098 |
2096 // Prepare the fast loop | 2099 // Prepare the fast loop |
2097 MachineType type = one_byte ? MachineType::Uint8() : MachineType::Uint16(); | 2100 MachineType type = |
2098 MachineRepresentation rep = | 2101 from_one_byte ? MachineType::Uint8() : MachineType::Uint16(); |
2099 one_byte ? MachineRepresentation::kWord8 : MachineRepresentation::kWord16; | 2102 MachineRepresentation rep = to_one_byte ? MachineRepresentation::kWord8 |
2100 int increment = -(1 << ElementsKindToShiftSize(kind)); | 2103 : MachineRepresentation::kWord16; |
| 2104 int from_increment = 1 << ElementsKindToShiftSize(from_kind); |
| 2105 int to_increment = 1 << ElementsKindToShiftSize(to_kind); |
2101 | 2106 |
2102 Node* to_string_adjusted = IntPtrAddFoldConstants( | 2107 Variable current_to_offset(this, MachineType::PointerRepresentation()); |
2103 to_string, IntPtrSubFoldConstants(to_offset, from_offset)); | 2108 VariableList vars({¤t_to_offset}, zone()); |
2104 limit_offset = | 2109 current_to_offset.Bind(to_offset); |
2105 IntPtrAddFoldConstants(limit_offset, IntPtrConstant(header_size)); | 2110 int to_index_constant = 0, from_index_constant = 0; |
2106 from_offset = | 2111 Smi* to_index_smi = nullptr; |
2107 IntPtrAddFoldConstants(from_offset, IntPtrConstant(header_size)); | 2112 Smi* from_index_smi = nullptr; |
2108 | 2113 bool index_same = (from_encoding == to_encoding) && |
2109 BuildFastLoop(MachineType::PointerRepresentation(), limit_offset, from_offset, | 2114 (from_index == to_index || |
2110 [from_string, to_string_adjusted, type, rep]( | 2115 (ToInt32Constant(from_index, from_index_constant) && |
2111 CodeStubAssembler* assembler, Node* offset) { | 2116 ToInt32Constant(to_index, to_index_constant) && |
| 2117 from_index_constant == to_index_constant) || |
| 2118 (ToSmiConstant(from_index, from_index_smi) && |
| 2119 ToSmiConstant(to_index, to_index_smi) && |
| 2120 to_index_smi == from_index_smi)); |
| 2121 BuildFastLoop(vars, MachineType::PointerRepresentation(), from_offset, |
| 2122 limit_offset, |
| 2123 [from_string, to_string, ¤t_to_offset, to_increment, type, |
| 2124 rep, index_same](CodeStubAssembler* assembler, Node* offset) { |
2112 Node* value = assembler->Load(type, from_string, offset); | 2125 Node* value = assembler->Load(type, from_string, offset); |
2113 assembler->StoreNoWriteBarrier(rep, to_string_adjusted, | 2126 assembler->StoreNoWriteBarrier( |
2114 offset, value); | 2127 rep, to_string, |
| 2128 index_same ? offset : current_to_offset.value(), value); |
| 2129 if (!index_same) { |
| 2130 current_to_offset.Bind(assembler->IntPtrAdd( |
| 2131 current_to_offset.value(), |
| 2132 assembler->IntPtrConstant(to_increment))); |
| 2133 } |
2115 }, | 2134 }, |
2116 increment); | 2135 from_increment, IndexAdvanceMode::kPost); |
2117 } | 2136 } |
2118 | 2137 |
2119 Node* CodeStubAssembler::LoadElementAndPrepareForStore(Node* array, | 2138 Node* CodeStubAssembler::LoadElementAndPrepareForStore(Node* array, |
2120 Node* offset, | 2139 Node* offset, |
2121 ElementsKind from_kind, | 2140 ElementsKind from_kind, |
2122 ElementsKind to_kind, | 2141 ElementsKind to_kind, |
2123 Label* if_hole) { | 2142 Label* if_hole) { |
2124 if (IsFastDoubleElementsKind(from_kind)) { | 2143 if (IsFastDoubleElementsKind(from_kind)) { |
2125 Node* value = | 2144 Node* value = |
2126 LoadDoubleWithHoleCheck(array, offset, if_hole, MachineType::Float64()); | 2145 LoadDoubleWithHoleCheck(array, offset, if_hole, MachineType::Float64()); |
(...skipping 849 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2976 a->Int32Constant(kStringEncodingMask)), | 2995 a->Int32Constant(kStringEncodingMask)), |
2977 a->Int32Constant(0)), | 2996 a->Int32Constant(0)), |
2978 &two_byte_sequential); | 2997 &two_byte_sequential); |
2979 | 2998 |
2980 // The subject string is a sequential one-byte string. | 2999 // The subject string is a sequential one-byte string. |
2981 { | 3000 { |
2982 Node* result = | 3001 Node* result = |
2983 a->AllocateSeqOneByteString(context, a->SmiToWord(character_count)); | 3002 a->AllocateSeqOneByteString(context, a->SmiToWord(character_count)); |
2984 a->CopyStringCharacters(from, result, from_index, smi_zero, character_count, | 3003 a->CopyStringCharacters(from, result, from_index, smi_zero, character_count, |
2985 String::ONE_BYTE_ENCODING, | 3004 String::ONE_BYTE_ENCODING, |
| 3005 String::ONE_BYTE_ENCODING, |
2986 CodeStubAssembler::SMI_PARAMETERS); | 3006 CodeStubAssembler::SMI_PARAMETERS); |
2987 var_result.Bind(result); | 3007 var_result.Bind(result); |
2988 | 3008 |
2989 a->Goto(&end); | 3009 a->Goto(&end); |
2990 } | 3010 } |
2991 | 3011 |
2992 // The subject string is a sequential two-byte string. | 3012 // The subject string is a sequential two-byte string. |
2993 a->Bind(&two_byte_sequential); | 3013 a->Bind(&two_byte_sequential); |
2994 { | 3014 { |
2995 Node* result = | 3015 Node* result = |
2996 a->AllocateSeqTwoByteString(context, a->SmiToWord(character_count)); | 3016 a->AllocateSeqTwoByteString(context, a->SmiToWord(character_count)); |
2997 a->CopyStringCharacters(from, result, from_index, smi_zero, character_count, | 3017 a->CopyStringCharacters(from, result, from_index, smi_zero, character_count, |
2998 String::TWO_BYTE_ENCODING, | 3018 String::TWO_BYTE_ENCODING, |
| 3019 String::TWO_BYTE_ENCODING, |
2999 CodeStubAssembler::SMI_PARAMETERS); | 3020 CodeStubAssembler::SMI_PARAMETERS); |
3000 var_result.Bind(result); | 3021 var_result.Bind(result); |
3001 | 3022 |
3002 a->Goto(&end); | 3023 a->Goto(&end); |
3003 } | 3024 } |
3004 | 3025 |
3005 a->Bind(&end); | 3026 a->Bind(&end); |
3006 return var_result.value(); | 3027 return var_result.value(); |
3007 } | 3028 } |
3008 | 3029 |
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3290 Label two_byte(this); | 3311 Label two_byte(this); |
3291 GotoIf(WordEqual( | 3312 GotoIf(WordEqual( |
3292 WordAnd(ored_instance_types, IntPtrConstant(kStringEncodingMask)), | 3313 WordAnd(ored_instance_types, IntPtrConstant(kStringEncodingMask)), |
3293 IntPtrConstant(kTwoByteStringTag)), | 3314 IntPtrConstant(kTwoByteStringTag)), |
3294 &two_byte); | 3315 &two_byte); |
3295 // One-byte sequential string case | 3316 // One-byte sequential string case |
3296 Node* new_string = | 3317 Node* new_string = |
3297 AllocateSeqOneByteString(context, new_length, SMI_PARAMETERS); | 3318 AllocateSeqOneByteString(context, new_length, SMI_PARAMETERS); |
3298 CopyStringCharacters(left, new_string, SmiConstant(Smi::kZero), | 3319 CopyStringCharacters(left, new_string, SmiConstant(Smi::kZero), |
3299 SmiConstant(Smi::kZero), left_length, | 3320 SmiConstant(Smi::kZero), left_length, |
| 3321 String::ONE_BYTE_ENCODING, String::ONE_BYTE_ENCODING, |
| 3322 SMI_PARAMETERS); |
| 3323 CopyStringCharacters(right, new_string, SmiConstant(Smi::kZero), left_length, |
| 3324 right_length, String::ONE_BYTE_ENCODING, |
3300 String::ONE_BYTE_ENCODING, SMI_PARAMETERS); | 3325 String::ONE_BYTE_ENCODING, SMI_PARAMETERS); |
3301 CopyStringCharacters(right, new_string, SmiConstant(Smi::kZero), left_length, | |
3302 right_length, String::ONE_BYTE_ENCODING, SMI_PARAMETERS); | |
3303 result.Bind(new_string); | 3326 result.Bind(new_string); |
3304 Goto(&done_native); | 3327 Goto(&done_native); |
3305 | 3328 |
3306 Bind(&two_byte); | 3329 Bind(&two_byte); |
3307 { | 3330 { |
3308 // Two-byte sequential string case | 3331 // Two-byte sequential string case |
3309 new_string = AllocateSeqTwoByteString(context, new_length, SMI_PARAMETERS); | 3332 new_string = AllocateSeqTwoByteString(context, new_length, SMI_PARAMETERS); |
3310 CopyStringCharacters(left, new_string, SmiConstant(Smi::kZero), | 3333 CopyStringCharacters(left, new_string, SmiConstant(Smi::kZero), |
3311 SmiConstant(Smi::kZero), left_length, | 3334 SmiConstant(Smi::kZero), left_length, |
3312 String::TWO_BYTE_ENCODING, SMI_PARAMETERS); | 3335 String::TWO_BYTE_ENCODING, String::TWO_BYTE_ENCODING, |
| 3336 SMI_PARAMETERS); |
3313 CopyStringCharacters(right, new_string, SmiConstant(Smi::kZero), | 3337 CopyStringCharacters(right, new_string, SmiConstant(Smi::kZero), |
3314 left_length, right_length, String::TWO_BYTE_ENCODING, | 3338 left_length, right_length, String::TWO_BYTE_ENCODING, |
3315 SMI_PARAMETERS); | 3339 String::TWO_BYTE_ENCODING, SMI_PARAMETERS); |
3316 result.Bind(new_string); | 3340 result.Bind(new_string); |
3317 Goto(&done_native); | 3341 Goto(&done_native); |
3318 } | 3342 } |
3319 | 3343 |
3320 Bind(&runtime); | 3344 Bind(&runtime); |
3321 { | 3345 { |
3322 result.Bind(CallRuntime(Runtime::kStringAdd, context, left, right)); | 3346 result.Bind(CallRuntime(Runtime::kStringAdd, context, left, right)); |
3323 Goto(&done); | 3347 Goto(&done); |
3324 } | 3348 } |
3325 | 3349 |
(...skipping 3631 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6957 StoreObjectFieldRoot(cell, WeakCell::kNextOffset, | 6981 StoreObjectFieldRoot(cell, WeakCell::kNextOffset, |
6958 Heap::kTheHoleValueRootIndex); | 6982 Heap::kTheHoleValueRootIndex); |
6959 | 6983 |
6960 // Store the WeakCell in the feedback vector. | 6984 // Store the WeakCell in the feedback vector. |
6961 StoreFixedArrayElement(feedback_vector, slot, cell, UPDATE_WRITE_BARRIER, | 6985 StoreFixedArrayElement(feedback_vector, slot, cell, UPDATE_WRITE_BARRIER, |
6962 CodeStubAssembler::SMI_PARAMETERS); | 6986 CodeStubAssembler::SMI_PARAMETERS); |
6963 return cell; | 6987 return cell; |
6964 } | 6988 } |
6965 | 6989 |
6966 void CodeStubAssembler::BuildFastLoop( | 6990 void CodeStubAssembler::BuildFastLoop( |
| 6991 const CodeStubAssembler::VariableList& vars, |
6967 MachineRepresentation index_rep, Node* start_index, Node* end_index, | 6992 MachineRepresentation index_rep, Node* start_index, Node* end_index, |
6968 std::function<void(CodeStubAssembler* assembler, Node* index)> body, | 6993 std::function<void(CodeStubAssembler* assembler, Node* index)> body, |
6969 int increment, IndexAdvanceMode mode) { | 6994 int increment, IndexAdvanceMode mode) { |
6970 Variable var(this, index_rep); | 6995 Variable var(this, index_rep); |
| 6996 VariableList vars_copy(vars, zone()); |
| 6997 vars_copy.Add(&var, zone()); |
6971 var.Bind(start_index); | 6998 var.Bind(start_index); |
6972 Label loop(this, &var); | 6999 Label loop(this, vars_copy); |
6973 Label after_loop(this); | 7000 Label after_loop(this); |
6974 // Introduce an explicit second check of the termination condition before the | 7001 // Introduce an explicit second check of the termination condition before the |
6975 // loop that helps turbofan generate better code. If there's only a single | 7002 // loop that helps turbofan generate better code. If there's only a single |
6976 // check, then the CodeStubAssembler forces it to be at the beginning of the | 7003 // check, then the CodeStubAssembler forces it to be at the beginning of the |
6977 // loop requiring a backwards branch at the end of the loop (it's not possible | 7004 // loop requiring a backwards branch at the end of the loop (it's not possible |
6978 // to force the loop header check at the end of the loop and branch forward to | 7005 // to force the loop header check at the end of the loop and branch forward to |
6979 // it from the pre-header). The extra branch is slower in the case that the | 7006 // it from the pre-header). The extra branch is slower in the case that the |
6980 // loop actually iterates. | 7007 // loop actually iterates. |
6981 Branch(WordEqual(var.value(), end_index), &after_loop, &loop); | 7008 Branch(WordEqual(var.value(), end_index), &after_loop, &loop); |
6982 Bind(&loop); | 7009 Bind(&loop); |
(...skipping 1741 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8724 Node* buffer_bit_field = LoadObjectField( | 8751 Node* buffer_bit_field = LoadObjectField( |
8725 buffer, JSArrayBuffer::kBitFieldOffset, MachineType::Uint32()); | 8752 buffer, JSArrayBuffer::kBitFieldOffset, MachineType::Uint32()); |
8726 Node* was_neutered_mask = Int32Constant(JSArrayBuffer::WasNeutered::kMask); | 8753 Node* was_neutered_mask = Int32Constant(JSArrayBuffer::WasNeutered::kMask); |
8727 | 8754 |
8728 return Word32NotEqual(Word32And(buffer_bit_field, was_neutered_mask), | 8755 return Word32NotEqual(Word32And(buffer_bit_field, was_neutered_mask), |
8729 Int32Constant(0)); | 8756 Int32Constant(0)); |
8730 } | 8757 } |
8731 | 8758 |
8732 } // namespace internal | 8759 } // namespace internal |
8733 } // namespace v8 | 8760 } // namespace v8 |
OLD | NEW |