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

Side by Side Diff: src/objects.cc

Issue 11347037: Object.observe: generate change records for named properties. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Addressing comments. Created 8 years, 1 month 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/objects.h ('k') | src/objects-inl.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 1659 matching lines...) Expand 10 before | Expand all | Expand 10 after
1670 1670
1671 MaybeObject* JSObject::AddProperty(String* name, 1671 MaybeObject* JSObject::AddProperty(String* name,
1672 Object* value, 1672 Object* value,
1673 PropertyAttributes attributes, 1673 PropertyAttributes attributes,
1674 StrictModeFlag strict_mode, 1674 StrictModeFlag strict_mode,
1675 JSReceiver::StoreFromKeyed store_mode, 1675 JSReceiver::StoreFromKeyed store_mode,
1676 ExtensibilityCheck extensibility_check) { 1676 ExtensibilityCheck extensibility_check) {
1677 ASSERT(!IsJSGlobalProxy()); 1677 ASSERT(!IsJSGlobalProxy());
1678 Map* map_of_this = map(); 1678 Map* map_of_this = map();
1679 Heap* heap = GetHeap(); 1679 Heap* heap = GetHeap();
1680 MaybeObject* result;
1680 if (extensibility_check == PERFORM_EXTENSIBILITY_CHECK && 1681 if (extensibility_check == PERFORM_EXTENSIBILITY_CHECK &&
1681 !map_of_this->is_extensible()) { 1682 !map_of_this->is_extensible()) {
1682 if (strict_mode == kNonStrictMode) { 1683 if (strict_mode == kNonStrictMode) {
1683 return value; 1684 return value;
1684 } else { 1685 } else {
1685 Handle<Object> args[1] = {Handle<String>(name)}; 1686 Handle<Object> args[1] = {Handle<String>(name)};
1686 return heap->isolate()->Throw( 1687 return heap->isolate()->Throw(
1687 *FACTORY->NewTypeError("object_not_extensible", 1688 *FACTORY->NewTypeError("object_not_extensible",
1688 HandleVector(args, 1))); 1689 HandleVector(args, 1)));
1689 } 1690 }
1690 } 1691 }
1692
1691 if (HasFastProperties()) { 1693 if (HasFastProperties()) {
1692 // Ensure the descriptor array does not get too big. 1694 // Ensure the descriptor array does not get too big.
1693 if (map_of_this->NumberOfOwnDescriptors() < 1695 if (map_of_this->NumberOfOwnDescriptors() <
1694 DescriptorArray::kMaxNumberOfDescriptors) { 1696 DescriptorArray::kMaxNumberOfDescriptors) {
1695 if (value->IsJSFunction()) { 1697 if (value->IsJSFunction()) {
1696 return AddConstantFunctionProperty(name, 1698 result = AddConstantFunctionProperty(name,
1697 JSFunction::cast(value), 1699 JSFunction::cast(value),
1698 attributes); 1700 attributes);
1699 } else { 1701 } else {
1700 return AddFastProperty(name, value, attributes, store_mode); 1702 result = AddFastProperty(name, value, attributes, store_mode);
1701 } 1703 }
1702 } else { 1704 } else {
1703 // Normalize the object to prevent very large instance descriptors. 1705 // Normalize the object to prevent very large instance descriptors.
1704 // This eliminates unwanted N^2 allocation and lookup behavior. 1706 // This eliminates unwanted N^2 allocation and lookup behavior.
1705 Object* obj; 1707 Object* obj;
1706 { MaybeObject* maybe_obj = 1708 MaybeObject* maybe = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
1707 NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); 1709 if (!maybe->To(&obj)) return maybe;
1708 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 1710 result = AddSlowProperty(name, value, attributes);
1709 }
1710 } 1711 }
1712 } else {
1713 result = AddSlowProperty(name, value, attributes);
1711 } 1714 }
1712 return AddSlowProperty(name, value, attributes); 1715
1716 Handle<Object> hresult;
1717 if (!result->ToHandle(&hresult)) return result;
1718
1719 if (FLAG_harmony_observation && map()->is_observed()) {
1720 this->EnqueueChangeRecord(
1721 "new", handle(name), handle(heap->the_hole_value()));
1722 }
1723
1724 return *hresult;
1713 } 1725 }
1714 1726
1715 1727
1728 void JSObject::EnqueueChangeRecord(
1729 const char* type_str, Handle<String> name, Handle<Object> old_value) {
1730 Isolate* isolate = GetIsolate();
1731 HandleScope scope;
1732 Handle<String> type = isolate->factory()->LookupAsciiSymbol(type_str);
1733 Handle<JSObject> object(this);
1734 Handle<Object> args[] = { type, object, name, old_value };
1735 bool threw;
1736 Execution::Call(Handle<JSFunction>(isolate->observers_notify_change()),
1737 Handle<Object>(isolate->heap()->undefined_value()),
1738 old_value->IsTheHole() ? 3 : 4, args,
1739 &threw);
1740 ASSERT(!threw);
1741 }
1742
1743
1716 MaybeObject* JSObject::SetPropertyPostInterceptor( 1744 MaybeObject* JSObject::SetPropertyPostInterceptor(
1717 String* name, 1745 String* name,
1718 Object* value, 1746 Object* value,
1719 PropertyAttributes attributes, 1747 PropertyAttributes attributes,
1720 StrictModeFlag strict_mode, 1748 StrictModeFlag strict_mode,
1721 ExtensibilityCheck extensibility_check) { 1749 ExtensibilityCheck extensibility_check) {
1722 // Check local property, ignore interceptor. 1750 // Check local property, ignore interceptor.
1723 LookupResult result(GetIsolate()); 1751 LookupResult result(GetIsolate());
1724 LocalLookupRealNamedProperty(name, &result); 1752 LocalLookupRealNamedProperty(name, &result);
1725 if (!result.IsFound()) map()->LookupTransition(this, name, &result); 1753 if (!result.IsFound()) map()->LookupTransition(this, name, &result);
(...skipping 1069 matching lines...) Expand 10 before | Expand all | Expand 10 after
2795 2823
2796 2824
2797 void JSObject::AddFastPropertyUsingMap(Handle<JSObject> object, 2825 void JSObject::AddFastPropertyUsingMap(Handle<JSObject> object,
2798 Handle<Map> map) { 2826 Handle<Map> map) {
2799 CALL_HEAP_FUNCTION_VOID( 2827 CALL_HEAP_FUNCTION_VOID(
2800 object->GetIsolate(), 2828 object->GetIsolate(),
2801 object->AddFastPropertyUsingMap(*map)); 2829 object->AddFastPropertyUsingMap(*map));
2802 } 2830 }
2803 2831
2804 2832
2805 MaybeObject* JSObject::SetPropertyForResult(LookupResult* result, 2833 MaybeObject* JSObject::SetPropertyForResult(LookupResult* lookup,
2806 String* name_raw, 2834 String* name_raw,
2807 Object* value_raw, 2835 Object* value_raw,
2808 PropertyAttributes attributes, 2836 PropertyAttributes attributes,
2809 StrictModeFlag strict_mode, 2837 StrictModeFlag strict_mode,
2810 StoreFromKeyed store_mode) { 2838 StoreFromKeyed store_mode) {
2811 Heap* heap = GetHeap(); 2839 Heap* heap = GetHeap();
2812 // Make sure that the top context does not change when doing callbacks or 2840 // Make sure that the top context does not change when doing callbacks or
2813 // interceptor calls. 2841 // interceptor calls.
2814 AssertNoContextChange ncc; 2842 AssertNoContextChange ncc;
2815 2843
2816 // Optimization for 2-byte strings often used as keys in a decompression 2844 // Optimization for 2-byte strings often used as keys in a decompression
2817 // dictionary. We make these short keys into symbols to avoid constantly 2845 // dictionary. We make these short keys into symbols to avoid constantly
2818 // reallocating them. 2846 // reallocating them.
2819 if (!name_raw->IsSymbol() && name_raw->length() <= 2) { 2847 if (!name_raw->IsSymbol() && name_raw->length() <= 2) {
2820 Object* symbol_version; 2848 Object* symbol_version;
2821 { MaybeObject* maybe_symbol_version = heap->LookupSymbol(name_raw); 2849 { MaybeObject* maybe_symbol_version = heap->LookupSymbol(name_raw);
2822 if (maybe_symbol_version->ToObject(&symbol_version)) { 2850 if (maybe_symbol_version->ToObject(&symbol_version)) {
2823 name_raw = String::cast(symbol_version); 2851 name_raw = String::cast(symbol_version);
2824 } 2852 }
2825 } 2853 }
2826 } 2854 }
2827 2855
2828 // Check access rights if needed. 2856 // Check access rights if needed.
2829 if (IsAccessCheckNeeded()) { 2857 if (IsAccessCheckNeeded()) {
2830 if (!heap->isolate()->MayNamedAccess(this, name_raw, v8::ACCESS_SET)) { 2858 if (!heap->isolate()->MayNamedAccess(this, name_raw, v8::ACCESS_SET)) {
2831 return SetPropertyWithFailedAccessCheck( 2859 return SetPropertyWithFailedAccessCheck(
2832 result, name_raw, value_raw, true, strict_mode); 2860 lookup, name_raw, value_raw, true, strict_mode);
2833 } 2861 }
2834 } 2862 }
2835 2863
2836 if (IsJSGlobalProxy()) { 2864 if (IsJSGlobalProxy()) {
2837 Object* proto = GetPrototype(); 2865 Object* proto = GetPrototype();
2838 if (proto->IsNull()) return value_raw; 2866 if (proto->IsNull()) return value_raw;
2839 ASSERT(proto->IsJSGlobalObject()); 2867 ASSERT(proto->IsJSGlobalObject());
2840 return JSObject::cast(proto)->SetPropertyForResult( 2868 return JSObject::cast(proto)->SetPropertyForResult(
2841 result, name_raw, value_raw, attributes, strict_mode, store_mode); 2869 lookup, name_raw, value_raw, attributes, strict_mode, store_mode);
2842 } 2870 }
2843 2871
2844 // From this point on everything needs to be handlified, because 2872 // From this point on everything needs to be handlified, because
2845 // SetPropertyViaPrototypes might call back into JavaScript. 2873 // SetPropertyViaPrototypes might call back into JavaScript.
2846 HandleScope scope(GetIsolate()); 2874 HandleScope scope(GetIsolate());
2847 Handle<JSObject> self(this); 2875 Handle<JSObject> self(this);
2848 Handle<String> name(name_raw); 2876 Handle<String> name(name_raw);
2849 Handle<Object> value(value_raw); 2877 Handle<Object> value(value_raw);
2850 2878
2851 if (!result->IsProperty() && !self->IsJSContextExtensionObject()) { 2879 if (!lookup->IsProperty() && !self->IsJSContextExtensionObject()) {
2852 bool done = false; 2880 bool done = false;
2853 MaybeObject* result_object = self->SetPropertyViaPrototypes( 2881 MaybeObject* result_object = self->SetPropertyViaPrototypes(
2854 *name, *value, attributes, strict_mode, &done); 2882 *name, *value, attributes, strict_mode, &done);
2855 if (done) return result_object; 2883 if (done) return result_object;
2856 } 2884 }
2857 2885
2858 if (!result->IsFound()) { 2886 if (!lookup->IsFound()) {
2859 // Neither properties nor transitions found. 2887 // Neither properties nor transitions found.
2860 return self->AddProperty( 2888 return self->AddProperty(
2861 *name, *value, attributes, strict_mode, store_mode); 2889 *name, *value, attributes, strict_mode, store_mode);
2862 } 2890 }
2863 if (result->IsProperty() && result->IsReadOnly()) { 2891
2892 if (lookup->IsProperty() && lookup->IsReadOnly()) {
2864 if (strict_mode == kStrictMode) { 2893 if (strict_mode == kStrictMode) {
2865 Handle<Object> args[] = { name, self }; 2894 Handle<Object> args[] = { name, self };
2866 return heap->isolate()->Throw(*heap->isolate()->factory()->NewTypeError( 2895 return heap->isolate()->Throw(*heap->isolate()->factory()->NewTypeError(
2867 "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args)))); 2896 "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args))));
2868 } else { 2897 } else {
2869 return *value; 2898 return *value;
2870 } 2899 }
2871 } 2900 }
2872 2901
2902 Handle<Object> old_value(heap->the_hole_value());
2903 if (FLAG_harmony_observation && map()->is_observed()) {
2904 // TODO(observe): save oldValue
2905 }
2906
2873 // This is a real property that is not read-only, or it is a 2907 // This is a real property that is not read-only, or it is a
2874 // transition or null descriptor and there are no setters in the prototypes. 2908 // transition or null descriptor and there are no setters in the prototypes.
2875 switch (result->type()) { 2909 MaybeObject* result = *value;
2910 switch (lookup->type()) {
2876 case NORMAL: 2911 case NORMAL:
2877 return self->SetNormalizedProperty(result, *value); 2912 result = self->SetNormalizedProperty(lookup, *value);
2913 break;
2878 case FIELD: 2914 case FIELD:
2879 return self->FastPropertyAtPut(result->GetFieldIndex(), *value); 2915 result = self->FastPropertyAtPut(lookup->GetFieldIndex(), *value);
2916 break;
2880 case CONSTANT_FUNCTION: 2917 case CONSTANT_FUNCTION:
2881 // Only replace the function if necessary. 2918 // Only replace the function if necessary.
2882 if (*value == result->GetConstantFunction()) return *value; 2919 if (*value == lookup->GetConstantFunction()) return *value;
2883 // Preserve the attributes of this existing property. 2920 // Preserve the attributes of this existing property.
2884 attributes = result->GetAttributes(); 2921 attributes = lookup->GetAttributes();
2885 return self->ConvertDescriptorToField(*name, *value, attributes); 2922 result = self->ConvertDescriptorToField(*name, *value, attributes);
2923 break;
2886 case CALLBACKS: { 2924 case CALLBACKS: {
2887 Object* callback_object = result->GetCallbackObject(); 2925 Object* callback_object = lookup->GetCallbackObject();
2888 return self->SetPropertyWithCallback(callback_object, 2926 return self->SetPropertyWithCallback(callback_object,
2889 *name, 2927 *name,
2890 *value, 2928 *value,
2891 result->holder(), 2929 lookup->holder(),
2892 strict_mode); 2930 strict_mode);
2893 } 2931 }
2894 case INTERCEPTOR: 2932 case INTERCEPTOR:
2895 return self->SetPropertyWithInterceptor(*name, 2933 result = self->SetPropertyWithInterceptor(*name,
2896 *value, 2934 *value,
2897 attributes, 2935 attributes,
2898 strict_mode); 2936 strict_mode);
2937 break;
2899 case TRANSITION: { 2938 case TRANSITION: {
2900 Map* transition_map = result->GetTransitionTarget(); 2939 Map* transition_map = lookup->GetTransitionTarget();
2901 int descriptor = transition_map->LastAdded(); 2940 int descriptor = transition_map->LastAdded();
2902 2941
2903 DescriptorArray* descriptors = transition_map->instance_descriptors(); 2942 DescriptorArray* descriptors = transition_map->instance_descriptors();
2904 PropertyDetails details = descriptors->GetDetails(descriptor); 2943 PropertyDetails details = descriptors->GetDetails(descriptor);
2905 2944
2906 if (details.type() == FIELD) { 2945 if (details.type() == FIELD) {
2907 if (attributes == details.attributes()) { 2946 if (attributes == details.attributes()) {
2908 int field_index = descriptors->GetFieldIndex(descriptor); 2947 int field_index = descriptors->GetFieldIndex(descriptor);
2909 return self->AddFastPropertyUsingMap(transition_map, 2948 result = self->AddFastPropertyUsingMap(transition_map,
2910 *name, 2949 *name,
2911 *value, 2950 *value,
2912 field_index); 2951 field_index);
2952 } else {
2953 result = self->ConvertDescriptorToField(*name, *value, attributes);
2913 } 2954 }
2914 return self->ConvertDescriptorToField(*name, *value, attributes);
2915 } else if (details.type() == CALLBACKS) { 2955 } else if (details.type() == CALLBACKS) {
2916 return ConvertDescriptorToField(*name, *value, attributes); 2956 result = ConvertDescriptorToField(*name, *value, attributes);
2957 } else {
2958 ASSERT(details.type() == CONSTANT_FUNCTION);
2959
2960 Object* constant_function = descriptors->GetValue(descriptor);
2961 if (constant_function == *value) {
2962 // If the same constant function is being added we can simply
2963 // transition to the target map.
2964 self->set_map(transition_map);
2965 result = constant_function;
2966 } else {
2967 // Otherwise, replace with a map transition to a new map with a FIELD,
2968 // even if the value is a constant function.
2969 result = ConvertTransitionToMapTransition(
2970 lookup->GetTransitionIndex(), *name, *value, attributes);
2971 }
2917 } 2972 }
2918 2973 break;
2919 ASSERT(details.type() == CONSTANT_FUNCTION);
2920
2921 Object* constant_function = descriptors->GetValue(descriptor);
2922 // If the same constant function is being added we can simply
2923 // transition to the target map.
2924 if (constant_function == *value) {
2925 self->set_map(transition_map);
2926 return constant_function;
2927 }
2928 // Otherwise, replace with a map transition to a new map with a FIELD,
2929 // even if the value is a constant function.
2930 return ConvertTransitionToMapTransition(
2931 result->GetTransitionIndex(), *name, *value, attributes);
2932 } 2974 }
2933 case HANDLER: 2975 case HANDLER:
2934 case NONEXISTENT: 2976 case NONEXISTENT:
2935 UNREACHABLE(); 2977 UNREACHABLE();
2936 return *value;
2937 } 2978 }
2938 UNREACHABLE(); // keep the compiler happy 2979
2939 return *value; 2980 Handle<Object> hresult;
2981 if (!result->ToHandle(&hresult)) return result;
2982
2983 if (FLAG_harmony_observation && map()->is_observed()) {
2984 this->EnqueueChangeRecord("updated", name, old_value);
2985 }
2986
2987 return *hresult;
2940 } 2988 }
2941 2989
2942 2990
2943 // Set a real local property, even if it is READ_ONLY. If the property is not 2991 // Set a real local property, even if it is READ_ONLY. If the property is not
2944 // present, add it with attributes NONE. This code is an exact clone of 2992 // present, add it with attributes NONE. This code is an exact clone of
2945 // SetProperty, with the check for IsReadOnly and the check for a 2993 // SetProperty, with the check for IsReadOnly and the check for a
2946 // callback setter removed. The two lines looking up the LookupResult 2994 // callback setter removed. The two lines looking up the LookupResult
2947 // result are also added. If one of the functions is changed, the other 2995 // result are also added. If one of the functions is changed, the other
2948 // should be. 2996 // should be.
2949 // Note that this method cannot be used to set the prototype of a function 2997 // Note that this method cannot be used to set the prototype of a function
(...skipping 12 matching lines...) Expand all
2962 3010
2963 3011
2964 MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes( 3012 MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes(
2965 String* name, 3013 String* name,
2966 Object* value, 3014 Object* value,
2967 PropertyAttributes attributes) { 3015 PropertyAttributes attributes) {
2968 // Make sure that the top context does not change when doing callbacks or 3016 // Make sure that the top context does not change when doing callbacks or
2969 // interceptor calls. 3017 // interceptor calls.
2970 AssertNoContextChange ncc; 3018 AssertNoContextChange ncc;
2971 Isolate* isolate = GetIsolate(); 3019 Isolate* isolate = GetIsolate();
2972 LookupResult result(isolate); 3020 LookupResult lookup(isolate);
2973 LocalLookup(name, &result); 3021 LocalLookup(name, &lookup);
2974 if (!result.IsFound()) map()->LookupTransition(this, name, &result); 3022 if (!lookup.IsFound()) map()->LookupTransition(this, name, &lookup);
2975 // Check access rights if needed. 3023 // Check access rights if needed.
2976 if (IsAccessCheckNeeded()) { 3024 if (IsAccessCheckNeeded()) {
2977 if (!isolate->MayNamedAccess(this, name, v8::ACCESS_SET)) { 3025 if (!isolate->MayNamedAccess(this, name, v8::ACCESS_SET)) {
2978 return SetPropertyWithFailedAccessCheck(&result, 3026 return SetPropertyWithFailedAccessCheck(&lookup,
2979 name, 3027 name,
2980 value, 3028 value,
2981 false, 3029 false,
2982 kNonStrictMode); 3030 kNonStrictMode);
2983 } 3031 }
2984 } 3032 }
2985 3033
2986 if (IsJSGlobalProxy()) { 3034 if (IsJSGlobalProxy()) {
2987 Object* proto = GetPrototype(); 3035 Object* proto = GetPrototype();
2988 if (proto->IsNull()) return value; 3036 if (proto->IsNull()) return value;
2989 ASSERT(proto->IsJSGlobalObject()); 3037 ASSERT(proto->IsJSGlobalObject());
2990 return JSObject::cast(proto)->SetLocalPropertyIgnoreAttributes( 3038 return JSObject::cast(proto)->SetLocalPropertyIgnoreAttributes(
2991 name, 3039 name,
2992 value, 3040 value,
2993 attributes); 3041 attributes);
2994 } 3042 }
2995 3043
2996 // Check for accessor in prototype chain removed here in clone. 3044 // Check for accessor in prototype chain removed here in clone.
2997 if (!result.IsFound()) { 3045 if (!lookup.IsFound()) {
2998 // Neither properties nor transitions found. 3046 // Neither properties nor transitions found.
2999 return AddProperty(name, value, attributes, kNonStrictMode); 3047 return AddProperty(name, value, attributes, kNonStrictMode);
3000 } 3048 }
3001 3049
3050 Handle<Object> old_value(isolate->heap()->the_hole_value());
3051 if (FLAG_harmony_observation && map()->is_observed()) {
3052 // TODO(observe): save oldValue
3053 }
3054
3002 // Check of IsReadOnly removed from here in clone. 3055 // Check of IsReadOnly removed from here in clone.
3003 switch (result.type()) { 3056 MaybeObject* result = value;
3057 switch (lookup.type()) {
3004 case NORMAL: { 3058 case NORMAL: {
3005 PropertyDetails details = PropertyDetails(attributes, NORMAL); 3059 PropertyDetails details = PropertyDetails(attributes, NORMAL);
3006 return SetNormalizedProperty(name, value, details); 3060 result = SetNormalizedProperty(name, value, details);
3061 break;
3007 } 3062 }
3008 case FIELD: 3063 case FIELD:
3009 return FastPropertyAtPut(result.GetFieldIndex(), value); 3064 result = FastPropertyAtPut(lookup.GetFieldIndex(), value);
3065 break;
3010 case CONSTANT_FUNCTION: 3066 case CONSTANT_FUNCTION:
3011 // Only replace the function if necessary. 3067 // Only replace the function if necessary.
3012 if (value == result.GetConstantFunction()) return value; 3068 if (value == lookup.GetConstantFunction()) return value;
3013 // Preserve the attributes of this existing property. 3069 // Preserve the attributes of this existing property.
3014 attributes = result.GetAttributes(); 3070 attributes = lookup.GetAttributes();
3015 return ConvertDescriptorToField(name, value, attributes); 3071 result = ConvertDescriptorToField(name, value, attributes);
3072 break;
3016 case CALLBACKS: 3073 case CALLBACKS:
3017 case INTERCEPTOR: 3074 case INTERCEPTOR:
3018 // Override callback in clone 3075 // Override callback in clone
3019 return ConvertDescriptorToField(name, value, attributes); 3076 result = ConvertDescriptorToField(name, value, attributes);
3077 break;
3020 case TRANSITION: { 3078 case TRANSITION: {
3021 Map* transition_map = result.GetTransitionTarget(); 3079 Map* transition_map = lookup.GetTransitionTarget();
3022 int descriptor = transition_map->LastAdded(); 3080 int descriptor = transition_map->LastAdded();
3023 3081
3024 DescriptorArray* descriptors = transition_map->instance_descriptors(); 3082 DescriptorArray* descriptors = transition_map->instance_descriptors();
3025 PropertyDetails details = descriptors->GetDetails(descriptor); 3083 PropertyDetails details = descriptors->GetDetails(descriptor);
3026 3084
3027 if (details.type() == FIELD) { 3085 if (details.type() == FIELD) {
3028 if (attributes == details.attributes()) { 3086 if (attributes == details.attributes()) {
3029 int field_index = descriptors->GetFieldIndex(descriptor); 3087 int field_index = descriptors->GetFieldIndex(descriptor);
3030 return AddFastPropertyUsingMap(transition_map, 3088 result = AddFastPropertyUsingMap(transition_map,
3031 name, 3089 name,
3032 value, 3090 value,
3033 field_index); 3091 field_index);
3092 } else {
3093 result = ConvertDescriptorToField(name, value, attributes);
3034 } 3094 }
3035 return ConvertDescriptorToField(name, value, attributes);
3036 } else if (details.type() == CALLBACKS) { 3095 } else if (details.type() == CALLBACKS) {
3037 return ConvertDescriptorToField(name, value, attributes); 3096 result = ConvertDescriptorToField(name, value, attributes);
3097 } else {
3098 ASSERT(details.type() == CONSTANT_FUNCTION);
3099
3100 // Replace transition to CONSTANT FUNCTION with a map transition to a
3101 // new map with a FIELD, even if the value is a function.
3102 result = ConvertTransitionToMapTransition(
3103 lookup.GetTransitionIndex(), name, value, attributes);
3038 } 3104 }
3039 3105 break;
3040 ASSERT(details.type() == CONSTANT_FUNCTION);
3041
3042 // Replace transition to CONSTANT FUNCTION with a map transition to a new
3043 // map with a FIELD, even if the value is a function.
3044 return ConvertTransitionToMapTransition(
3045 result.GetTransitionIndex(), name, value, attributes);
3046 } 3106 }
3047 case HANDLER: 3107 case HANDLER:
3048 case NONEXISTENT: 3108 case NONEXISTENT:
3049 UNREACHABLE(); 3109 UNREACHABLE();
3050 } 3110 }
3051 UNREACHABLE(); // keep the compiler happy 3111
3052 return value; 3112 Handle<Object> hresult;
3113 if (!result->ToHandle(&hresult)) return result;
3114
3115 if (FLAG_harmony_observation && map()->is_observed()) {
3116 const char* type =
3117 attributes == lookup.GetAttributes() ? "updated" : "reconfigured";
3118 this->EnqueueChangeRecord(type, handle(name), old_value);
3119 }
3120
3121 return *hresult;
3053 } 3122 }
3054 3123
3055 3124
3056 PropertyAttributes JSObject::GetPropertyAttributePostInterceptor( 3125 PropertyAttributes JSObject::GetPropertyAttributePostInterceptor(
3057 JSObject* receiver, 3126 JSObject* receiver,
3058 String* name, 3127 String* name,
3059 bool continue_search) { 3128 bool continue_search) {
3060 // Check local property, ignore interceptor. 3129 // Check local property, ignore interceptor.
3061 LookupResult result(GetIsolate()); 3130 LookupResult result(GetIsolate());
3062 LocalLookupRealNamedProperty(name, &result); 3131 LocalLookupRealNamedProperty(name, &result);
(...skipping 883 matching lines...) Expand 10 before | Expand all | Expand 10 after
3946 if (IsJSGlobalProxy()) { 4015 if (IsJSGlobalProxy()) {
3947 Object* proto = GetPrototype(); 4016 Object* proto = GetPrototype();
3948 if (proto->IsNull()) return isolate->heap()->false_value(); 4017 if (proto->IsNull()) return isolate->heap()->false_value();
3949 ASSERT(proto->IsJSGlobalObject()); 4018 ASSERT(proto->IsJSGlobalObject());
3950 return JSGlobalObject::cast(proto)->DeleteProperty(name, mode); 4019 return JSGlobalObject::cast(proto)->DeleteProperty(name, mode);
3951 } 4020 }
3952 4021
3953 uint32_t index = 0; 4022 uint32_t index = 0;
3954 if (name->AsArrayIndex(&index)) { 4023 if (name->AsArrayIndex(&index)) {
3955 return DeleteElement(index, mode); 4024 return DeleteElement(index, mode);
4025 }
4026
4027 LookupResult lookup(isolate);
4028 LocalLookup(name, &lookup);
4029 if (!lookup.IsFound()) return isolate->heap()->true_value();
4030 // Ignore attributes if forcing a deletion.
4031 if (lookup.IsDontDelete() && mode != FORCE_DELETION) {
4032 if (mode == STRICT_DELETION) {
4033 // Deleting a non-configurable property in strict mode.
4034 HandleScope scope(isolate);
4035 Handle<Object> args[2] = { Handle<Object>(name), Handle<Object>(this) };
4036 return isolate->Throw(*isolate->factory()->NewTypeError(
4037 "strict_delete_property", HandleVector(args, 2)));
4038 }
4039 return isolate->heap()->false_value();
4040 }
4041
4042 HandleScope scope(isolate);
4043 Handle<Object> old_value(isolate->heap()->the_hole_value());
4044 if (FLAG_harmony_observation && map()->is_observed()) {
4045 // TODO(observe): save oldValue
4046 }
4047 MaybeObject* result;
4048
4049 // Check for interceptor.
4050 if (lookup.IsInterceptor()) {
4051 // Skip interceptor if forcing a deletion.
4052 if (mode == FORCE_DELETION) {
4053 result = DeletePropertyPostInterceptor(name, mode);
4054 } else {
4055 result = DeletePropertyWithInterceptor(name);
4056 }
3956 } else { 4057 } else {
3957 LookupResult result(isolate);
3958 LocalLookup(name, &result);
3959 if (!result.IsFound()) return isolate->heap()->true_value();
3960 // Ignore attributes if forcing a deletion.
3961 if (result.IsDontDelete() && mode != FORCE_DELETION) {
3962 if (mode == STRICT_DELETION) {
3963 // Deleting a non-configurable property in strict mode.
3964 HandleScope scope(isolate);
3965 Handle<Object> args[2] = { Handle<Object>(name), Handle<Object>(this) };
3966 return isolate->Throw(*isolate->factory()->NewTypeError(
3967 "strict_delete_property", HandleVector(args, 2)));
3968 }
3969 return isolate->heap()->false_value();
3970 }
3971 // Check for interceptor.
3972 if (result.IsInterceptor()) {
3973 // Skip interceptor if forcing a deletion.
3974 if (mode == FORCE_DELETION) {
3975 return DeletePropertyPostInterceptor(name, mode);
3976 }
3977 return DeletePropertyWithInterceptor(name);
3978 }
3979 // Normalize object if needed. 4058 // Normalize object if needed.
3980 Object* obj; 4059 Object* obj;
3981 { MaybeObject* maybe_obj = 4060 result = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
3982 NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); 4061 if (!result->ToObject(&obj)) return result;
3983 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
3984 }
3985 // Make sure the properties are normalized before removing the entry. 4062 // Make sure the properties are normalized before removing the entry.
3986 return DeleteNormalizedProperty(name, mode); 4063 result = DeleteNormalizedProperty(name, mode);
3987 } 4064 }
4065
4066 Handle<Object> hresult;
4067 if (!result->ToHandle(&hresult)) return result;
4068
4069 if (FLAG_harmony_observation && map()->is_observed()) {
4070 this->EnqueueChangeRecord("deleted", handle(name), old_value);
4071 }
4072
4073 return *hresult;
3988 } 4074 }
3989 4075
3990 4076
3991 MaybeObject* JSReceiver::DeleteElement(uint32_t index, DeleteMode mode) { 4077 MaybeObject* JSReceiver::DeleteElement(uint32_t index, DeleteMode mode) {
3992 if (IsJSProxy()) { 4078 if (IsJSProxy()) {
3993 return JSProxy::cast(this)->DeleteElementWithHandler(index, mode); 4079 return JSProxy::cast(this)->DeleteElementWithHandler(index, mode);
3994 } 4080 }
3995 return JSObject::cast(this)->DeleteElement(index, mode); 4081 return JSObject::cast(this)->DeleteElement(index, mode);
3996 } 4082 }
3997 4083
(...skipping 607 matching lines...) Expand 10 before | Expand all | Expand 10 after
4605 4691
4606 // Make sure that the top context does not change when doing callbacks or 4692 // Make sure that the top context does not change when doing callbacks or
4607 // interceptor calls. 4693 // interceptor calls.
4608 AssertNoContextChange ncc; 4694 AssertNoContextChange ncc;
4609 4695
4610 // Try to flatten before operating on the string. 4696 // Try to flatten before operating on the string.
4611 name->TryFlatten(); 4697 name->TryFlatten();
4612 4698
4613 if (!CanSetCallback(name)) return isolate->heap()->undefined_value(); 4699 if (!CanSetCallback(name)) return isolate->heap()->undefined_value();
4614 4700
4701 Handle<Object> old_value(isolate->heap()->the_hole_value());
4702 bool preexists;
4703 if (FLAG_harmony_observation && map()->is_observed()) {
4704 LookupResult result(isolate);
4705 LocalLookup(name, &result);
4706 preexists = result.IsFound();
4707 // TODO(observe): save oldValue
4708 }
4709
4615 uint32_t index = 0; 4710 uint32_t index = 0;
4616 return name->AsArrayIndex(&index) ? 4711 MaybeObject* result = name->AsArrayIndex(&index)
4617 DefineElementAccessor(index, getter, setter, attributes) : 4712 ? DefineElementAccessor(index, getter, setter, attributes)
4618 DefinePropertyAccessor(name, getter, setter, attributes); 4713 : DefinePropertyAccessor(name, getter, setter, attributes);
4714
4715 Handle<Object> hresult;
4716 if (!result->ToHandle(&hresult)) return result;
4717
4718 if (FLAG_harmony_observation && map()->is_observed()) {
4719 const char* type = preexists ? "reconfigured" : "new";
4720 this->EnqueueChangeRecord(type, handle(name), old_value);
4721 }
4722
4723 return *hresult;
4619 } 4724 }
4620 4725
4621 4726
4622 static MaybeObject* TryAccessorTransition(JSObject* self, 4727 static MaybeObject* TryAccessorTransition(JSObject* self,
4623 Map* transitioned_map, 4728 Map* transitioned_map,
4624 int target_descriptor, 4729 int target_descriptor,
4625 AccessorComponent component, 4730 AccessorComponent component,
4626 Object* accessor, 4731 Object* accessor,
4627 PropertyAttributes attributes) { 4732 PropertyAttributes attributes) {
4628 DescriptorArray* descs = transitioned_map->instance_descriptors(); 4733 DescriptorArray* descs = transitioned_map->instance_descriptors();
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after
4889 MaybeObject* Map::RawCopy(int instance_size) { 4994 MaybeObject* Map::RawCopy(int instance_size) {
4890 Map* result; 4995 Map* result;
4891 MaybeObject* maybe_result = 4996 MaybeObject* maybe_result =
4892 GetHeap()->AllocateMap(instance_type(), instance_size); 4997 GetHeap()->AllocateMap(instance_type(), instance_size);
4893 if (!maybe_result->To(&result)) return maybe_result; 4998 if (!maybe_result->To(&result)) return maybe_result;
4894 4999
4895 result->set_prototype(prototype()); 5000 result->set_prototype(prototype());
4896 result->set_constructor(constructor()); 5001 result->set_constructor(constructor());
4897 result->set_bit_field(bit_field()); 5002 result->set_bit_field(bit_field());
4898 result->set_bit_field2(bit_field2()); 5003 result->set_bit_field2(bit_field2());
4899 result->set_bit_field3(bit_field3());
4900 int new_bit_field3 = bit_field3(); 5004 int new_bit_field3 = bit_field3();
4901 new_bit_field3 = OwnsDescriptors::update(new_bit_field3, true); 5005 new_bit_field3 = OwnsDescriptors::update(new_bit_field3, true);
4902 new_bit_field3 = NumberOfOwnDescriptorsBits::update(new_bit_field3, 0); 5006 new_bit_field3 = NumberOfOwnDescriptorsBits::update(new_bit_field3, 0);
4903 new_bit_field3 = EnumLengthBits::update(new_bit_field3, kInvalidEnumCache); 5007 new_bit_field3 = EnumLengthBits::update(new_bit_field3, kInvalidEnumCache);
4904 result->set_bit_field3(new_bit_field3); 5008 result->set_bit_field3(new_bit_field3);
4905 return result; 5009 return result;
4906 } 5010 }
4907 5011
4908 5012
4909 MaybeObject* Map::CopyNormalized(PropertyNormalizationMode mode, 5013 MaybeObject* Map::CopyNormalized(PropertyNormalizationMode mode,
(...skipping 2602 matching lines...) Expand 10 before | Expand all | Expand 10 after
7512 PropertyNormalizationMode mode) { 7616 PropertyNormalizationMode mode) {
7513 return 7617 return
7514 constructor() == other->constructor() && 7618 constructor() == other->constructor() &&
7515 prototype() == other->prototype() && 7619 prototype() == other->prototype() &&
7516 inobject_properties() == ((mode == CLEAR_INOBJECT_PROPERTIES) ? 7620 inobject_properties() == ((mode == CLEAR_INOBJECT_PROPERTIES) ?
7517 0 : 7621 0 :
7518 other->inobject_properties()) && 7622 other->inobject_properties()) &&
7519 instance_type() == other->instance_type() && 7623 instance_type() == other->instance_type() &&
7520 bit_field() == other->bit_field() && 7624 bit_field() == other->bit_field() &&
7521 bit_field2() == other->bit_field2() && 7625 bit_field2() == other->bit_field2() &&
7626 is_observed() == other->is_observed() &&
7522 function_with_prototype() == other->function_with_prototype(); 7627 function_with_prototype() == other->function_with_prototype();
7523 } 7628 }
7524 7629
7525 7630
7526 void JSFunction::JSFunctionIterateBody(int object_size, ObjectVisitor* v) { 7631 void JSFunction::JSFunctionIterateBody(int object_size, ObjectVisitor* v) {
7527 // Iterate over all fields in the body but take care in dealing with 7632 // Iterate over all fields in the body but take care in dealing with
7528 // the code entry. 7633 // the code entry.
7529 IteratePointers(v, kPropertiesOffset, kCodeEntryOffset); 7634 IteratePointers(v, kPropertiesOffset, kCodeEntryOffset);
7530 v->VisitCodeEntry(this->address() + kCodeEntryOffset); 7635 v->VisitCodeEntry(this->address() + kCodeEntryOffset);
7531 IteratePointers(v, kCodeEntryOffset + kPointerSize, object_size); 7636 IteratePointers(v, kCodeEntryOffset + kPointerSize, object_size);
(...skipping 5941 matching lines...) Expand 10 before | Expand all | Expand 10 after
13473 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); 13578 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER);
13474 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); 13579 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER);
13475 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); 13580 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER);
13476 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); 13581 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER);
13477 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); 13582 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER);
13478 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); 13583 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER);
13479 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); 13584 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER);
13480 } 13585 }
13481 13586
13482 } } // namespace v8::internal 13587 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698