OLD | NEW |
---|---|
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 Loading... | |
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* ret; | |
Toon Verwaest
2012/11/05 13:33:22
Can we call this maybe_result for consistency?
rossberg
2012/11/05 17:11:08
Done.
| |
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 ret = AddConstantFunctionProperty(name, |
1697 JSFunction::cast(value), | 1699 JSFunction::cast(value), |
rafaelw
2012/10/31 14:44:31
whitespace
rossberg
2012/11/05 17:11:08
Done.
| |
1698 attributes); | 1700 attributes); |
1699 } else { | 1701 } else { |
1700 return AddFastProperty(name, value, attributes, store_mode); | 1702 ret = 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 ret = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); |
1707 NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); | 1709 if (!ret->ToObject(&obj)) return ret; |
Toon Verwaest
2012/11/05 13:33:22
if (ret->IsFailure()) return ret;
I actually pref
rossberg
2012/11/05 17:11:08
Done.
| |
1708 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 1710 ret = AddSlowProperty(name, value, attributes); |
1709 } | |
1710 } | 1711 } |
1712 } else { | |
1713 ret = AddSlowProperty(name, value, attributes); | |
1711 } | 1714 } |
1712 return AddSlowProperty(name, value, attributes); | 1715 |
1716 if (FLAG_harmony_observation && map()->is_observed() && !ret->IsFailure()) { | |
1717 this->NotifyObservers("new", name, heap->the_hole_value()); | |
1718 } | |
1719 | |
1720 return ret; | |
rafaelw
2012/10/31 14:44:31
Isn't this unsafe? The notifyObservers could have
Toon Verwaest
2012/11/05 13:33:22
Yes. We should not jump into handlified code from
rossberg
2012/11/05 17:11:08
Indeed.
rossberg
2012/11/05 17:11:08
Most of the methods in question are already docume
| |
1713 } | 1721 } |
1714 | 1722 |
1715 | 1723 |
1724 void JSObject::NotifyObservers( | |
1725 const char* type_raw, String* name_raw, Object* oldValue_raw) { | |
1726 Isolate* isolate = GetIsolate(); | |
1727 HandleScope scope; | |
1728 Handle<String> type = isolate->factory()->LookupAsciiSymbol(type_raw); | |
1729 Handle<JSObject> object(this); | |
1730 Handle<String> name(name_raw); | |
1731 bool threw; | |
1732 if (oldValue_raw->IsTheHole()) { | |
rafaelw
2012/10/31 14:44:31
nit: This can be cleaner if you make argv a Scoped
rossberg
2012/11/05 17:11:08
Well, that would make the code pretty verbose as w
| |
1733 Handle<Object> args[] = { type, object, name }; | |
1734 Execution::Call(Handle<JSFunction>(isolate->observers_notify_change()), | |
1735 Handle<Object>(isolate->heap()->undefined_value()), | |
1736 ARRAY_SIZE(args), args, | |
1737 &threw); | |
1738 } else { | |
1739 Handle<Object> oldValue(oldValue_raw); | |
1740 Handle<Object> args[] = { type, object, name, oldValue }; | |
1741 Execution::Call(Handle<JSFunction>(isolate->observers_notify_change()), | |
1742 Handle<Object>(isolate->heap()->undefined_value()), | |
1743 ARRAY_SIZE(args), args, | |
1744 &threw); | |
1745 } | |
1746 ASSERT(!threw); | |
1747 } | |
1748 | |
1749 | |
1716 MaybeObject* JSObject::SetPropertyPostInterceptor( | 1750 MaybeObject* JSObject::SetPropertyPostInterceptor( |
1717 String* name, | 1751 String* name, |
1718 Object* value, | 1752 Object* value, |
1719 PropertyAttributes attributes, | 1753 PropertyAttributes attributes, |
1720 StrictModeFlag strict_mode, | 1754 StrictModeFlag strict_mode, |
1721 ExtensibilityCheck extensibility_check) { | 1755 ExtensibilityCheck extensibility_check) { |
1722 // Check local property, ignore interceptor. | 1756 // Check local property, ignore interceptor. |
1723 LookupResult result(GetIsolate()); | 1757 LookupResult result(GetIsolate()); |
1724 LocalLookupRealNamedProperty(name, &result); | 1758 LocalLookupRealNamedProperty(name, &result); |
1725 if (!result.IsFound()) map()->LookupTransition(this, name, &result); | 1759 if (!result.IsFound()) map()->LookupTransition(this, name, &result); |
(...skipping 1127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2853 MaybeObject* result_object = self->SetPropertyViaPrototypes( | 2887 MaybeObject* result_object = self->SetPropertyViaPrototypes( |
2854 *name, *value, attributes, strict_mode, &done); | 2888 *name, *value, attributes, strict_mode, &done); |
2855 if (done) return result_object; | 2889 if (done) return result_object; |
2856 } | 2890 } |
2857 | 2891 |
2858 if (!result->IsFound()) { | 2892 if (!result->IsFound()) { |
2859 // Neither properties nor transitions found. | 2893 // Neither properties nor transitions found. |
2860 return self->AddProperty( | 2894 return self->AddProperty( |
2861 *name, *value, attributes, strict_mode, store_mode); | 2895 *name, *value, attributes, strict_mode, store_mode); |
2862 } | 2896 } |
2897 | |
2863 if (result->IsProperty() && result->IsReadOnly()) { | 2898 if (result->IsProperty() && result->IsReadOnly()) { |
2864 if (strict_mode == kStrictMode) { | 2899 if (strict_mode == kStrictMode) { |
2865 Handle<Object> args[] = { name, self }; | 2900 Handle<Object> args[] = { name, self }; |
2866 return heap->isolate()->Throw(*heap->isolate()->factory()->NewTypeError( | 2901 return heap->isolate()->Throw(*heap->isolate()->factory()->NewTypeError( |
2867 "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args)))); | 2902 "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args)))); |
2868 } else { | 2903 } else { |
2869 return *value; | 2904 return *value; |
2870 } | 2905 } |
2871 } | 2906 } |
2872 | 2907 |
2908 Object* oldValue = heap->the_hole_value(); | |
2909 if (FLAG_harmony_observation && map()->is_observed()) { | |
2910 // TODO(observe): save oldValue | |
2911 } | |
2912 | |
2873 // This is a real property that is not read-only, or it is a | 2913 // 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. | 2914 // transition or null descriptor and there are no setters in the prototypes. |
2915 MaybeObject* ret = *value; | |
2875 switch (result->type()) { | 2916 switch (result->type()) { |
2876 case NORMAL: | 2917 case NORMAL: |
2877 return self->SetNormalizedProperty(result, *value); | 2918 ret = self->SetNormalizedProperty(result, *value); |
2919 break; | |
2878 case FIELD: | 2920 case FIELD: |
2879 return self->FastPropertyAtPut(result->GetFieldIndex(), *value); | 2921 ret = self->FastPropertyAtPut(result->GetFieldIndex(), *value); |
2922 break; | |
2880 case CONSTANT_FUNCTION: | 2923 case CONSTANT_FUNCTION: |
2881 // Only replace the function if necessary. | 2924 // Only replace the function if necessary. |
2882 if (*value == result->GetConstantFunction()) return *value; | 2925 if (*value == result->GetConstantFunction()) return *value; |
2883 // Preserve the attributes of this existing property. | 2926 // Preserve the attributes of this existing property. |
2884 attributes = result->GetAttributes(); | 2927 attributes = result->GetAttributes(); |
2885 return self->ConvertDescriptorToField(*name, *value, attributes); | 2928 ret = self->ConvertDescriptorToField(*name, *value, attributes); |
2929 break; | |
2886 case CALLBACKS: { | 2930 case CALLBACKS: { |
2887 Object* callback_object = result->GetCallbackObject(); | 2931 Object* callback_object = result->GetCallbackObject(); |
2888 return self->SetPropertyWithCallback(callback_object, | 2932 return self->SetPropertyWithCallback(callback_object, |
2889 *name, | 2933 *name, |
2890 *value, | 2934 *value, |
2891 result->holder(), | 2935 result->holder(), |
2892 strict_mode); | 2936 strict_mode); |
2893 } | 2937 } |
2894 case INTERCEPTOR: | 2938 case INTERCEPTOR: |
2895 return self->SetPropertyWithInterceptor(*name, | 2939 ret = self->SetPropertyWithInterceptor(*name, |
2896 *value, | 2940 *value, |
2897 attributes, | 2941 attributes, |
2898 strict_mode); | 2942 strict_mode); |
2943 break; | |
2899 case TRANSITION: { | 2944 case TRANSITION: { |
2900 Map* transition_map = result->GetTransitionTarget(); | 2945 Map* transition_map = result->GetTransitionTarget(); |
2901 int descriptor = transition_map->LastAdded(); | 2946 int descriptor = transition_map->LastAdded(); |
2902 | 2947 |
2903 DescriptorArray* descriptors = transition_map->instance_descriptors(); | 2948 DescriptorArray* descriptors = transition_map->instance_descriptors(); |
2904 PropertyDetails details = descriptors->GetDetails(descriptor); | 2949 PropertyDetails details = descriptors->GetDetails(descriptor); |
2905 | 2950 |
2906 if (details.type() == FIELD) { | 2951 if (details.type() == FIELD) { |
2907 if (attributes == details.attributes()) { | 2952 if (attributes == details.attributes()) { |
2908 int field_index = descriptors->GetFieldIndex(descriptor); | 2953 int field_index = descriptors->GetFieldIndex(descriptor); |
2909 return self->AddFastPropertyUsingMap(transition_map, | 2954 ret = self->AddFastPropertyUsingMap(transition_map, |
2910 *name, | 2955 *name, |
2911 *value, | 2956 *value, |
2912 field_index); | 2957 field_index); |
2958 } else { | |
2959 ret = self->ConvertDescriptorToField(*name, *value, attributes); | |
2913 } | 2960 } |
2914 return self->ConvertDescriptorToField(*name, *value, attributes); | |
2915 } else if (details.type() == CALLBACKS) { | 2961 } else if (details.type() == CALLBACKS) { |
2916 return ConvertDescriptorToField(*name, *value, attributes); | 2962 ret = ConvertDescriptorToField(*name, *value, attributes); |
2963 } else { | |
2964 ASSERT(details.type() == CONSTANT_FUNCTION); | |
2965 | |
2966 Object* constant_function = descriptors->GetValue(descriptor); | |
2967 if (constant_function == *value) { | |
2968 // If the same constant function is being added we can simply | |
2969 // transition to the target map. | |
2970 self->set_map(transition_map); | |
2971 ret = constant_function; | |
2972 } else { | |
2973 // Otherwise, replace with a map transition to a new map with a FIELD, | |
2974 // even if the value is a constant function. | |
2975 ret = ConvertTransitionToMapTransition( | |
2976 result->GetTransitionIndex(), *name, *value, attributes); | |
2977 } | |
2917 } | 2978 } |
2918 | 2979 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 } | 2980 } |
2933 case HANDLER: | 2981 case HANDLER: |
2934 case NONEXISTENT: | 2982 case NONEXISTENT: |
2935 UNREACHABLE(); | 2983 UNREACHABLE(); |
2936 return *value; | |
2937 } | 2984 } |
2938 UNREACHABLE(); // keep the compiler happy | 2985 |
2939 return *value; | 2986 if (FLAG_harmony_observation && map()->is_observed() && !ret->IsFailure()) { |
2987 this->NotifyObservers("updated", *name, oldValue); | |
2988 } | |
2989 | |
2990 return ret; | |
rafaelw
2012/10/31 14:44:31
same question about returning MaybeObject after in
rossberg
2012/11/05 17:11:08
Done.
| |
2940 } | 2991 } |
2941 | 2992 |
2942 | 2993 |
2943 // Set a real local property, even if it is READ_ONLY. If the property is not | 2994 // 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 | 2995 // 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 | 2996 // SetProperty, with the check for IsReadOnly and the check for a |
2946 // callback setter removed. The two lines looking up the LookupResult | 2997 // callback setter removed. The two lines looking up the LookupResult |
2947 // result are also added. If one of the functions is changed, the other | 2998 // result are also added. If one of the functions is changed, the other |
2948 // should be. | 2999 // should be. |
2949 // Note that this method cannot be used to set the prototype of a function | 3000 // Note that this method cannot be used to set the prototype of a function |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2992 value, | 3043 value, |
2993 attributes); | 3044 attributes); |
2994 } | 3045 } |
2995 | 3046 |
2996 // Check for accessor in prototype chain removed here in clone. | 3047 // Check for accessor in prototype chain removed here in clone. |
2997 if (!result.IsFound()) { | 3048 if (!result.IsFound()) { |
2998 // Neither properties nor transitions found. | 3049 // Neither properties nor transitions found. |
2999 return AddProperty(name, value, attributes, kNonStrictMode); | 3050 return AddProperty(name, value, attributes, kNonStrictMode); |
3000 } | 3051 } |
3001 | 3052 |
3053 Object* oldValue = isolate->heap()->the_hole_value(); | |
3054 if (FLAG_harmony_observation && map()->is_observed()) { | |
3055 // TODO(observe): save oldValue | |
3056 } | |
3057 | |
3002 // Check of IsReadOnly removed from here in clone. | 3058 // Check of IsReadOnly removed from here in clone. |
3059 MaybeObject* ret = value; | |
3003 switch (result.type()) { | 3060 switch (result.type()) { |
3004 case NORMAL: { | 3061 case NORMAL: { |
3005 PropertyDetails details = PropertyDetails(attributes, NORMAL); | 3062 PropertyDetails details = PropertyDetails(attributes, NORMAL); |
3006 return SetNormalizedProperty(name, value, details); | 3063 ret = SetNormalizedProperty(name, value, details); |
3064 break; | |
3007 } | 3065 } |
3008 case FIELD: | 3066 case FIELD: |
3009 return FastPropertyAtPut(result.GetFieldIndex(), value); | 3067 ret = FastPropertyAtPut(result.GetFieldIndex(), value); |
3068 break; | |
3010 case CONSTANT_FUNCTION: | 3069 case CONSTANT_FUNCTION: |
3011 // Only replace the function if necessary. | 3070 // Only replace the function if necessary. |
3012 if (value == result.GetConstantFunction()) return value; | 3071 if (value == result.GetConstantFunction()) return value; |
3013 // Preserve the attributes of this existing property. | 3072 // Preserve the attributes of this existing property. |
3014 attributes = result.GetAttributes(); | 3073 attributes = result.GetAttributes(); |
3015 return ConvertDescriptorToField(name, value, attributes); | 3074 ret = ConvertDescriptorToField(name, value, attributes); |
3075 break; | |
3016 case CALLBACKS: | 3076 case CALLBACKS: |
3017 case INTERCEPTOR: | 3077 case INTERCEPTOR: |
3018 // Override callback in clone | 3078 // Override callback in clone |
3019 return ConvertDescriptorToField(name, value, attributes); | 3079 ret = ConvertDescriptorToField(name, value, attributes); |
3080 break; | |
3020 case TRANSITION: { | 3081 case TRANSITION: { |
3021 Map* transition_map = result.GetTransitionTarget(); | 3082 Map* transition_map = result.GetTransitionTarget(); |
3022 int descriptor = transition_map->LastAdded(); | 3083 int descriptor = transition_map->LastAdded(); |
3023 | 3084 |
3024 DescriptorArray* descriptors = transition_map->instance_descriptors(); | 3085 DescriptorArray* descriptors = transition_map->instance_descriptors(); |
3025 PropertyDetails details = descriptors->GetDetails(descriptor); | 3086 PropertyDetails details = descriptors->GetDetails(descriptor); |
3026 | 3087 |
3027 if (details.type() == FIELD) { | 3088 if (details.type() == FIELD) { |
3028 if (attributes == details.attributes()) { | 3089 if (attributes == details.attributes()) { |
3029 int field_index = descriptors->GetFieldIndex(descriptor); | 3090 int field_index = descriptors->GetFieldIndex(descriptor); |
3030 return AddFastPropertyUsingMap(transition_map, | 3091 ret = AddFastPropertyUsingMap(transition_map, |
3031 name, | 3092 name, |
3032 value, | 3093 value, |
3033 field_index); | 3094 field_index); |
3095 } else { | |
3096 ret = ConvertDescriptorToField(name, value, attributes); | |
3034 } | 3097 } |
3035 return ConvertDescriptorToField(name, value, attributes); | |
3036 } else if (details.type() == CALLBACKS) { | 3098 } else if (details.type() == CALLBACKS) { |
3037 return ConvertDescriptorToField(name, value, attributes); | 3099 ret = ConvertDescriptorToField(name, value, attributes); |
3100 } else { | |
3101 ASSERT(details.type() == CONSTANT_FUNCTION); | |
3102 | |
3103 // Replace transition to CONSTANT FUNCTION with a map transition to a ne w | |
3104 // map with a FIELD, even if the value is a function. | |
3105 ret = ConvertTransitionToMapTransition( | |
3106 result.GetTransitionIndex(), name, value, attributes); | |
3038 } | 3107 } |
3039 | 3108 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 } | 3109 } |
3047 case HANDLER: | 3110 case HANDLER: |
3048 case NONEXISTENT: | 3111 case NONEXISTENT: |
3049 UNREACHABLE(); | 3112 UNREACHABLE(); |
3050 } | 3113 } |
3051 UNREACHABLE(); // keep the compiler happy | 3114 |
3052 return value; | 3115 if (FLAG_harmony_observation && map()->is_observed() && !ret->IsFailure()) { |
3116 const char* type = | |
3117 attributes == result.GetAttributes() ? "updated" : "reconfigured"; | |
3118 this->NotifyObservers(type, name, oldValue); | |
3119 } | |
3120 | |
3121 return ret; | |
rafaelw
2012/10/31 14:44:31
same question about returning MaybeObject
rossberg
2012/11/05 17:11:08
Done.
| |
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 Loading... | |
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 result(isolate); | |
4028 LocalLookup(name, &result); | |
4029 if (!result.IsFound()) return isolate->heap()->true_value(); | |
4030 // Ignore attributes if forcing a deletion. | |
4031 if (result.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 Object* oldValue = isolate->heap()->the_hole_value(); | |
4043 if (FLAG_harmony_observation && map()->is_observed()) { | |
4044 // TODO(observe): save oldValue | |
4045 } | |
4046 MaybeObject* ret; | |
4047 | |
4048 // Check for interceptor. | |
4049 if (result.IsInterceptor()) { | |
4050 // Skip interceptor if forcing a deletion. | |
4051 if (mode == FORCE_DELETION) { | |
4052 ret = DeletePropertyPostInterceptor(name, mode); | |
4053 } else { | |
4054 ret = DeletePropertyWithInterceptor(name); | |
4055 } | |
3956 } else { | 4056 } 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. | 4057 // Normalize object if needed. |
3980 Object* obj; | 4058 Object* obj; |
3981 { MaybeObject* maybe_obj = | 4059 ret = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); |
3982 NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); | 4060 if (!ret->ToObject(&obj)) return ret; |
3983 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | |
3984 } | |
3985 // Make sure the properties are normalized before removing the entry. | 4061 // Make sure the properties are normalized before removing the entry. |
3986 return DeleteNormalizedProperty(name, mode); | 4062 ret = DeleteNormalizedProperty(name, mode); |
3987 } | 4063 } |
4064 | |
4065 if (FLAG_harmony_observation && map()->is_observed() && !ret->IsFailure()) { | |
4066 this->NotifyObservers("deleted", name, oldValue); | |
4067 } | |
4068 | |
4069 return ret; | |
rafaelw
2012/10/31 14:44:31
ditto
rossberg
2012/11/05 17:11:08
Done.
| |
3988 } | 4070 } |
3989 | 4071 |
3990 | 4072 |
3991 MaybeObject* JSReceiver::DeleteElement(uint32_t index, DeleteMode mode) { | 4073 MaybeObject* JSReceiver::DeleteElement(uint32_t index, DeleteMode mode) { |
3992 if (IsJSProxy()) { | 4074 if (IsJSProxy()) { |
3993 return JSProxy::cast(this)->DeleteElementWithHandler(index, mode); | 4075 return JSProxy::cast(this)->DeleteElementWithHandler(index, mode); |
3994 } | 4076 } |
3995 return JSObject::cast(this)->DeleteElement(index, mode); | 4077 return JSObject::cast(this)->DeleteElement(index, mode); |
3996 } | 4078 } |
3997 | 4079 |
(...skipping 607 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4605 | 4687 |
4606 // Make sure that the top context does not change when doing callbacks or | 4688 // Make sure that the top context does not change when doing callbacks or |
4607 // interceptor calls. | 4689 // interceptor calls. |
4608 AssertNoContextChange ncc; | 4690 AssertNoContextChange ncc; |
4609 | 4691 |
4610 // Try to flatten before operating on the string. | 4692 // Try to flatten before operating on the string. |
4611 name->TryFlatten(); | 4693 name->TryFlatten(); |
4612 | 4694 |
4613 if (!CanSetCallback(name)) return isolate->heap()->undefined_value(); | 4695 if (!CanSetCallback(name)) return isolate->heap()->undefined_value(); |
4614 | 4696 |
4697 Object* oldValue = isolate->heap()->the_hole_value(); | |
4698 bool preexists; | |
4699 if (FLAG_harmony_observation && map()->is_observed()) { | |
4700 LookupResult result(isolate); | |
4701 LocalLookup(name, &result); | |
4702 preexists = result.IsFound(); | |
4703 // TODO(observe): save oldValue | |
4704 } | |
4705 | |
4615 uint32_t index = 0; | 4706 uint32_t index = 0; |
4616 return name->AsArrayIndex(&index) ? | 4707 MaybeObject* ret = name->AsArrayIndex(&index) ? |
4617 DefineElementAccessor(index, getter, setter, attributes) : | 4708 DefineElementAccessor(index, getter, setter, attributes) : |
4618 DefinePropertyAccessor(name, getter, setter, attributes); | 4709 DefinePropertyAccessor(name, getter, setter, attributes); |
4710 | |
4711 if (FLAG_harmony_observation && map()->is_observed() && !ret->IsFailure()) { | |
4712 const char* type = preexists ? "reconfigured" : "new"; | |
4713 this->NotifyObservers(type, name, oldValue); | |
4714 } | |
4715 | |
4716 return ret; | |
rafaelw
2012/10/31 14:44:31
ditto
rossberg
2012/11/05 17:11:08
Done.
| |
4619 } | 4717 } |
4620 | 4718 |
4621 | 4719 |
4622 static MaybeObject* TryAccessorTransition(JSObject* self, | 4720 static MaybeObject* TryAccessorTransition(JSObject* self, |
4623 Map* transitioned_map, | 4721 Map* transitioned_map, |
4624 int target_descriptor, | 4722 int target_descriptor, |
4625 AccessorComponent component, | 4723 AccessorComponent component, |
4626 Object* accessor, | 4724 Object* accessor, |
4627 PropertyAttributes attributes) { | 4725 PropertyAttributes attributes) { |
4628 DescriptorArray* descs = transitioned_map->instance_descriptors(); | 4726 DescriptorArray* descs = transitioned_map->instance_descriptors(); |
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4889 MaybeObject* Map::RawCopy(int instance_size) { | 4987 MaybeObject* Map::RawCopy(int instance_size) { |
4890 Map* result; | 4988 Map* result; |
4891 MaybeObject* maybe_result = | 4989 MaybeObject* maybe_result = |
4892 GetHeap()->AllocateMap(instance_type(), instance_size); | 4990 GetHeap()->AllocateMap(instance_type(), instance_size); |
4893 if (!maybe_result->To(&result)) return maybe_result; | 4991 if (!maybe_result->To(&result)) return maybe_result; |
4894 | 4992 |
4895 result->set_prototype(prototype()); | 4993 result->set_prototype(prototype()); |
4896 result->set_constructor(constructor()); | 4994 result->set_constructor(constructor()); |
4897 result->set_bit_field(bit_field()); | 4995 result->set_bit_field(bit_field()); |
4898 result->set_bit_field2(bit_field2()); | 4996 result->set_bit_field2(bit_field2()); |
4899 result->set_bit_field3(bit_field3()); | |
4900 int new_bit_field3 = bit_field3(); | 4997 int new_bit_field3 = bit_field3(); |
4901 new_bit_field3 = OwnsDescriptors::update(new_bit_field3, true); | 4998 new_bit_field3 = OwnsDescriptors::update(new_bit_field3, true); |
4902 new_bit_field3 = NumberOfOwnDescriptorsBits::update(new_bit_field3, 0); | 4999 new_bit_field3 = NumberOfOwnDescriptorsBits::update(new_bit_field3, 0); |
4903 new_bit_field3 = EnumLengthBits::update(new_bit_field3, kInvalidEnumCache); | 5000 new_bit_field3 = EnumLengthBits::update(new_bit_field3, kInvalidEnumCache); |
4904 result->set_bit_field3(new_bit_field3); | 5001 result->set_bit_field3(new_bit_field3); |
4905 return result; | 5002 return result; |
4906 } | 5003 } |
4907 | 5004 |
4908 | 5005 |
4909 MaybeObject* Map::CopyNormalized(PropertyNormalizationMode mode, | 5006 MaybeObject* Map::CopyNormalized(PropertyNormalizationMode mode, |
(...skipping 2602 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
7512 PropertyNormalizationMode mode) { | 7609 PropertyNormalizationMode mode) { |
7513 return | 7610 return |
7514 constructor() == other->constructor() && | 7611 constructor() == other->constructor() && |
7515 prototype() == other->prototype() && | 7612 prototype() == other->prototype() && |
7516 inobject_properties() == ((mode == CLEAR_INOBJECT_PROPERTIES) ? | 7613 inobject_properties() == ((mode == CLEAR_INOBJECT_PROPERTIES) ? |
7517 0 : | 7614 0 : |
7518 other->inobject_properties()) && | 7615 other->inobject_properties()) && |
7519 instance_type() == other->instance_type() && | 7616 instance_type() == other->instance_type() && |
7520 bit_field() == other->bit_field() && | 7617 bit_field() == other->bit_field() && |
7521 bit_field2() == other->bit_field2() && | 7618 bit_field2() == other->bit_field2() && |
7619 (bit_field3() & IsObserved::kMask) == | |
7620 (other->bit_field3() & IsObserved::kMask) && | |
Toon Verwaest
2012/11/05 13:33:22
Can we just use is_observed() == other->is_observe
rossberg
2012/11/05 17:11:08
Done.
| |
7522 function_with_prototype() == other->function_with_prototype(); | 7621 function_with_prototype() == other->function_with_prototype(); |
7523 } | 7622 } |
7524 | 7623 |
7525 | 7624 |
7526 void JSFunction::JSFunctionIterateBody(int object_size, ObjectVisitor* v) { | 7625 void JSFunction::JSFunctionIterateBody(int object_size, ObjectVisitor* v) { |
7527 // Iterate over all fields in the body but take care in dealing with | 7626 // Iterate over all fields in the body but take care in dealing with |
7528 // the code entry. | 7627 // the code entry. |
7529 IteratePointers(v, kPropertiesOffset, kCodeEntryOffset); | 7628 IteratePointers(v, kPropertiesOffset, kCodeEntryOffset); |
7530 v->VisitCodeEntry(this->address() + kCodeEntryOffset); | 7629 v->VisitCodeEntry(this->address() + kCodeEntryOffset); |
7531 IteratePointers(v, kCodeEntryOffset + kPointerSize, object_size); | 7630 IteratePointers(v, kCodeEntryOffset + kPointerSize, object_size); |
(...skipping 5941 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
13473 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); | 13572 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); |
13474 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); | 13573 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); |
13475 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); | 13574 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); |
13476 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); | 13575 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); |
13477 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); | 13576 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); |
13478 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); | 13577 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); |
13479 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); | 13578 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); |
13480 } | 13579 } |
13481 | 13580 |
13482 } } // namespace v8::internal | 13581 } } // namespace v8::internal |
OLD | NEW |