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

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

Issue 2532403002: [regexp] Migrate @@split to TurboFan (Closed)
Patch Set: Fix compilation errors Created 4 years 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/builtins/builtins.h ('k') | src/code-stub-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 4
5 #include "src/builtins/builtins-utils.h" 5 #include "src/builtins/builtins-utils.h"
6 #include "src/builtins/builtins.h" 6 #include "src/builtins/builtins.h"
7 7
8 #include "src/code-factory.h" 8 #include "src/code-factory.h"
9 #include "src/regexp/jsregexp.h" 9 #include "src/regexp/jsregexp.h"
10 #include "src/regexp/regexp-utils.h" 10 #include "src/regexp/regexp-utils.h"
11 #include "src/string-builder.h" 11 #include "src/string-builder.h"
12 12
13 namespace v8 { 13 namespace v8 {
14 namespace internal { 14 namespace internal {
15 15
16 typedef compiler::Node Node; 16 typedef compiler::Node Node;
17 typedef CodeStubAssembler::Label CLabel; 17 typedef CodeStubAssembler::Label CLabel;
18 typedef CodeStubAssembler::Variable CVariable; 18 typedef CodeStubAssembler::Variable CVariable;
19 typedef CodeStubAssembler::ParameterMode ParameterMode;
19 typedef compiler::CodeAssemblerState CodeAssemblerState; 20 typedef compiler::CodeAssemblerState CodeAssemblerState;
20 21
21 // ----------------------------------------------------------------------------- 22 // -----------------------------------------------------------------------------
22 // ES6 section 21.2 RegExp Objects 23 // ES6 section 21.2 RegExp Objects
23 24
24 namespace { 25 namespace {
25 26
26 Handle<String> PatternFlags(Isolate* isolate, Handle<JSRegExp> regexp) { 27 Handle<String> PatternFlags(Isolate* isolate, Handle<JSRegExp> regexp) {
27 static const int kMaxFlagsLength = 5 + 1; // 5 flags and '\0'; 28 static const int kMaxFlagsLength = 5 + 1; // 5 flags and '\0';
28 char flags_string[kMaxFlagsLength]; 29 char flags_string[kMaxFlagsLength];
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after
252 } 253 }
253 254
254 a->Bind(&out); 255 a->Bind(&out);
255 } 256 }
256 257
257 Node* ConstructNewResultFromMatchInfo(Isolate* isolate, CodeStubAssembler* a, 258 Node* ConstructNewResultFromMatchInfo(Isolate* isolate, CodeStubAssembler* a,
258 Node* context, Node* match_info, 259 Node* context, Node* match_info,
259 Node* string) { 260 Node* string) {
260 CLabel out(a); 261 CLabel out(a);
261 262
262 CodeStubAssembler::ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS; 263 ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS;
263 Node* const num_indices = a->SmiUntag(a->LoadFixedArrayElement( 264 Node* const num_indices = a->SmiUntag(a->LoadFixedArrayElement(
264 match_info, a->IntPtrConstant(RegExpMatchInfo::kNumberOfCapturesIndex), 0, 265 match_info, a->IntPtrConstant(RegExpMatchInfo::kNumberOfCapturesIndex), 0,
265 mode)); 266 mode));
266 Node* const num_results = a->SmiTag(a->WordShr(num_indices, 1)); 267 Node* const num_results = a->SmiTag(a->WordShr(num_indices, 1));
267 Node* const start = a->LoadFixedArrayElement( 268 Node* const start = a->LoadFixedArrayElement(
268 match_info, a->IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex), 0, 269 match_info, a->IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex), 0,
269 mode); 270 mode);
270 Node* const end = a->LoadFixedArrayElement( 271 Node* const end = a->LoadFixedArrayElement(
271 match_info, a->IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex + 1), 0, 272 match_info, a->IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex + 1), 0,
272 mode); 273 mode);
(...skipping 900 matching lines...) Expand 10 before | Expand all | Expand 10 after
1173 Node* length() const { return var_length_.value(); } 1174 Node* length() const { return var_length_.value(); }
1174 1175
1175 CVariable* var_array() { return &var_array_; } 1176 CVariable* var_array() { return &var_array_; }
1176 CVariable* var_length() { return &var_length_; } 1177 CVariable* var_length() { return &var_length_; }
1177 CVariable* var_capacity() { return &var_capacity_; } 1178 CVariable* var_capacity() { return &var_capacity_; }
1178 1179
1179 void Push(Node* const value) { 1180 void Push(Node* const value) {
1180 CodeStubAssembler* a = assembler_; 1181 CodeStubAssembler* a = assembler_;
1181 1182
1182 const WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER; 1183 const WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER;
1183 const CodeStubAssembler::ParameterMode mode = 1184 const ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS;
1184 CodeStubAssembler::INTPTR_PARAMETERS;
1185 1185
1186 Node* const length = var_length_.value(); 1186 Node* const length = var_length_.value();
1187 Node* const capacity = var_capacity_.value(); 1187 Node* const capacity = var_capacity_.value();
1188 1188
1189 CLabel grow(a), store(a); 1189 CLabel grow(a), store(a);
1190 a->Branch(a->IntPtrEqual(capacity, length), &grow, &store); 1190 a->Branch(a->IntPtrEqual(capacity, length), &grow, &store);
1191 1191
1192 a->Bind(&grow); 1192 a->Bind(&grow);
1193 { 1193 {
1194 Node* const new_capacity = NewCapacity(a, capacity); 1194 Node* const new_capacity = NewCapacity(a, capacity);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1226 a->StoreObjectField(result, JSObject::kElementsOffset, var_array_.value()); 1226 a->StoreObjectField(result, JSObject::kElementsOffset, var_array_.value());
1227 1227
1228 return result; 1228 return result;
1229 } 1229 }
1230 1230
1231 private: 1231 private:
1232 void Initialize() { 1232 void Initialize() {
1233 CodeStubAssembler* a = assembler_; 1233 CodeStubAssembler* a = assembler_;
1234 1234
1235 const ElementsKind kind = FAST_ELEMENTS; 1235 const ElementsKind kind = FAST_ELEMENTS;
1236 const CodeStubAssembler::ParameterMode mode = 1236 const ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS;
1237 CodeStubAssembler::INTPTR_PARAMETERS;
1238 1237
1239 static const int kInitialArraySize = 8; 1238 static const int kInitialArraySize = 8;
1240 Node* const capacity = a->IntPtrConstant(kInitialArraySize); 1239 Node* const capacity = a->IntPtrConstant(kInitialArraySize);
1241 Node* const array = a->AllocateFixedArray(kind, capacity, mode); 1240 Node* const array = a->AllocateFixedArray(kind, capacity, mode);
1242 1241
1243 a->FillFixedArrayWithValue(kind, array, a->IntPtrConstant(0), capacity, 1242 a->FillFixedArrayWithValue(kind, array, a->IntPtrConstant(0), capacity,
1244 Heap::kTheHoleValueRootIndex, mode); 1243 Heap::kTheHoleValueRootIndex, mode);
1245 1244
1246 var_array_.Bind(array); 1245 var_array_.Bind(array);
1247 var_capacity_.Bind(capacity); 1246 var_capacity_.Bind(capacity);
1248 var_length_.Bind(a->IntPtrConstant(0)); 1247 var_length_.Bind(a->IntPtrConstant(0));
1249 } 1248 }
1250 1249
1251 Node* NewCapacity(CodeStubAssembler* a, Node* const current_capacity) { 1250 Node* NewCapacity(CodeStubAssembler* a, Node* const current_capacity) {
1252 CSA_ASSERT(a, a->IntPtrGreaterThan(current_capacity, a->IntPtrConstant(0))); 1251 CSA_ASSERT(a, a->IntPtrGreaterThan(current_capacity, a->IntPtrConstant(0)));
1253 1252
1254 // Growth rate is analog to JSObject::NewElementsCapacity: 1253 // Growth rate is analog to JSObject::NewElementsCapacity:
1255 // new_capacity = (current_capacity + (current_capacity >> 1)) + 16. 1254 // new_capacity = (current_capacity + (current_capacity >> 1)) + 16.
1256 1255
1257 Node* const new_capacity = a->IntPtrAdd( 1256 Node* const new_capacity = a->IntPtrAdd(
1258 a->IntPtrAdd(current_capacity, a->WordShr(current_capacity, 1)), 1257 a->IntPtrAdd(current_capacity, a->WordShr(current_capacity, 1)),
1259 a->IntPtrConstant(16)); 1258 a->IntPtrConstant(16));
1260 1259
1261 return new_capacity; 1260 return new_capacity;
1262 } 1261 }
1263 1262
1264 Node* GrowFixedArray(Node* const current_capacity, Node* const new_capacity, 1263 Node* GrowFixedArray(Node* const current_capacity, Node* const new_capacity,
1265 CodeStubAssembler::ParameterMode mode) { 1264 ParameterMode mode) {
1266 DCHECK(mode == CodeStubAssembler::INTPTR_PARAMETERS); 1265 DCHECK(mode == CodeStubAssembler::INTPTR_PARAMETERS);
1267 1266
1268 CodeStubAssembler* a = assembler_; 1267 CodeStubAssembler* a = assembler_;
1269 1268
1270 CSA_ASSERT(a, a->IntPtrGreaterThan(current_capacity, a->IntPtrConstant(0))); 1269 CSA_ASSERT(a, a->IntPtrGreaterThan(current_capacity, a->IntPtrConstant(0)));
1271 CSA_ASSERT(a, a->IntPtrGreaterThan(new_capacity, current_capacity)); 1270 CSA_ASSERT(a, a->IntPtrGreaterThan(new_capacity, current_capacity));
1272 1271
1273 const ElementsKind kind = FAST_ELEMENTS; 1272 const ElementsKind kind = FAST_ELEMENTS;
1274 const WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER; 1273 const WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER;
1275 1274
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
1353 a->Return(null); 1352 a->Return(null);
1354 } 1353 }
1355 1354
1356 a->Bind(&if_didmatch); 1355 a->Bind(&if_didmatch);
1357 { 1356 {
1358 Node* match = nullptr; 1357 Node* match = nullptr;
1359 if (is_fastpath) { 1358 if (is_fastpath) {
1360 // TODO(jgruber): We could optimize further here and in other 1359 // TODO(jgruber): We could optimize further here and in other
1361 // methods (e.g. @@search) by bypassing RegExp result construction. 1360 // methods (e.g. @@search) by bypassing RegExp result construction.
1362 Node* const result_fixed_array = a->LoadElements(result); 1361 Node* const result_fixed_array = a->LoadElements(result);
1363 const CodeStubAssembler::ParameterMode mode = 1362 const ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS;
1364 CodeStubAssembler::INTPTR_PARAMETERS;
1365 match = 1363 match =
1366 a->LoadFixedArrayElement(result_fixed_array, int_zero, 0, mode); 1364 a->LoadFixedArrayElement(result_fixed_array, int_zero, 0, mode);
1367 1365
1368 // The match is guaranteed to be a string on the fast path. 1366 // The match is guaranteed to be a string on the fast path.
1369 CSA_ASSERT(a, a->IsStringInstanceType(a->LoadInstanceType(match))); 1367 CSA_ASSERT(a, a->IsStringInstanceType(a->LoadInstanceType(match)));
1370 } else { 1368 } else {
1371 DCHECK(!is_fastpath); 1369 DCHECK(!is_fastpath);
1372 1370
1373 CVariable var_match(a, MachineRepresentation::kTagged); 1371 CVariable var_match(a, MachineRepresentation::kTagged);
1374 CLabel fast_result(a), slow_result(a), match_loaded(a); 1372 CLabel fast_result(a), slow_result(a), match_loaded(a);
1375 BranchIfFastRegExpResult(a, context, a->LoadMap(result), &fast_result, 1373 BranchIfFastRegExpResult(a, context, a->LoadMap(result), &fast_result,
1376 &slow_result); 1374 &slow_result);
1377 1375
1378 a->Bind(&fast_result); 1376 a->Bind(&fast_result);
1379 { 1377 {
1380 // TODO(jgruber): We could optimize further here and in other 1378 // TODO(jgruber): We could optimize further here and in other
1381 // methods (e.g. @@search) by bypassing RegExp result construction. 1379 // methods (e.g. @@search) by bypassing RegExp result construction.
1382 Node* const result_fixed_array = a->LoadElements(result); 1380 Node* const result_fixed_array = a->LoadElements(result);
1383 const CodeStubAssembler::ParameterMode mode = 1381 const ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS;
1384 CodeStubAssembler::INTPTR_PARAMETERS;
1385 Node* const match = 1382 Node* const match =
1386 a->LoadFixedArrayElement(result_fixed_array, int_zero, 0, mode); 1383 a->LoadFixedArrayElement(result_fixed_array, int_zero, 0, mode);
1387 1384
1388 // The match is guaranteed to be a string on the fast path. 1385 // The match is guaranteed to be a string on the fast path.
1389 CSA_ASSERT(a, a->IsStringInstanceType(a->LoadInstanceType(match))); 1386 CSA_ASSERT(a, a->IsStringInstanceType(a->LoadInstanceType(match)));
1390 1387
1391 var_match.Bind(match); 1388 var_match.Bind(match);
1392 a->Goto(&match_loaded); 1389 a->Goto(&match_loaded);
1393 } 1390 }
1394 1391
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
1591 1588
1592 a.Bind(&fast_path); 1589 a.Bind(&fast_path);
1593 Generate_RegExpPrototypeSearchBody(&a, receiver, string, context, true); 1590 Generate_RegExpPrototypeSearchBody(&a, receiver, string, context, true);
1594 1591
1595 a.Bind(&slow_path); 1592 a.Bind(&slow_path);
1596 Generate_RegExpPrototypeSearchBody(&a, receiver, string, context, false); 1593 Generate_RegExpPrototypeSearchBody(&a, receiver, string, context, false);
1597 } 1594 }
1598 1595
1599 namespace { 1596 namespace {
1600 1597
1601 MUST_USE_RESULT MaybeHandle<Object> ToUint32(Isolate* isolate, 1598 // Generates the fast path for @@split. {regexp} is an unmodified JSRegExp,
1602 Handle<Object> object, 1599 // {string} is a String, and {limit} is a Smi.
1603 uint32_t* out) { 1600 void Generate_RegExpPrototypeSplitBody(CodeStubAssembler* a, Node* const regexp,
1604 if (object->IsUndefined(isolate)) { 1601 Node* const string, Node* const limit,
1605 *out = kMaxUInt32; 1602 Node* const context) {
1606 return object; 1603 Isolate* isolate = a->isolate();
1607 } 1604
1608 1605 Node* const null = a->NullConstant();
1609 Handle<Object> number; 1606 Node* const smi_zero = a->SmiConstant(0);
1610 ASSIGN_RETURN_ON_EXCEPTION(isolate, number, Object::ToNumber(object), Object); 1607 Node* const int_zero = a->IntPtrConstant(0);
1611 *out = NumberToUint32(*number); 1608 Node* const int_limit = a->SmiUntag(limit);
1612 return object; 1609
1613 } 1610 const ElementsKind kind = FAST_ELEMENTS;
1614 1611 const ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS;
1615 bool AtSurrogatePair(Isolate* isolate, Handle<String> string, int index) { 1612
1616 if (index + 1 >= string->length()) return false; 1613 Node* const allocation_site = nullptr;
1617 const uint16_t first = string->Get(index); 1614 Node* const native_context = a->LoadNativeContext(context);
1618 if (first < 0xD800 || first > 0xDBFF) return false; 1615 Node* const array_map = a->LoadJSArrayElementsMap(kind, native_context);
1619 const uint16_t second = string->Get(index + 1); 1616
1620 return (second >= 0xDC00 && second <= 0xDFFF); 1617 // If limit is zero, return an empty array.
1621 } 1618 {
1622 1619 CLabel next(a), if_limitiszero(a, CLabel::kDeferred);
1623 Handle<JSArray> NewJSArrayWithElements(Isolate* isolate, 1620 a->Branch(a->SmiEqual(limit, smi_zero), &if_limitiszero, &next);
1624 Handle<FixedArray> elems, 1621
1625 int num_elems) { 1622 a->Bind(&if_limitiszero);
1626 elems->Shrink(num_elems); 1623 {
1627 return isolate->factory()->NewJSArrayWithElements(elems); 1624 Node* const length = smi_zero;
1628 } 1625 Node* const capacity = int_zero;
1629 1626 Node* const result = a->AllocateJSArray(kind, array_map, capacity, length,
1630 MaybeHandle<JSArray> RegExpSplit(Isolate* isolate, Handle<JSRegExp> regexp, 1627 allocation_site, mode);
1631 Handle<String> string, 1628 a->Return(result);
1632 Handle<Object> limit_obj) { 1629 }
1633 Factory* factory = isolate->factory(); 1630
1634 1631 a->Bind(&next);
1635 uint32_t limit; 1632 }
1636 RETURN_ON_EXCEPTION(isolate, ToUint32(isolate, limit_obj, &limit), JSArray); 1633
1637 1634 Node* const string_length = a->LoadStringLength(string);
1638 const int length = string->length(); 1635
1639 1636 // If passed the empty {string}, return either an empty array or a singleton
1640 if (limit == 0) return factory->NewJSArray(0); 1637 // array depending on whether the {regexp} matches.
1641 1638 {
1642 Handle<RegExpMatchInfo> last_match_info = isolate->regexp_last_match_info(); 1639 CLabel next(a), if_stringisempty(a, CLabel::kDeferred);
1643 1640 a->Branch(a->SmiEqual(string_length, smi_zero), &if_stringisempty, &next);
1644 if (length == 0) { 1641
1645 Handle<Object> match_indices; 1642 a->Bind(&if_stringisempty);
1646 ASSIGN_RETURN_ON_EXCEPTION( 1643 {
1647 isolate, match_indices, 1644 Node* const last_match_info = a->LoadContextElement(
1648 RegExpImpl::Exec(regexp, string, 0, last_match_info), JSArray); 1645 native_context, Context::REGEXP_LAST_MATCH_INFO_INDEX);
1649 1646
1650 if (!match_indices->IsNull(isolate)) return factory->NewJSArray(0); 1647 Callable exec_callable = CodeFactory::RegExpExec(isolate);
Igor Sheludko 2016/11/30 10:56:37 You can probably use RegExpExecInternal here since
jgruber 2016/11/30 12:45:33 The naming here can be a bit confusing. * CodeFac
Igor Sheludko 2016/11/30 20:47:31 Acknowledged.
1651 1648 Node* const match_indices = a->CallStub(
1652 Handle<FixedArray> elems = factory->NewUninitializedFixedArray(1); 1649 exec_callable, context, regexp, string, smi_zero, last_match_info);
1653 elems->set(0, *string); 1650
1654 return factory->NewJSArrayWithElements(elems); 1651 CLabel if_didmatch(a), if_didnotmatch(a);
1655 } 1652 a->Branch(a->WordEqual(match_indices, null), &if_didnotmatch,
1656 1653 &if_didmatch);
1657 int current_index = 0; 1654
1658 int start_index = 0; 1655 a->Bind(&if_didnotmatch);
1659 int start_match = 0; 1656 {
1660 1657 Node* const length = a->SmiConstant(1);
1661 static const int kInitialArraySize = 8; 1658 Node* const capacity = a->IntPtrConstant(1);
1662 Handle<FixedArray> elems = factory->NewFixedArrayWithHoles(kInitialArraySize); 1659 Node* const result = a->AllocateJSArray(kind, array_map, capacity,
1663 int num_elems = 0; 1660 length, allocation_site, mode);
1664 1661
1665 while (true) { 1662 Node* const fixed_array = a->LoadElements(result);
1666 if (start_index == length) { 1663 a->StoreFixedArrayElement(fixed_array, 0, string);
1667 Handle<String> substr = 1664
1668 factory->NewSubString(string, current_index, length); 1665 a->Return(result);
1669 elems = FixedArray::SetAndGrow(elems, num_elems++, substr);
1670 break;
1671 }
1672
1673 Handle<Object> match_indices_obj;
1674 ASSIGN_RETURN_ON_EXCEPTION(
1675 isolate, match_indices_obj,
1676 RegExpImpl::Exec(regexp, string, start_index,
1677 isolate->regexp_last_match_info()),
1678 JSArray);
1679
1680 if (match_indices_obj->IsNull(isolate)) {
1681 Handle<String> substr =
1682 factory->NewSubString(string, current_index, length);
1683 elems = FixedArray::SetAndGrow(elems, num_elems++, substr);
1684 break;
1685 }
1686
1687 auto match_indices = Handle<RegExpMatchInfo>::cast(match_indices_obj);
1688
1689 start_match = match_indices->Capture(0);
1690
1691 if (start_match == length) {
1692 Handle<String> substr =
1693 factory->NewSubString(string, current_index, length);
1694 elems = FixedArray::SetAndGrow(elems, num_elems++, substr);
1695 break;
1696 }
1697
1698 const int end_index = match_indices->Capture(1);
1699
1700 if (start_index == end_index && end_index == current_index) {
1701 const bool unicode = (regexp->GetFlags() & JSRegExp::kUnicode) != 0;
1702 if (unicode && AtSurrogatePair(isolate, string, start_index)) {
1703 start_index += 2;
1704 } else {
1705 start_index += 1;
1706 } 1666 }
1707 continue; 1667
1708 } 1668 a->Bind(&if_didmatch);
Igor Sheludko 2016/11/30 10:56:38 I think you can remove this block in favor of {if_
jgruber 2016/11/30 12:45:33 Done.
1709 1669 {
1710 { 1670 Node* const length = smi_zero;
1711 Handle<String> substr = 1671 Node* const capacity = int_zero;
1712 factory->NewSubString(string, current_index, start_match); 1672 Node* const result = a->AllocateJSArray(kind, array_map, capacity,
1713 elems = FixedArray::SetAndGrow(elems, num_elems++, substr); 1673 length, allocation_site, mode);
1714 } 1674 a->Return(result);
1715
1716 if (static_cast<uint32_t>(num_elems) == limit) break;
1717
1718 for (int i = 2; i < match_indices->NumberOfCaptureRegisters(); i += 2) {
1719 const int start = match_indices->Capture(i);
1720 const int end = match_indices->Capture(i + 1);
1721
1722 if (end != -1) {
1723 Handle<String> substr = factory->NewSubString(string, start, end);
1724 elems = FixedArray::SetAndGrow(elems, num_elems++, substr);
1725 } else {
1726 elems = FixedArray::SetAndGrow(elems, num_elems++,
1727 factory->undefined_value());
1728 } 1675 }
1729 1676 }
1730 if (static_cast<uint32_t>(num_elems) == limit) { 1677
1731 return NewJSArrayWithElements(isolate, elems, num_elems); 1678 a->Bind(&next);
1679 }
1680
1681 // Loop preparations.
1682
1683 GrowableFixedArray array(a);
1684
1685 CVariable var_last_matched_until(a, MachineRepresentation::kTagged);
1686 CVariable var_next_search_from(a, MachineRepresentation::kTagged);
1687
1688 var_last_matched_until.Bind(smi_zero);
1689 var_next_search_from.Bind(smi_zero);
1690
1691 CVariable* vars[] = {array.var_array(), array.var_length(),
1692 array.var_capacity(), &var_last_matched_until,
1693 &var_next_search_from};
1694 const int vars_count = sizeof(vars) / sizeof(vars[0]);
1695 CLabel loop(a, vars_count, vars), push_suffix_and_out(a), out(a);
1696 a->Goto(&loop);
1697
1698 a->Bind(&loop);
1699 {
1700 Node* const next_search_from = var_next_search_from.value();
1701 Node* const last_matched_until = var_last_matched_until.value();
1702
1703 // We're done if we've reached the end of the string.
1704 {
1705 CLabel next(a);
1706 a->Branch(a->SmiEqual(next_search_from, string_length),
1707 &push_suffix_and_out, &next);
1708 a->Bind(&next);
1709 }
1710
1711 // Search for the given {regexp}.
1712
1713 Node* const last_match_info = a->LoadContextElement(
1714 native_context, Context::REGEXP_LAST_MATCH_INFO_INDEX);
1715
1716 Callable exec_callable = CodeFactory::RegExpExec(isolate);
Igor Sheludko 2016/11/30 10:56:37 Same here.
jgruber 2016/11/30 12:45:33 See reply above.
1717 Node* const match_indices =
1718 a->CallStub(exec_callable, context, regexp, string, next_search_from,
1719 last_match_info);
1720
1721 // We're done if no match was found.
1722 {
1723 CLabel next(a);
1724 a->Branch(a->WordEqual(match_indices, null), &push_suffix_and_out, &next);
1725 a->Bind(&next);
1726 }
1727
1728 Node* const match_from = a->LoadFixedArrayElement(
1729 match_indices, a->IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex),
1730 0, mode);
1731
1732 // We're done if the match starts beyond the string.
1733 {
1734 CLabel next(a);
1735 a->Branch(a->WordEqual(match_from, string_length), &push_suffix_and_out,
1736 &next);
1737 a->Bind(&next);
1738 }
1739
1740 Node* const match_to = a->LoadFixedArrayElement(
1741 match_indices,
1742 a->IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex + 1), 0, mode);
1743
1744 // Advance index and continue if the match is empty.
1745 {
1746 CLabel next(a);
1747
1748 a->GotoUnless(a->SmiEqual(match_to, next_search_from), &next);
1749 a->GotoUnless(a->SmiEqual(match_to, last_matched_until), &next);
1750
1751 Node* const is_unicode = FastFlagGetter(a, regexp, JSRegExp::kUnicode);
1752 Node* const new_next_search_from =
1753 AdvanceStringIndex(a, string, next_search_from, is_unicode);
1754 var_next_search_from.Bind(new_next_search_from);
1755 a->Goto(&loop);
1756
1757 a->Bind(&next);
1758 }
1759
1760 // A valid match was found, add the new substring to the array.
1761 {
1762 Node* const from = last_matched_until;
1763 Node* const to = match_from;
1764
1765 Node* const substr = a->SubString(context, string, from, to);
1766 array.Push(substr);
1767
1768 a->GotoIf(a->WordEqual(array.length(), int_limit), &out);
1769 }
1770
1771 // Add all captures to the array.
1772 {
1773 Node* const num_registers = a->LoadFixedArrayElement(
1774 match_indices,
1775 a->IntPtrConstant(RegExpMatchInfo::kNumberOfCapturesIndex), 0, mode);
1776 Node* const int_num_registers = a->SmiUntag(num_registers);
1777
1778 CVariable var_reg(a, MachineType::PointerRepresentation());
1779 var_reg.Bind(a->IntPtrConstant(2));
1780
1781 CVariable* vars[] = {array.var_array(), array.var_length(),
1782 array.var_capacity(), &var_reg};
1783 const int vars_count = sizeof(vars) / sizeof(vars[0]);
1784 CLabel nested_loop(a, vars_count, vars), nested_loop_out(a);
1785 a->Branch(a->IntPtrLessThan(var_reg.value(), int_num_registers),
1786 &nested_loop, &nested_loop_out);
1787
1788 a->Bind(&nested_loop);
1789 {
1790 Node* const reg = var_reg.value();
1791 Node* const from = a->LoadFixedArrayElement(
1792 match_indices, reg,
1793 RegExpMatchInfo::kFirstCaptureIndex * kPointerSize, mode);
1794
1795 Node* const reg_plus_one = a->IntPtrAdd(reg, a->IntPtrConstant(1));
1796 Node* const to = a->LoadFixedArrayElement(
1797 match_indices, reg_plus_one,
1798 RegExpMatchInfo::kFirstCaptureIndex * kPointerSize, mode);
1799
1800 CLabel select_capture(a), select_undefined(a), store_value(a);
1801 CVariable var_value(a, MachineRepresentation::kTagged);
1802 a->Branch(a->SmiEqual(to, a->SmiConstant(-1)), &select_undefined,
1803 &select_capture);
1804
1805 a->Bind(&select_capture);
1806 {
1807 Node* const substr = a->SubString(context, string, from, to);
1808 var_value.Bind(substr);
1809 a->Goto(&store_value);
1810 }
1811
1812 a->Bind(&select_undefined);
1813 {
1814 Node* const undefined = a->UndefinedConstant();
1815 var_value.Bind(undefined);
1816 a->Goto(&store_value);
1817 }
1818
1819 a->Bind(&store_value);
1820 {
1821 array.Push(var_value.value());
1822 a->GotoIf(a->WordEqual(array.length(), int_limit), &out);
1823
1824 Node* const new_reg = a->IntPtrAdd(reg, a->IntPtrConstant(2));
1825 var_reg.Bind(new_reg);
1826
1827 a->Branch(a->IntPtrLessThan(new_reg, int_num_registers), &nested_loop,
1828 &nested_loop_out);
1829 }
1732 } 1830 }
1733 } 1831
1734 1832 a->Bind(&nested_loop_out);
1735 start_index = current_index = end_index; 1833 }
1736 } 1834
1737 1835 var_last_matched_until.Bind(match_to);
1738 return NewJSArrayWithElements(isolate, elems, num_elems); 1836 var_next_search_from.Bind(match_to);
1739 } 1837 a->Goto(&loop);
1740 1838 }
1741 // ES##sec-speciesconstructor 1839
1742 // SpeciesConstructor ( O, defaultConstructor ) 1840 a->Bind(&push_suffix_and_out);
1743 MUST_USE_RESULT MaybeHandle<Object> SpeciesConstructor( 1841 {
1744 Isolate* isolate, Handle<JSReceiver> recv, 1842 Node* const from = var_last_matched_until.value();
1745 Handle<JSFunction> default_ctor) { 1843 Node* const to = string_length;
1746 Handle<Object> ctor_obj; 1844
1747 ASSIGN_RETURN_ON_EXCEPTION( 1845 Node* const substr = a->SubString(context, string, from, to);
1748 isolate, ctor_obj, 1846 array.Push(substr);
1749 JSObject::GetProperty(recv, isolate->factory()->constructor_string()), 1847
1750 Object); 1848 Node* const result = array.ToJSArray(context);
Igor Sheludko 2016/11/30 10:56:37 Goto(&out) to generate less code.
jgruber 2016/11/30 12:45:33 Done. As an aside, I initially did not Goto(&out)
1751 1849 a->Return(result);
1752 if (ctor_obj->IsUndefined(isolate)) return default_ctor; 1850 }
1753 1851
1754 if (!ctor_obj->IsJSReceiver()) { 1852 a->Bind(&out);
1755 THROW_NEW_ERROR(isolate, 1853 {
1756 NewTypeError(MessageTemplate::kConstructorNotReceiver), 1854 Node* const result = array.ToJSArray(context);
1757 Object); 1855 a->Return(result);
1758 } 1856 }
1759
1760 Handle<JSReceiver> ctor = Handle<JSReceiver>::cast(ctor_obj);
1761
1762 Handle<Object> species;
1763 ASSIGN_RETURN_ON_EXCEPTION(
1764 isolate, species,
1765 JSObject::GetProperty(ctor, isolate->factory()->species_symbol()),
1766 Object);
1767
1768 if (species->IsNull(isolate) || species->IsUndefined(isolate)) {
1769 return default_ctor;
1770 }
1771
1772 if (species->IsConstructor()) return species;
1773
1774 THROW_NEW_ERROR(
1775 isolate, NewTypeError(MessageTemplate::kSpeciesNotConstructor), Object);
1776 } 1857 }
1777 1858
1778 } // namespace 1859 } // namespace
1779 1860
1780 // ES#sec-regexp.prototype-@@split 1861 // ES#sec-regexp.prototype-@@split
1781 // RegExp.prototype [ @@split ] ( string, limit ) 1862 // RegExp.prototype [ @@split ] ( string, limit )
1782 BUILTIN(RegExpPrototypeSplit) { 1863 void Builtins::Generate_RegExpPrototypeSplit(CodeAssemblerState* state) {
1783 HandleScope scope(isolate); 1864 CodeStubAssembler a(state);
1784 CHECK_RECEIVER(JSReceiver, recv, "RegExp.prototype.@@split"); 1865
1785 1866 Isolate* const isolate = a.isolate();
1786 Factory* factory = isolate->factory(); 1867
1787 1868 Node* const undefined = a.UndefinedConstant();
1788 Handle<Object> string_obj = args.atOrUndefined(isolate, 1); 1869
1789 Handle<Object> limit_obj = args.atOrUndefined(isolate, 2); 1870 Node* const maybe_receiver = a.Parameter(0);
1790 1871 Node* const maybe_string = a.Parameter(1);
1791 Handle<String> string; 1872 Node* const maybe_limit = a.Parameter(2);
1792 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, string, 1873 Node* const context = a.Parameter(5);
1793 Object::ToString(isolate, string_obj)); 1874
1794 1875 // Ensure {maybe_receiver} is a JSReceiver.
1795 if (RegExpUtils::IsUnmodifiedRegExp(isolate, recv)) { 1876 Node* const map = ThrowIfNotJSReceiver(
1796 RETURN_RESULT_OR_FAILURE( 1877 &a, isolate, context, maybe_receiver,
1797 isolate, 1878 MessageTemplate::kIncompatibleMethodReceiver, "RegExp.prototype.@@split");
1798 RegExpSplit(isolate, Handle<JSRegExp>::cast(recv), string, limit_obj)); 1879 Node* const receiver = maybe_receiver;
1799 } 1880
1800 1881 // Convert {maybe_string} to a String.
1801 Handle<JSFunction> regexp_fun = isolate->regexp_function(); 1882 Node* const string = a.ToString(context, maybe_string);
1802 Handle<Object> ctor; 1883
1803 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 1884 CLabel fast_path(&a), slow_path(&a);
1804 isolate, ctor, SpeciesConstructor(isolate, recv, regexp_fun)); 1885 BranchIfFastPath(&a, context, map, &fast_path, &slow_path);
1805 1886
1806 Handle<Object> flags_obj; 1887 a.Bind(&fast_path);
1807 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 1888 {
1808 isolate, flags_obj, JSObject::GetProperty(recv, factory->flags_string())); 1889 // Convert {maybe_limit} to a uint32, capping at the maximal smi value.
1809 1890 CVariable var_limit(&a, MachineRepresentation::kTagged);
1810 Handle<String> flags; 1891 CLabel if_limitissmimax(&a), limit_done(&a);
1811 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, flags, 1892
1812 Object::ToString(isolate, flags_obj)); 1893 a.GotoIf(a.WordEqual(maybe_limit, undefined), &if_limitissmimax);
1813 1894
1814 Handle<String> u_str = factory->LookupSingleCharacterStringFromCode('u'); 1895 Node* const uint32_limit = a.ToUint32(context, maybe_limit);
1815 const bool unicode = (String::IndexOf(isolate, flags, u_str, 0) >= 0); 1896 a.GotoUnless(a.TaggedIsSmi(uint32_limit), &if_limitissmimax);
1816 1897
1817 Handle<String> y_str = factory->LookupSingleCharacterStringFromCode('y'); 1898 var_limit.Bind(uint32_limit);
1818 const bool sticky = (String::IndexOf(isolate, flags, y_str, 0) >= 0); 1899 a.Goto(&limit_done);
1819 1900
1820 Handle<String> new_flags = flags; 1901 a.Bind(&if_limitissmimax);
1821 if (!sticky) { 1902 {
1822 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, new_flags, 1903 const uint32_t kSmiMaxValue = static_cast<uint32_t>(
1823 factory->NewConsString(flags, y_str)); 1904 (1ULL << (PlatformSmiTagging::SmiValueSize() - 1)) - 1);
1824 } 1905 Node* const smi_max = a.SmiConstant(kSmiMaxValue);
1825 1906 var_limit.Bind(smi_max);
1826 Handle<JSReceiver> splitter; 1907 a.Goto(&limit_done);
1827 { 1908 }
1828 const int argc = 2; 1909
1829 1910 a.Bind(&limit_done);
1830 ScopedVector<Handle<Object>> argv(argc); 1911 Node* const limit = var_limit.value();
1831 argv[0] = recv; 1912
1832 argv[1] = new_flags; 1913 Generate_RegExpPrototypeSplitBody(&a, receiver, string, limit, context);
1833 1914 }
1834 Handle<JSFunction> ctor_fun = Handle<JSFunction>::cast(ctor); 1915
1835 Handle<Object> splitter_obj; 1916 a.Bind(&slow_path);
1836 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 1917 {
1837 isolate, splitter_obj, Execution::New(ctor_fun, argc, argv.start())); 1918 Node* const result = a.CallRuntime(Runtime::kRegExpSplit, context, receiver,
1838 1919 string, maybe_limit);
1839 splitter = Handle<JSReceiver>::cast(splitter_obj); 1920 a.Return(result);
1840 } 1921 }
1841
1842 uint32_t limit;
1843 RETURN_FAILURE_ON_EXCEPTION(isolate, ToUint32(isolate, limit_obj, &limit));
1844
1845 const int length = string->length();
1846
1847 if (limit == 0) return *factory->NewJSArray(0);
1848
1849 if (length == 0) {
1850 Handle<Object> result;
1851 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1852 isolate, result, RegExpUtils::RegExpExec(isolate, splitter, string,
1853 factory->undefined_value()));
1854
1855 if (!result->IsNull(isolate)) return *factory->NewJSArray(0);
1856
1857 Handle<FixedArray> elems = factory->NewUninitializedFixedArray(1);
1858 elems->set(0, *string);
1859 return *factory->NewJSArrayWithElements(elems);
1860 }
1861
1862 // TODO(jgruber): Wrap this in a helper class.
1863 static const int kInitialArraySize = 8;
1864 Handle<FixedArray> elems = factory->NewFixedArrayWithHoles(kInitialArraySize);
1865 int num_elems = 0;
1866
1867 int string_index = 0;
1868 int prev_string_index = 0;
1869 while (string_index < length) {
1870 RETURN_FAILURE_ON_EXCEPTION(
1871 isolate, RegExpUtils::SetLastIndex(isolate, splitter, string_index));
1872
1873 Handle<Object> result;
1874 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1875 isolate, result, RegExpUtils::RegExpExec(isolate, splitter, string,
1876 factory->undefined_value()));
1877
1878 if (result->IsNull(isolate)) {
1879 string_index = RegExpUtils::AdvanceStringIndex(isolate, string,
1880 string_index, unicode);
1881 continue;
1882 }
1883
1884 // TODO(jgruber): Extract toLength of some property into function.
1885 Handle<Object> last_index_obj;
1886 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1887 isolate, last_index_obj, RegExpUtils::GetLastIndex(isolate, splitter));
1888
1889 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1890 isolate, last_index_obj, Object::ToLength(isolate, last_index_obj));
1891 const int last_index = Handle<Smi>::cast(last_index_obj)->value();
1892
1893 const int end = std::min(last_index, length);
1894 if (end == prev_string_index) {
1895 string_index = RegExpUtils::AdvanceStringIndex(isolate, string,
1896 string_index, unicode);
1897 continue;
1898 }
1899
1900 {
1901 Handle<String> substr =
1902 factory->NewSubString(string, prev_string_index, string_index);
1903 elems = FixedArray::SetAndGrow(elems, num_elems++, substr);
1904 if (static_cast<uint32_t>(num_elems) == limit) {
1905 return *NewJSArrayWithElements(isolate, elems, num_elems);
1906 }
1907 }
1908
1909 prev_string_index = end;
1910
1911 Handle<Object> num_captures_obj;
1912 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1913 isolate, num_captures_obj,
1914 Object::GetProperty(result, isolate->factory()->length_string()));
1915
1916 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1917 isolate, num_captures_obj, Object::ToLength(isolate, num_captures_obj));
1918 const int num_captures =
1919 std::max(Handle<Smi>::cast(num_captures_obj)->value(), 0);
1920
1921 for (int i = 1; i < num_captures; i++) {
1922 Handle<Object> capture;
1923 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1924 isolate, capture, Object::GetElement(isolate, result, i));
1925 elems = FixedArray::SetAndGrow(elems, num_elems++, capture);
1926 if (static_cast<uint32_t>(num_elems) == limit) {
1927 return *NewJSArrayWithElements(isolate, elems, num_elems);
1928 }
1929 }
1930
1931 string_index = prev_string_index;
1932 }
1933
1934 {
1935 Handle<String> substr =
1936 factory->NewSubString(string, prev_string_index, length);
1937 elems = FixedArray::SetAndGrow(elems, num_elems++, substr);
1938 }
1939
1940 return *NewJSArrayWithElements(isolate, elems, num_elems);
1941 } 1922 }
1942 1923
1943 namespace { 1924 namespace {
1944 1925
1945 Node* ReplaceGlobalCallableFastPath(CodeStubAssembler* a, Node* context, 1926 Node* ReplaceGlobalCallableFastPath(CodeStubAssembler* a, Node* context,
1946 Node* regexp, Node* subject_string, 1927 Node* regexp, Node* subject_string,
1947 Node* replace_callable) { 1928 Node* replace_callable) {
1948 // The fast path is reached only if {receiver} is a global unmodified 1929 // The fast path is reached only if {receiver} is a global unmodified
1949 // JSRegExp instance and {replace_callable} is callable. 1930 // JSRegExp instance and {replace_callable} is callable.
1950 1931
(...skipping 14 matching lines...) Expand all
1965 FastStoreLastIndex(a, context, regexp, smi_zero); 1946 FastStoreLastIndex(a, context, regexp, smi_zero);
1966 1947
1967 // Allocate {result_array}. 1948 // Allocate {result_array}.
1968 Node* result_array; 1949 Node* result_array;
1969 { 1950 {
1970 ElementsKind kind = FAST_ELEMENTS; 1951 ElementsKind kind = FAST_ELEMENTS;
1971 Node* const array_map = a->LoadJSArrayElementsMap(kind, native_context); 1952 Node* const array_map = a->LoadJSArrayElementsMap(kind, native_context);
1972 Node* const capacity = a->IntPtrConstant(16); 1953 Node* const capacity = a->IntPtrConstant(16);
1973 Node* const length = smi_zero; 1954 Node* const length = smi_zero;
1974 Node* const allocation_site = nullptr; 1955 Node* const allocation_site = nullptr;
1975 CodeStubAssembler::ParameterMode capacity_mode = 1956 ParameterMode capacity_mode = CodeStubAssembler::INTPTR_PARAMETERS;
1976 CodeStubAssembler::INTPTR_PARAMETERS;
1977 1957
1978 result_array = a->AllocateJSArray(kind, array_map, capacity, length, 1958 result_array = a->AllocateJSArray(kind, array_map, capacity, length,
1979 allocation_site, capacity_mode); 1959 allocation_site, capacity_mode);
1980 } 1960 }
1981 1961
1982 // Call into runtime for RegExpExecMultiple. 1962 // Call into runtime for RegExpExecMultiple.
1983 Node* last_match_info = a->LoadContextElement( 1963 Node* last_match_info = a->LoadContextElement(
1984 native_context, Context::REGEXP_LAST_MATCH_INFO_INDEX); 1964 native_context, Context::REGEXP_LAST_MATCH_INFO_INDEX);
1985 Node* const res = 1965 Node* const res =
1986 a->CallRuntime(Runtime::kRegExpExecMultiple, context, regexp, 1966 a->CallRuntime(Runtime::kRegExpExecMultiple, context, regexp,
1987 subject_string, last_match_info, result_array); 1967 subject_string, last_match_info, result_array);
1988 1968
1989 // Reset last index to 0. 1969 // Reset last index to 0.
1990 FastStoreLastIndex(a, context, regexp, smi_zero); 1970 FastStoreLastIndex(a, context, regexp, smi_zero);
1991 1971
1992 // If no matches, return the subject string. 1972 // If no matches, return the subject string.
1993 var_result.Bind(subject_string); 1973 var_result.Bind(subject_string);
1994 a->GotoIf(a->WordEqual(res, null), &out); 1974 a->GotoIf(a->WordEqual(res, null), &out);
1995 1975
1996 // Reload last match info since it might have changed. 1976 // Reload last match info since it might have changed.
1997 last_match_info = a->LoadContextElement( 1977 last_match_info = a->LoadContextElement(
1998 native_context, Context::REGEXP_LAST_MATCH_INFO_INDEX); 1978 native_context, Context::REGEXP_LAST_MATCH_INFO_INDEX);
1999 1979
2000 Node* const res_length = a->LoadJSArrayLength(res); 1980 Node* const res_length = a->LoadJSArrayLength(res);
2001 Node* const res_elems = a->LoadElements(res); 1981 Node* const res_elems = a->LoadElements(res);
2002 CSA_ASSERT(a, a->HasInstanceType(res_elems, FIXED_ARRAY_TYPE)); 1982 CSA_ASSERT(a, a->HasInstanceType(res_elems, FIXED_ARRAY_TYPE));
2003 1983
2004 CodeStubAssembler::ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS; 1984 ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS;
2005 Node* const num_capture_registers = a->LoadFixedArrayElement( 1985 Node* const num_capture_registers = a->LoadFixedArrayElement(
2006 last_match_info, 1986 last_match_info,
2007 a->IntPtrConstant(RegExpMatchInfo::kNumberOfCapturesIndex), 0, mode); 1987 a->IntPtrConstant(RegExpMatchInfo::kNumberOfCapturesIndex), 0, mode);
2008 1988
2009 CLabel if_hasexplicitcaptures(a), if_noexplicitcaptures(a), create_result(a); 1989 CLabel if_hasexplicitcaptures(a), if_noexplicitcaptures(a), create_result(a);
2010 a->Branch(a->SmiEqual(num_capture_registers, a->SmiConstant(Smi::FromInt(2))), 1990 a->Branch(a->SmiEqual(num_capture_registers, a->SmiConstant(Smi::FromInt(2))),
2011 &if_noexplicitcaptures, &if_hasexplicitcaptures); 1991 &if_noexplicitcaptures, &if_hasexplicitcaptures);
2012 1992
2013 a->Bind(&if_noexplicitcaptures); 1993 a->Bind(&if_noexplicitcaptures);
2014 { 1994 {
(...skipping 12 matching lines...) Expand all
2027 var_i.Bind(int_zero); 2007 var_i.Bind(int_zero);
2028 2008
2029 CVariable* vars[] = {&var_i, &var_match_start}; 2009 CVariable* vars[] = {&var_i, &var_match_start};
2030 CLabel loop(a, 2, vars); 2010 CLabel loop(a, 2, vars);
2031 a->Goto(&loop); 2011 a->Goto(&loop);
2032 a->Bind(&loop); 2012 a->Bind(&loop);
2033 { 2013 {
2034 Node* const i = var_i.value(); 2014 Node* const i = var_i.value();
2035 a->GotoUnless(a->IntPtrLessThan(i, end), &create_result); 2015 a->GotoUnless(a->IntPtrLessThan(i, end), &create_result);
2036 2016
2037 CodeStubAssembler::ParameterMode mode = 2017 ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS;
2038 CodeStubAssembler::INTPTR_PARAMETERS;
2039 Node* const elem = a->LoadFixedArrayElement(res_elems, i, 0, mode); 2018 Node* const elem = a->LoadFixedArrayElement(res_elems, i, 0, mode);
2040 2019
2041 CLabel if_issmi(a), if_isstring(a), loop_epilogue(a); 2020 CLabel if_issmi(a), if_isstring(a), loop_epilogue(a);
2042 a->Branch(a->TaggedIsSmi(elem), &if_issmi, &if_isstring); 2021 a->Branch(a->TaggedIsSmi(elem), &if_issmi, &if_isstring);
2043 2022
2044 a->Bind(&if_issmi); 2023 a->Bind(&if_issmi);
2045 { 2024 {
2046 // Integers represent slices of the original string. 2025 // Integers represent slices of the original string.
2047 CLabel if_isnegativeorzero(a), if_ispositive(a); 2026 CLabel if_isnegativeorzero(a), if_ispositive(a);
2048 a->BranchIfSmiLessThanOrEqual(elem, smi_zero, &if_isnegativeorzero, 2027 a->BranchIfSmiLessThanOrEqual(elem, smi_zero, &if_isnegativeorzero,
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
2095 a->Bind(&loop_epilogue); 2074 a->Bind(&loop_epilogue);
2096 { 2075 {
2097 var_i.Bind(a->IntPtrAdd(var_i.value(), int_one)); 2076 var_i.Bind(a->IntPtrAdd(var_i.value(), int_one));
2098 a->Goto(&loop); 2077 a->Goto(&loop);
2099 } 2078 }
2100 } 2079 }
2101 } 2080 }
2102 2081
2103 a->Bind(&if_hasexplicitcaptures); 2082 a->Bind(&if_hasexplicitcaptures);
2104 { 2083 {
2105 CodeStubAssembler::ParameterMode mode = 2084 ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS;
2106 CodeStubAssembler::INTPTR_PARAMETERS;
2107 2085
2108 Node* const from = int_zero; 2086 Node* const from = int_zero;
2109 Node* const to = a->SmiUntag(res_length); 2087 Node* const to = a->SmiUntag(res_length);
2110 const int increment = 1; 2088 const int increment = 1;
2111 2089
2112 a->BuildFastLoop( 2090 a->BuildFastLoop(
2113 MachineType::PointerRepresentation(), from, to, 2091 MachineType::PointerRepresentation(), from, to,
2114 [res_elems, isolate, native_context, context, undefined, 2092 [res_elems, isolate, native_context, context, undefined,
2115 replace_callable, mode](CodeStubAssembler* a, Node* index) { 2093 replace_callable, mode](CodeStubAssembler* a, Node* index) {
2116 Node* const elem = 2094 Node* const elem =
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
2213 2191
2214 a->Bind(&if_didnotmatch); 2192 a->Bind(&if_didnotmatch);
2215 { 2193 {
2216 FastStoreLastIndex(a, context, regexp, smi_zero); 2194 FastStoreLastIndex(a, context, regexp, smi_zero);
2217 var_result.Bind(subject_string); 2195 var_result.Bind(subject_string);
2218 a->Goto(&out); 2196 a->Goto(&out);
2219 } 2197 }
2220 2198
2221 a->Bind(&if_matched); 2199 a->Bind(&if_matched);
2222 { 2200 {
2223 CodeStubAssembler::ParameterMode mode = 2201 ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS;
2224 CodeStubAssembler::INTPTR_PARAMETERS;
2225 2202
2226 Node* const subject_start = smi_zero; 2203 Node* const subject_start = smi_zero;
2227 Node* const match_start = a->LoadFixedArrayElement( 2204 Node* const match_start = a->LoadFixedArrayElement(
2228 match_indices, a->IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex), 2205 match_indices, a->IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex),
2229 0, mode); 2206 0, mode);
2230 Node* const match_end = a->LoadFixedArrayElement( 2207 Node* const match_end = a->LoadFixedArrayElement(
2231 match_indices, 2208 match_indices,
2232 a->IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex + 1), 0, mode); 2209 a->IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex + 1), 0, mode);
2233 Node* const subject_end = a->LoadStringLength(subject_string); 2210 Node* const subject_end = a->LoadStringLength(subject_string);
2234 2211
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
2397 a.Bind(&if_matched); 2374 a.Bind(&if_matched);
2398 { 2375 {
2399 Node* result = ConstructNewResultFromMatchInfo(isolate, &a, context, 2376 Node* result = ConstructNewResultFromMatchInfo(isolate, &a, context,
2400 match_indices, string); 2377 match_indices, string);
2401 a.Return(result); 2378 a.Return(result);
2402 } 2379 }
2403 } 2380 }
2404 2381
2405 } // namespace internal 2382 } // namespace internal
2406 } // namespace v8 2383 } // namespace v8
OLDNEW
« no previous file with comments | « src/builtins/builtins.h ('k') | src/code-stub-assembler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698