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

Side by Side Diff: src/runtime.cc

Issue 210683003: Reland "No longer OOM on invalid string length." (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 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 | Annotate | Revision Log
« no previous file with comments | « src/parser.cc ('k') | src/uri.h » ('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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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 3345 matching lines...) Expand 10 before | Expand all | Expand 10 after
3356 3356
3357 class ReplacementStringBuilder { 3357 class ReplacementStringBuilder {
3358 public: 3358 public:
3359 ReplacementStringBuilder(Heap* heap, 3359 ReplacementStringBuilder(Heap* heap,
3360 Handle<String> subject, 3360 Handle<String> subject,
3361 int estimated_part_count) 3361 int estimated_part_count)
3362 : heap_(heap), 3362 : heap_(heap),
3363 array_builder_(heap->isolate(), estimated_part_count), 3363 array_builder_(heap->isolate(), estimated_part_count),
3364 subject_(subject), 3364 subject_(subject),
3365 character_count_(0), 3365 character_count_(0),
3366 is_ascii_(subject->IsOneByteRepresentation()), 3366 is_ascii_(subject->IsOneByteRepresentation()) {
3367 overflowed_(false) {
3368 // Require a non-zero initial size. Ensures that doubling the size to 3367 // Require a non-zero initial size. Ensures that doubling the size to
3369 // extend the array will work. 3368 // extend the array will work.
3370 ASSERT(estimated_part_count > 0); 3369 ASSERT(estimated_part_count > 0);
3371 } 3370 }
3372 3371
3373 static inline void AddSubjectSlice(FixedArrayBuilder* builder, 3372 static inline void AddSubjectSlice(FixedArrayBuilder* builder,
3374 int from, 3373 int from,
3375 int to) { 3374 int to) {
3376 ASSERT(from >= 0); 3375 ASSERT(from >= 0);
3377 int length = to - from; 3376 int length = to - from;
(...skipping 27 matching lines...) Expand all
3405 ASSERT(length > 0); 3404 ASSERT(length > 0);
3406 AddElement(*string); 3405 AddElement(*string);
3407 if (!string->IsOneByteRepresentation()) { 3406 if (!string->IsOneByteRepresentation()) {
3408 is_ascii_ = false; 3407 is_ascii_ = false;
3409 } 3408 }
3410 IncrementCharacterCount(length); 3409 IncrementCharacterCount(length);
3411 } 3410 }
3412 3411
3413 3412
3414 Handle<String> ToString() { 3413 Handle<String> ToString() {
3415 if (overflowed_) {
3416 heap_->isolate()->ThrowInvalidStringLength();
3417 return Handle<String>();
3418 }
3419
3420 if (array_builder_.length() == 0) { 3414 if (array_builder_.length() == 0) {
3421 return heap_->isolate()->factory()->empty_string(); 3415 return heap_->isolate()->factory()->empty_string();
3422 } 3416 }
3423 3417
3424 Handle<String> joined_string; 3418 Handle<String> joined_string;
3425 if (is_ascii_) { 3419 if (is_ascii_) {
3426 Handle<SeqOneByteString> seq = NewRawOneByteString(character_count_); 3420 Handle<SeqOneByteString> seq = NewRawOneByteString(character_count_);
3421 RETURN_IF_EMPTY_HANDLE_VALUE(heap_->isolate(), seq, Handle<String>());
3427 DisallowHeapAllocation no_gc; 3422 DisallowHeapAllocation no_gc;
3428 uint8_t* char_buffer = seq->GetChars(); 3423 uint8_t* char_buffer = seq->GetChars();
3429 StringBuilderConcatHelper(*subject_, 3424 StringBuilderConcatHelper(*subject_,
3430 char_buffer, 3425 char_buffer,
3431 *array_builder_.array(), 3426 *array_builder_.array(),
3432 array_builder_.length()); 3427 array_builder_.length());
3433 joined_string = Handle<String>::cast(seq); 3428 joined_string = Handle<String>::cast(seq);
3434 } else { 3429 } else {
3435 // Non-ASCII. 3430 // Non-ASCII.
3436 Handle<SeqTwoByteString> seq = NewRawTwoByteString(character_count_); 3431 Handle<SeqTwoByteString> seq = NewRawTwoByteString(character_count_);
3432 RETURN_IF_EMPTY_HANDLE_VALUE(heap_->isolate(), seq, Handle<String>());
3437 DisallowHeapAllocation no_gc; 3433 DisallowHeapAllocation no_gc;
3438 uc16* char_buffer = seq->GetChars(); 3434 uc16* char_buffer = seq->GetChars();
3439 StringBuilderConcatHelper(*subject_, 3435 StringBuilderConcatHelper(*subject_,
3440 char_buffer, 3436 char_buffer,
3441 *array_builder_.array(), 3437 *array_builder_.array(),
3442 array_builder_.length()); 3438 array_builder_.length());
3443 joined_string = Handle<String>::cast(seq); 3439 joined_string = Handle<String>::cast(seq);
3444 } 3440 }
3445 return joined_string; 3441 return joined_string;
3446 } 3442 }
3447 3443
3448 3444
3449 void IncrementCharacterCount(int by) { 3445 void IncrementCharacterCount(int by) {
3450 if (character_count_ > String::kMaxLength - by) { 3446 if (character_count_ > String::kMaxLength - by) {
3451 overflowed_ = true; 3447 STATIC_ASSERT(String::kMaxLength < kMaxInt);
3448 character_count_ = kMaxInt;
3449 } else {
3450 character_count_ += by;
3452 } 3451 }
3453 character_count_ += by;
3454 } 3452 }
3455 3453
3456 private: 3454 private:
3457 Handle<SeqOneByteString> NewRawOneByteString(int length) { 3455 Handle<SeqOneByteString> NewRawOneByteString(int length) {
3458 return heap_->isolate()->factory()->NewRawOneByteString(length); 3456 return heap_->isolate()->factory()->NewRawOneByteString(length);
3459 } 3457 }
3460 3458
3461 3459
3462 Handle<SeqTwoByteString> NewRawTwoByteString(int length) { 3460 Handle<SeqTwoByteString> NewRawTwoByteString(int length) {
3463 return heap_->isolate()->factory()->NewRawTwoByteString(length); 3461 return heap_->isolate()->factory()->NewRawTwoByteString(length);
3464 } 3462 }
3465 3463
3466 3464
3467 void AddElement(Object* element) { 3465 void AddElement(Object* element) {
3468 ASSERT(element->IsSmi() || element->IsString()); 3466 ASSERT(element->IsSmi() || element->IsString());
3469 ASSERT(array_builder_.capacity() > array_builder_.length()); 3467 ASSERT(array_builder_.capacity() > array_builder_.length());
3470 array_builder_.Add(element); 3468 array_builder_.Add(element);
3471 } 3469 }
3472 3470
3473 Heap* heap_; 3471 Heap* heap_;
3474 FixedArrayBuilder array_builder_; 3472 FixedArrayBuilder array_builder_;
3475 Handle<String> subject_; 3473 Handle<String> subject_;
3476 int character_count_; 3474 int character_count_;
3477 bool is_ascii_; 3475 bool is_ascii_;
3478 bool overflowed_;
3479 }; 3476 };
3480 3477
3481 3478
3482 class CompiledReplacement { 3479 class CompiledReplacement {
3483 public: 3480 public:
3484 explicit CompiledReplacement(Zone* zone) 3481 explicit CompiledReplacement(Zone* zone)
3485 : parts_(1, zone), replacement_substrings_(0, zone), zone_(zone) {} 3482 : parts_(1, zone), replacement_substrings_(0, zone), zone_(zone) {}
3486 3483
3487 // Return whether the replacement is simple. 3484 // Return whether the replacement is simple.
3488 bool Compile(Handle<String> replacement, 3485 bool Compile(Handle<String> replacement,
(...skipping 436 matching lines...) Expand 10 before | Expand all | Expand 10 after
3925 3922
3926 int matches = indices.length(); 3923 int matches = indices.length();
3927 if (matches == 0) return *subject; 3924 if (matches == 0) return *subject;
3928 3925
3929 // Detect integer overflow. 3926 // Detect integer overflow.
3930 int64_t result_len_64 = 3927 int64_t result_len_64 =
3931 (static_cast<int64_t>(replacement_len) - 3928 (static_cast<int64_t>(replacement_len) -
3932 static_cast<int64_t>(pattern_len)) * 3929 static_cast<int64_t>(pattern_len)) *
3933 static_cast<int64_t>(matches) + 3930 static_cast<int64_t>(matches) +
3934 static_cast<int64_t>(subject_len); 3931 static_cast<int64_t>(subject_len);
3935 if (result_len_64 > INT_MAX) { 3932 int result_len;
3936 v8::internal::Heap::FatalProcessOutOfMemory("invalid string length", true); 3933 if (result_len_64 > static_cast<int64_t>(String::kMaxLength)) {
3934 STATIC_ASSERT(String::kMaxLength < kMaxInt);
3935 result_len = kMaxInt; // Provoke exception.
3936 } else {
3937 result_len = static_cast<int>(result_len_64);
3937 } 3938 }
3938 int result_len = static_cast<int>(result_len_64);
3939 3939
3940 int subject_pos = 0; 3940 int subject_pos = 0;
3941 int result_pos = 0; 3941 int result_pos = 0;
3942 3942
3943 Handle<ResultSeqString> result; 3943 Handle<String> result_seq;
3944 if (ResultSeqString::kHasAsciiEncoding) { 3944 if (ResultSeqString::kHasAsciiEncoding) {
3945 result = Handle<ResultSeqString>::cast( 3945 result_seq = isolate->factory()->NewRawOneByteString(result_len);
3946 isolate->factory()->NewRawOneByteString(result_len));
3947 } else { 3946 } else {
3948 result = Handle<ResultSeqString>::cast( 3947 result_seq = isolate->factory()->NewRawTwoByteString(result_len);
3949 isolate->factory()->NewRawTwoByteString(result_len));
3950 } 3948 }
3949 RETURN_IF_EMPTY_HANDLE(isolate, result_seq);
3950 Handle<ResultSeqString> result = Handle<ResultSeqString>::cast(result_seq);
3951 3951
3952 for (int i = 0; i < matches; i++) { 3952 for (int i = 0; i < matches; i++) {
3953 // Copy non-matched subject content. 3953 // Copy non-matched subject content.
3954 if (subject_pos < indices.at(i)) { 3954 if (subject_pos < indices.at(i)) {
3955 String::WriteToFlat(*subject, 3955 String::WriteToFlat(*subject,
3956 result->GetChars() + result_pos, 3956 result->GetChars() + result_pos,
3957 subject_pos, 3957 subject_pos,
3958 indices.at(i)); 3958 indices.at(i));
3959 result_pos += indices.at(i) - subject_pos; 3959 result_pos += indices.at(i) - subject_pos;
3960 } 3960 }
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
4120 if (new_length == 0) return isolate->heap()->empty_string(); 4120 if (new_length == 0) return isolate->heap()->empty_string();
4121 4121
4122 Handle<ResultSeqString> answer; 4122 Handle<ResultSeqString> answer;
4123 if (ResultSeqString::kHasAsciiEncoding) { 4123 if (ResultSeqString::kHasAsciiEncoding) {
4124 answer = Handle<ResultSeqString>::cast( 4124 answer = Handle<ResultSeqString>::cast(
4125 isolate->factory()->NewRawOneByteString(new_length)); 4125 isolate->factory()->NewRawOneByteString(new_length));
4126 } else { 4126 } else {
4127 answer = Handle<ResultSeqString>::cast( 4127 answer = Handle<ResultSeqString>::cast(
4128 isolate->factory()->NewRawTwoByteString(new_length)); 4128 isolate->factory()->NewRawTwoByteString(new_length));
4129 } 4129 }
4130 ASSERT(!answer.is_null());
4130 4131
4131 int prev = 0; 4132 int prev = 0;
4132 int position = 0; 4133 int position = 0;
4133 4134
4134 do { 4135 do {
4135 start = current_match[0]; 4136 start = current_match[0];
4136 end = current_match[1]; 4137 end = current_match[1];
4137 if (prev < start) { 4138 if (prev < start) {
4138 // Add substring subject[prev;start] to answer string. 4139 // Add substring subject[prev;start] to answer string.
4139 String::WriteToFlat(*subject, answer->GetChars() + position, prev, start); 4140 String::WriteToFlat(*subject, answer->GetChars() + position, prev, start);
(...skipping 2437 matching lines...) Expand 10 before | Expand all | Expand 10 after
6577 6578
6578 // Simpler handling of ASCII strings. 6579 // Simpler handling of ASCII strings.
6579 // 6580 //
6580 // NOTE: This assumes that the upper/lower case of an ASCII 6581 // NOTE: This assumes that the upper/lower case of an ASCII
6581 // character is also ASCII. This is currently the case, but it 6582 // character is also ASCII. This is currently the case, but it
6582 // might break in the future if we implement more context and locale 6583 // might break in the future if we implement more context and locale
6583 // dependent upper/lower conversions. 6584 // dependent upper/lower conversions.
6584 if (s->IsOneByteRepresentationUnderneath()) { 6585 if (s->IsOneByteRepresentationUnderneath()) {
6585 Handle<SeqOneByteString> result = 6586 Handle<SeqOneByteString> result =
6586 isolate->factory()->NewRawOneByteString(length); 6587 isolate->factory()->NewRawOneByteString(length);
6587 6588 ASSERT(!result.is_null()); // Same length as input.
6588 DisallowHeapAllocation no_gc; 6589 DisallowHeapAllocation no_gc;
6589 String::FlatContent flat_content = s->GetFlatContent(); 6590 String::FlatContent flat_content = s->GetFlatContent();
6590 ASSERT(flat_content.IsFlat()); 6591 ASSERT(flat_content.IsFlat());
6591 bool has_changed_character = false; 6592 bool has_changed_character = false;
6592 bool is_ascii = FastAsciiConvert<Converter>( 6593 bool is_ascii = FastAsciiConvert<Converter>(
6593 reinterpret_cast<char*>(result->GetChars()), 6594 reinterpret_cast<char*>(result->GetChars()),
6594 reinterpret_cast<const char*>(flat_content.ToOneByteVector().start()), 6595 reinterpret_cast<const char*>(flat_content.ToOneByteVector().start()),
6595 length, 6596 length,
6596 &has_changed_character); 6597 &has_changed_character);
6597 // If not ASCII, we discard the result and take the 2 byte path. 6598 // If not ASCII, we discard the result and take the 2 byte path.
6598 if (is_ascii) return has_changed_character ? *result : *s; 6599 if (is_ascii) return has_changed_character ? *result : *s;
6599 } 6600 }
6600 6601
6601 Handle<SeqString> result; 6602 Handle<SeqString> result;
6602 if (s->IsOneByteRepresentation()) { 6603 if (s->IsOneByteRepresentation()) {
6603 result = isolate->factory()->NewRawOneByteString(length); 6604 result = isolate->factory()->NewRawOneByteString(length);
6604 } else { 6605 } else {
6605 result = isolate->factory()->NewRawTwoByteString(length); 6606 result = isolate->factory()->NewRawTwoByteString(length);
6606 } 6607 }
6608 ASSERT(!result.is_null()); // Same length as input.
6609
6607 MaybeObject* maybe = ConvertCaseHelper(isolate, *s, *result, length, mapping); 6610 MaybeObject* maybe = ConvertCaseHelper(isolate, *s, *result, length, mapping);
6608 Object* answer; 6611 Object* answer;
6609 if (!maybe->ToObject(&answer)) return maybe; 6612 if (!maybe->ToObject(&answer)) return maybe;
6610 if (answer->IsString()) return answer; 6613 if (answer->IsString()) return answer;
6611 6614
6612 ASSERT(answer->IsSmi()); 6615 ASSERT(answer->IsSmi());
6613 length = Smi::cast(answer)->value(); 6616 length = Smi::cast(answer)->value();
6614 if (s->IsOneByteRepresentation() && length > 0) { 6617 if (s->IsOneByteRepresentation() && length > 0) {
6615 result = isolate->factory()->NewRawOneByteString(length); 6618 result = isolate->factory()->NewRawOneByteString(length);
6616 } else { 6619 } else {
6617 if (length < 0) length = -length; 6620 if (length < 0) length = -length;
6618 result = isolate->factory()->NewRawTwoByteString(length); 6621 result = isolate->factory()->NewRawTwoByteString(length);
6619 } 6622 }
6623 RETURN_IF_EMPTY_HANDLE(isolate, result);
6620 return ConvertCaseHelper(isolate, *s, *result, length, mapping); 6624 return ConvertCaseHelper(isolate, *s, *result, length, mapping);
6621 } 6625 }
6622 6626
6623 6627
6624 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToLowerCase) { 6628 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToLowerCase) {
6625 return ConvertCase( 6629 return ConvertCase(
6626 args, isolate, isolate->runtime_state()->to_lower_mapping()); 6630 args, isolate, isolate->runtime_state()->to_lower_mapping());
6627 } 6631 }
6628 6632
6629 6633
(...skipping 624 matching lines...) Expand 10 before | Expand all | Expand 10 after
7254 if (max_nof_separators < (array_length - 1)) { 7258 if (max_nof_separators < (array_length - 1)) {
7255 return isolate->ThrowInvalidStringLength(); 7259 return isolate->ThrowInvalidStringLength();
7256 } 7260 }
7257 int length = (array_length - 1) * separator_length; 7261 int length = (array_length - 1) * separator_length;
7258 for (int i = 0; i < array_length; i++) { 7262 for (int i = 0; i < array_length; i++) {
7259 Object* element_obj = fixed_array->get(i); 7263 Object* element_obj = fixed_array->get(i);
7260 RUNTIME_ASSERT(element_obj->IsString()); 7264 RUNTIME_ASSERT(element_obj->IsString());
7261 String* element = String::cast(element_obj); 7265 String* element = String::cast(element_obj);
7262 int increment = element->length(); 7266 int increment = element->length();
7263 if (increment > String::kMaxLength - length) { 7267 if (increment > String::kMaxLength - length) {
7264 return isolate->ThrowInvalidStringLength(); 7268 STATIC_ASSERT(String::kMaxLength < kMaxInt);
7269 length = kMaxInt; // Provoke exception;
7270 break;
7265 } 7271 }
7266 length += increment; 7272 length += increment;
7267 } 7273 }
7268 7274
7269 Handle<SeqTwoByteString> answer = 7275 Handle<SeqTwoByteString> answer =
7270 isolate->factory()->NewRawTwoByteString(length); 7276 isolate->factory()->NewRawTwoByteString(length);
7277 RETURN_IF_EMPTY_HANDLE(isolate, answer);
7271 7278
7272 DisallowHeapAllocation no_gc; 7279 DisallowHeapAllocation no_gc;
7273 7280
7274 uc16* sink = answer->GetChars(); 7281 uc16* sink = answer->GetChars();
7275 #ifdef DEBUG 7282 #ifdef DEBUG
7276 uc16* end = sink + length; 7283 uc16* end = sink + length;
7277 #endif 7284 #endif
7278 7285
7279 String* first = String::cast(fixed_array->get(0)); 7286 String* first = String::cast(fixed_array->get(0));
7280 String* seperator_raw = *separator; 7287 String* seperator_raw = *separator;
(...skipping 2224 matching lines...) Expand 10 before | Expand all | Expand 10 after
9505 "not_date_object", HandleVector<Object>(NULL, 0))); 9512 "not_date_object", HandleVector<Object>(NULL, 0)));
9506 } 9513 }
9507 9514
9508 9515
9509 RUNTIME_FUNCTION(MaybeObject*, Runtime_ThrowMessage) { 9516 RUNTIME_FUNCTION(MaybeObject*, Runtime_ThrowMessage) {
9510 HandleScope scope(isolate); 9517 HandleScope scope(isolate);
9511 ASSERT(args.length() == 1); 9518 ASSERT(args.length() == 1);
9512 CONVERT_SMI_ARG_CHECKED(message_id, 0); 9519 CONVERT_SMI_ARG_CHECKED(message_id, 0);
9513 const char* message = GetBailoutReason( 9520 const char* message = GetBailoutReason(
9514 static_cast<BailoutReason>(message_id)); 9521 static_cast<BailoutReason>(message_id));
9515 Handle<Name> message_handle = 9522 Handle<String> message_handle =
9516 isolate->factory()->NewStringFromAscii(CStrVector(message)); 9523 isolate->factory()->NewStringFromAscii(CStrVector(message));
9524 RETURN_IF_EMPTY_HANDLE(isolate, message_handle);
9517 return isolate->Throw(*message_handle); 9525 return isolate->Throw(*message_handle);
9518 } 9526 }
9519 9527
9520 9528
9521 RUNTIME_FUNCTION(MaybeObject*, Runtime_StackGuard) { 9529 RUNTIME_FUNCTION(MaybeObject*, Runtime_StackGuard) {
9522 SealHandleScope shs(isolate); 9530 SealHandleScope shs(isolate);
9523 ASSERT(args.length() == 0); 9531 ASSERT(args.length() == 0);
9524 9532
9525 // First check if this is a real stack overflow. 9533 // First check if this is a real stack overflow.
9526 if (isolate->stack_guard()->IsStackOverflow()) { 9534 if (isolate->stack_guard()->IsStackOverflow()) {
(...skipping 5571 matching lines...) Expand 10 before | Expand all | Expand 10 after
15098 // Handle last resort GC and make sure to allow future allocations 15106 // Handle last resort GC and make sure to allow future allocations
15099 // to grow the heap without causing GCs (if possible). 15107 // to grow the heap without causing GCs (if possible).
15100 isolate->counters()->gc_last_resort_from_js()->Increment(); 15108 isolate->counters()->gc_last_resort_from_js()->Increment();
15101 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, 15109 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags,
15102 "Runtime::PerformGC"); 15110 "Runtime::PerformGC");
15103 } 15111 }
15104 } 15112 }
15105 15113
15106 15114
15107 } } // namespace v8::internal 15115 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/parser.cc ('k') | src/uri.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698