OLD | NEW |
---|---|
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 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 740 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
751 Handle<Object> value(args[0]); | 751 Handle<Object> value(args[0]); |
752 ASSERT(!value->IsTheHole()); | 752 ASSERT(!value->IsTheHole()); |
753 CONVERT_ARG_CHECKED(Context, context, 1); | 753 CONVERT_ARG_CHECKED(Context, context, 1); |
754 Handle<String> name(String::cast(args[2])); | 754 Handle<String> name(String::cast(args[2])); |
755 | 755 |
756 // Initializations are always done in the function context. | 756 // Initializations are always done in the function context. |
757 context = Handle<Context>(context->fcontext()); | 757 context = Handle<Context>(context->fcontext()); |
758 | 758 |
759 int index; | 759 int index; |
760 PropertyAttributes attributes; | 760 PropertyAttributes attributes; |
761 ContextLookupFlags flags = DONT_FOLLOW_CHAINS; | 761 ContextLookupFlags flags = FOLLOW_CHAINS; |
762 Handle<Object> holder = | 762 Handle<Object> holder = |
763 context->Lookup(name, flags, &index, &attributes); | 763 context->Lookup(name, flags, &index, &attributes); |
764 | 764 |
765 // The property should always be present. It is always declared | 765 // In most situations, the property introduced by the const |
766 // before being initialized through DeclareContextSlot. | 766 // declaration should be present in the context extension object. |
767 ASSERT(attributes != ABSENT && (attributes & READ_ONLY) != 0); | 767 // However, because declaration and initialization are separate, the |
768 | 768 // property might have been deleted (if it was introduced by eval) |
769 // If the slot is in the context, we set it but only if it hasn't | 769 // before we reach the initialization point. |
770 // been set before. | 770 // |
771 // Example: | |
772 // | |
773 // function f() { eval("delete x; const x;"); } | |
774 // | |
775 // In that case, the initialization behaves like a normal assignment | |
776 // to property 'x'. | |
771 if (index >= 0) { | 777 if (index >= 0) { |
772 // The constant context slot should always be in the function | 778 // Property was found in a context. |
773 // context; not in any outer context nor in the arguments object. | 779 if (holder->IsContext()) { |
774 ASSERT(holder.is_identical_to(context)); | 780 // The holder cannot be the function context. If it is, there |
775 if (context->get(index)->IsTheHole()) { | 781 // should have been a const redeclaration error when declaring |
776 context->set(index, *value); | 782 // the const property. |
783 ASSERT(!holder.is_identical_to(context)); | |
784 if ((attributes & READ_ONLY) == 0) { | |
785 Handle<Context>::cast(holder)->set(index, *value); | |
786 } | |
787 } else { | |
788 // The holder is an arguments object. | |
789 ASSERT((attributes & READ_ONLY) == 0); | |
790 Handle<JSObject>::cast(holder)->SetElement(index, *value); | |
777 } | 791 } |
778 return *value; | 792 return *value; |
779 } | 793 } |
780 | 794 |
781 // Otherwise, the slot must be in a JS object extension. | 795 // The property could not be found, we introduce it in the global |
782 Handle<JSObject> context_ext(JSObject::cast(*holder)); | 796 // context. |
797 if (attributes == ABSENT) { | |
798 Handle<JSObject> global = Handle<JSObject>(Top::context()->global()); | |
799 SetProperty(global, name, value, NONE); | |
800 return *value; | |
801 } | |
783 | 802 |
784 // We must initialize the value only if it wasn't initialized | 803 // The property was present in a context extension object. |
785 // before, e.g. for const declarations in a loop. The property has | 804 Handle<JSObject> context_ext = Handle<JSObject>::cast(holder); |
786 // the hole value if it wasn't initialized yet. NOTE: We cannot use | |
787 // GetProperty() to get the current value as it 'unholes' the value. | |
788 LookupResult lookup; | |
789 context_ext->LocalLookupRealNamedProperty(*name, &lookup); | |
790 ASSERT(lookup.IsProperty()); // the property was declared | |
791 ASSERT(lookup.IsReadOnly()); // and it was declared as read-only | |
792 | 805 |
793 PropertyType type = lookup.type(); | 806 if (*context_ext == context->extension()) { |
794 if (type == FIELD) { | 807 // This is the property that was introduced by the const |
795 FixedArray* properties = context_ext->properties(); | 808 // declaration. Set it if it hasn't been set before. NOTE: We |
796 int index = lookup.GetFieldIndex(); | 809 // cannot use GetProperty() to get the current value as it |
797 if (properties->get(index)->IsTheHole()) { | 810 // 'unholes' the value. |
798 properties->set(index, *value); | 811 LookupResult lookup; |
799 } | 812 context_ext->LocalLookupRealNamedProperty(*name, &lookup); |
800 } else if (type == NORMAL) { | 813 ASSERT(lookup.IsProperty()); // the property was declared |
801 Dictionary* dictionary = context_ext->property_dictionary(); | 814 ASSERT(lookup.IsReadOnly()); // and it was declared as read-only |
802 int entry = lookup.GetDictionaryEntry(); | 815 |
803 if (dictionary->ValueAt(entry)->IsTheHole()) { | 816 PropertyType type = lookup.type(); |
804 dictionary->ValueAtPut(entry, *value); | 817 if (type == FIELD) { |
818 FixedArray* properties = context_ext->properties(); | |
819 int index = lookup.GetFieldIndex(); | |
820 if (properties->get(index)->IsTheHole()) { | |
821 properties->set(index, *value); | |
822 } | |
823 } else if (type == NORMAL) { | |
824 Dictionary* dictionary = context_ext->property_dictionary(); | |
825 int entry = lookup.GetDictionaryEntry(); | |
826 if (dictionary->ValueAt(entry)->IsTheHole()) { | |
827 dictionary->ValueAtPut(entry, *value); | |
828 } | |
829 } else { | |
830 // We should not reach here. Any real, named property should be | |
831 // either a field or a dictionary slot. | |
832 UNREACHABLE(); | |
805 } | 833 } |
806 } else { | 834 } else { |
807 // We should not reach here. Any real, named property should be | 835 // The property was found in a different context extension object. |
808 // either a field or a dictionary slot. | 836 // Set it if it is not a read_only property. |
Kasper Lund
2009/01/22 13:38:47
read-only with a - instead of _?
| |
809 UNREACHABLE(); | 837 if ((attributes & READ_ONLY) == 0) { |
838 Handle<Object> set = SetProperty(context_ext, name, value, attributes); | |
839 // Setting a property might throw an exception. Exceptions | |
840 // are converted to empty handles in handle operations. We | |
841 // need to convert back to excpetions here. | |
Kasper Lund
2009/01/22 13:38:47
exceptions
| |
842 if (set.is_null()) { | |
843 ASSERT(Top::has_pending_exception()); | |
844 return Failure::Exception(); | |
845 } | |
846 } | |
810 } | 847 } |
848 | |
811 return *value; | 849 return *value; |
812 } | 850 } |
813 | 851 |
814 | 852 |
815 static Object* Runtime_RegExpExec(Arguments args) { | 853 static Object* Runtime_RegExpExec(Arguments args) { |
816 HandleScope scope; | 854 HandleScope scope; |
817 ASSERT(args.length() == 3); | 855 ASSERT(args.length() == 3); |
818 CONVERT_CHECKED(JSRegExp, raw_regexp, args[0]); | 856 CONVERT_CHECKED(JSRegExp, raw_regexp, args[0]); |
819 Handle<JSRegExp> regexp(raw_regexp); | 857 Handle<JSRegExp> regexp(raw_regexp); |
820 CONVERT_CHECKED(String, raw_subject, args[1]); | 858 CONVERT_CHECKED(String, raw_subject, args[1]); |
(...skipping 5160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5981 } else { | 6019 } else { |
5982 // Handle last resort GC and make sure to allow future allocations | 6020 // Handle last resort GC and make sure to allow future allocations |
5983 // to grow the heap without causing GCs (if possible). | 6021 // to grow the heap without causing GCs (if possible). |
5984 Counters::gc_last_resort_from_js.Increment(); | 6022 Counters::gc_last_resort_from_js.Increment(); |
5985 Heap::CollectAllGarbage(); | 6023 Heap::CollectAllGarbage(); |
5986 } | 6024 } |
5987 } | 6025 } |
5988 | 6026 |
5989 | 6027 |
5990 } } // namespace v8::internal | 6028 } } // namespace v8::internal |
OLD | NEW |