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

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

Issue 2438683005: [regexp] Move RegExp.prototype[@@search] to TF (Closed)
Patch Set: Fix typo in lastindex restoration Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/builtins/builtins.h ('k') | no next file » | 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"
(...skipping 1126 matching lines...) Expand 10 before | Expand all | Expand 10 after
1137 isolate, recv, string, unicode)); 1137 isolate, recv, string, unicode));
1138 } 1138 }
1139 } 1139 }
1140 1140
1141 elems->Shrink(n); 1141 elems->Shrink(n);
1142 return *isolate->factory()->NewJSArrayWithElements(elems); 1142 return *isolate->factory()->NewJSArrayWithElements(elems);
1143 } 1143 }
1144 1144
1145 // ES#sec-regexp.prototype-@@search 1145 // ES#sec-regexp.prototype-@@search
1146 // RegExp.prototype [ @@search ] ( string ) 1146 // RegExp.prototype [ @@search ] ( string )
1147 BUILTIN(RegExpPrototypeSearch) { 1147 void Builtins::Generate_RegExpPrototypeSearch(CodeStubAssembler* a) {
1148 HandleScope scope(isolate); 1148 typedef CodeStubAssembler::Label Label;
1149 CHECK_RECEIVER(JSReceiver, recv, "RegExp.prototype.@@search"); 1149 typedef compiler::Node Node;
1150 1150
1151 Handle<Object> string_obj = args.atOrUndefined(isolate, 1); 1151 Isolate* const isolate = a->isolate();
1152 1152
1153 Handle<String> string; 1153 Node* const maybe_receiver = a->Parameter(0);
1154 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, string, 1154 Node* const maybe_string = a->Parameter(1);
1155 Object::ToString(isolate, string_obj)); 1155 Node* const context = a->Parameter(4);
1156 1156
1157 Handle<Object> previous_last_index_obj; 1157 Node* const smi_zero = a->SmiConstant(Smi::kZero);
1158 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, previous_last_index_obj,
1159 RegExpUtils::GetLastIndex(isolate, recv));
1160 1158
1161 if (!previous_last_index_obj->IsSmi() || 1159 // TODO(jgruber): If we need to optimize this further, we could add an entire
1162 Smi::cast(*previous_last_index_obj)->value() != 0) { 1160 // separate fast-path, skipping all follow-up map checks since we can
1163 RETURN_FAILURE_ON_EXCEPTION(isolate, 1161 // guarantee they won't change. The downside is more code to maintain.
1164 RegExpUtils::SetLastIndex(isolate, recv, 0)); 1162
1163 // Ensure {maybe_receiver} is a JSReceiver.
1164 Node* const map =
1165 ThrowIfNotJSReceiver(a, isolate, context, maybe_receiver,
1166 MessageTemplate::kIncompatibleMethodReceiver,
1167 "RegExp.prototype.@@search");
1168 Node* const receiver = maybe_receiver;
1169
1170 // Convert {maybe_string} to a String.
1171 Node* const string = a->ToString(context, maybe_string);
1172
1173 // Grab the initial value of last index.
1174 Node* has_initialmap = IsInitialRegExpMap(a, context, map);
1175 Node* const previous_last_index =
1176 LoadLastIndex(a, context, has_initialmap, receiver);
1177
1178 // Ensure last index is 0.
1179 {
1180 Label next(a);
1181 a->GotoIf(a->WordEqual(previous_last_index, smi_zero), &next);
1182
1183 StoreLastIndex(a, context, has_initialmap, receiver, smi_zero);
Yang 2016/10/25 07:30:12 The spec actually suggests to always set the last
jgruber 2016/10/25 08:40:57 The spec has changed fairly recently to avoid unne
1184 a->Goto(&next);
1185
1186 a->Bind(&next);
1165 } 1187 }
1166 1188
1167 Handle<Object> result; 1189 // Call exec.
1168 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 1190 Node* const match_indices = RegExpExec(a, context, receiver, string);
1169 isolate, result,
1170 RegExpUtils::RegExpExec(isolate, recv, string,
1171 isolate->factory()->undefined_value()));
1172 1191
1173 Handle<Object> current_last_index_obj; 1192 // Reset last index if necessary.
1174 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, current_last_index_obj, 1193 {
1175 RegExpUtils::GetLastIndex(isolate, recv)); 1194 Label next(a);
1176 1195
1177 Maybe<bool> is_last_index_unchanged = 1196 // Recheck the map since it might have changed.
1178 Object::Equals(current_last_index_obj, previous_last_index_obj); 1197 has_initialmap = IsInitialRegExpMap(a, context, map);
1179 if (is_last_index_unchanged.IsNothing()) return isolate->pending_exception(); 1198
Yang 2016/10/25 07:30:13 This does not seem correct. To throw an exception
jgruber 2016/10/25 08:40:57 Great catch. Looking at this further, we actually
1180 if (!is_last_index_unchanged.FromJust()) { 1199 Node* const current_last_index =
1181 if (previous_last_index_obj->IsSmi()) { 1200 LoadLastIndex(a, context, has_initialmap, receiver);
Yang 2016/10/25 07:30:12 Again, the spec suggests to always overwrite the l
jgruber 2016/10/25 08:40:57 The spec has changed recently (see above).
1182 RETURN_FAILURE_ON_EXCEPTION( 1201
1183 isolate, 1202 a->GotoIf(a->WordEqual(current_last_index, previous_last_index), &next);
1184 RegExpUtils::SetLastIndex( 1203
1185 isolate, recv, Smi::cast(*previous_last_index_obj)->value())); 1204 StoreLastIndex(a, context, has_initialmap, receiver, previous_last_index);
1186 } else { 1205 a->Goto(&next);
1187 RETURN_FAILURE_ON_EXCEPTION( 1206
1188 isolate, 1207 a->Bind(&next);
1189 Object::SetProperty(recv, isolate->factory()->lastIndex_string(), 1208 }
1190 previous_last_index_obj, STRICT)); 1209
1210 // Return -1 if no match was found.
1211 {
1212 Label next(a);
1213 a->GotoUnless(a->WordEqual(match_indices, a->NullConstant()), &next);
1214 a->Return(a->SmiConstant(Smi::FromInt(-1)));
1215 a->Bind(&next);
1216 }
1217
1218 // Return the index of the match.
1219 {
1220 Label fast_path(a), slow_path(a, Label::kDeferred);
1221
1222 Node* const native_context = a->LoadNativeContext(context);
1223 Node* const initial_regexp_result_map =
1224 a->LoadContextElement(native_context, Context::REGEXP_RESULT_MAP_INDEX);
1225 Node* const match_indices_map = a->LoadMap(match_indices);
1226
1227 a->Branch(a->WordEqual(match_indices_map, initial_regexp_result_map),
1228 &fast_path, &slow_path);
1229
1230 a->Bind(&fast_path);
1231 {
1232 Node* const index =
1233 a->LoadObjectField(match_indices, JSRegExpResult::kIndexOffset,
1234 MachineType::AnyTagged());
1235 a->Return(index);
1236 }
1237
1238 a->Bind(&slow_path);
1239 {
1240 Node* const name = a->HeapConstant(isolate->factory()->index_string());
1241 Callable getproperty_callable = CodeFactory::GetProperty(a->isolate());
1242 Node* const index =
1243 a->CallStub(getproperty_callable, context, match_indices, name);
1244 a->Return(index);
1191 } 1245 }
1192 } 1246 }
1193
1194 if (result->IsNull(isolate)) return Smi::FromInt(-1);
1195
1196 RETURN_RESULT_OR_FAILURE(
1197 isolate, Object::GetProperty(result, isolate->factory()->index_string()));
1198 } 1247 }
1199 1248
1200 namespace { 1249 namespace {
1201 1250
1202 MUST_USE_RESULT MaybeHandle<Object> ToUint32(Isolate* isolate, 1251 MUST_USE_RESULT MaybeHandle<Object> ToUint32(Isolate* isolate,
1203 Handle<Object> object, 1252 Handle<Object> object,
1204 uint32_t* out) { 1253 uint32_t* out) {
1205 if (object->IsUndefined(isolate)) { 1254 if (object->IsUndefined(isolate)) {
1206 *out = kMaxUInt32; 1255 *out = kMaxUInt32;
1207 return object; 1256 return object;
(...skipping 802 matching lines...) Expand 10 before | Expand all | Expand 10 after
2010 a->Bind(&if_matched); 2059 a->Bind(&if_matched);
2011 { 2060 {
2012 Node* result = ConstructNewResultFromMatchInfo(isolate, a, context, 2061 Node* result = ConstructNewResultFromMatchInfo(isolate, a, context,
2013 match_indices, string); 2062 match_indices, string);
2014 a->Return(result); 2063 a->Return(result);
2015 } 2064 }
2016 } 2065 }
2017 2066
2018 } // namespace internal 2067 } // namespace internal
2019 } // namespace v8 2068 } // namespace v8
OLDNEW
« no previous file with comments | « src/builtins/builtins.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698