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

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

Issue 2532403002: [regexp] Migrate @@split to TurboFan (Closed)
Patch Set: Address comments 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
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 CLabel return_empty_array(a, CLabel::kDeferred);
1621 } 1618
1622 1619 // If limit is zero, return an empty array.
1623 Handle<JSArray> NewJSArrayWithElements(Isolate* isolate, 1620 {
1624 Handle<FixedArray> elems, 1621 CLabel next(a), if_limitiszero(a, CLabel::kDeferred);
1625 int num_elems) { 1622 a->Branch(a->SmiEqual(limit, smi_zero), &return_empty_array, &next);
1626 elems->Shrink(num_elems); 1623 a->Bind(&next);
1627 return isolate->factory()->NewJSArrayWithElements(elems); 1624 }
1628 } 1625
1629 1626 Node* const string_length = a->LoadStringLength(string);
1630 MaybeHandle<JSArray> RegExpSplit(Isolate* isolate, Handle<JSRegExp> regexp, 1627
1631 Handle<String> string, 1628 // If passed the empty {string}, return either an empty array or a singleton
1632 Handle<Object> limit_obj) { 1629 // array depending on whether the {regexp} matches.
1633 Factory* factory = isolate->factory(); 1630 {
1634 1631 CLabel next(a), if_stringisempty(a, CLabel::kDeferred);
1635 uint32_t limit; 1632 a->Branch(a->SmiEqual(string_length, smi_zero), &if_stringisempty, &next);
1636 RETURN_ON_EXCEPTION(isolate, ToUint32(isolate, limit_obj, &limit), JSArray); 1633
1637 1634 a->Bind(&if_stringisempty);
1638 const int length = string->length(); 1635 {
1639 1636 Node* const last_match_info = a->LoadContextElement(
1640 if (limit == 0) return factory->NewJSArray(0); 1637 native_context, Context::REGEXP_LAST_MATCH_INFO_INDEX);
1641 1638
1642 Handle<RegExpMatchInfo> last_match_info = isolate->regexp_last_match_info(); 1639 Callable exec_callable = CodeFactory::RegExpExec(isolate);
1643 1640 Node* const match_indices = a->CallStub(
1644 if (length == 0) { 1641 exec_callable, context, regexp, string, smi_zero, last_match_info);
1645 Handle<Object> match_indices; 1642
1646 ASSIGN_RETURN_ON_EXCEPTION( 1643 CLabel return_singleton_array(a);
1647 isolate, match_indices, 1644 a->Branch(a->WordEqual(match_indices, null), &return_singleton_array,
1648 RegExpImpl::Exec(regexp, string, 0, last_match_info), JSArray); 1645 &return_empty_array);
1649 1646
1650 if (!match_indices->IsNull(isolate)) return factory->NewJSArray(0); 1647 a->Bind(&return_singleton_array);
1651 1648 {
1652 Handle<FixedArray> elems = factory->NewUninitializedFixedArray(1); 1649 Node* const length = a->SmiConstant(1);
1653 elems->set(0, *string); 1650 Node* const capacity = a->IntPtrConstant(1);
1654 return factory->NewJSArrayWithElements(elems); 1651 Node* const result = a->AllocateJSArray(kind, array_map, capacity,
1655 } 1652 length, allocation_site, mode);
1656 1653
1657 int current_index = 0; 1654 Node* const fixed_array = a->LoadElements(result);
1658 int start_index = 0; 1655 a->StoreFixedArrayElement(fixed_array, 0, string);
1659 int start_match = 0; 1656
1660 1657 a->Return(result);
1661 static const int kInitialArraySize = 8;
1662 Handle<FixedArray> elems = factory->NewFixedArrayWithHoles(kInitialArraySize);
1663 int num_elems = 0;
1664
1665 while (true) {
1666 if (start_index == length) {
1667 Handle<String> substr =
1668 factory->NewSubString(string, current_index, length);
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 } 1658 }
1707 continue; 1659 }
1708 } 1660
1709 1661 a->Bind(&next);
1710 { 1662 }
1711 Handle<String> substr = 1663
1712 factory->NewSubString(string, current_index, start_match); 1664 // Loop preparations.
1713 elems = FixedArray::SetAndGrow(elems, num_elems++, substr); 1665
1714 } 1666 GrowableFixedArray array(a);
1715 1667
1716 if (static_cast<uint32_t>(num_elems) == limit) break; 1668 CVariable var_last_matched_until(a, MachineRepresentation::kTagged);
1717 1669 CVariable var_next_search_from(a, MachineRepresentation::kTagged);
1718 for (int i = 2; i < match_indices->NumberOfCaptureRegisters(); i += 2) { 1670
1719 const int start = match_indices->Capture(i); 1671 var_last_matched_until.Bind(smi_zero);
1720 const int end = match_indices->Capture(i + 1); 1672 var_next_search_from.Bind(smi_zero);
1721 1673
1722 if (end != -1) { 1674 CVariable* vars[] = {array.var_array(), array.var_length(),
1723 Handle<String> substr = factory->NewSubString(string, start, end); 1675 array.var_capacity(), &var_last_matched_until,
1724 elems = FixedArray::SetAndGrow(elems, num_elems++, substr); 1676 &var_next_search_from};
1725 } else { 1677 const int vars_count = sizeof(vars) / sizeof(vars[0]);
1726 elems = FixedArray::SetAndGrow(elems, num_elems++, 1678 CLabel loop(a, vars_count, vars), push_suffix_and_out(a), out(a);
1727 factory->undefined_value()); 1679 a->Goto(&loop);
1680
1681 a->Bind(&loop);
1682 {
1683 Node* const next_search_from = var_next_search_from.value();
1684 Node* const last_matched_until = var_last_matched_until.value();
1685
1686 // We're done if we've reached the end of the string.
1687 {
1688 CLabel next(a);
1689 a->Branch(a->SmiEqual(next_search_from, string_length),
1690 &push_suffix_and_out, &next);
1691 a->Bind(&next);
1692 }
1693
1694 // Search for the given {regexp}.
1695
1696 Node* const last_match_info = a->LoadContextElement(
1697 native_context, Context::REGEXP_LAST_MATCH_INFO_INDEX);
1698
1699 Callable exec_callable = CodeFactory::RegExpExec(isolate);
1700 Node* const match_indices =
1701 a->CallStub(exec_callable, context, regexp, string, next_search_from,
1702 last_match_info);
1703
1704 // We're done if no match was found.
1705 {
1706 CLabel next(a);
1707 a->Branch(a->WordEqual(match_indices, null), &push_suffix_and_out, &next);
1708 a->Bind(&next);
1709 }
1710
1711 Node* const match_from = a->LoadFixedArrayElement(
1712 match_indices, a->IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex),
1713 0, mode);
1714
1715 // We're done if the match starts beyond the string.
1716 {
1717 CLabel next(a);
1718 a->Branch(a->WordEqual(match_from, string_length), &push_suffix_and_out,
1719 &next);
1720 a->Bind(&next);
1721 }
1722
1723 Node* const match_to = a->LoadFixedArrayElement(
1724 match_indices,
1725 a->IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex + 1), 0, mode);
1726
1727 // Advance index and continue if the match is empty.
1728 {
1729 CLabel next(a);
1730
1731 a->GotoUnless(a->SmiEqual(match_to, next_search_from), &next);
1732 a->GotoUnless(a->SmiEqual(match_to, last_matched_until), &next);
1733
1734 Node* const is_unicode = FastFlagGetter(a, regexp, JSRegExp::kUnicode);
1735 Node* const new_next_search_from =
1736 AdvanceStringIndex(a, string, next_search_from, is_unicode);
1737 var_next_search_from.Bind(new_next_search_from);
1738 a->Goto(&loop);
1739
1740 a->Bind(&next);
1741 }
1742
1743 // A valid match was found, add the new substring to the array.
1744 {
1745 Node* const from = last_matched_until;
1746 Node* const to = match_from;
1747
1748 Node* const substr = a->SubString(context, string, from, to);
1749 array.Push(substr);
1750
1751 a->GotoIf(a->WordEqual(array.length(), int_limit), &out);
1752 }
1753
1754 // Add all captures to the array.
1755 {
1756 Node* const num_registers = a->LoadFixedArrayElement(
1757 match_indices,
1758 a->IntPtrConstant(RegExpMatchInfo::kNumberOfCapturesIndex), 0, mode);
1759 Node* const int_num_registers = a->SmiUntag(num_registers);
1760
1761 CVariable var_reg(a, MachineType::PointerRepresentation());
1762 var_reg.Bind(a->IntPtrConstant(2));
1763
1764 CVariable* vars[] = {array.var_array(), array.var_length(),
1765 array.var_capacity(), &var_reg};
1766 const int vars_count = sizeof(vars) / sizeof(vars[0]);
1767 CLabel nested_loop(a, vars_count, vars), nested_loop_out(a);
Igor Sheludko 2016/11/30 20:47:31 Consider using CSA::BuildFastLoop(). Maybe in next
jgruber 2016/12/01 07:56:24 Acknowledged.
1768 a->Branch(a->IntPtrLessThan(var_reg.value(), int_num_registers),
1769 &nested_loop, &nested_loop_out);
1770
1771 a->Bind(&nested_loop);
1772 {
1773 Node* const reg = var_reg.value();
1774 Node* const from = a->LoadFixedArrayElement(
1775 match_indices, reg,
1776 RegExpMatchInfo::kFirstCaptureIndex * kPointerSize, mode);
1777
1778 Node* const reg_plus_one = a->IntPtrAdd(reg, a->IntPtrConstant(1));
1779 Node* const to = a->LoadFixedArrayElement(
1780 match_indices, reg_plus_one,
1781 RegExpMatchInfo::kFirstCaptureIndex * kPointerSize, mode);
Igor Sheludko 2016/11/30 20:47:31 I think the generated code will be better if you a
jgruber 2016/12/01 07:56:24 You're right, we save one lea instruction. Done.
1782
1783 CLabel select_capture(a), select_undefined(a), store_value(a);
1784 CVariable var_value(a, MachineRepresentation::kTagged);
1785 a->Branch(a->SmiEqual(to, a->SmiConstant(-1)), &select_undefined,
1786 &select_capture);
1787
1788 a->Bind(&select_capture);
1789 {
1790 Node* const substr = a->SubString(context, string, from, to);
1791 var_value.Bind(substr);
1792 a->Goto(&store_value);
1793 }
1794
1795 a->Bind(&select_undefined);
1796 {
1797 Node* const undefined = a->UndefinedConstant();
1798 var_value.Bind(undefined);
1799 a->Goto(&store_value);
1800 }
1801
1802 a->Bind(&store_value);
1803 {
1804 array.Push(var_value.value());
1805 a->GotoIf(a->WordEqual(array.length(), int_limit), &out);
1806
1807 Node* const new_reg = a->IntPtrAdd(reg, a->IntPtrConstant(2));
1808 var_reg.Bind(new_reg);
1809
1810 a->Branch(a->IntPtrLessThan(new_reg, int_num_registers), &nested_loop,
1811 &nested_loop_out);
1812 }
1728 } 1813 }
1729 1814
1730 if (static_cast<uint32_t>(num_elems) == limit) { 1815 a->Bind(&nested_loop_out);
1731 return NewJSArrayWithElements(isolate, elems, num_elems); 1816 }
1732 } 1817
1733 } 1818 var_last_matched_until.Bind(match_to);
1734 1819 var_next_search_from.Bind(match_to);
1735 start_index = current_index = end_index; 1820 a->Goto(&loop);
1736 } 1821 }
1737 1822
1738 return NewJSArrayWithElements(isolate, elems, num_elems); 1823 a->Bind(&push_suffix_and_out);
1739 } 1824 {
1740 1825 Node* const from = var_last_matched_until.value();
1741 // ES##sec-speciesconstructor 1826 Node* const to = string_length;
1742 // SpeciesConstructor ( O, defaultConstructor ) 1827
1743 MUST_USE_RESULT MaybeHandle<Object> SpeciesConstructor( 1828 Node* const substr = a->SubString(context, string, from, to);
1744 Isolate* isolate, Handle<JSReceiver> recv, 1829 array.Push(substr);
1745 Handle<JSFunction> default_ctor) { 1830
1746 Handle<Object> ctor_obj; 1831 a->Goto(&out);
1747 ASSIGN_RETURN_ON_EXCEPTION( 1832 }
1748 isolate, ctor_obj, 1833
1749 JSObject::GetProperty(recv, isolate->factory()->constructor_string()), 1834 a->Bind(&out);
1750 Object); 1835 {
1751 1836 Node* const result = array.ToJSArray(context);
1752 if (ctor_obj->IsUndefined(isolate)) return default_ctor; 1837 a->Return(result);
1753 1838 }
1754 if (!ctor_obj->IsJSReceiver()) { 1839
1755 THROW_NEW_ERROR(isolate, 1840 a->Bind(&return_empty_array);
1756 NewTypeError(MessageTemplate::kConstructorNotReceiver), 1841 {
1757 Object); 1842 Node* const length = smi_zero;
1758 } 1843 Node* const capacity = int_zero;
1759 1844 Node* const result = a->AllocateJSArray(kind, array_map, capacity, length,
1760 Handle<JSReceiver> ctor = Handle<JSReceiver>::cast(ctor_obj); 1845 allocation_site, mode);
1761 1846 a->Return(result);
1762 Handle<Object> species; 1847 }
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 } 1848 }
1777 1849
1778 } // namespace 1850 } // namespace
1779 1851
1780 // ES#sec-regexp.prototype-@@split 1852 // ES#sec-regexp.prototype-@@split
1781 // RegExp.prototype [ @@split ] ( string, limit ) 1853 // RegExp.prototype [ @@split ] ( string, limit )
1782 BUILTIN(RegExpPrototypeSplit) { 1854 void Builtins::Generate_RegExpPrototypeSplit(CodeAssemblerState* state) {
1783 HandleScope scope(isolate); 1855 CodeStubAssembler a(state);
1784 CHECK_RECEIVER(JSReceiver, recv, "RegExp.prototype.@@split"); 1856
1785 1857 Isolate* const isolate = a.isolate();
1786 Factory* factory = isolate->factory(); 1858
1787 1859 Node* const undefined = a.UndefinedConstant();
1788 Handle<Object> string_obj = args.atOrUndefined(isolate, 1); 1860
1789 Handle<Object> limit_obj = args.atOrUndefined(isolate, 2); 1861 Node* const maybe_receiver = a.Parameter(0);
1790 1862 Node* const maybe_string = a.Parameter(1);
1791 Handle<String> string; 1863 Node* const maybe_limit = a.Parameter(2);
1792 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, string, 1864 Node* const context = a.Parameter(5);
1793 Object::ToString(isolate, string_obj)); 1865
1794 1866 // Ensure {maybe_receiver} is a JSReceiver.
1795 if (RegExpUtils::IsUnmodifiedRegExp(isolate, recv)) { 1867 Node* const map = ThrowIfNotJSReceiver(
1796 RETURN_RESULT_OR_FAILURE( 1868 &a, isolate, context, maybe_receiver,
1797 isolate, 1869 MessageTemplate::kIncompatibleMethodReceiver, "RegExp.prototype.@@split");
1798 RegExpSplit(isolate, Handle<JSRegExp>::cast(recv), string, limit_obj)); 1870 Node* const receiver = maybe_receiver;
1799 } 1871
1800 1872 // Convert {maybe_string} to a String.
1801 Handle<JSFunction> regexp_fun = isolate->regexp_function(); 1873 Node* const string = a.ToString(context, maybe_string);
1802 Handle<Object> ctor; 1874
1803 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 1875 CLabel fast_path(&a), slow_path(&a);
1804 isolate, ctor, SpeciesConstructor(isolate, recv, regexp_fun)); 1876 BranchIfFastPath(&a, context, map, &fast_path, &slow_path);
1805 1877
1806 Handle<Object> flags_obj; 1878 a.Bind(&fast_path);
1807 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 1879 {
1808 isolate, flags_obj, JSObject::GetProperty(recv, factory->flags_string())); 1880 // Convert {maybe_limit} to a uint32, capping at the maximal smi value.
1809 1881 CVariable var_limit(&a, MachineRepresentation::kTagged);
1810 Handle<String> flags; 1882 CLabel if_limitissmimax(&a), limit_done(&a);
1811 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, flags, 1883
1812 Object::ToString(isolate, flags_obj)); 1884 a.GotoIf(a.WordEqual(maybe_limit, undefined), &if_limitissmimax);
1813 1885
1814 Handle<String> u_str = factory->LookupSingleCharacterStringFromCode('u'); 1886 Node* const uint32_limit = a.ToUint32(context, maybe_limit);
Igor Sheludko 2016/11/30 20:47:31 uint32_limit name is confusing. How about just lim
jgruber 2016/12/01 07:56:24 Done.
1815 const bool unicode = (String::IndexOf(isolate, flags, u_str, 0) >= 0); 1887 a.GotoUnless(a.TaggedIsSmi(uint32_limit), &if_limitissmimax);
1816 1888
1817 Handle<String> y_str = factory->LookupSingleCharacterStringFromCode('y'); 1889 var_limit.Bind(uint32_limit);
1818 const bool sticky = (String::IndexOf(isolate, flags, y_str, 0) >= 0); 1890 a.Goto(&limit_done);
1819 1891
1820 Handle<String> new_flags = flags; 1892 a.Bind(&if_limitissmimax);
1821 if (!sticky) { 1893 {
1822 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, new_flags, 1894 const uint32_t kSmiMaxValue = static_cast<uint32_t>(
1823 factory->NewConsString(flags, y_str)); 1895 (1ULL << (PlatformSmiTagging::SmiValueSize() - 1)) - 1);
1824 } 1896 Node* const smi_max = a.SmiConstant(kSmiMaxValue);
Igor Sheludko 2016/11/30 20:47:31 Smi::kMaxValue
jgruber 2016/12/01 07:56:24 Done.
1825 1897 var_limit.Bind(smi_max);
1826 Handle<JSReceiver> splitter; 1898 a.Goto(&limit_done);
1827 { 1899 }
1828 const int argc = 2; 1900
1829 1901 a.Bind(&limit_done);
1830 ScopedVector<Handle<Object>> argv(argc); 1902 Node* const limit = var_limit.value();
1831 argv[0] = recv; 1903
1832 argv[1] = new_flags; 1904 Generate_RegExpPrototypeSplitBody(&a, receiver, string, limit, context);
1833 1905 }
1834 Handle<JSFunction> ctor_fun = Handle<JSFunction>::cast(ctor); 1906
1835 Handle<Object> splitter_obj; 1907 a.Bind(&slow_path);
1836 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 1908 {
1837 isolate, splitter_obj, Execution::New(ctor_fun, argc, argv.start())); 1909 Node* const result = a.CallRuntime(Runtime::kRegExpSplit, context, receiver,
1838 1910 string, maybe_limit);
1839 splitter = Handle<JSReceiver>::cast(splitter_obj); 1911 a.Return(result);
1840 } 1912 }
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 } 1913 }
1942 1914
1943 namespace { 1915 namespace {
1944 1916
1945 Node* ReplaceGlobalCallableFastPath(CodeStubAssembler* a, Node* context, 1917 Node* ReplaceGlobalCallableFastPath(CodeStubAssembler* a, Node* context,
1946 Node* regexp, Node* subject_string, 1918 Node* regexp, Node* subject_string,
1947 Node* replace_callable) { 1919 Node* replace_callable) {
1948 // The fast path is reached only if {receiver} is a global unmodified 1920 // The fast path is reached only if {receiver} is a global unmodified
1949 // JSRegExp instance and {replace_callable} is callable. 1921 // JSRegExp instance and {replace_callable} is callable.
1950 1922
(...skipping 14 matching lines...) Expand all
1965 FastStoreLastIndex(a, context, regexp, smi_zero); 1937 FastStoreLastIndex(a, context, regexp, smi_zero);
1966 1938
1967 // Allocate {result_array}. 1939 // Allocate {result_array}.
1968 Node* result_array; 1940 Node* result_array;
1969 { 1941 {
1970 ElementsKind kind = FAST_ELEMENTS; 1942 ElementsKind kind = FAST_ELEMENTS;
1971 Node* const array_map = a->LoadJSArrayElementsMap(kind, native_context); 1943 Node* const array_map = a->LoadJSArrayElementsMap(kind, native_context);
1972 Node* const capacity = a->IntPtrConstant(16); 1944 Node* const capacity = a->IntPtrConstant(16);
1973 Node* const length = smi_zero; 1945 Node* const length = smi_zero;
1974 Node* const allocation_site = nullptr; 1946 Node* const allocation_site = nullptr;
1975 CodeStubAssembler::ParameterMode capacity_mode = 1947 ParameterMode capacity_mode = CodeStubAssembler::INTPTR_PARAMETERS;
1976 CodeStubAssembler::INTPTR_PARAMETERS;
1977 1948
1978 result_array = a->AllocateJSArray(kind, array_map, capacity, length, 1949 result_array = a->AllocateJSArray(kind, array_map, capacity, length,
1979 allocation_site, capacity_mode); 1950 allocation_site, capacity_mode);
1980 } 1951 }
1981 1952
1982 // Call into runtime for RegExpExecMultiple. 1953 // Call into runtime for RegExpExecMultiple.
1983 Node* last_match_info = a->LoadContextElement( 1954 Node* last_match_info = a->LoadContextElement(
1984 native_context, Context::REGEXP_LAST_MATCH_INFO_INDEX); 1955 native_context, Context::REGEXP_LAST_MATCH_INFO_INDEX);
1985 Node* const res = 1956 Node* const res =
1986 a->CallRuntime(Runtime::kRegExpExecMultiple, context, regexp, 1957 a->CallRuntime(Runtime::kRegExpExecMultiple, context, regexp,
1987 subject_string, last_match_info, result_array); 1958 subject_string, last_match_info, result_array);
1988 1959
1989 // Reset last index to 0. 1960 // Reset last index to 0.
1990 FastStoreLastIndex(a, context, regexp, smi_zero); 1961 FastStoreLastIndex(a, context, regexp, smi_zero);
1991 1962
1992 // If no matches, return the subject string. 1963 // If no matches, return the subject string.
1993 var_result.Bind(subject_string); 1964 var_result.Bind(subject_string);
1994 a->GotoIf(a->WordEqual(res, null), &out); 1965 a->GotoIf(a->WordEqual(res, null), &out);
1995 1966
1996 // Reload last match info since it might have changed. 1967 // Reload last match info since it might have changed.
1997 last_match_info = a->LoadContextElement( 1968 last_match_info = a->LoadContextElement(
1998 native_context, Context::REGEXP_LAST_MATCH_INFO_INDEX); 1969 native_context, Context::REGEXP_LAST_MATCH_INFO_INDEX);
1999 1970
2000 Node* const res_length = a->LoadJSArrayLength(res); 1971 Node* const res_length = a->LoadJSArrayLength(res);
2001 Node* const res_elems = a->LoadElements(res); 1972 Node* const res_elems = a->LoadElements(res);
2002 CSA_ASSERT(a, a->HasInstanceType(res_elems, FIXED_ARRAY_TYPE)); 1973 CSA_ASSERT(a, a->HasInstanceType(res_elems, FIXED_ARRAY_TYPE));
2003 1974
2004 CodeStubAssembler::ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS; 1975 ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS;
2005 Node* const num_capture_registers = a->LoadFixedArrayElement( 1976 Node* const num_capture_registers = a->LoadFixedArrayElement(
2006 last_match_info, 1977 last_match_info,
2007 a->IntPtrConstant(RegExpMatchInfo::kNumberOfCapturesIndex), 0, mode); 1978 a->IntPtrConstant(RegExpMatchInfo::kNumberOfCapturesIndex), 0, mode);
2008 1979
2009 CLabel if_hasexplicitcaptures(a), if_noexplicitcaptures(a), create_result(a); 1980 CLabel if_hasexplicitcaptures(a), if_noexplicitcaptures(a), create_result(a);
2010 a->Branch(a->SmiEqual(num_capture_registers, a->SmiConstant(Smi::FromInt(2))), 1981 a->Branch(a->SmiEqual(num_capture_registers, a->SmiConstant(Smi::FromInt(2))),
2011 &if_noexplicitcaptures, &if_hasexplicitcaptures); 1982 &if_noexplicitcaptures, &if_hasexplicitcaptures);
2012 1983
2013 a->Bind(&if_noexplicitcaptures); 1984 a->Bind(&if_noexplicitcaptures);
2014 { 1985 {
(...skipping 12 matching lines...) Expand all
2027 var_i.Bind(int_zero); 1998 var_i.Bind(int_zero);
2028 1999
2029 CVariable* vars[] = {&var_i, &var_match_start}; 2000 CVariable* vars[] = {&var_i, &var_match_start};
2030 CLabel loop(a, 2, vars); 2001 CLabel loop(a, 2, vars);
2031 a->Goto(&loop); 2002 a->Goto(&loop);
2032 a->Bind(&loop); 2003 a->Bind(&loop);
2033 { 2004 {
2034 Node* const i = var_i.value(); 2005 Node* const i = var_i.value();
2035 a->GotoUnless(a->IntPtrLessThan(i, end), &create_result); 2006 a->GotoUnless(a->IntPtrLessThan(i, end), &create_result);
2036 2007
2037 CodeStubAssembler::ParameterMode mode = 2008 ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS;
2038 CodeStubAssembler::INTPTR_PARAMETERS;
2039 Node* const elem = a->LoadFixedArrayElement(res_elems, i, 0, mode); 2009 Node* const elem = a->LoadFixedArrayElement(res_elems, i, 0, mode);
2040 2010
2041 CLabel if_issmi(a), if_isstring(a), loop_epilogue(a); 2011 CLabel if_issmi(a), if_isstring(a), loop_epilogue(a);
2042 a->Branch(a->TaggedIsSmi(elem), &if_issmi, &if_isstring); 2012 a->Branch(a->TaggedIsSmi(elem), &if_issmi, &if_isstring);
2043 2013
2044 a->Bind(&if_issmi); 2014 a->Bind(&if_issmi);
2045 { 2015 {
2046 // Integers represent slices of the original string. 2016 // Integers represent slices of the original string.
2047 CLabel if_isnegativeorzero(a), if_ispositive(a); 2017 CLabel if_isnegativeorzero(a), if_ispositive(a);
2048 a->BranchIfSmiLessThanOrEqual(elem, smi_zero, &if_isnegativeorzero, 2018 a->BranchIfSmiLessThanOrEqual(elem, smi_zero, &if_isnegativeorzero,
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
2095 a->Bind(&loop_epilogue); 2065 a->Bind(&loop_epilogue);
2096 { 2066 {
2097 var_i.Bind(a->IntPtrAdd(var_i.value(), int_one)); 2067 var_i.Bind(a->IntPtrAdd(var_i.value(), int_one));
2098 a->Goto(&loop); 2068 a->Goto(&loop);
2099 } 2069 }
2100 } 2070 }
2101 } 2071 }
2102 2072
2103 a->Bind(&if_hasexplicitcaptures); 2073 a->Bind(&if_hasexplicitcaptures);
2104 { 2074 {
2105 CodeStubAssembler::ParameterMode mode = 2075 ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS;
2106 CodeStubAssembler::INTPTR_PARAMETERS;
2107 2076
2108 Node* const from = int_zero; 2077 Node* const from = int_zero;
2109 Node* const to = a->SmiUntag(res_length); 2078 Node* const to = a->SmiUntag(res_length);
2110 const int increment = 1; 2079 const int increment = 1;
2111 2080
2112 a->BuildFastLoop( 2081 a->BuildFastLoop(
2113 MachineType::PointerRepresentation(), from, to, 2082 MachineType::PointerRepresentation(), from, to,
2114 [res_elems, isolate, native_context, context, undefined, 2083 [res_elems, isolate, native_context, context, undefined,
2115 replace_callable, mode](CodeStubAssembler* a, Node* index) { 2084 replace_callable, mode](CodeStubAssembler* a, Node* index) {
2116 Node* const elem = 2085 Node* const elem =
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
2213 2182
2214 a->Bind(&if_didnotmatch); 2183 a->Bind(&if_didnotmatch);
2215 { 2184 {
2216 FastStoreLastIndex(a, context, regexp, smi_zero); 2185 FastStoreLastIndex(a, context, regexp, smi_zero);
2217 var_result.Bind(subject_string); 2186 var_result.Bind(subject_string);
2218 a->Goto(&out); 2187 a->Goto(&out);
2219 } 2188 }
2220 2189
2221 a->Bind(&if_matched); 2190 a->Bind(&if_matched);
2222 { 2191 {
2223 CodeStubAssembler::ParameterMode mode = 2192 ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS;
2224 CodeStubAssembler::INTPTR_PARAMETERS;
2225 2193
2226 Node* const subject_start = smi_zero; 2194 Node* const subject_start = smi_zero;
2227 Node* const match_start = a->LoadFixedArrayElement( 2195 Node* const match_start = a->LoadFixedArrayElement(
2228 match_indices, a->IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex), 2196 match_indices, a->IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex),
2229 0, mode); 2197 0, mode);
2230 Node* const match_end = a->LoadFixedArrayElement( 2198 Node* const match_end = a->LoadFixedArrayElement(
2231 match_indices, 2199 match_indices,
2232 a->IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex + 1), 0, mode); 2200 a->IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex + 1), 0, mode);
2233 Node* const subject_end = a->LoadStringLength(subject_string); 2201 Node* const subject_end = a->LoadStringLength(subject_string);
2234 2202
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
2397 a.Bind(&if_matched); 2365 a.Bind(&if_matched);
2398 { 2366 {
2399 Node* result = ConstructNewResultFromMatchInfo(isolate, &a, context, 2367 Node* result = ConstructNewResultFromMatchInfo(isolate, &a, context,
2400 match_indices, string); 2368 match_indices, string);
2401 a.Return(result); 2369 a.Return(result);
2402 } 2370 }
2403 } 2371 }
2404 2372
2405 } // namespace internal 2373 } // namespace internal
2406 } // namespace v8 2374 } // namespace v8
OLDNEW
« no previous file with comments | « src/builtins/builtins.h ('k') | src/code-stub-assembler.h » ('j') | src/code-stub-assembler.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698