| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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/objects.h" | 5 #include "src/objects.h" |
| 6 | 6 |
| 7 #include <cmath> | 7 #include <cmath> |
| 8 #include <iomanip> | 8 #include <iomanip> |
| 9 #include <sstream> | 9 #include <sstream> |
| 10 | 10 |
| (...skipping 15636 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 15647 } | 15647 } |
| 15648 | 15648 |
| 15649 private: | 15649 private: |
| 15650 Handle<String> source_; | 15650 Handle<String> source_; |
| 15651 Handle<SharedFunctionInfo> shared_; | 15651 Handle<SharedFunctionInfo> shared_; |
| 15652 LanguageMode language_mode_; | 15652 LanguageMode language_mode_; |
| 15653 int scope_position_; | 15653 int scope_position_; |
| 15654 }; | 15654 }; |
| 15655 | 15655 |
| 15656 | 15656 |
| 15657 // static | 15657 namespace { |
| 15658 MaybeHandle<JSRegExp> JSRegExp::New(Handle<String> pattern, | |
| 15659 Handle<String> flags) { | |
| 15660 Isolate* isolate = pattern->GetIsolate(); | |
| 15661 Handle<JSFunction> constructor = isolate->regexp_function(); | |
| 15662 Handle<JSRegExp> regexp = | |
| 15663 Handle<JSRegExp>::cast(isolate->factory()->NewJSObject(constructor)); | |
| 15664 | 15658 |
| 15665 return JSRegExp::Initialize(regexp, pattern, flags); | 15659 JSRegExp::Flags RegExpFlagsFromString(Handle<String> flags, bool* success) { |
| 15666 } | 15660 JSRegExp::Flags value = JSRegExp::kNone; |
| 15667 | |
| 15668 | |
| 15669 // static | |
| 15670 Handle<JSRegExp> JSRegExp::Copy(Handle<JSRegExp> regexp) { | |
| 15671 Isolate* const isolate = regexp->GetIsolate(); | |
| 15672 return Handle<JSRegExp>::cast(isolate->factory()->CopyJSObject(regexp)); | |
| 15673 } | |
| 15674 | |
| 15675 | |
| 15676 static JSRegExp::Flags RegExpFlagsFromString(Handle<String> flags, | |
| 15677 bool* success) { | |
| 15678 uint32_t value = JSRegExp::NONE; | |
| 15679 int length = flags->length(); | 15661 int length = flags->length(); |
| 15680 // A longer flags string cannot be valid. | 15662 // A longer flags string cannot be valid. |
| 15681 if (length > 5) return JSRegExp::Flags(0); | 15663 if (length > 5) return JSRegExp::Flags(0); |
| 15682 for (int i = 0; i < length; i++) { | 15664 for (int i = 0; i < length; i++) { |
| 15683 uint32_t flag = JSRegExp::NONE; | 15665 JSRegExp::Flag flag = JSRegExp::kNone; |
| 15684 switch (flags->Get(i)) { | 15666 switch (flags->Get(i)) { |
| 15685 case 'g': | 15667 case 'g': |
| 15686 flag = JSRegExp::GLOBAL; | 15668 flag = JSRegExp::kGlobal; |
| 15687 break; | 15669 break; |
| 15688 case 'i': | 15670 case 'i': |
| 15689 flag = JSRegExp::IGNORE_CASE; | 15671 flag = JSRegExp::kIgnoreCase; |
| 15690 break; | 15672 break; |
| 15691 case 'm': | 15673 case 'm': |
| 15692 flag = JSRegExp::MULTILINE; | 15674 flag = JSRegExp::kMultiline; |
| 15693 break; | 15675 break; |
| 15694 case 'u': | 15676 case 'u': |
| 15695 if (!FLAG_harmony_unicode_regexps) return JSRegExp::Flags(0); | 15677 if (!FLAG_harmony_unicode_regexps) return JSRegExp::Flags(0); |
| 15696 flag = JSRegExp::UNICODE_ESCAPES; | 15678 flag = JSRegExp::kUnicode; |
| 15697 break; | 15679 break; |
| 15698 case 'y': | 15680 case 'y': |
| 15699 if (!FLAG_harmony_regexps) return JSRegExp::Flags(0); | 15681 if (!FLAG_harmony_regexps) return JSRegExp::Flags(0); |
| 15700 flag = JSRegExp::STICKY; | 15682 flag = JSRegExp::kSticky; |
| 15701 break; | 15683 break; |
| 15702 default: | 15684 default: |
| 15703 return JSRegExp::Flags(0); | 15685 return JSRegExp::Flags(0); |
| 15704 } | 15686 } |
| 15705 // Duplicate flag. | 15687 // Duplicate flag. |
| 15706 if (value & flag) return JSRegExp::Flags(0); | 15688 if (value & flag) return JSRegExp::Flags(0); |
| 15707 value |= flag; | 15689 value |= flag; |
| 15708 } | 15690 } |
| 15709 *success = true; | 15691 *success = true; |
| 15710 return JSRegExp::Flags(value); | 15692 return value; |
| 15693 } |
| 15694 |
| 15695 } // namespace |
| 15696 |
| 15697 |
| 15698 // static |
| 15699 MaybeHandle<JSRegExp> JSRegExp::New(Handle<String> pattern, Flags flags) { |
| 15700 Isolate* isolate = pattern->GetIsolate(); |
| 15701 Handle<JSFunction> constructor = isolate->regexp_function(); |
| 15702 Handle<JSRegExp> regexp = |
| 15703 Handle<JSRegExp>::cast(isolate->factory()->NewJSObject(constructor)); |
| 15704 |
| 15705 return JSRegExp::Initialize(regexp, pattern, flags); |
| 15711 } | 15706 } |
| 15712 | 15707 |
| 15713 | 15708 |
| 15709 // static |
| 15710 MaybeHandle<JSRegExp> JSRegExp::New(Handle<String> pattern, |
| 15711 Handle<String> flags_string) { |
| 15712 Isolate* isolate = pattern->GetIsolate(); |
| 15713 bool success = false; |
| 15714 Flags flags = RegExpFlagsFromString(flags_string, &success); |
| 15715 if (!success) { |
| 15716 THROW_NEW_ERROR( |
| 15717 isolate, |
| 15718 NewSyntaxError(MessageTemplate::kInvalidRegExpFlags, flags_string), |
| 15719 JSRegExp); |
| 15720 } |
| 15721 return New(pattern, flags); |
| 15722 } |
| 15723 |
| 15724 |
| 15725 // static |
| 15726 Handle<JSRegExp> JSRegExp::Copy(Handle<JSRegExp> regexp) { |
| 15727 Isolate* const isolate = regexp->GetIsolate(); |
| 15728 return Handle<JSRegExp>::cast(isolate->factory()->CopyJSObject(regexp)); |
| 15729 } |
| 15730 |
| 15731 |
| 15714 template <typename Char> | 15732 template <typename Char> |
| 15715 inline int CountRequiredEscapes(Handle<String> source) { | 15733 inline int CountRequiredEscapes(Handle<String> source) { |
| 15716 DisallowHeapAllocation no_gc; | 15734 DisallowHeapAllocation no_gc; |
| 15717 int escapes = 0; | 15735 int escapes = 0; |
| 15718 Vector<const Char> src = source->GetCharVector<Char>(); | 15736 Vector<const Char> src = source->GetCharVector<Char>(); |
| 15719 for (int i = 0; i < src.length(); i++) { | 15737 for (int i = 0; i < src.length(); i++) { |
| 15720 if (src[i] == '/' && (i == 0 || src[i - 1] != '\\')) escapes++; | 15738 if (src[i] == '/' && (i == 0 || src[i - 1] != '\\')) escapes++; |
| 15721 } | 15739 } |
| 15722 return escapes; | 15740 return escapes; |
| 15723 } | 15741 } |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 15762 String); | 15780 String); |
| 15763 return WriteEscapedRegExpSource<uc16>(source, result); | 15781 return WriteEscapedRegExpSource<uc16>(source, result); |
| 15764 } | 15782 } |
| 15765 } | 15783 } |
| 15766 | 15784 |
| 15767 | 15785 |
| 15768 // static | 15786 // static |
| 15769 MaybeHandle<JSRegExp> JSRegExp::Initialize(Handle<JSRegExp> regexp, | 15787 MaybeHandle<JSRegExp> JSRegExp::Initialize(Handle<JSRegExp> regexp, |
| 15770 Handle<String> source, | 15788 Handle<String> source, |
| 15771 Handle<String> flags_string) { | 15789 Handle<String> flags_string) { |
| 15790 Isolate* isolate = source->GetIsolate(); |
| 15791 bool success = false; |
| 15792 Flags flags = RegExpFlagsFromString(flags_string, &success); |
| 15793 if (!success) { |
| 15794 THROW_NEW_ERROR( |
| 15795 isolate, |
| 15796 NewSyntaxError(MessageTemplate::kInvalidRegExpFlags, flags_string), |
| 15797 JSRegExp); |
| 15798 } |
| 15799 return Initialize(regexp, source, flags); |
| 15800 } |
| 15801 |
| 15802 |
| 15803 // static |
| 15804 MaybeHandle<JSRegExp> JSRegExp::Initialize(Handle<JSRegExp> regexp, |
| 15805 Handle<String> source, Flags flags) { |
| 15772 Isolate* isolate = regexp->GetIsolate(); | 15806 Isolate* isolate = regexp->GetIsolate(); |
| 15773 Factory* factory = isolate->factory(); | 15807 Factory* factory = isolate->factory(); |
| 15774 // If source is the empty string we set it to "(?:)" instead as | 15808 // If source is the empty string we set it to "(?:)" instead as |
| 15775 // suggested by ECMA-262, 5th, section 15.10.4.1. | 15809 // suggested by ECMA-262, 5th, section 15.10.4.1. |
| 15776 if (source->length() == 0) source = factory->query_colon_string(); | 15810 if (source->length() == 0) source = factory->query_colon_string(); |
| 15777 | 15811 |
| 15778 bool success = false; | |
| 15779 JSRegExp::Flags flags = RegExpFlagsFromString(flags_string, &success); | |
| 15780 if (!success) { | |
| 15781 THROW_NEW_ERROR( | |
| 15782 isolate, | |
| 15783 NewSyntaxError(MessageTemplate::kInvalidRegExpFlags, flags_string), | |
| 15784 JSRegExp); | |
| 15785 } | |
| 15786 | |
| 15787 Handle<String> escaped_source; | 15812 Handle<String> escaped_source; |
| 15788 ASSIGN_RETURN_ON_EXCEPTION(isolate, escaped_source, | 15813 ASSIGN_RETURN_ON_EXCEPTION(isolate, escaped_source, |
| 15789 EscapeRegExpSource(isolate, source), JSRegExp); | 15814 EscapeRegExpSource(isolate, source), JSRegExp); |
| 15790 | 15815 |
| 15791 regexp->set_source(*escaped_source); | 15816 regexp->set_source(*escaped_source); |
| 15792 regexp->set_flags(Smi::FromInt(flags.value())); | 15817 regexp->set_flags(Smi::FromInt(flags)); |
| 15793 | 15818 |
| 15794 Map* map = regexp->map(); | 15819 Map* map = regexp->map(); |
| 15795 Object* constructor = map->GetConstructor(); | 15820 Object* constructor = map->GetConstructor(); |
| 15796 if (constructor->IsJSFunction() && | 15821 if (constructor->IsJSFunction() && |
| 15797 JSFunction::cast(constructor)->initial_map() == map) { | 15822 JSFunction::cast(constructor)->initial_map() == map) { |
| 15798 // If we still have the original map, set in-object properties directly. | 15823 // If we still have the original map, set in-object properties directly. |
| 15799 regexp->InObjectPropertyAtPut(JSRegExp::kLastIndexFieldIndex, | 15824 regexp->InObjectPropertyAtPut(JSRegExp::kLastIndexFieldIndex, |
| 15800 Smi::FromInt(0), SKIP_WRITE_BARRIER); | 15825 Smi::FromInt(0), SKIP_WRITE_BARRIER); |
| 15801 } else { | 15826 } else { |
| 15802 // Map has changed, so use generic, but slower, method. | 15827 // Map has changed, so use generic, but slower, method. |
| 15803 PropertyAttributes writable = | 15828 PropertyAttributes writable = |
| 15804 static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE); | 15829 static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE); |
| 15805 JSObject::SetOwnPropertyIgnoreAttributes( | 15830 JSObject::SetOwnPropertyIgnoreAttributes( |
| 15806 regexp, factory->last_index_string(), | 15831 regexp, factory->last_index_string(), |
| 15807 Handle<Smi>(Smi::FromInt(0), isolate), writable) | 15832 Handle<Smi>(Smi::FromInt(0), isolate), writable) |
| 15808 .Check(); | 15833 .Check(); |
| 15809 } | 15834 } |
| 15810 | 15835 |
| 15811 RETURN_ON_EXCEPTION(isolate, RegExpImpl::Compile(regexp, source, flags), | 15836 RETURN_ON_EXCEPTION(isolate, RegExpImpl::Compile(regexp, source, flags), |
| 15812 JSRegExp); | 15837 JSRegExp); |
| 15813 | 15838 |
| 15814 return regexp; | 15839 return regexp; |
| 15815 } | 15840 } |
| 15816 | 15841 |
| 15817 | 15842 |
| 15818 // RegExpKey carries the source and flags of a regular expression as key. | 15843 // RegExpKey carries the source and flags of a regular expression as key. |
| 15819 class RegExpKey : public HashTableKey { | 15844 class RegExpKey : public HashTableKey { |
| 15820 public: | 15845 public: |
| 15821 RegExpKey(Handle<String> string, JSRegExp::Flags flags) | 15846 RegExpKey(Handle<String> string, JSRegExp::Flags flags) |
| 15822 : string_(string), | 15847 : string_(string), flags_(Smi::FromInt(flags)) {} |
| 15823 flags_(Smi::FromInt(flags.value())) { } | |
| 15824 | 15848 |
| 15825 // Rather than storing the key in the hash table, a pointer to the | 15849 // Rather than storing the key in the hash table, a pointer to the |
| 15826 // stored value is stored where the key should be. IsMatch then | 15850 // stored value is stored where the key should be. IsMatch then |
| 15827 // compares the search key to the found object, rather than comparing | 15851 // compares the search key to the found object, rather than comparing |
| 15828 // a key to a key. | 15852 // a key to a key. |
| 15829 bool IsMatch(Object* obj) override { | 15853 bool IsMatch(Object* obj) override { |
| 15830 FixedArray* val = FixedArray::cast(obj); | 15854 FixedArray* val = FixedArray::cast(obj); |
| 15831 return string_->Equals(String::cast(val->get(JSRegExp::kSourceIndex))) | 15855 return string_->Equals(String::cast(val->get(JSRegExp::kSourceIndex))) |
| 15832 && (flags_ == val->get(JSRegExp::kFlagsIndex)); | 15856 && (flags_ == val->get(JSRegExp::kFlagsIndex)); |
| 15833 } | 15857 } |
| (...skipping 2714 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 18548 if (cell->value() != *new_value) { | 18572 if (cell->value() != *new_value) { |
| 18549 cell->set_value(*new_value); | 18573 cell->set_value(*new_value); |
| 18550 Isolate* isolate = cell->GetIsolate(); | 18574 Isolate* isolate = cell->GetIsolate(); |
| 18551 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 18575 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
| 18552 isolate, DependentCode::kPropertyCellChangedGroup); | 18576 isolate, DependentCode::kPropertyCellChangedGroup); |
| 18553 } | 18577 } |
| 18554 } | 18578 } |
| 18555 | 18579 |
| 18556 } // namespace internal | 18580 } // namespace internal |
| 18557 } // namespace v8 | 18581 } // namespace v8 |
| OLD | NEW |