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

Side by Side Diff: src/builtins/builtins-string.cc

Issue 2382013002: [builtins] don't pre-flatten strings for JSStringIterator (Closed)
Patch Set: Also fix JSStringIteratorVerify() Created 4 years, 2 months 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 | « no previous file | src/objects-debug.cc » ('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 4
5 #include "src/builtins/builtins.h" 5 #include "src/builtins/builtins.h"
6 #include "src/builtins/builtins-utils.h" 6 #include "src/builtins/builtins-utils.h"
7 7
8 #include "src/code-factory.h" 8 #include "src/code-factory.h"
9 9
10 namespace v8 { 10 namespace v8 {
(...skipping 1011 matching lines...) Expand 10 before | Expand all | Expand 10 after
1022 1022
1023 Node* receiver = assembler->Parameter(0); 1023 Node* receiver = assembler->Parameter(0);
1024 Node* context = assembler->Parameter(3); 1024 Node* context = assembler->Parameter(3);
1025 1025
1026 Node* result = assembler->ToThisValue( 1026 Node* result = assembler->ToThisValue(
1027 context, receiver, PrimitiveType::kString, "String.prototype.valueOf"); 1027 context, receiver, PrimitiveType::kString, "String.prototype.valueOf");
1028 assembler->Return(result); 1028 assembler->Return(result);
1029 } 1029 }
1030 1030
1031 void Builtins::Generate_StringPrototypeIterator(CodeStubAssembler* assembler) { 1031 void Builtins::Generate_StringPrototypeIterator(CodeStubAssembler* assembler) {
1032 typedef CodeStubAssembler::Label Label;
1033 typedef compiler::Node Node; 1032 typedef compiler::Node Node;
1034 typedef CodeStubAssembler::Variable Variable;
1035
1036 Variable var_string(assembler, MachineRepresentation::kTagged);
1037 Variable var_index(assembler, MachineRepresentation::kTagged);
1038
1039 Variable* loop_inputs[] = {&var_string, &var_index};
1040 Label loop(assembler, 2, loop_inputs);
1041 Label allocate_iterator(assembler);
1042 1033
1043 Node* receiver = assembler->Parameter(0); 1034 Node* receiver = assembler->Parameter(0);
1044 Node* context = assembler->Parameter(3); 1035 Node* context = assembler->Parameter(3);
1045 1036
1046 var_string.Bind(assembler->ToThisString(context, receiver, 1037 Node* string = assembler->ToThisString(context, receiver,
1047 "String.prototype[Symbol.iterator]")); 1038 "String.prototype[Symbol.iterator]");
1048 var_index.Bind(assembler->SmiConstant(Smi::FromInt(0)));
1049 1039
1050 assembler->Goto(&loop); 1040 Node* native_context = assembler->LoadNativeContext(context);
1051 assembler->Bind(&loop); 1041 Node* map = assembler->LoadFixedArrayElement(
1052 { 1042 native_context,
1053 Node* string = var_string.value(); 1043 assembler->IntPtrConstant(Context::STRING_ITERATOR_MAP_INDEX), 0,
1054 // Load the instance type of the {string}. 1044 CodeStubAssembler::INTPTR_PARAMETERS);
1055 Node* string_instance_type = assembler->LoadInstanceType(string); 1045 Node* iterator = assembler->Allocate(JSStringIterator::kSize);
1056 1046 assembler->StoreMapNoWriteBarrier(iterator, map);
1057 // Check if the {string} is a SeqString. 1047 assembler->StoreObjectFieldRoot(iterator, JSValue::kPropertiesOffset,
1058 Label if_stringisnotsequential(assembler); 1048 Heap::kEmptyFixedArrayRootIndex);
1059 assembler->Branch(assembler->Word32Equal( 1049 assembler->StoreObjectFieldRoot(iterator, JSObject::kElementsOffset,
1060 assembler->Word32And(string_instance_type, 1050 Heap::kEmptyFixedArrayRootIndex);
1061 assembler->Int32Constant( 1051 assembler->StoreObjectFieldNoWriteBarrier(
1062 kStringRepresentationMask)), 1052 iterator, JSStringIterator::kStringOffset, string);
1063 assembler->Int32Constant(kSeqStringTag)), 1053 Node* index = assembler->SmiConstant(Smi::FromInt(0));
1064 &allocate_iterator, &if_stringisnotsequential); 1054 assembler->StoreObjectFieldNoWriteBarrier(
1065 1055 iterator, JSStringIterator::kNextIndexOffset, index);
1066 assembler->Bind(&if_stringisnotsequential); 1056 assembler->Return(iterator);
1067 {
1068 // Check if the {string} is a ConsString.
1069 Label if_stringiscons(assembler), if_stringisnotcons(assembler);
1070 assembler->Branch(
1071 assembler->Word32Equal(
1072 assembler->Word32And(
1073 string_instance_type,
1074 assembler->Int32Constant(kStringRepresentationMask)),
1075 assembler->Int32Constant(kConsStringTag)),
1076 &if_stringiscons, &if_stringisnotcons);
1077
1078 assembler->Bind(&if_stringiscons);
1079 {
1080 // Flatten cons-string and finish.
1081 var_string.Bind(assembler->CallRuntime(
1082 Runtime::kFlattenString, assembler->NoContextConstant(), string));
1083 assembler->Goto(&allocate_iterator);
1084 }
1085
1086 assembler->Bind(&if_stringisnotcons);
1087 {
1088 // Check if the {string} is an ExternalString.
1089 Label if_stringisnotexternal(assembler);
1090 assembler->Branch(
1091 assembler->Word32Equal(
1092 assembler->Word32And(
1093 string_instance_type,
1094 assembler->Int32Constant(kStringRepresentationMask)),
1095 assembler->Int32Constant(kExternalStringTag)),
1096 &allocate_iterator, &if_stringisnotexternal);
1097
1098 assembler->Bind(&if_stringisnotexternal);
1099 {
1100 // The {string} is a SlicedString, continue with its parent.
1101 Node* index = var_index.value();
1102 Node* string_offset =
1103 assembler->LoadObjectField(string, SlicedString::kOffsetOffset);
1104 Node* string_parent =
1105 assembler->LoadObjectField(string, SlicedString::kParentOffset);
1106 var_index.Bind(assembler->SmiAdd(index, string_offset));
1107 var_string.Bind(string_parent);
1108 assembler->Goto(&loop);
1109 }
1110 }
1111 }
1112 }
1113
1114 assembler->Bind(&allocate_iterator);
1115 {
1116 Node* native_context = assembler->LoadNativeContext(context);
1117 Node* map = assembler->LoadFixedArrayElement(
1118 native_context,
1119 assembler->IntPtrConstant(Context::STRING_ITERATOR_MAP_INDEX), 0,
1120 CodeStubAssembler::INTPTR_PARAMETERS);
1121 Node* iterator = assembler->Allocate(JSStringIterator::kSize);
1122 assembler->StoreMapNoWriteBarrier(iterator, map);
1123 assembler->StoreObjectFieldRoot(iterator, JSValue::kPropertiesOffset,
1124 Heap::kEmptyFixedArrayRootIndex);
1125 assembler->StoreObjectFieldRoot(iterator, JSObject::kElementsOffset,
1126 Heap::kEmptyFixedArrayRootIndex);
1127 assembler->StoreObjectFieldNoWriteBarrier(
1128 iterator, JSStringIterator::kStringOffset, var_string.value());
1129
1130 assembler->StoreObjectFieldNoWriteBarrier(
1131 iterator, JSStringIterator::kNextIndexOffset, var_index.value());
1132 assembler->Return(iterator);
1133 }
1134 } 1057 }
1135 1058
1136 namespace { 1059 namespace {
1137 1060
1138 // Return the |word32| codepoint at {index}. Supports SeqStrings and 1061 // Return the |word32| codepoint at {index}. Supports SeqStrings and
1139 // ExternalStrings. 1062 // ExternalStrings.
1140 compiler::Node* LoadSurrogatePairInternal(CodeStubAssembler* assembler, 1063 compiler::Node* LoadSurrogatePairInternal(CodeStubAssembler* assembler,
1141 compiler::Node* string, 1064 compiler::Node* string,
1142 compiler::Node* length, 1065 compiler::Node* length,
1143 compiler::Node* index, 1066 compiler::Node* index,
1144 UnicodeEncoding encoding) { 1067 UnicodeEncoding encoding) {
1145 typedef CodeStubAssembler::Label Label; 1068 typedef CodeStubAssembler::Label Label;
1146 typedef compiler::Node Node; 1069 typedef compiler::Node Node;
1147 typedef CodeStubAssembler::Variable Variable; 1070 typedef CodeStubAssembler::Variable Variable;
1148 Label handle_surrogate_pair(assembler), return_result(assembler); 1071 Label handle_surrogate_pair(assembler), return_result(assembler);
1149 Variable var_result(assembler, MachineRepresentation::kWord32); 1072 Variable var_result(assembler, MachineRepresentation::kWord32);
1150 Variable var_trail(assembler, MachineRepresentation::kWord16); 1073 Variable var_trail(assembler, MachineRepresentation::kWord16);
1151 var_result.Bind(assembler->Int32Constant(0)); 1074 var_result.Bind(assembler->StringCharCodeAt(string, index));
1152 var_trail.Bind(assembler->Int32Constant(0)); 1075 var_trail.Bind(assembler->Int32Constant(0));
1153 1076
1154 Node* string_instance_type = assembler->LoadInstanceType(string); 1077 assembler->GotoIf(assembler->Word32NotEqual(
1078 assembler->Word32And(var_result.value(),
1079 assembler->Int32Constant(0xFC00)),
1080 assembler->Int32Constant(0xD800)),
1081 &return_result);
1082 Node* next_index =
1083 assembler->SmiAdd(index, assembler->SmiConstant(Smi::FromInt(1)));
1155 1084
1156 Label if_stringissequential(assembler), if_stringisexternal(assembler); 1085 assembler->GotoUnless(assembler->SmiLessThan(next_index, length),
1086 &return_result);
1087 var_trail.Bind(assembler->StringCharCodeAt(string, next_index));
1157 assembler->Branch(assembler->Word32Equal( 1088 assembler->Branch(assembler->Word32Equal(
1158 assembler->Word32And(string_instance_type, 1089 assembler->Word32And(var_trail.value(),
1159 assembler->Int32Constant( 1090 assembler->Int32Constant(0xFC00)),
1160 kStringRepresentationMask)), 1091 assembler->Int32Constant(0xDC00)),
1161 assembler->Int32Constant(kSeqStringTag)), 1092 &handle_surrogate_pair, &return_result);
1162 &if_stringissequential, &if_stringisexternal);
1163
1164 assembler->Bind(&if_stringissequential);
1165 {
1166 Label if_stringisonebyte(assembler), if_stringistwobyte(assembler);
1167 assembler->Branch(
1168 assembler->Word32Equal(
1169 assembler->Word32And(string_instance_type,
1170 assembler->Int32Constant(kStringEncodingMask)),
1171 assembler->Int32Constant(kOneByteStringTag)),
1172 &if_stringisonebyte, &if_stringistwobyte);
1173
1174 assembler->Bind(&if_stringisonebyte);
1175 {
1176 var_result.Bind(assembler->Load(
1177 MachineType::Uint8(), string,
1178 assembler->IntPtrAdd(
1179 index, assembler->IntPtrConstant(SeqOneByteString::kHeaderSize -
1180 kHeapObjectTag))));
1181 assembler->Goto(&return_result);
1182 }
1183
1184 assembler->Bind(&if_stringistwobyte);
1185 {
1186 Node* lead = assembler->Load(
1187 MachineType::Uint16(), string,
1188 assembler->IntPtrAdd(
1189 assembler->WordShl(index, assembler->IntPtrConstant(1)),
1190 assembler->IntPtrConstant(SeqTwoByteString::kHeaderSize -
1191 kHeapObjectTag)));
1192 var_result.Bind(lead);
1193 Node* next_pos = assembler->Int32Add(index, assembler->Int32Constant(1));
1194
1195 Label if_isdoublecodeunit(assembler);
1196 assembler->GotoIf(assembler->Int32GreaterThanOrEqual(next_pos, length),
1197 &return_result);
1198 assembler->GotoIf(
1199 assembler->Uint32LessThan(lead, assembler->Int32Constant(0xD800)),
1200 &return_result);
1201 assembler->Branch(
1202 assembler->Uint32LessThan(lead, assembler->Int32Constant(0xDC00)),
1203 &if_isdoublecodeunit, &return_result);
1204
1205 assembler->Bind(&if_isdoublecodeunit);
1206 {
1207 Node* trail = assembler->Load(
1208 MachineType::Uint16(), string,
1209 assembler->IntPtrAdd(
1210 assembler->WordShl(next_pos, assembler->IntPtrConstant(1)),
1211 assembler->IntPtrConstant(SeqTwoByteString::kHeaderSize -
1212 kHeapObjectTag)));
1213 assembler->GotoIf(
1214 assembler->Uint32LessThan(trail, assembler->Int32Constant(0xDC00)),
1215 &return_result);
1216 assembler->GotoIf(assembler->Uint32GreaterThanOrEqual(
1217 trail, assembler->Int32Constant(0xE000)),
1218 &return_result);
1219
1220 var_trail.Bind(trail);
1221 assembler->Goto(&handle_surrogate_pair);
1222 }
1223 }
1224 }
1225
1226 assembler->Bind(&if_stringisexternal);
1227 {
1228 assembler->Assert(assembler->Word32Equal(
1229 assembler->Word32And(
1230 string_instance_type,
1231 assembler->Int32Constant(kStringRepresentationMask)),
1232 assembler->Int32Constant(kExternalStringTag)));
1233 Label if_stringisshort(assembler), if_stringisnotshort(assembler);
1234
1235 assembler->Branch(assembler->Word32Equal(
1236 assembler->Word32And(string_instance_type,
1237 assembler->Int32Constant(
1238 kShortExternalStringMask)),
1239 assembler->Int32Constant(0)),
1240 &if_stringisshort, &if_stringisnotshort);
1241
1242 assembler->Bind(&if_stringisshort);
1243 {
1244 // Load the actual resource data from the {string}.
1245 Node* string_resource_data = assembler->LoadObjectField(
1246 string, ExternalString::kResourceDataOffset, MachineType::Pointer());
1247
1248 Label if_stringistwobyte(assembler), if_stringisonebyte(assembler);
1249 assembler->Branch(assembler->Word32Equal(
1250 assembler->Word32And(
1251 string_instance_type,
1252 assembler->Int32Constant(kStringEncodingMask)),
1253 assembler->Int32Constant(kTwoByteStringTag)),
1254 &if_stringistwobyte, &if_stringisonebyte);
1255
1256 assembler->Bind(&if_stringisonebyte);
1257 {
1258 var_result.Bind(
1259 assembler->Load(MachineType::Uint8(), string_resource_data, index));
1260 assembler->Goto(&return_result);
1261 }
1262
1263 assembler->Bind(&if_stringistwobyte);
1264 {
1265 Label if_isdoublecodeunit(assembler);
1266 Node* lead = assembler->Load(
1267 MachineType::Uint16(), string_resource_data,
1268 assembler->WordShl(index, assembler->IntPtrConstant(1)));
1269 var_result.Bind(lead);
1270 Node* next_pos =
1271 assembler->Int32Add(index, assembler->Int32Constant(1));
1272
1273 assembler->GotoIf(assembler->Int32GreaterThanOrEqual(next_pos, length),
1274 &return_result);
1275 assembler->GotoIf(
1276 assembler->Uint32LessThan(lead, assembler->Int32Constant(0xD800)),
1277 &return_result);
1278 assembler->Branch(
1279 assembler->Uint32LessThan(lead, assembler->Int32Constant(0xDC00)),
1280 &if_isdoublecodeunit, &return_result);
1281
1282 assembler->Bind(&if_isdoublecodeunit);
1283 {
1284 Node* trail = assembler->Load(
1285 MachineType::Uint16(), string,
1286 assembler->IntPtrAdd(
1287 assembler->WordShl(next_pos, assembler->IntPtrConstant(1)),
1288 assembler->IntPtrConstant(SeqTwoByteString::kHeaderSize -
1289 kHeapObjectTag)));
1290 assembler->GotoIf(assembler->Uint32LessThan(
1291 trail, assembler->Int32Constant(0xDC00)),
1292 &return_result);
1293 assembler->GotoIf(assembler->Uint32GreaterThanOrEqual(
1294 trail, assembler->Int32Constant(0xE000)),
1295 &return_result);
1296
1297 var_trail.Bind(trail);
1298 assembler->Goto(&handle_surrogate_pair);
1299 }
1300 }
1301 }
1302
1303 assembler->Bind(&if_stringisnotshort);
1304 {
1305 Label if_isdoublecodeunit(assembler);
1306 Node* lead = assembler->SmiToWord32(assembler->CallRuntime(
1307 Runtime::kExternalStringGetChar, assembler->NoContextConstant(),
1308 string, assembler->SmiTag(index)));
1309 var_result.Bind(lead);
1310 Node* next_pos = assembler->Int32Add(index, assembler->Int32Constant(1));
1311
1312 assembler->GotoIf(assembler->Int32GreaterThanOrEqual(next_pos, length),
1313 &return_result);
1314 assembler->GotoIf(
1315 assembler->Uint32LessThan(lead, assembler->Int32Constant(0xD800)),
1316 &return_result);
1317 assembler->Branch(assembler->Uint32GreaterThanOrEqual(
1318 lead, assembler->Int32Constant(0xDC00)),
1319 &return_result, &if_isdoublecodeunit);
1320
1321 assembler->Bind(&if_isdoublecodeunit);
1322 {
1323 Node* trail = assembler->SmiToWord32(assembler->CallRuntime(
1324 Runtime::kExternalStringGetChar, assembler->NoContextConstant(),
1325 string, assembler->SmiTag(next_pos)));
1326 assembler->GotoIf(
1327 assembler->Uint32LessThan(trail, assembler->Int32Constant(0xDC00)),
1328 &return_result);
1329 assembler->GotoIf(assembler->Uint32GreaterThanOrEqual(
1330 trail, assembler->Int32Constant(0xE000)),
1331 &return_result);
1332 var_trail.Bind(trail);
1333 assembler->Goto(&handle_surrogate_pair);
1334 }
1335 }
1336 }
1337 1093
1338 assembler->Bind(&handle_surrogate_pair); 1094 assembler->Bind(&handle_surrogate_pair);
1339 { 1095 {
1340 Node* lead = var_result.value(); 1096 Node* lead = var_result.value();
1341 Node* trail = var_trail.value(); 1097 Node* trail = var_trail.value();
1342 #ifdef ENABLE_SLOW_DCHECKS 1098 #ifdef ENABLE_SLOW_DCHECKS
1343 // Check that this path is only taken if a surrogate pair is found 1099 // Check that this path is only taken if a surrogate pair is found
1344 assembler->Assert(assembler->Uint32GreaterThanOrEqual( 1100 assembler->Assert(assembler->Uint32GreaterThanOrEqual(
1345 lead, assembler->Int32Constant(0xD800))); 1101 lead, assembler->Int32Constant(0xD800)));
1346 assembler->Assert( 1102 assembler->Assert(
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
1415 assembler->LoadObjectField(iterator, JSStringIterator::kStringOffset); 1171 assembler->LoadObjectField(iterator, JSStringIterator::kStringOffset);
1416 Node* position = 1172 Node* position =
1417 assembler->LoadObjectField(iterator, JSStringIterator::kNextIndexOffset); 1173 assembler->LoadObjectField(iterator, JSStringIterator::kNextIndexOffset);
1418 Node* length = assembler->LoadObjectField(string, String::kLengthOffset); 1174 Node* length = assembler->LoadObjectField(string, String::kLengthOffset);
1419 1175
1420 assembler->Branch(assembler->SmiLessThan(position, length), &next_codepoint, 1176 assembler->Branch(assembler->SmiLessThan(position, length), &next_codepoint,
1421 &return_result); 1177 &return_result);
1422 1178
1423 assembler->Bind(&next_codepoint); 1179 assembler->Bind(&next_codepoint);
1424 { 1180 {
1425 Node* ch = 1181 Node* ch = LoadSurrogatePairAt(assembler, string, length, position);
1426 LoadSurrogatePairAt(assembler, string, assembler->SmiUntag(length),
1427 assembler->SmiUntag(position));
1428 Node* value = assembler->StringFromCodePoint(ch, UnicodeEncoding::UTF16); 1182 Node* value = assembler->StringFromCodePoint(ch, UnicodeEncoding::UTF16);
1429 var_value.Bind(value); 1183 var_value.Bind(value);
1430 Node* length = assembler->LoadObjectField(value, String::kLengthOffset); 1184 Node* length = assembler->LoadObjectField(value, String::kLengthOffset);
1431 assembler->StoreObjectFieldNoWriteBarrier( 1185 assembler->StoreObjectFieldNoWriteBarrier(
1432 iterator, JSStringIterator::kNextIndexOffset, 1186 iterator, JSStringIterator::kNextIndexOffset,
1433 assembler->SmiAdd(position, length)); 1187 assembler->SmiAdd(position, length));
1434 var_done.Bind(assembler->BooleanConstant(false)); 1188 var_done.Bind(assembler->BooleanConstant(false));
1435 assembler->Goto(&return_result); 1189 assembler->Goto(&return_result);
1436 } 1190 }
1437 1191
(...skipping 24 matching lines...) Expand all
1462 Runtime::kThrowIncompatibleMethodReceiver, context, 1216 Runtime::kThrowIncompatibleMethodReceiver, context,
1463 assembler->HeapConstant(assembler->factory()->NewStringFromAsciiChecked( 1217 assembler->HeapConstant(assembler->factory()->NewStringFromAsciiChecked(
1464 "String Iterator.prototype.next", TENURED)), 1218 "String Iterator.prototype.next", TENURED)),
1465 iterator); 1219 iterator);
1466 assembler->Return(result); // Never reached. 1220 assembler->Return(result); // Never reached.
1467 } 1221 }
1468 } 1222 }
1469 1223
1470 } // namespace internal 1224 } // namespace internal
1471 } // namespace v8 1225 } // namespace v8
OLDNEW
« no previous file with comments | « no previous file | src/objects-debug.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698