V8 Project
runtime-strings.cc
Go to the documentation of this file.
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
3 // found in the LICENSE file.
4 
5 #include "src/v8.h"
6 
7 #include "src/arguments.h"
8 #include "src/jsregexp-inl.h"
9 #include "src/jsregexp.h"
10 #include "src/runtime/runtime.h"
13 #include "src/string-search.h"
14 
15 namespace v8 {
16 namespace internal {
17 
18 
19 // This may return an empty MaybeHandle if an exception is thrown or
20 // we abort due to reaching the recursion limit.
22  Isolate* isolate, Handle<String> subject, Handle<String> search,
23  Handle<String> replace, bool* found, int recursion_limit) {
24  StackLimitCheck stackLimitCheck(isolate);
25  if (stackLimitCheck.HasOverflowed() || (recursion_limit == 0)) {
26  return MaybeHandle<String>();
27  }
28  recursion_limit--;
29  if (subject->IsConsString()) {
30  ConsString* cons = ConsString::cast(*subject);
31  Handle<String> first = Handle<String>(cons->first());
32  Handle<String> second = Handle<String>(cons->second());
33  Handle<String> new_first;
34  if (!StringReplaceOneCharWithString(isolate, first, search, replace, found,
35  recursion_limit).ToHandle(&new_first)) {
36  return MaybeHandle<String>();
37  }
38  if (*found) return isolate->factory()->NewConsString(new_first, second);
39 
40  Handle<String> new_second;
41  if (!StringReplaceOneCharWithString(isolate, second, search, replace, found,
42  recursion_limit)
43  .ToHandle(&new_second)) {
44  return MaybeHandle<String>();
45  }
46  if (*found) return isolate->factory()->NewConsString(first, new_second);
47 
48  return subject;
49  } else {
50  int index = Runtime::StringMatch(isolate, subject, search, 0);
51  if (index == -1) return subject;
52  *found = true;
53  Handle<String> first = isolate->factory()->NewSubString(subject, 0, index);
54  Handle<String> cons1;
56  isolate, cons1, isolate->factory()->NewConsString(first, replace),
57  String);
58  Handle<String> second =
59  isolate->factory()->NewSubString(subject, index + 1, subject->length());
60  return isolate->factory()->NewConsString(cons1, second);
61  }
62 }
63 
64 
65 RUNTIME_FUNCTION(Runtime_StringReplaceOneCharWithString) {
66  HandleScope scope(isolate);
67  DCHECK(args.length() == 3);
71 
72  // If the cons string tree is too deep, we simply abort the recursion and
73  // retry with a flattened subject string.
74  const int kRecursionLimit = 0x1000;
75  bool found = false;
76  Handle<String> result;
77  if (StringReplaceOneCharWithString(isolate, subject, search, replace, &found,
78  kRecursionLimit).ToHandle(&result)) {
79  return *result;
80  }
81  if (isolate->has_pending_exception()) return isolate->heap()->exception();
82 
83  subject = String::Flatten(subject);
85  isolate, result,
86  StringReplaceOneCharWithString(isolate, subject, search, replace, &found,
87  kRecursionLimit));
88  return *result;
89 }
90 
91 
92 RUNTIME_FUNCTION(Runtime_StringIndexOf) {
93  HandleScope scope(isolate);
94  DCHECK(args.length() == 3);
95 
99 
100  uint32_t start_index;
101  if (!index->ToArrayIndex(&start_index)) return Smi::FromInt(-1);
102 
103  RUNTIME_ASSERT(start_index <= static_cast<uint32_t>(sub->length()));
104  int position = Runtime::StringMatch(isolate, sub, pat, start_index);
105  return Smi::FromInt(position);
106 }
107 
108 
109 template <typename schar, typename pchar>
111  Vector<const pchar> pattern, int idx) {
112  int pattern_length = pattern.length();
113  DCHECK(pattern_length >= 1);
114  DCHECK(idx + pattern_length <= subject.length());
115 
116  if (sizeof(schar) == 1 && sizeof(pchar) > 1) {
117  for (int i = 0; i < pattern_length; i++) {
118  uc16 c = pattern[i];
119  if (c > String::kMaxOneByteCharCode) {
120  return -1;
121  }
122  }
123  }
124 
125  pchar pattern_first_char = pattern[0];
126  for (int i = idx; i >= 0; i--) {
127  if (subject[i] != pattern_first_char) continue;
128  int j = 1;
129  while (j < pattern_length) {
130  if (pattern[j] != subject[i + j]) {
131  break;
132  }
133  j++;
134  }
135  if (j == pattern_length) {
136  return i;
137  }
138  }
139  return -1;
140 }
141 
142 
143 RUNTIME_FUNCTION(Runtime_StringLastIndexOf) {
144  HandleScope scope(isolate);
145  DCHECK(args.length() == 3);
146 
150 
151  uint32_t start_index;
152  if (!index->ToArrayIndex(&start_index)) return Smi::FromInt(-1);
153 
154  uint32_t pat_length = pat->length();
155  uint32_t sub_length = sub->length();
156 
157  if (start_index + pat_length > sub_length) {
158  start_index = sub_length - pat_length;
159  }
160 
161  if (pat_length == 0) {
162  return Smi::FromInt(start_index);
163  }
164 
165  sub = String::Flatten(sub);
166  pat = String::Flatten(pat);
167 
168  int position = -1;
169  DisallowHeapAllocation no_gc; // ensure vectors stay valid
170 
171  String::FlatContent sub_content = sub->GetFlatContent();
172  String::FlatContent pat_content = pat->GetFlatContent();
173 
174  if (pat_content.IsOneByte()) {
175  Vector<const uint8_t> pat_vector = pat_content.ToOneByteVector();
176  if (sub_content.IsOneByte()) {
177  position = StringMatchBackwards(sub_content.ToOneByteVector(), pat_vector,
178  start_index);
179  } else {
180  position = StringMatchBackwards(sub_content.ToUC16Vector(), pat_vector,
181  start_index);
182  }
183  } else {
184  Vector<const uc16> pat_vector = pat_content.ToUC16Vector();
185  if (sub_content.IsOneByte()) {
186  position = StringMatchBackwards(sub_content.ToOneByteVector(), pat_vector,
187  start_index);
188  } else {
189  position = StringMatchBackwards(sub_content.ToUC16Vector(), pat_vector,
190  start_index);
191  }
192  }
193 
194  return Smi::FromInt(position);
195 }
196 
197 
198 RUNTIME_FUNCTION(Runtime_StringLocaleCompare) {
199  HandleScope handle_scope(isolate);
200  DCHECK(args.length() == 2);
201 
204 
205  if (str1.is_identical_to(str2)) return Smi::FromInt(0); // Equal.
206  int str1_length = str1->length();
207  int str2_length = str2->length();
208 
209  // Decide trivial cases without flattening.
210  if (str1_length == 0) {
211  if (str2_length == 0) return Smi::FromInt(0); // Equal.
212  return Smi::FromInt(-str2_length);
213  } else {
214  if (str2_length == 0) return Smi::FromInt(str1_length);
215  }
216 
217  int end = str1_length < str2_length ? str1_length : str2_length;
218 
219  // No need to flatten if we are going to find the answer on the first
220  // character. At this point we know there is at least one character
221  // in each string, due to the trivial case handling above.
222  int d = str1->Get(0) - str2->Get(0);
223  if (d != 0) return Smi::FromInt(d);
224 
225  str1 = String::Flatten(str1);
226  str2 = String::Flatten(str2);
227 
229  String::FlatContent flat1 = str1->GetFlatContent();
230  String::FlatContent flat2 = str2->GetFlatContent();
231 
232  for (int i = 0; i < end; i++) {
233  if (flat1.Get(i) != flat2.Get(i)) {
234  return Smi::FromInt(flat1.Get(i) - flat2.Get(i));
235  }
236  }
237 
238  return Smi::FromInt(str1_length - str2_length);
239 }
240 
241 
242 RUNTIME_FUNCTION(Runtime_SubString) {
243  HandleScope scope(isolate);
244  DCHECK(args.length() == 3);
245 
247  int start, end;
248  // We have a fast integer-only case here to avoid a conversion to double in
249  // the common case where from and to are Smis.
250  if (args[1]->IsSmi() && args[2]->IsSmi()) {
251  CONVERT_SMI_ARG_CHECKED(from_number, 1);
252  CONVERT_SMI_ARG_CHECKED(to_number, 2);
253  start = from_number;
254  end = to_number;
255  } else {
256  CONVERT_DOUBLE_ARG_CHECKED(from_number, 1);
257  CONVERT_DOUBLE_ARG_CHECKED(to_number, 2);
258  start = FastD2IChecked(from_number);
259  end = FastD2IChecked(to_number);
260  }
261  RUNTIME_ASSERT(end >= start);
262  RUNTIME_ASSERT(start >= 0);
263  RUNTIME_ASSERT(end <= string->length());
264  isolate->counters()->sub_string_runtime()->Increment();
265 
266  return *isolate->factory()->NewSubString(string, start, end);
267 }
268 
269 
270 RUNTIME_FUNCTION(Runtime_StringAdd) {
271  HandleScope scope(isolate);
272  DCHECK(args.length() == 2);
275  isolate->counters()->string_add_runtime()->Increment();
276  Handle<String> result;
278  isolate, result, isolate->factory()->NewConsString(str1, str2));
279  return *result;
280 }
281 
282 
283 RUNTIME_FUNCTION(Runtime_InternalizeString) {
284  HandleScope handles(isolate);
285  RUNTIME_ASSERT(args.length() == 1);
287  return *isolate->factory()->InternalizeString(string);
288 }
289 
290 
291 RUNTIME_FUNCTION(Runtime_StringMatch) {
292  HandleScope handles(isolate);
293  DCHECK(args.length() == 3);
294 
295  CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
297  CONVERT_ARG_HANDLE_CHECKED(JSArray, regexp_info, 2);
298 
299  RUNTIME_ASSERT(regexp_info->HasFastObjectElements());
300 
301  RegExpImpl::GlobalCache global_cache(regexp, subject, true, isolate);
302  if (global_cache.HasException()) return isolate->heap()->exception();
303 
304  int capture_count = regexp->CaptureCount();
305 
306  ZoneScope zone_scope(isolate->runtime_zone());
307  ZoneList<int> offsets(8, zone_scope.zone());
308 
309  while (true) {
310  int32_t* match = global_cache.FetchNext();
311  if (match == NULL) break;
312  offsets.Add(match[0], zone_scope.zone()); // start
313  offsets.Add(match[1], zone_scope.zone()); // end
314  }
315 
316  if (global_cache.HasException()) return isolate->heap()->exception();
317 
318  if (offsets.length() == 0) {
319  // Not a single match.
320  return isolate->heap()->null_value();
321  }
322 
323  RegExpImpl::SetLastMatchInfo(regexp_info, subject, capture_count,
324  global_cache.LastSuccessfulMatch());
325 
326  int matches = offsets.length() / 2;
327  Handle<FixedArray> elements = isolate->factory()->NewFixedArray(matches);
328  Handle<String> substring =
329  isolate->factory()->NewSubString(subject, offsets.at(0), offsets.at(1));
330  elements->set(0, *substring);
331  for (int i = 1; i < matches; i++) {
332  HandleScope temp_scope(isolate);
333  int from = offsets.at(i * 2);
334  int to = offsets.at(i * 2 + 1);
335  Handle<String> substring =
336  isolate->factory()->NewProperSubString(subject, from, to);
337  elements->set(i, *substring);
338  }
339  Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(elements);
340  result->set_length(Smi::FromInt(matches));
341  return *result;
342 }
343 
344 
345 RUNTIME_FUNCTION(Runtime_StringCharCodeAtRT) {
346  HandleScope handle_scope(isolate);
347  DCHECK(args.length() == 2);
348 
349  CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
351 
352  // Flatten the string. If someone wants to get a char at an index
353  // in a cons string, it is likely that more indices will be
354  // accessed.
355  subject = String::Flatten(subject);
356 
357  if (i >= static_cast<uint32_t>(subject->length())) {
358  return isolate->heap()->nan_value();
359  }
360 
361  return Smi::FromInt(subject->Get(i));
362 }
363 
364 
365 RUNTIME_FUNCTION(Runtime_CharFromCode) {
366  HandleScope handlescope(isolate);
367  DCHECK(args.length() == 1);
368  if (args[0]->IsNumber()) {
369  CONVERT_NUMBER_CHECKED(uint32_t, code, Uint32, args[0]);
370  code &= 0xffff;
371  return *isolate->factory()->LookupSingleCharacterStringFromCode(code);
372  }
373  return isolate->heap()->empty_string();
374 }
375 
376 
377 RUNTIME_FUNCTION(Runtime_StringCompare) {
378  HandleScope handle_scope(isolate);
379  DCHECK(args.length() == 2);
380 
383 
384  isolate->counters()->string_compare_runtime()->Increment();
385 
386  // A few fast case tests before we flatten.
387  if (x.is_identical_to(y)) return Smi::FromInt(EQUAL);
388  if (y->length() == 0) {
389  if (x->length() == 0) return Smi::FromInt(EQUAL);
390  return Smi::FromInt(GREATER);
391  } else if (x->length() == 0) {
392  return Smi::FromInt(LESS);
393  }
394 
395  int d = x->Get(0) - y->Get(0);
396  if (d < 0)
397  return Smi::FromInt(LESS);
398  else if (d > 0)
399  return Smi::FromInt(GREATER);
400 
401  // Slow case.
402  x = String::Flatten(x);
403  y = String::Flatten(y);
404 
406  Object* equal_prefix_result = Smi::FromInt(EQUAL);
407  int prefix_length = x->length();
408  if (y->length() < prefix_length) {
409  prefix_length = y->length();
410  equal_prefix_result = Smi::FromInt(GREATER);
411  } else if (y->length() > prefix_length) {
412  equal_prefix_result = Smi::FromInt(LESS);
413  }
414  int r;
415  String::FlatContent x_content = x->GetFlatContent();
416  String::FlatContent y_content = y->GetFlatContent();
417  if (x_content.IsOneByte()) {
418  Vector<const uint8_t> x_chars = x_content.ToOneByteVector();
419  if (y_content.IsOneByte()) {
420  Vector<const uint8_t> y_chars = y_content.ToOneByteVector();
421  r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
422  } else {
423  Vector<const uc16> y_chars = y_content.ToUC16Vector();
424  r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
425  }
426  } else {
427  Vector<const uc16> x_chars = x_content.ToUC16Vector();
428  if (y_content.IsOneByte()) {
429  Vector<const uint8_t> y_chars = y_content.ToOneByteVector();
430  r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
431  } else {
432  Vector<const uc16> y_chars = y_content.ToUC16Vector();
433  r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
434  }
435  }
436  Object* result;
437  if (r == 0) {
438  result = equal_prefix_result;
439  } else {
440  result = (r < 0) ? Smi::FromInt(LESS) : Smi::FromInt(GREATER);
441  }
442  return result;
443 }
444 
445 
446 RUNTIME_FUNCTION(Runtime_StringBuilderConcat) {
447  HandleScope scope(isolate);
448  DCHECK(args.length() == 3);
450  int32_t array_length;
451  if (!args[1]->ToInt32(&array_length)) {
452  THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewInvalidStringLengthError());
453  }
454  CONVERT_ARG_HANDLE_CHECKED(String, special, 2);
455 
456  size_t actual_array_length = 0;
458  TryNumberToSize(isolate, array->length(), &actual_array_length));
459  RUNTIME_ASSERT(array_length >= 0);
460  RUNTIME_ASSERT(static_cast<size_t>(array_length) <= actual_array_length);
461 
462  // This assumption is used by the slice encoding in one or two smis.
464 
465  RUNTIME_ASSERT(array->HasFastElements());
467 
468  int special_length = special->length();
469  if (!array->HasFastObjectElements()) {
470  return isolate->Throw(isolate->heap()->illegal_argument_string());
471  }
472 
473  int length;
474  bool one_byte = special->HasOnlyOneByteChars();
475 
476  {
478  FixedArray* fixed_array = FixedArray::cast(array->elements());
479  if (fixed_array->length() < array_length) {
480  array_length = fixed_array->length();
481  }
482 
483  if (array_length == 0) {
484  return isolate->heap()->empty_string();
485  } else if (array_length == 1) {
486  Object* first = fixed_array->get(0);
487  if (first->IsString()) return first;
488  }
489  length = StringBuilderConcatLength(special_length, fixed_array,
490  array_length, &one_byte);
491  }
492 
493  if (length == -1) {
494  return isolate->Throw(isolate->heap()->illegal_argument_string());
495  }
496 
497  if (one_byte) {
500  isolate, answer, isolate->factory()->NewRawOneByteString(length));
501  StringBuilderConcatHelper(*special, answer->GetChars(),
502  FixedArray::cast(array->elements()),
503  array_length);
504  return *answer;
505  } else {
508  isolate, answer, isolate->factory()->NewRawTwoByteString(length));
509  StringBuilderConcatHelper(*special, answer->GetChars(),
510  FixedArray::cast(array->elements()),
511  array_length);
512  return *answer;
513  }
514 }
515 
516 
517 RUNTIME_FUNCTION(Runtime_StringBuilderJoin) {
518  HandleScope scope(isolate);
519  DCHECK(args.length() == 3);
521  int32_t array_length;
522  if (!args[1]->ToInt32(&array_length)) {
523  THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewInvalidStringLengthError());
524  }
525  CONVERT_ARG_HANDLE_CHECKED(String, separator, 2);
526  RUNTIME_ASSERT(array->HasFastObjectElements());
527  RUNTIME_ASSERT(array_length >= 0);
528 
529  Handle<FixedArray> fixed_array(FixedArray::cast(array->elements()));
530  if (fixed_array->length() < array_length) {
531  array_length = fixed_array->length();
532  }
533 
534  if (array_length == 0) {
535  return isolate->heap()->empty_string();
536  } else if (array_length == 1) {
537  Object* first = fixed_array->get(0);
538  RUNTIME_ASSERT(first->IsString());
539  return first;
540  }
541 
542  int separator_length = separator->length();
543  RUNTIME_ASSERT(separator_length > 0);
544  int max_nof_separators =
545  (String::kMaxLength + separator_length - 1) / separator_length;
546  if (max_nof_separators < (array_length - 1)) {
547  THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewInvalidStringLengthError());
548  }
549  int length = (array_length - 1) * separator_length;
550  for (int i = 0; i < array_length; i++) {
551  Object* element_obj = fixed_array->get(i);
552  RUNTIME_ASSERT(element_obj->IsString());
553  String* element = String::cast(element_obj);
554  int increment = element->length();
555  if (increment > String::kMaxLength - length) {
557  length = kMaxInt; // Provoke exception;
558  break;
559  }
560  length += increment;
561  }
562 
565  isolate, answer, isolate->factory()->NewRawTwoByteString(length));
566 
568 
569  uc16* sink = answer->GetChars();
570 #ifdef DEBUG
571  uc16* end = sink + length;
572 #endif
573 
574  RUNTIME_ASSERT(fixed_array->get(0)->IsString());
575  String* first = String::cast(fixed_array->get(0));
576  String* separator_raw = *separator;
577  int first_length = first->length();
578  String::WriteToFlat(first, sink, 0, first_length);
579  sink += first_length;
580 
581  for (int i = 1; i < array_length; i++) {
582  DCHECK(sink + separator_length <= end);
583  String::WriteToFlat(separator_raw, sink, 0, separator_length);
584  sink += separator_length;
585 
586  RUNTIME_ASSERT(fixed_array->get(i)->IsString());
587  String* element = String::cast(fixed_array->get(i));
588  int element_length = element->length();
589  DCHECK(sink + element_length <= end);
590  String::WriteToFlat(element, sink, 0, element_length);
591  sink += element_length;
592  }
593  DCHECK(sink == end);
594 
595  // Use %_FastOneByteArrayJoin instead.
596  DCHECK(!answer->IsOneByteRepresentation());
597  return *answer;
598 }
599 
600 template <typename Char>
602  int elements_length,
603  uint32_t array_length,
604  String* separator,
605  Vector<Char> buffer) {
607  int previous_separator_position = 0;
608  int separator_length = separator->length();
609  int cursor = 0;
610  for (int i = 0; i < elements_length; i += 2) {
611  int position = NumberToInt32(elements->get(i));
612  String* string = String::cast(elements->get(i + 1));
613  int string_length = string->length();
614  if (string->length() > 0) {
615  while (previous_separator_position < position) {
616  String::WriteToFlat<Char>(separator, &buffer[cursor], 0,
617  separator_length);
618  cursor += separator_length;
619  previous_separator_position++;
620  }
621  String::WriteToFlat<Char>(string, &buffer[cursor], 0, string_length);
622  cursor += string->length();
623  }
624  }
625  if (separator_length > 0) {
626  // Array length must be representable as a signed 32-bit number,
627  // otherwise the total string length would have been too large.
628  DCHECK(array_length <= 0x7fffffff); // Is int32_t.
629  int last_array_index = static_cast<int>(array_length - 1);
630  while (previous_separator_position < last_array_index) {
631  String::WriteToFlat<Char>(separator, &buffer[cursor], 0,
632  separator_length);
633  cursor += separator_length;
634  previous_separator_position++;
635  }
636  }
637  DCHECK(cursor <= buffer.length());
638 }
639 
640 
641 RUNTIME_FUNCTION(Runtime_SparseJoinWithSeparator) {
642  HandleScope scope(isolate);
643  DCHECK(args.length() == 3);
644  CONVERT_ARG_HANDLE_CHECKED(JSArray, elements_array, 0);
645  CONVERT_NUMBER_CHECKED(uint32_t, array_length, Uint32, args[1]);
646  CONVERT_ARG_HANDLE_CHECKED(String, separator, 2);
647  // elements_array is fast-mode JSarray of alternating positions
648  // (increasing order) and strings.
649  RUNTIME_ASSERT(elements_array->HasFastSmiOrObjectElements());
650  // array_length is length of original array (used to add separators);
651  // separator is string to put between elements. Assumed to be non-empty.
652  RUNTIME_ASSERT(array_length > 0);
653 
654  // Find total length of join result.
655  int string_length = 0;
656  bool is_one_byte = separator->IsOneByteRepresentation();
657  bool overflow = false;
658  CONVERT_NUMBER_CHECKED(int, elements_length, Int32, elements_array->length());
659  RUNTIME_ASSERT(elements_length <= elements_array->elements()->length());
660  RUNTIME_ASSERT((elements_length & 1) == 0); // Even length.
661  FixedArray* elements = FixedArray::cast(elements_array->elements());
662  for (int i = 0; i < elements_length; i += 2) {
663  RUNTIME_ASSERT(elements->get(i)->IsNumber());
664  CONVERT_NUMBER_CHECKED(uint32_t, position, Uint32, elements->get(i));
665  RUNTIME_ASSERT(position < array_length);
666  RUNTIME_ASSERT(elements->get(i + 1)->IsString());
667  }
668 
669  {
671  for (int i = 0; i < elements_length; i += 2) {
672  String* string = String::cast(elements->get(i + 1));
673  int length = string->length();
674  if (is_one_byte && !string->IsOneByteRepresentation()) {
675  is_one_byte = false;
676  }
677  if (length > String::kMaxLength ||
678  String::kMaxLength - length < string_length) {
679  overflow = true;
680  break;
681  }
682  string_length += length;
683  }
684  }
685 
686  int separator_length = separator->length();
687  if (!overflow && separator_length > 0) {
688  if (array_length <= 0x7fffffffu) {
689  int separator_count = static_cast<int>(array_length) - 1;
690  int remaining_length = String::kMaxLength - string_length;
691  if ((remaining_length / separator_length) >= separator_count) {
692  string_length += separator_length * (array_length - 1);
693  } else {
694  // Not room for the separators within the maximal string length.
695  overflow = true;
696  }
697  } else {
698  // Nonempty separator and at least 2^31-1 separators necessary
699  // means that the string is too large to create.
700  STATIC_ASSERT(String::kMaxLength < 0x7fffffff);
701  overflow = true;
702  }
703  }
704  if (overflow) {
705  // Throw an exception if the resulting string is too large. See
706  // https://code.google.com/p/chromium/issues/detail?id=336820
707  // for details.
708  THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewInvalidStringLengthError());
709  }
710 
711  if (is_one_byte) {
712  Handle<SeqOneByteString> result = isolate->factory()
713  ->NewRawOneByteString(string_length)
714  .ToHandleChecked();
715  JoinSparseArrayWithSeparator<uint8_t>(
716  FixedArray::cast(elements_array->elements()), elements_length,
717  array_length, *separator,
718  Vector<uint8_t>(result->GetChars(), string_length));
719  return *result;
720  } else {
721  Handle<SeqTwoByteString> result = isolate->factory()
722  ->NewRawTwoByteString(string_length)
723  .ToHandleChecked();
724  JoinSparseArrayWithSeparator<uc16>(
725  FixedArray::cast(elements_array->elements()), elements_length,
726  array_length, *separator,
727  Vector<uc16>(result->GetChars(), string_length));
728  return *result;
729  }
730 }
731 
732 
733 // Copies Latin1 characters to the given fixed array looking up
734 // one-char strings in the cache. Gives up on the first char that is
735 // not in the cache and fills the remainder with smi zeros. Returns
736 // the length of the successfully copied prefix.
737 static int CopyCachedOneByteCharsToArray(Heap* heap, const uint8_t* chars,
738  FixedArray* elements, int length) {
740  FixedArray* one_byte_cache = heap->single_character_string_cache();
741  Object* undefined = heap->undefined_value();
742  int i;
743  WriteBarrierMode mode = elements->GetWriteBarrierMode(no_gc);
744  for (i = 0; i < length; ++i) {
745  Object* value = one_byte_cache->get(chars[i]);
746  if (value == undefined) break;
747  elements->set(i, value, mode);
748  }
749  if (i < length) {
750  DCHECK(Smi::FromInt(0) == 0);
751  memset(elements->data_start() + i, 0, kPointerSize * (length - i));
752  }
753 #ifdef DEBUG
754  for (int j = 0; j < length; ++j) {
755  Object* element = elements->get(j);
756  DCHECK(element == Smi::FromInt(0) ||
757  (element->IsString() && String::cast(element)->LooksValid()));
758  }
759 #endif
760  return i;
761 }
762 
763 
764 // Converts a String to JSArray.
765 // For example, "foo" => ["f", "o", "o"].
766 RUNTIME_FUNCTION(Runtime_StringToArray) {
767  HandleScope scope(isolate);
768  DCHECK(args.length() == 2);
770  CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[1]);
771 
772  s = String::Flatten(s);
773  const int length = static_cast<int>(Min<uint32_t>(s->length(), limit));
774 
775  Handle<FixedArray> elements;
776  int position = 0;
777  if (s->IsFlat() && s->IsOneByteRepresentation()) {
778  // Try using cached chars where possible.
779  elements = isolate->factory()->NewUninitializedFixedArray(length);
780 
782  String::FlatContent content = s->GetFlatContent();
783  if (content.IsOneByte()) {
784  Vector<const uint8_t> chars = content.ToOneByteVector();
785  // Note, this will initialize all elements (not only the prefix)
786  // to prevent GC from seeing partially initialized array.
787  position = CopyCachedOneByteCharsToArray(isolate->heap(), chars.start(),
788  *elements, length);
789  } else {
790  MemsetPointer(elements->data_start(), isolate->heap()->undefined_value(),
791  length);
792  }
793  } else {
794  elements = isolate->factory()->NewFixedArray(length);
795  }
796  for (int i = position; i < length; ++i) {
797  Handle<Object> str =
798  isolate->factory()->LookupSingleCharacterStringFromCode(s->Get(i));
799  elements->set(i, *str);
800  }
801 
802 #ifdef DEBUG
803  for (int i = 0; i < length; ++i) {
804  DCHECK(String::cast(elements->get(i))->length() == 1);
805  }
806 #endif
807 
808  return *isolate->factory()->NewJSArrayWithElements(elements);
809 }
810 
811 
812 static inline bool ToUpperOverflows(uc32 character) {
813  // y with umlauts and the micro sign are the only characters that stop
814  // fitting into one-byte when converting to uppercase.
815  static const uc32 yuml_code = 0xff;
816  static const uc32 micro_code = 0xb5;
817  return (character == yuml_code || character == micro_code);
818 }
819 
820 
821 template <class Converter>
823  Isolate* isolate, String* string, SeqString* result, int result_length,
826  // We try this twice, once with the assumption that the result is no longer
827  // than the input and, if that assumption breaks, again with the exact
828  // length. This may not be pretty, but it is nicer than what was here before
829  // and I hereby claim my vaffel-is.
830  //
831  // NOTE: This assumes that the upper/lower case of an ASCII
832  // character is also ASCII. This is currently the case, but it
833  // might break in the future if we implement more context and locale
834  // dependent upper/lower conversions.
835  bool has_changed_character = false;
836 
837  // Convert all characters to upper case, assuming that they will fit
838  // in the buffer
840  StringCharacterStream stream(string, op.value());
841  unibrow::uchar chars[Converter::kMaxWidth];
842  // We can assume that the string is not empty
843  uc32 current = stream.GetNext();
844  bool ignore_overflow = Converter::kIsToLower || result->IsSeqTwoByteString();
845  for (int i = 0; i < result_length;) {
846  bool has_next = stream.HasMore();
847  uc32 next = has_next ? stream.GetNext() : 0;
848  int char_length = mapping->get(current, next, chars);
849  if (char_length == 0) {
850  // The case conversion of this character is the character itself.
851  result->Set(i, current);
852  i++;
853  } else if (char_length == 1 &&
854  (ignore_overflow || !ToUpperOverflows(current))) {
855  // Common case: converting the letter resulted in one character.
856  DCHECK(static_cast<uc32>(chars[0]) != current);
857  result->Set(i, chars[0]);
858  has_changed_character = true;
859  i++;
860  } else if (result_length == string->length()) {
861  bool overflows = ToUpperOverflows(current);
862  // We've assumed that the result would be as long as the
863  // input but here is a character that converts to several
864  // characters. No matter, we calculate the exact length
865  // of the result and try the whole thing again.
866  //
867  // Note that this leaves room for optimization. We could just
868  // memcpy what we already have to the result string. Also,
869  // the result string is the last object allocated we could
870  // "realloc" it and probably, in the vast majority of cases,
871  // extend the existing string to be able to hold the full
872  // result.
873  int next_length = 0;
874  if (has_next) {
875  next_length = mapping->get(next, 0, chars);
876  if (next_length == 0) next_length = 1;
877  }
878  int current_length = i + char_length + next_length;
879  while (stream.HasMore()) {
880  current = stream.GetNext();
881  overflows |= ToUpperOverflows(current);
882  // NOTE: we use 0 as the next character here because, while
883  // the next character may affect what a character converts to,
884  // it does not in any case affect the length of what it convert
885  // to.
886  int char_length = mapping->get(current, 0, chars);
887  if (char_length == 0) char_length = 1;
888  current_length += char_length;
889  if (current_length > String::kMaxLength) {
890  AllowHeapAllocation allocate_error_and_return;
892  NewInvalidStringLengthError());
893  }
894  }
895  // Try again with the real length. Return signed if we need
896  // to allocate a two-byte string for to uppercase.
897  return (overflows && !ignore_overflow) ? Smi::FromInt(-current_length)
898  : Smi::FromInt(current_length);
899  } else {
900  for (int j = 0; j < char_length; j++) {
901  result->Set(i, chars[j]);
902  i++;
903  }
904  has_changed_character = true;
905  }
906  current = next;
907  }
908  if (has_changed_character) {
909  return result;
910  } else {
911  // If we didn't actually change anything in doing the conversion
912  // we simple return the result and let the converted string
913  // become garbage; there is no reason to keep two identical strings
914  // alive.
915  return string;
916  }
917 }
918 
919 
922 
923 // Given a word and two range boundaries returns a word with high bit
924 // set in every byte iff the corresponding input byte was strictly in
925 // the range (m, n). All the other bits in the result are cleared.
926 // This function is only useful when it can be inlined and the
927 // boundaries are statically known.
928 // Requires: all bytes in the input word and the boundaries must be
929 // ASCII (less than 0x7F).
930 static inline uintptr_t AsciiRangeMask(uintptr_t w, char m, char n) {
931  // Use strict inequalities since in edge cases the function could be
932  // further simplified.
933  DCHECK(0 < m && m < n);
934  // Has high bit set in every w byte less than n.
935  uintptr_t tmp1 = kOneInEveryByte * (0x7F + n) - w;
936  // Has high bit set in every w byte greater than m.
937  uintptr_t tmp2 = w + kOneInEveryByte * (0x7F - m);
938  return (tmp1 & tmp2 & (kOneInEveryByte * 0x80));
939 }
940 
941 
942 #ifdef DEBUG
943 static bool CheckFastAsciiConvert(char* dst, const char* src, int length,
944  bool changed, bool is_to_lower) {
945  bool expected_changed = false;
946  for (int i = 0; i < length; i++) {
947  if (dst[i] == src[i]) continue;
948  expected_changed = true;
949  if (is_to_lower) {
950  DCHECK('A' <= src[i] && src[i] <= 'Z');
951  DCHECK(dst[i] == src[i] + ('a' - 'A'));
952  } else {
953  DCHECK('a' <= src[i] && src[i] <= 'z');
954  DCHECK(dst[i] == src[i] - ('a' - 'A'));
955  }
956  }
957  return (expected_changed == changed);
958 }
959 #endif
960 
961 
962 template <class Converter>
963 static bool FastAsciiConvert(char* dst, const char* src, int length,
964  bool* changed_out) {
965 #ifdef DEBUG
966  char* saved_dst = dst;
967  const char* saved_src = src;
968 #endif
970  // We rely on the distance between upper and lower case letters
971  // being a known power of 2.
972  DCHECK('a' - 'A' == (1 << 5));
973  // Boundaries for the range of input characters than require conversion.
974  static const char lo = Converter::kIsToLower ? 'A' - 1 : 'a' - 1;
975  static const char hi = Converter::kIsToLower ? 'Z' + 1 : 'z' + 1;
976  bool changed = false;
977  uintptr_t or_acc = 0;
978  const char* const limit = src + length;
979 
980  // dst is newly allocated and always aligned.
981  DCHECK(IsAligned(reinterpret_cast<intptr_t>(dst), sizeof(uintptr_t)));
982  // Only attempt processing one word at a time if src is also aligned.
983  if (IsAligned(reinterpret_cast<intptr_t>(src), sizeof(uintptr_t))) {
984  // Process the prefix of the input that requires no conversion one aligned
985  // (machine) word at a time.
986  while (src <= limit - sizeof(uintptr_t)) {
987  const uintptr_t w = *reinterpret_cast<const uintptr_t*>(src);
988  or_acc |= w;
989  if (AsciiRangeMask(w, lo, hi) != 0) {
990  changed = true;
991  break;
992  }
993  *reinterpret_cast<uintptr_t*>(dst) = w;
994  src += sizeof(uintptr_t);
995  dst += sizeof(uintptr_t);
996  }
997  // Process the remainder of the input performing conversion when
998  // required one word at a time.
999  while (src <= limit - sizeof(uintptr_t)) {
1000  const uintptr_t w = *reinterpret_cast<const uintptr_t*>(src);
1001  or_acc |= w;
1002  uintptr_t m = AsciiRangeMask(w, lo, hi);
1003  // The mask has high (7th) bit set in every byte that needs
1004  // conversion and we know that the distance between cases is
1005  // 1 << 5.
1006  *reinterpret_cast<uintptr_t*>(dst) = w ^ (m >> 2);
1007  src += sizeof(uintptr_t);
1008  dst += sizeof(uintptr_t);
1009  }
1010  }
1011  // Process the last few bytes of the input (or the whole input if
1012  // unaligned access is not supported).
1013  while (src < limit) {
1014  char c = *src;
1015  or_acc |= c;
1016  if (lo < c && c < hi) {
1017  c ^= (1 << 5);
1018  changed = true;
1019  }
1020  *dst = c;
1021  ++src;
1022  ++dst;
1023  }
1024 
1025  if ((or_acc & kAsciiMask) != 0) return false;
1026 
1027  DCHECK(CheckFastAsciiConvert(saved_dst, saved_src, length, changed,
1028  Converter::kIsToLower));
1029 
1030  *changed_out = changed;
1031  return true;
1032 }
1033 
1034 
1035 template <class Converter>
1037  Handle<String> s, Isolate* isolate,
1039  s = String::Flatten(s);
1040  int length = s->length();
1041  // Assume that the string is not empty; we need this assumption later
1042  if (length == 0) return *s;
1043 
1044  // Simpler handling of ASCII strings.
1045  //
1046  // NOTE: This assumes that the upper/lower case of an ASCII
1047  // character is also ASCII. This is currently the case, but it
1048  // might break in the future if we implement more context and locale
1049  // dependent upper/lower conversions.
1050  if (s->IsOneByteRepresentationUnderneath()) {
1051  // Same length as input.
1052  Handle<SeqOneByteString> result =
1053  isolate->factory()->NewRawOneByteString(length).ToHandleChecked();
1054  DisallowHeapAllocation no_gc;
1055  String::FlatContent flat_content = s->GetFlatContent();
1056  DCHECK(flat_content.IsFlat());
1057  bool has_changed_character = false;
1058  bool is_ascii = FastAsciiConvert<Converter>(
1059  reinterpret_cast<char*>(result->GetChars()),
1060  reinterpret_cast<const char*>(flat_content.ToOneByteVector().start()),
1061  length, &has_changed_character);
1062  // If not ASCII, we discard the result and take the 2 byte path.
1063  if (is_ascii) return has_changed_character ? *result : *s;
1064  }
1065 
1066  Handle<SeqString> result; // Same length as input.
1067  if (s->IsOneByteRepresentation()) {
1068  result = isolate->factory()->NewRawOneByteString(length).ToHandleChecked();
1069  } else {
1070  result = isolate->factory()->NewRawTwoByteString(length).ToHandleChecked();
1071  }
1072 
1073  Object* answer = ConvertCaseHelper(isolate, *s, *result, length, mapping);
1074  if (answer->IsException() || answer->IsString()) return answer;
1075 
1076  DCHECK(answer->IsSmi());
1077  length = Smi::cast(answer)->value();
1078  if (s->IsOneByteRepresentation() && length > 0) {
1080  isolate, result, isolate->factory()->NewRawOneByteString(length));
1081  } else {
1082  if (length < 0) length = -length;
1084  isolate, result, isolate->factory()->NewRawTwoByteString(length));
1085  }
1086  return ConvertCaseHelper(isolate, *s, *result, length, mapping);
1087 }
1088 
1089 
1090 RUNTIME_FUNCTION(Runtime_StringToLowerCase) {
1091  HandleScope scope(isolate);
1092  DCHECK(args.length() == 1);
1094  return ConvertCase(s, isolate, isolate->runtime_state()->to_lower_mapping());
1095 }
1096 
1097 
1098 RUNTIME_FUNCTION(Runtime_StringToUpperCase) {
1099  HandleScope scope(isolate);
1100  DCHECK(args.length() == 1);
1102  return ConvertCase(s, isolate, isolate->runtime_state()->to_upper_mapping());
1103 }
1104 
1105 
1106 RUNTIME_FUNCTION(Runtime_StringTrim) {
1107  HandleScope scope(isolate);
1108  DCHECK(args.length() == 3);
1109 
1110  CONVERT_ARG_HANDLE_CHECKED(String, string, 0);
1111  CONVERT_BOOLEAN_ARG_CHECKED(trimLeft, 1);
1112  CONVERT_BOOLEAN_ARG_CHECKED(trimRight, 2);
1113 
1114  string = String::Flatten(string);
1115  int length = string->length();
1116 
1117  int left = 0;
1118  UnicodeCache* unicode_cache = isolate->unicode_cache();
1119  if (trimLeft) {
1120  while (left < length &&
1121  unicode_cache->IsWhiteSpaceOrLineTerminator(string->Get(left))) {
1122  left++;
1123  }
1124  }
1125 
1126  int right = length;
1127  if (trimRight) {
1128  while (
1129  right > left &&
1130  unicode_cache->IsWhiteSpaceOrLineTerminator(string->Get(right - 1))) {
1131  right--;
1132  }
1133  }
1134 
1135  return *isolate->factory()->NewSubString(string, left, right);
1136 }
1137 
1138 
1139 RUNTIME_FUNCTION(Runtime_TruncateString) {
1140  HandleScope scope(isolate);
1141  DCHECK(args.length() == 2);
1143  CONVERT_INT32_ARG_CHECKED(new_length, 1);
1144  RUNTIME_ASSERT(new_length >= 0);
1145  return *SeqString::Truncate(string, new_length);
1146 }
1147 
1148 
1149 RUNTIME_FUNCTION(Runtime_NewString) {
1150  HandleScope scope(isolate);
1151  DCHECK(args.length() == 2);
1152  CONVERT_INT32_ARG_CHECKED(length, 0);
1153  CONVERT_BOOLEAN_ARG_CHECKED(is_one_byte, 1);
1154  if (length == 0) return isolate->heap()->empty_string();
1155  Handle<String> result;
1156  if (is_one_byte) {
1158  isolate, result, isolate->factory()->NewRawOneByteString(length));
1159  } else {
1161  isolate, result, isolate->factory()->NewRawTwoByteString(length));
1162  }
1163  return *result;
1164 }
1165 
1166 
1167 RUNTIME_FUNCTION(Runtime_StringEquals) {
1168  HandleScope handle_scope(isolate);
1169  DCHECK(args.length() == 2);
1170 
1173 
1174  bool not_equal = !String::Equals(x, y);
1175  // This is slightly convoluted because the value that signifies
1176  // equality is 0 and inequality is 1 so we have to negate the result
1177  // from String::Equals.
1178  DCHECK(not_equal == 0 || not_equal == 1);
1179  STATIC_ASSERT(EQUAL == 0);
1180  STATIC_ASSERT(NOT_EQUAL == 1);
1181  return Smi::FromInt(not_equal);
1182 }
1183 
1184 
1185 RUNTIME_FUNCTION(Runtime_FlattenString) {
1186  HandleScope scope(isolate);
1187  DCHECK(args.length() == 1);
1189  return *String::Flatten(str);
1190 }
1191 
1192 
1193 RUNTIME_FUNCTION(RuntimeReference_StringCharFromCode) {
1194  SealHandleScope shs(isolate);
1195  return __RT_impl_Runtime_CharFromCode(args, isolate);
1196 }
1197 
1198 
1199 RUNTIME_FUNCTION(RuntimeReference_StringCharAt) {
1200  SealHandleScope shs(isolate);
1201  DCHECK(args.length() == 2);
1202  if (!args[0]->IsString()) return Smi::FromInt(0);
1203  if (!args[1]->IsNumber()) return Smi::FromInt(0);
1204  if (std::isinf(args.number_at(1))) return isolate->heap()->empty_string();
1205  Object* code = __RT_impl_Runtime_StringCharCodeAtRT(args, isolate);
1206  if (code->IsNaN()) return isolate->heap()->empty_string();
1207  return __RT_impl_Runtime_CharFromCode(Arguments(1, &code), isolate);
1208 }
1209 
1210 
1211 RUNTIME_FUNCTION(RuntimeReference_OneByteSeqStringSetChar) {
1212  SealHandleScope shs(isolate);
1213  DCHECK(args.length() == 3);
1214  CONVERT_INT32_ARG_CHECKED(index, 0);
1215  CONVERT_INT32_ARG_CHECKED(value, 1);
1217  string->SeqOneByteStringSet(index, value);
1218  return string;
1219 }
1220 
1221 
1222 RUNTIME_FUNCTION(RuntimeReference_TwoByteSeqStringSetChar) {
1223  SealHandleScope shs(isolate);
1224  DCHECK(args.length() == 3);
1225  CONVERT_INT32_ARG_CHECKED(index, 0);
1226  CONVERT_INT32_ARG_CHECKED(value, 1);
1228  string->SeqTwoByteStringSet(index, value);
1229  return string;
1230 }
1231 
1232 
1233 RUNTIME_FUNCTION(RuntimeReference_StringCompare) {
1234  SealHandleScope shs(isolate);
1235  return __RT_impl_Runtime_StringCompare(args, isolate);
1236 }
1237 
1238 
1239 RUNTIME_FUNCTION(RuntimeReference_StringCharCodeAt) {
1240  SealHandleScope shs(isolate);
1241  DCHECK(args.length() == 2);
1242  if (!args[0]->IsString()) return isolate->heap()->undefined_value();
1243  if (!args[1]->IsNumber()) return isolate->heap()->undefined_value();
1244  if (std::isinf(args.number_at(1))) return isolate->heap()->nan_value();
1245  return __RT_impl_Runtime_StringCharCodeAtRT(args, isolate);
1246 }
1247 
1248 
1249 RUNTIME_FUNCTION(RuntimeReference_SubString) {
1250  SealHandleScope shs(isolate);
1251  return __RT_impl_Runtime_SubString(args, isolate);
1252 }
1253 
1254 
1255 RUNTIME_FUNCTION(RuntimeReference_StringAdd) {
1256  SealHandleScope shs(isolate);
1257  return __RT_impl_Runtime_StringAdd(args, isolate);
1258 }
1259 }
1260 } // namespace v8::internal
int get(uchar c, uchar n, uchar *result)
Definition: unicode-inl.h:27
A JavaScript value representing a 32-bit signed integer.
Definition: v8.h:2191
A JavaScript value representing a 32-bit unsigned integer.
Definition: v8.h:2202
Object * get(int index)
Definition: objects-inl.h:2165
void set(int index, Object *value)
Definition: objects-inl.h:2190
WriteBarrierMode GetWriteBarrierMode(const DisallowHeapAllocation &promise)
Definition: objects-inl.h:2660
RuntimeState * runtime_state()
Definition: isolate.h:945
Factory * factory()
Definition: isolate.h:982
static void EnsureCanContainHeapObjectElements(Handle< JSObject > obj)
Definition: objects-inl.h:1725
void Add(const T &element, AllocationPolicy allocator=AllocationPolicy())
Definition: list-inl.h:17
T & at(int i) const
Definition: list.h:69
static Handle< JSArray > SetLastMatchInfo(Handle< JSArray > last_match_info, Handle< String > subject, int capture_count, int32_t *match)
Definition: jsregexp.cc:662
StaticResource< ConsStringIteratorOp > * string_iterator()
Definition: runtime.h:732
static int StringMatch(Isolate *isolate, Handle< String > sub, Handle< String > pat, int index)
static MUST_USE_RESULT Handle< String > Truncate(Handle< SeqString > string, int new_length)
Definition: objects.cc:8883
static const int kMaxValue
Definition: objects.h:1272
static Smi * FromInt(int value)
Definition: objects-inl.h:1321
Vector< const uint8_t > ToOneByteVector()
Definition: objects.h:8639
Vector< const uc16 > ToUC16Vector()
Definition: objects.h:8645
static void WriteToFlat(String *source, sinkchar *sink, int from, int to)
Definition: objects.cc:8370
static const int32_t kMaxOneByteCharCode
Definition: objects.h:8811
static const int kMaxLength
Definition: objects.h:8820
bool IsOneByteRepresentation() const
Definition: objects-inl.h:337
static Handle< String > Flatten(Handle< String > string, PretenureFlag pretenure=NOT_TENURED)
Definition: objects-inl.h:3354
void Set(int index, uint16_t value)
Definition: objects-inl.h:3388
bool Equals(String *other)
Definition: objects-inl.h:3336
bool IsWhiteSpaceOrLineTerminator(unibrow::uchar c)
Definition: scanner.h:124
T * start() const
Definition: vector.h:47
int length() const
Definition: vector.h:41
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be expose gc extension under the specified name show built in functions in stack traces use random jit cookie to mask large constants minimum length for automatic enable preparsing CPU profiler sampling interval in microseconds trace out of bounds accesses to external arrays default size of stack region v8 is allowed to maximum length of function source code printed in a stack trace min size of a semi the new space consists of two semi spaces print one trace line following each garbage collection do not print trace line after scavenger collection print cumulative GC statistics in only print modified registers Trace simulator debug messages Implied by trace sim abort randomize hashes to avoid predictable hash Fixed seed to use to hash property Print the time it takes to deserialize the snapshot A filename with extra code to be included in the A file to write the raw snapshot bytes to(mksnapshot only)") DEFINE_STRING(raw_context_file
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long mode(MIPS only)") DEFINE_BOOL(enable_always_align_csp
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be NULL
#define ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, dst, call)
Definition: isolate.h:131
#define THROW_NEW_ERROR_RETURN_FAILURE(isolate, call)
Definition: isolate.h:146
#define ASSIGN_RETURN_ON_EXCEPTION(isolate, dst, call, T)
Definition: isolate.h:135
#define DCHECK(condition)
Definition: logging.h:205
#define MUST_USE_RESULT
Definition: macros.h:266
unsigned int uchar
Definition: unicode.h:17
int int32_t
Definition: unicode.cc:24
const int kPointerSize
Definition: globals.h:129
static int CopyCachedOneByteCharsToArray(Heap *heap, const uint8_t *chars, FixedArray *elements, int length)
static MUST_USE_RESULT Object * ConvertCase(Handle< String > s, Isolate *isolate, unibrow::Mapping< Converter, 128 > *mapping)
const uintptr_t kUintptrAllBitsSet
Definition: globals.h:149
static void StringBuilderConcatHelper(String *special, sinkchar *sink, FixedArray *fixed_array, int array_length)
int CompareChars(const lchar *lhs, const rchar *rhs, int chars)
Definition: utils.h:705
static const uintptr_t kAsciiMask
static bool FastAsciiConvert(char *dst, const char *src, int length, bool *changed_out)
static int StringMatchBackwards(Vector< const schar > subject, Vector< const pchar > pattern, int idx)
void MemsetPointer(T **dest, U *value, int counter)
Definition: utils.h:1183
const int kMaxInt
Definition: globals.h:109
static uintptr_t AsciiRangeMask(uintptr_t w, char m, char n)
int32_t NumberToInt32(Object *number)
Definition: conversions.h:189
static MUST_USE_RESULT Object * ConvertCaseHelper(Isolate *isolate, String *string, SeqString *result, int result_length, unibrow::Mapping< Converter, 128 > *mapping)
static void JoinSparseArrayWithSeparator(FixedArray *elements, int elements_length, uint32_t array_length, String *separator, Vector< Char > buffer)
STATIC_ASSERT(sizeof(CPURegister)==sizeof(Register))
MaybeHandle< String > StringReplaceOneCharWithString(Isolate *isolate, Handle< String > subject, Handle< String > search, Handle< String > replace, bool *found, int recursion_limit)
uint16_t uc16
Definition: globals.h:184
static bool ToUpperOverflows(uc32 character)
bool TryNumberToSize(Isolate *isolate, Object *number, size_t *result)
Definition: conversions.h:207
int32_t uc32
Definition: globals.h:185
bool IsAligned(T value, U alignment)
Definition: utils.h:123
int FastD2IChecked(double x)
Definition: conversions.h:46
static int StringBuilderConcatLength(int special_length, FixedArray *fixed_array, int array_length, bool *one_byte)
static const uintptr_t kOneInEveryByte
@ RUNTIME_FUNCTION
Definition: serialize.h:23
Debugger support for the V8 JavaScript engine.
Definition: accessors.cc:20
#define CONVERT_BOOLEAN_ARG_CHECKED(name, index)
Definition: runtime-utils.h:39
#define CONVERT_ARG_CHECKED(Type, name, index)
Definition: runtime-utils.h:24
#define RUNTIME_ASSERT(value)
Definition: runtime-utils.h:12
#define CONVERT_ARG_HANDLE_CHECKED(Type, name, index)
Definition: runtime-utils.h:28
#define CONVERT_NUMBER_CHECKED(type, name, Type, obj)
Definition: runtime-utils.h:60
#define CONVERT_DOUBLE_ARG_CHECKED(name, index)
Definition: runtime-utils.h:53
#define CONVERT_INT32_ARG_CHECKED(name, index)
Definition: runtime-utils.h:85
#define CONVERT_SMI_ARG_CHECKED(name, index)
Definition: runtime-utils.h:46