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

Side by Side Diff: src/runtime.cc

Issue 1014005: Attempt at pre-calculating replace regexp matches. (Closed)
Patch Set: Reuse result array. Avoid using apply. Created 10 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/runtime.h ('k') | src/string.js » ('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 2006-2009 the V8 project authors. All rights reserved. 1 // Copyright 2006-2009 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 1208 matching lines...) Expand 10 before | Expand all | Expand 10 after
1219 RUNTIME_ASSERT(index <= subject->length()); 1219 RUNTIME_ASSERT(index <= subject->length());
1220 Counters::regexp_entry_runtime.Increment(); 1220 Counters::regexp_entry_runtime.Increment();
1221 Handle<Object> result = RegExpImpl::Exec(regexp, 1221 Handle<Object> result = RegExpImpl::Exec(regexp,
1222 subject, 1222 subject,
1223 index, 1223 index,
1224 last_match_info); 1224 last_match_info);
1225 if (result.is_null()) return Failure::Exception(); 1225 if (result.is_null()) return Failure::Exception();
1226 return *result; 1226 return *result;
1227 } 1227 }
1228 1228
1229 static Object* Runtime_RegExpExecMultiple(Arguments args) {
1230 HandleScope scope;
1231 ASSERT(args.length() == 4);
1232
1233 CONVERT_ARG_CHECKED(JSRegExp, regexp, 0);
1234 CONVERT_ARG_CHECKED(String, subject, 1);
1235 CONVERT_ARG_CHECKED(JSArray, last_match_info, 2);
1236 CONVERT_ARG_CHECKED(JSArray, result_array, 3);
1237 RUNTIME_ASSERT(last_match_info->HasFastElements());
1238 RUNTIME_ASSERT(result_array->HasFastElements());
1239 RUNTIME_ASSERT(regexp->GetFlags().is_global());
1240
1241 ZoneScope zone(DELETE_ON_EXIT);
1242 // TODO(lrn): Be much smarter about calling the regexp exec
1243 // function in a loop! And split execution into Atom and Irregexp
1244 // parts (atoms never have captures and can call StringMatch directly).
1245 ZoneList<Smi*> captures(256);
1246 // Number of captures per regexp match (excluding the match itself).
1247
1248 int capture_count =
1249 RegExpImpl::RegExpNumberOfCaptures(FixedArray::cast(regexp->data()));
1250 int subject_length = subject->length();
1251
1252 // Execute regexp once. If absolutely no match, we exit fast.
1253 // Otherwise prepare to repeat execution.
1254 Handle<Object> result =
1255 RegExpImpl::Exec(regexp, subject, 0, last_match_info);
1256 if (result.is_null()) {
1257 return Failure::Exception();
1258 }
1259 if (result->IsNull()) {
1260 // No match at all, return null.
1261 return Smi::FromInt(0);
1262 }
1263
1264 ASSERT_EQ(*last_match_info, *result);
1265 ASSERT(last_match_info->HasFastElements());
1266
1267 // Include the match itself as a capture.
1268 int capture_reg_count = (capture_count + 1) * 2;
1269
1270 ASSERT_EQ(capture_reg_count,
1271 Smi::cast(FixedArray::cast(last_match_info->elements())->
1272 get(RegExpImpl::kLastCaptureCount))->value());
1273
1274 int index;
1275 int matches = 0;
1276 do {
1277 {
1278 AssertNoAllocation no_gc;
1279 ASSERT(last_match_info->HasFastElements());
1280
1281 FixedArray* match_array = FixedArray::cast(last_match_info->elements());
1282 Smi* match_start =
1283 Smi::cast(match_array->get(RegExpImpl::kFirstCapture));
1284 Smi* match_end =
1285 Smi::cast(match_array->get(RegExpImpl::kFirstCapture + 1));
1286 captures.Add(match_start);
1287 captures.Add(match_end);
1288 // TODO(lrn): Expand, if necessary, captures list in one go and
1289 // use memcpy to copy captures.
1290 for (int i = 2; i < capture_reg_count; i++) {
1291 captures.Add(
1292 Smi::cast(match_array->get(RegExpImpl::kFirstCapture + i)));
1293 }
1294 matches++;
1295 index = match_end->value();
1296 if (match_start == match_end) {
1297 index++;
1298 if (index > subject_length) {
1299 break;
1300 }
1301 }
1302 }
1303 result = RegExpImpl::Exec(regexp, subject, index, last_match_info);
1304 if (result.is_null()) {
1305 return Failure::Exception();
1306 }
1307 } while (!result->IsNull());
1308
1309 // Done collecting match indices. Now create a result array on the format:
1310 // - Smi number of captures (not including match) per match
1311 // - for each match:
1312 // - smi index of match
1313 // - match substring
1314 // - for each capture
1315 // - captured substring, or undefined if capture is not participating.
1316 int array_length = 1 + (2 + capture_count) * matches;
1317 result_array->Resize(array_length);
1318 result_array->set_length(Smi::FromInt(array_length));
1319 Handle<FixedArray> elements(FixedArray::cast(result_array->elements()));
1320
1321 elements->set(0, Smi::FromInt(capture_count));
1322 int capture_index = 0;
1323 int result_index = 1;
1324 for (int i = 0; i < matches; i++) {
1325 Smi* from = captures.at(capture_index);
1326 Smi* to = captures.at(capture_index + 1);
1327 elements->set(result_index, from);
1328 elements->set(result_index + 1, *Factory::NewSubString(subject,
1329 from->value(),
1330 to->value()));
1331 result_index += 2;
1332 capture_index += 2;
1333 for (int j = 0; j < capture_count; j++) {
1334 int from = captures.at(capture_index)->value();
1335 if (from >= 0) {
1336 int to = captures.at(capture_index + 1)->value();
1337 ASSERT(to >= 0);
1338 elements->set(result_index,
1339 *Factory::NewSubString(subject, from, to));
1340 } else {
1341 ASSERT(captures.at(capture_index + 1)->value() < 0);
1342 elements->set(result_index, Heap::undefined_value());
1343 }
1344 capture_index += 2;
1345 result_index++;
1346 }
1347 }
1348
1349 return Smi::FromInt(matches);
1350 }
1351
1229 1352
1230 static Object* Runtime_FinishArrayPrototypeSetup(Arguments args) { 1353 static Object* Runtime_FinishArrayPrototypeSetup(Arguments args) {
1231 HandleScope scope; 1354 HandleScope scope;
1232 ASSERT(args.length() == 1); 1355 ASSERT(args.length() == 1);
1233 CONVERT_ARG_CHECKED(JSArray, prototype, 0); 1356 CONVERT_ARG_CHECKED(JSArray, prototype, 0);
1234 // This is necessary to enable fast checks for absence of elements 1357 // This is necessary to enable fast checks for absence of elements
1235 // on Array.prototype and below. 1358 // on Array.prototype and below.
1236 prototype->set_elements(Heap::empty_fixed_array()); 1359 prototype->set_elements(Heap::empty_fixed_array());
1237 return Smi::FromInt(0); 1360 return Smi::FromInt(0);
1238 } 1361 }
(...skipping 3827 matching lines...) Expand 10 before | Expand all | Expand 10 after
5066 prefix_length = y->length(); 5189 prefix_length = y->length();
5067 equal_prefix_result = Smi::FromInt(GREATER); 5190 equal_prefix_result = Smi::FromInt(GREATER);
5068 } else if (y->length() > prefix_length) { 5191 } else if (y->length() > prefix_length) {
5069 equal_prefix_result = Smi::FromInt(LESS); 5192 equal_prefix_result = Smi::FromInt(LESS);
5070 } 5193 }
5071 int r; 5194 int r;
5072 if (x->IsAsciiRepresentation()) { 5195 if (x->IsAsciiRepresentation()) {
5073 Vector<const char> x_chars = x->ToAsciiVector(); 5196 Vector<const char> x_chars = x->ToAsciiVector();
5074 if (y->IsAsciiRepresentation()) { 5197 if (y->IsAsciiRepresentation()) {
5075 Vector<const char> y_chars = y->ToAsciiVector(); 5198 Vector<const char> y_chars = y->ToAsciiVector();
5076 r = CompareChars(x_chars.start(), y_chars.start(), prefix_length); 5199 r = memcmp(x_chars.start(), y_chars.start(), prefix_length);
5077 } else { 5200 } else {
5078 Vector<const uc16> y_chars = y->ToUC16Vector(); 5201 Vector<const uc16> y_chars = y->ToUC16Vector();
5079 r = CompareChars(x_chars.start(), y_chars.start(), prefix_length); 5202 r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
5080 } 5203 }
5081 } else { 5204 } else {
5082 Vector<const uc16> x_chars = x->ToUC16Vector(); 5205 Vector<const uc16> x_chars = x->ToUC16Vector();
5083 if (y->IsAsciiRepresentation()) { 5206 if (y->IsAsciiRepresentation()) {
5084 Vector<const char> y_chars = y->ToAsciiVector(); 5207 Vector<const char> y_chars = y->ToAsciiVector();
5085 r = CompareChars(x_chars.start(), y_chars.start(), prefix_length); 5208 r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
5086 } else { 5209 } else {
(...skipping 27 matching lines...) Expand all
5114 if (x->length() == 0) return Smi::FromInt(EQUAL); 5237 if (x->length() == 0) return Smi::FromInt(EQUAL);
5115 return Smi::FromInt(GREATER); 5238 return Smi::FromInt(GREATER);
5116 } else if (x->length() == 0) { 5239 } else if (x->length() == 0) {
5117 return Smi::FromInt(LESS); 5240 return Smi::FromInt(LESS);
5118 } 5241 }
5119 5242
5120 int d = x->Get(0) - y->Get(0); 5243 int d = x->Get(0) - y->Get(0);
5121 if (d < 0) return Smi::FromInt(LESS); 5244 if (d < 0) return Smi::FromInt(LESS);
5122 else if (d > 0) return Smi::FromInt(GREATER); 5245 else if (d > 0) return Smi::FromInt(GREATER);
5123 5246
5124 Object* obj = Heap::PrepareForCompare(x); 5247 x->TryFlatten();
5125 if (obj->IsFailure()) return obj; 5248 y->TryFlatten();
5126 obj = Heap::PrepareForCompare(y);
5127 if (obj->IsFailure()) return obj;
5128 5249
5129 return (x->IsFlat() && y->IsFlat()) ? FlatStringCompare(x, y) 5250 return (x->IsFlat() && y->IsFlat()) ? FlatStringCompare(x, y)
5130 : StringInputBufferCompare(x, y); 5251 : StringInputBufferCompare(x, y);
5131 } 5252 }
5132 5253
5133 5254
5134 static Object* Runtime_Math_acos(Arguments args) { 5255 static Object* Runtime_Math_acos(Arguments args) {
5135 NoHandleAllocation ha; 5256 NoHandleAllocation ha;
5136 ASSERT(args.length() == 1); 5257 ASSERT(args.length() == 1);
5137 Counters::math_acos.Increment(); 5258 Counters::math_acos.Increment();
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after
5318 } else { 5439 } else {
5319 return Heap::AllocateHeapNumber(pow(x, y)); 5440 return Heap::AllocateHeapNumber(pow(x, y));
5320 } 5441 }
5321 } 5442 }
5322 5443
5323 5444
5324 static Object* Runtime_Math_round(Arguments args) { 5445 static Object* Runtime_Math_round(Arguments args) {
5325 NoHandleAllocation ha; 5446 NoHandleAllocation ha;
5326 ASSERT(args.length() == 1); 5447 ASSERT(args.length() == 1);
5327 Counters::math_round.Increment(); 5448 Counters::math_round.Increment();
5449
5328 CONVERT_DOUBLE_CHECKED(x, args[0]); 5450 CONVERT_DOUBLE_CHECKED(x, args[0]);
5329
5330 if (x > 0 && x < Smi::kMaxValue) {
5331 return Smi::FromInt(static_cast<int>(x + 0.5));
5332 }
5333
5334 if (signbit(x) && x >= -0.5) return Heap::minus_zero_value(); 5451 if (signbit(x) && x >= -0.5) return Heap::minus_zero_value();
5335 5452 double integer = ceil(x);
5336 // if the magnitude is big enough, there's no place for fraction part. If we 5453 if (integer - x > 0.5) { integer -= 1.0; }
5337 // try to add 0.5 to this number, 1.0 will be added instead. 5454 return Heap::NumberFromDouble(integer);
5338 if (x >= 9007199254740991.0 || x <= -9007199254740991.0) {
5339 return args[0];
5340 }
5341
5342 return Heap::NumberFromDouble(floor(x + 0.5));
5343 } 5455 }
5344 5456
5345 5457
5346 static Object* Runtime_Math_sin(Arguments args) { 5458 static Object* Runtime_Math_sin(Arguments args) {
5347 NoHandleAllocation ha; 5459 NoHandleAllocation ha;
5348 ASSERT(args.length() == 1); 5460 ASSERT(args.length() == 1);
5349 Counters::math_sin.Increment(); 5461 Counters::math_sin.Increment();
5350 5462
5351 CONVERT_DOUBLE_CHECKED(x, args[0]); 5463 CONVERT_DOUBLE_CHECKED(x, args[0]);
5352 return TranscendentalCache::Get(TranscendentalCache::SIN, x); 5464 return TranscendentalCache::Get(TranscendentalCache::SIN, x);
(...skipping 4029 matching lines...) Expand 10 before | Expand all | Expand 10 after
9382 } else { 9494 } else {
9383 // Handle last resort GC and make sure to allow future allocations 9495 // Handle last resort GC and make sure to allow future allocations
9384 // to grow the heap without causing GCs (if possible). 9496 // to grow the heap without causing GCs (if possible).
9385 Counters::gc_last_resort_from_js.Increment(); 9497 Counters::gc_last_resort_from_js.Increment();
9386 Heap::CollectAllGarbage(false); 9498 Heap::CollectAllGarbage(false);
9387 } 9499 }
9388 } 9500 }
9389 9501
9390 9502
9391 } } // namespace v8::internal 9503 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/runtime.h ('k') | src/string.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698