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

Side by Side Diff: src/runtime.cc

Issue 18660: Fix handling of const initialization. We did not handle the fact that... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 11 years, 11 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 | « no previous file | test/mjsunit/const.js » ('j') | test/mjsunit/const.js » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
OLDNEW
« no previous file with comments | « no previous file | test/mjsunit/const.js » ('j') | test/mjsunit/const.js » ('J')

Powered by Google App Engine
This is Rietveld 408576698