Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(28)

Side by Side Diff: src/code-stub-assembler.cc

Issue 2461363002: [stubs]: Support 1->2 byte copies in CopyStringCharacters (Closed)
Patch Set: Review feedback Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/code-stub-assembler.h ('k') | src/compiler/code-assembler.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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({&current_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, &current_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
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
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
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
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
OLDNEW
« no previous file with comments | « src/code-stub-assembler.h ('k') | src/compiler/code-assembler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698