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

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

Issue 2335343007: Pool implementation for zone segments (Closed)
Patch Set: Fixed Regexp benchmark regression Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/list.h ('k') | src/runtime/runtime-strings.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 the V8 project authors. All rights reserved. 1 // Copyright 2014 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/runtime/runtime-utils.h" 5 #include "src/runtime/runtime-utils.h"
6 6
7 #include "src/arguments.h" 7 #include "src/arguments.h"
8 #include "src/conversions-inl.h" 8 #include "src/conversions-inl.h"
9 #include "src/isolate-inl.h" 9 #include "src/isolate-inl.h"
10 #include "src/messages.h" 10 #include "src/messages.h"
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after
272 case REPLACEMENT_SUBSTRING: 272 case REPLACEMENT_SUBSTRING:
273 case REPLACEMENT_STRING: 273 case REPLACEMENT_STRING:
274 builder->AddString(replacement_substrings_[part.data]); 274 builder->AddString(replacement_substrings_[part.data]);
275 break; 275 break;
276 default: 276 default:
277 UNREACHABLE(); 277 UNREACHABLE();
278 } 278 }
279 } 279 }
280 } 280 }
281 281
282
283 void FindOneByteStringIndices(Vector<const uint8_t> subject, uint8_t pattern, 282 void FindOneByteStringIndices(Vector<const uint8_t> subject, uint8_t pattern,
284 ZoneList<int>* indices, unsigned int limit, 283 List<int>* indices, unsigned int limit) {
285 Zone* zone) {
286 DCHECK(limit > 0); 284 DCHECK(limit > 0);
287 // Collect indices of pattern in subject using memchr. 285 // Collect indices of pattern in subject using memchr.
288 // Stop after finding at most limit values. 286 // Stop after finding at most limit values.
289 const uint8_t* subject_start = subject.start(); 287 const uint8_t* subject_start = subject.start();
290 const uint8_t* subject_end = subject_start + subject.length(); 288 const uint8_t* subject_end = subject_start + subject.length();
291 const uint8_t* pos = subject_start; 289 const uint8_t* pos = subject_start;
292 while (limit > 0) { 290 while (limit > 0) {
293 pos = reinterpret_cast<const uint8_t*>( 291 pos = reinterpret_cast<const uint8_t*>(
294 memchr(pos, pattern, subject_end - pos)); 292 memchr(pos, pattern, subject_end - pos));
295 if (pos == NULL) return; 293 if (pos == NULL) return;
296 indices->Add(static_cast<int>(pos - subject_start), zone); 294 indices->Add(static_cast<int>(pos - subject_start));
297 pos++; 295 pos++;
298 limit--; 296 limit--;
299 } 297 }
300 } 298 }
301 299
302
303 void FindTwoByteStringIndices(const Vector<const uc16> subject, uc16 pattern, 300 void FindTwoByteStringIndices(const Vector<const uc16> subject, uc16 pattern,
304 ZoneList<int>* indices, unsigned int limit, 301 List<int>* indices, unsigned int limit) {
305 Zone* zone) {
306 DCHECK(limit > 0); 302 DCHECK(limit > 0);
307 const uc16* subject_start = subject.start(); 303 const uc16* subject_start = subject.start();
308 const uc16* subject_end = subject_start + subject.length(); 304 const uc16* subject_end = subject_start + subject.length();
309 for (const uc16* pos = subject_start; pos < subject_end && limit > 0; pos++) { 305 for (const uc16* pos = subject_start; pos < subject_end && limit > 0; pos++) {
310 if (*pos == pattern) { 306 if (*pos == pattern) {
311 indices->Add(static_cast<int>(pos - subject_start), zone); 307 indices->Add(static_cast<int>(pos - subject_start));
312 limit--; 308 limit--;
313 } 309 }
314 } 310 }
315 } 311 }
316 312
317
318 template <typename SubjectChar, typename PatternChar> 313 template <typename SubjectChar, typename PatternChar>
319 void FindStringIndices(Isolate* isolate, Vector<const SubjectChar> subject, 314 void FindStringIndices(Isolate* isolate, Vector<const SubjectChar> subject,
320 Vector<const PatternChar> pattern, 315 Vector<const PatternChar> pattern, List<int>* indices,
321 ZoneList<int>* indices, unsigned int limit, Zone* zone) { 316 unsigned int limit) {
322 DCHECK(limit > 0); 317 DCHECK(limit > 0);
323 // Collect indices of pattern in subject. 318 // Collect indices of pattern in subject.
324 // Stop after finding at most limit values. 319 // Stop after finding at most limit values.
325 int pattern_length = pattern.length(); 320 int pattern_length = pattern.length();
326 int index = 0; 321 int index = 0;
327 StringSearch<PatternChar, SubjectChar> search(isolate, pattern); 322 StringSearch<PatternChar, SubjectChar> search(isolate, pattern);
328 while (limit > 0) { 323 while (limit > 0) {
329 index = search.Search(subject, index); 324 index = search.Search(subject, index);
330 if (index < 0) return; 325 if (index < 0) return;
331 indices->Add(index, zone); 326 indices->Add(index);
332 index += pattern_length; 327 index += pattern_length;
333 limit--; 328 limit--;
334 } 329 }
335 } 330 }
336 331
337
338 void FindStringIndicesDispatch(Isolate* isolate, String* subject, 332 void FindStringIndicesDispatch(Isolate* isolate, String* subject,
339 String* pattern, ZoneList<int>* indices, 333 String* pattern, List<int>* indices,
340 unsigned int limit, Zone* zone) { 334 unsigned int limit) {
341 { 335 {
342 DisallowHeapAllocation no_gc; 336 DisallowHeapAllocation no_gc;
343 String::FlatContent subject_content = subject->GetFlatContent(); 337 String::FlatContent subject_content = subject->GetFlatContent();
344 String::FlatContent pattern_content = pattern->GetFlatContent(); 338 String::FlatContent pattern_content = pattern->GetFlatContent();
345 DCHECK(subject_content.IsFlat()); 339 DCHECK(subject_content.IsFlat());
346 DCHECK(pattern_content.IsFlat()); 340 DCHECK(pattern_content.IsFlat());
347 if (subject_content.IsOneByte()) { 341 if (subject_content.IsOneByte()) {
348 Vector<const uint8_t> subject_vector = subject_content.ToOneByteVector(); 342 Vector<const uint8_t> subject_vector = subject_content.ToOneByteVector();
349 if (pattern_content.IsOneByte()) { 343 if (pattern_content.IsOneByte()) {
350 Vector<const uint8_t> pattern_vector = 344 Vector<const uint8_t> pattern_vector =
351 pattern_content.ToOneByteVector(); 345 pattern_content.ToOneByteVector();
352 if (pattern_vector.length() == 1) { 346 if (pattern_vector.length() == 1) {
353 FindOneByteStringIndices(subject_vector, pattern_vector[0], indices, 347 FindOneByteStringIndices(subject_vector, pattern_vector[0], indices,
354 limit, zone); 348 limit);
355 } else { 349 } else {
356 FindStringIndices(isolate, subject_vector, pattern_vector, indices, 350 FindStringIndices(isolate, subject_vector, pattern_vector, indices,
357 limit, zone); 351 limit);
358 } 352 }
359 } else { 353 } else {
360 FindStringIndices(isolate, subject_vector, 354 FindStringIndices(isolate, subject_vector,
361 pattern_content.ToUC16Vector(), indices, limit, zone); 355 pattern_content.ToUC16Vector(), indices, limit);
362 } 356 }
363 } else { 357 } else {
364 Vector<const uc16> subject_vector = subject_content.ToUC16Vector(); 358 Vector<const uc16> subject_vector = subject_content.ToUC16Vector();
365 if (pattern_content.IsOneByte()) { 359 if (pattern_content.IsOneByte()) {
366 Vector<const uint8_t> pattern_vector = 360 Vector<const uint8_t> pattern_vector =
367 pattern_content.ToOneByteVector(); 361 pattern_content.ToOneByteVector();
368 if (pattern_vector.length() == 1) { 362 if (pattern_vector.length() == 1) {
369 FindTwoByteStringIndices(subject_vector, pattern_vector[0], indices, 363 FindTwoByteStringIndices(subject_vector, pattern_vector[0], indices,
370 limit, zone); 364 limit);
371 } else { 365 } else {
372 FindStringIndices(isolate, subject_vector, pattern_vector, indices, 366 FindStringIndices(isolate, subject_vector, pattern_vector, indices,
373 limit, zone); 367 limit);
374 } 368 }
375 } else { 369 } else {
376 Vector<const uc16> pattern_vector = pattern_content.ToUC16Vector(); 370 Vector<const uc16> pattern_vector = pattern_content.ToUC16Vector();
377 if (pattern_vector.length() == 1) { 371 if (pattern_vector.length() == 1) {
378 FindTwoByteStringIndices(subject_vector, pattern_vector[0], indices, 372 FindTwoByteStringIndices(subject_vector, pattern_vector[0], indices,
379 limit, zone); 373 limit);
380 } else { 374 } else {
381 FindStringIndices(isolate, subject_vector, pattern_vector, indices, 375 FindStringIndices(isolate, subject_vector, pattern_vector, indices,
382 limit, zone); 376 limit);
383 } 377 }
384 } 378 }
385 } 379 }
386 } 380 }
387 } 381 }
388 382
383 namespace {
384 static List<int>* GetRewindedRegexpIndicesList(Isolate* isolate) {
jochen (gone - plz use gerrit) 2016/10/06 12:24:53 Rewound
385 List<int>* list = isolate->regexp_indices();
386 list->Rewind(0);
387 return list;
388 }
389
390 static void TruncateRegexpIndicesList(Isolate* isolate) {
391 // Same size as smallest zone segment, preserving behavior from the runtime
392 // zone.
393 static const size_t kMaxRegexpIndicesListCapacity = 8 * KB;
394 if (isolate->regexp_indices()->capacity() > kMaxRegexpIndicesListCapacity) {
395 isolate->regexp_indices()->Clear(); // Throw away backing storage
396 }
397 }
398 } // namespace
399
389 template <typename ResultSeqString> 400 template <typename ResultSeqString>
390 MUST_USE_RESULT static Object* StringReplaceGlobalAtomRegExpWithString( 401 MUST_USE_RESULT static Object* StringReplaceGlobalAtomRegExpWithString(
391 Isolate* isolate, Handle<String> subject, Handle<JSRegExp> pattern_regexp, 402 Isolate* isolate, Handle<String> subject, Handle<JSRegExp> pattern_regexp,
392 Handle<String> replacement, Handle<JSObject> last_match_info) { 403 Handle<String> replacement, Handle<JSObject> last_match_info) {
393 DCHECK(subject->IsFlat()); 404 DCHECK(subject->IsFlat());
394 DCHECK(replacement->IsFlat()); 405 DCHECK(replacement->IsFlat());
395 406
396 ZoneScope zone_scope(isolate->runtime_zone()); 407 List<int>* indices = GetRewindedRegexpIndicesList(isolate);
397 ZoneList<int> indices(8, zone_scope.zone()); 408
398 DCHECK_EQ(JSRegExp::ATOM, pattern_regexp->TypeTag()); 409 DCHECK_EQ(JSRegExp::ATOM, pattern_regexp->TypeTag());
399 String* pattern = 410 String* pattern =
400 String::cast(pattern_regexp->DataAt(JSRegExp::kAtomPatternIndex)); 411 String::cast(pattern_regexp->DataAt(JSRegExp::kAtomPatternIndex));
401 int subject_len = subject->length(); 412 int subject_len = subject->length();
402 int pattern_len = pattern->length(); 413 int pattern_len = pattern->length();
403 int replacement_len = replacement->length(); 414 int replacement_len = replacement->length();
404 415
405 FindStringIndicesDispatch(isolate, *subject, pattern, &indices, 0xffffffff, 416 FindStringIndicesDispatch(isolate, *subject, pattern, indices, 0xffffffff);
406 zone_scope.zone());
407 417
408 int matches = indices.length(); 418 int matches = indices->length();
409 if (matches == 0) return *subject; 419 if (matches == 0) return *subject;
410 420
411 // Detect integer overflow. 421 // Detect integer overflow.
412 int64_t result_len_64 = (static_cast<int64_t>(replacement_len) - 422 int64_t result_len_64 = (static_cast<int64_t>(replacement_len) -
413 static_cast<int64_t>(pattern_len)) * 423 static_cast<int64_t>(pattern_len)) *
414 static_cast<int64_t>(matches) + 424 static_cast<int64_t>(matches) +
415 static_cast<int64_t>(subject_len); 425 static_cast<int64_t>(subject_len);
416 int result_len; 426 int result_len;
417 if (result_len_64 > static_cast<int64_t>(String::kMaxLength)) { 427 if (result_len_64 > static_cast<int64_t>(String::kMaxLength)) {
418 STATIC_ASSERT(String::kMaxLength < kMaxInt); 428 STATIC_ASSERT(String::kMaxLength < kMaxInt);
(...skipping 10 matching lines...) Expand all
429 maybe_res = isolate->factory()->NewRawOneByteString(result_len); 439 maybe_res = isolate->factory()->NewRawOneByteString(result_len);
430 } else { 440 } else {
431 maybe_res = isolate->factory()->NewRawTwoByteString(result_len); 441 maybe_res = isolate->factory()->NewRawTwoByteString(result_len);
432 } 442 }
433 Handle<SeqString> untyped_res; 443 Handle<SeqString> untyped_res;
434 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, untyped_res, maybe_res); 444 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, untyped_res, maybe_res);
435 Handle<ResultSeqString> result = Handle<ResultSeqString>::cast(untyped_res); 445 Handle<ResultSeqString> result = Handle<ResultSeqString>::cast(untyped_res);
436 446
437 for (int i = 0; i < matches; i++) { 447 for (int i = 0; i < matches; i++) {
438 // Copy non-matched subject content. 448 // Copy non-matched subject content.
439 if (subject_pos < indices.at(i)) { 449 if (subject_pos < indices->at(i)) {
440 String::WriteToFlat(*subject, result->GetChars() + result_pos, 450 String::WriteToFlat(*subject, result->GetChars() + result_pos,
441 subject_pos, indices.at(i)); 451 subject_pos, indices->at(i));
442 result_pos += indices.at(i) - subject_pos; 452 result_pos += indices->at(i) - subject_pos;
443 } 453 }
444 454
445 // Replace match. 455 // Replace match.
446 if (replacement_len > 0) { 456 if (replacement_len > 0) {
447 String::WriteToFlat(*replacement, result->GetChars() + result_pos, 0, 457 String::WriteToFlat(*replacement, result->GetChars() + result_pos, 0,
448 replacement_len); 458 replacement_len);
449 result_pos += replacement_len; 459 result_pos += replacement_len;
450 } 460 }
451 461
452 subject_pos = indices.at(i) + pattern_len; 462 subject_pos = indices->at(i) + pattern_len;
453 } 463 }
454 // Add remaining subject content at the end. 464 // Add remaining subject content at the end.
455 if (subject_pos < subject_len) { 465 if (subject_pos < subject_len) {
456 String::WriteToFlat(*subject, result->GetChars() + result_pos, subject_pos, 466 String::WriteToFlat(*subject, result->GetChars() + result_pos, subject_pos,
457 subject_len); 467 subject_len);
458 } 468 }
459 469
460 int32_t match_indices[] = {indices.at(matches - 1), 470 int32_t match_indices[] = {indices->at(matches - 1),
461 indices.at(matches - 1) + pattern_len}; 471 indices->at(matches - 1) + pattern_len};
462 RegExpImpl::SetLastMatchInfo(last_match_info, subject, 0, match_indices); 472 RegExpImpl::SetLastMatchInfo(last_match_info, subject, 0, match_indices);
463 473
474 TruncateRegexpIndicesList(isolate);
475
464 return *result; 476 return *result;
465 } 477 }
466 478
467 MUST_USE_RESULT static Object* StringReplaceGlobalRegExpWithString( 479 MUST_USE_RESULT static Object* StringReplaceGlobalRegExpWithString(
468 Isolate* isolate, Handle<String> subject, Handle<JSRegExp> regexp, 480 Isolate* isolate, Handle<String> subject, Handle<JSRegExp> regexp,
469 Handle<String> replacement, Handle<JSObject> last_match_info) { 481 Handle<String> replacement, Handle<JSObject> last_match_info) {
470 DCHECK(subject->IsFlat()); 482 DCHECK(subject->IsFlat());
471 DCHECK(replacement->IsFlat()); 483 DCHECK(replacement->IsFlat());
472 484
473 int capture_count = regexp->CaptureCount(); 485 int capture_count = regexp->CaptureCount();
474 int subject_length = subject->length(); 486 int subject_length = subject->length();
475 487
476 // CompiledReplacement uses zone allocation. 488 // CompiledReplacement uses zone allocation.
477 ZoneScope zone_scope(isolate->runtime_zone()); 489 Zone zone(isolate->allocator());
478 CompiledReplacement compiled_replacement(zone_scope.zone()); 490 CompiledReplacement compiled_replacement(&zone);
479 bool simple_replace = 491 bool simple_replace =
480 compiled_replacement.Compile(replacement, capture_count, subject_length); 492 compiled_replacement.Compile(replacement, capture_count, subject_length);
481 493
482 // Shortcut for simple non-regexp global replacements 494 // Shortcut for simple non-regexp global replacements
483 if (regexp->TypeTag() == JSRegExp::ATOM && simple_replace) { 495 if (regexp->TypeTag() == JSRegExp::ATOM && simple_replace) {
484 if (subject->HasOnlyOneByteChars() && replacement->HasOnlyOneByteChars()) { 496 if (subject->HasOnlyOneByteChars() && replacement->HasOnlyOneByteChars()) {
485 return StringReplaceGlobalAtomRegExpWithString<SeqOneByteString>( 497 return StringReplaceGlobalAtomRegExpWithString<SeqOneByteString>(
486 isolate, subject, regexp, replacement, last_match_info); 498 isolate, subject, regexp, replacement, last_match_info);
487 } else { 499 } else {
488 return StringReplaceGlobalAtomRegExpWithString<SeqTwoByteString>( 500 return StringReplaceGlobalAtomRegExpWithString<SeqTwoByteString>(
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after
702 } 714 }
703 } 715 }
704 716
705 // The limit can be very large (0xffffffffu), but since the pattern 717 // The limit can be very large (0xffffffffu), but since the pattern
706 // isn't empty, we can never create more parts than ~half the length 718 // isn't empty, we can never create more parts than ~half the length
707 // of the subject. 719 // of the subject.
708 720
709 subject = String::Flatten(subject); 721 subject = String::Flatten(subject);
710 pattern = String::Flatten(pattern); 722 pattern = String::Flatten(pattern);
711 723
712 static const int kMaxInitialListCapacity = 16; 724 List<int>* indices = GetRewindedRegexpIndicesList(isolate);
713 725
714 ZoneScope zone_scope(isolate->runtime_zone()); 726 FindStringIndicesDispatch(isolate, *subject, *pattern, indices, limit);
715 727
716 // Find (up to limit) indices of separator and end-of-string in subject 728 if (static_cast<uint32_t>(indices->length()) < limit) {
717 int initial_capacity = Min<uint32_t>(kMaxInitialListCapacity, limit); 729 indices->Add(subject_length);
718 ZoneList<int> indices(initial_capacity, zone_scope.zone());
719
720 FindStringIndicesDispatch(isolate, *subject, *pattern, &indices, limit,
721 zone_scope.zone());
722
723 if (static_cast<uint32_t>(indices.length()) < limit) {
724 indices.Add(subject_length, zone_scope.zone());
725 } 730 }
726 731
727 // The list indices now contains the end of each part to create. 732 // The list indices now contains the end of each part to create.
728 733
729 // Create JSArray of substrings separated by separator. 734 // Create JSArray of substrings separated by separator.
730 int part_count = indices.length(); 735 int part_count = indices->length();
731 736
732 Handle<JSArray> result = 737 Handle<JSArray> result =
733 isolate->factory()->NewJSArray(FAST_ELEMENTS, part_count, part_count, 738 isolate->factory()->NewJSArray(FAST_ELEMENTS, part_count, part_count,
734 INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE); 739 INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE);
735 740
736 DCHECK(result->HasFastObjectElements()); 741 DCHECK(result->HasFastObjectElements());
737 742
738 Handle<FixedArray> elements(FixedArray::cast(result->elements())); 743 Handle<FixedArray> elements(FixedArray::cast(result->elements()));
739 744
740 if (part_count == 1 && indices.at(0) == subject_length) { 745 if (part_count == 1 && indices->at(0) == subject_length) {
741 elements->set(0, *subject); 746 elements->set(0, *subject);
742 } else { 747 } else {
743 int part_start = 0; 748 int part_start = 0;
744 FOR_WITH_HANDLE_SCOPE(isolate, int, i = 0, i, i < part_count, i++, { 749 FOR_WITH_HANDLE_SCOPE(isolate, int, i = 0, i, i < part_count, i++, {
745 int part_end = indices.at(i); 750 int part_end = indices->at(i);
746 Handle<String> substring = 751 Handle<String> substring =
747 isolate->factory()->NewProperSubString(subject, part_start, part_end); 752 isolate->factory()->NewProperSubString(subject, part_start, part_end);
748 elements->set(i, *substring); 753 elements->set(i, *substring);
749 part_start = part_end + pattern_length; 754 part_start = part_end + pattern_length;
750 }); 755 });
751 } 756 }
752 757
753 if (limit == 0xffffffffu) { 758 if (limit == 0xffffffffu) {
754 if (result->HasFastObjectElements()) { 759 if (result->HasFastObjectElements()) {
755 RegExpResultsCache::Enter(isolate, subject, pattern, elements, 760 RegExpResultsCache::Enter(isolate, subject, pattern, elements,
756 isolate->factory()->empty_fixed_array(), 761 isolate->factory()->empty_fixed_array(),
757 RegExpResultsCache::STRING_SPLIT_SUBSTRINGS); 762 RegExpResultsCache::STRING_SPLIT_SUBSTRINGS);
758 } 763 }
759 } 764 }
760 765
766 TruncateRegexpIndicesList(isolate);
767
761 return *result; 768 return *result;
762 } 769 }
763 770
764 771
765 RUNTIME_FUNCTION(Runtime_RegExpExec) { 772 RUNTIME_FUNCTION(Runtime_RegExpExec) {
766 HandleScope scope(isolate); 773 HandleScope scope(isolate);
767 DCHECK(args.length() == 4); 774 DCHECK(args.length() == 4);
768 CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0); 775 CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0);
769 CONVERT_ARG_HANDLE_CHECKED(String, subject, 1); 776 CONVERT_ARG_HANDLE_CHECKED(String, subject, 1);
770 CONVERT_INT32_ARG_CHECKED(index, 2); 777 CONVERT_INT32_ARG_CHECKED(index, 2);
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after
1013 1020
1014 1021
1015 RUNTIME_FUNCTION(Runtime_IsRegExp) { 1022 RUNTIME_FUNCTION(Runtime_IsRegExp) {
1016 SealHandleScope shs(isolate); 1023 SealHandleScope shs(isolate);
1017 DCHECK(args.length() == 1); 1024 DCHECK(args.length() == 1);
1018 CONVERT_ARG_CHECKED(Object, obj, 0); 1025 CONVERT_ARG_CHECKED(Object, obj, 0);
1019 return isolate->heap()->ToBoolean(obj->IsJSRegExp()); 1026 return isolate->heap()->ToBoolean(obj->IsJSRegExp());
1020 } 1027 }
1021 } // namespace internal 1028 } // namespace internal
1022 } // namespace v8 1029 } // namespace v8
OLDNEW
« no previous file with comments | « src/list.h ('k') | src/runtime/runtime-strings.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698