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 |