OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 866 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
877 return *desc; | 877 return *desc; |
878 } | 878 } |
879 | 879 |
880 | 880 |
881 static MaybeObject* Runtime_PreventExtensions(Arguments args) { | 881 static MaybeObject* Runtime_PreventExtensions(Arguments args) { |
882 ASSERT(args.length() == 1); | 882 ASSERT(args.length() == 1); |
883 CONVERT_CHECKED(JSObject, obj, args[0]); | 883 CONVERT_CHECKED(JSObject, obj, args[0]); |
884 return obj->PreventExtensions(); | 884 return obj->PreventExtensions(); |
885 } | 885 } |
886 | 886 |
| 887 |
887 static MaybeObject* Runtime_IsExtensible(Arguments args) { | 888 static MaybeObject* Runtime_IsExtensible(Arguments args) { |
888 ASSERT(args.length() == 1); | 889 ASSERT(args.length() == 1); |
889 CONVERT_CHECKED(JSObject, obj, args[0]); | 890 CONVERT_CHECKED(JSObject, obj, args[0]); |
890 return obj->map()->is_extensible() ? Heap::true_value() | 891 if (obj->IsJSGlobalProxy()) { |
| 892 Object* proto = obj->GetPrototype(); |
| 893 if (proto->IsNull()) return Heap::false_value(); |
| 894 ASSERT(proto->IsJSGlobalObject()); |
| 895 obj = JSObject::cast(proto); |
| 896 } |
| 897 return obj->map()->is_extensible() ? Heap::true_value() |
891 : Heap::false_value(); | 898 : Heap::false_value(); |
892 } | 899 } |
893 | 900 |
894 | 901 |
895 static MaybeObject* Runtime_RegExpCompile(Arguments args) { | 902 static MaybeObject* Runtime_RegExpCompile(Arguments args) { |
896 HandleScope scope; | 903 HandleScope scope; |
897 ASSERT(args.length() == 3); | 904 ASSERT(args.length() == 3); |
898 CONVERT_ARG_CHECKED(JSRegExp, re, 0); | 905 CONVERT_ARG_CHECKED(JSRegExp, re, 0); |
899 CONVERT_ARG_CHECKED(String, pattern, 1); | 906 CONVERT_ARG_CHECKED(String, pattern, 1); |
900 CONVERT_ARG_CHECKED(String, flags, 2); | 907 CONVERT_ARG_CHECKED(String, flags, 2); |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1075 // that claims the property is absent. | 1082 // that claims the property is absent. |
1076 | 1083 |
1077 // Check for conflicting re-declarations. We cannot have | 1084 // Check for conflicting re-declarations. We cannot have |
1078 // conflicting types in case of intercepted properties because | 1085 // conflicting types in case of intercepted properties because |
1079 // they are absent. | 1086 // they are absent. |
1080 if (lookup.type() != INTERCEPTOR && | 1087 if (lookup.type() != INTERCEPTOR && |
1081 (lookup.IsReadOnly() || is_const_property)) { | 1088 (lookup.IsReadOnly() || is_const_property)) { |
1082 const char* type = (lookup.IsReadOnly()) ? "const" : "var"; | 1089 const char* type = (lookup.IsReadOnly()) ? "const" : "var"; |
1083 return ThrowRedeclarationError(type, name); | 1090 return ThrowRedeclarationError(type, name); |
1084 } | 1091 } |
1085 SetProperty(global, name, value, attributes); | 1092 Handle<Object> result = SetProperty(global, name, value, attributes); |
| 1093 if (result.is_null()) { |
| 1094 ASSERT(Top::has_pending_exception()); |
| 1095 return Failure::Exception(); |
| 1096 } |
1086 } else { | 1097 } else { |
1087 // If a property with this name does not already exist on the | 1098 // If a property with this name does not already exist on the |
1088 // global object add the property locally. We take special | 1099 // global object add the property locally. We take special |
1089 // precautions to always add it as a local property even in case | 1100 // precautions to always add it as a local property even in case |
1090 // of callbacks in the prototype chain (this rules out using | 1101 // of callbacks in the prototype chain (this rules out using |
1091 // SetProperty). Also, we must use the handle-based version to | 1102 // SetProperty). Also, we must use the handle-based version to |
1092 // avoid GC issues. | 1103 // avoid GC issues. |
1093 SetLocalPropertyIgnoreAttributes(global, name, value, attributes); | 1104 Handle<Object> result = |
| 1105 SetLocalPropertyIgnoreAttributes(global, name, value, attributes); |
| 1106 if (result.is_null()) { |
| 1107 ASSERT(Top::has_pending_exception()); |
| 1108 return Failure::Exception(); |
| 1109 } |
1094 } | 1110 } |
1095 } | 1111 } |
1096 | 1112 |
| 1113 ASSERT(!Top::has_pending_exception()); |
1097 return Heap::undefined_value(); | 1114 return Heap::undefined_value(); |
1098 } | 1115 } |
1099 | 1116 |
1100 | 1117 |
1101 static MaybeObject* Runtime_DeclareContextSlot(Arguments args) { | 1118 static MaybeObject* Runtime_DeclareContextSlot(Arguments args) { |
1102 HandleScope scope; | 1119 HandleScope scope; |
1103 ASSERT(args.length() == 4); | 1120 ASSERT(args.length() == 4); |
1104 | 1121 |
1105 CONVERT_ARG_CHECKED(Context, context, 0); | 1122 CONVERT_ARG_CHECKED(Context, context, 0); |
1106 Handle<String> name(String::cast(args[1])); | 1123 Handle<String> name(String::cast(args[1])); |
(...skipping 29 matching lines...) Expand all Loading... |
1136 // the function context or the arguments object. | 1153 // the function context or the arguments object. |
1137 if (holder->IsContext()) { | 1154 if (holder->IsContext()) { |
1138 ASSERT(holder.is_identical_to(context)); | 1155 ASSERT(holder.is_identical_to(context)); |
1139 if (((attributes & READ_ONLY) == 0) || | 1156 if (((attributes & READ_ONLY) == 0) || |
1140 context->get(index)->IsTheHole()) { | 1157 context->get(index)->IsTheHole()) { |
1141 context->set(index, *initial_value); | 1158 context->set(index, *initial_value); |
1142 } | 1159 } |
1143 } else { | 1160 } else { |
1144 // The holder is an arguments object. | 1161 // The holder is an arguments object. |
1145 Handle<JSObject> arguments(Handle<JSObject>::cast(holder)); | 1162 Handle<JSObject> arguments(Handle<JSObject>::cast(holder)); |
1146 SetElement(arguments, index, initial_value); | 1163 Handle<Object> result = SetElement(arguments, index, initial_value); |
| 1164 if (result.is_null()) return Failure::Exception(); |
1147 } | 1165 } |
1148 } else { | 1166 } else { |
1149 // Slow case: The property is not in the FixedArray part of the context. | 1167 // Slow case: The property is not in the FixedArray part of the context. |
1150 Handle<JSObject> context_ext = Handle<JSObject>::cast(holder); | 1168 Handle<JSObject> context_ext = Handle<JSObject>::cast(holder); |
1151 SetProperty(context_ext, name, initial_value, mode); | 1169 Handle<Object> result = |
| 1170 SetProperty(context_ext, name, initial_value, mode); |
| 1171 if (result.is_null()) return Failure::Exception(); |
1152 } | 1172 } |
1153 } | 1173 } |
1154 | 1174 |
1155 } else { | 1175 } else { |
1156 // The property is not in the function context. It needs to be | 1176 // The property is not in the function context. It needs to be |
1157 // "declared" in the function context's extension context, or in the | 1177 // "declared" in the function context's extension context, or in the |
1158 // global context. | 1178 // global context. |
1159 Handle<JSObject> context_ext; | 1179 Handle<JSObject> context_ext; |
1160 if (context->has_extension()) { | 1180 if (context->has_extension()) { |
1161 // The function context's extension context exists - use it. | 1181 // The function context's extension context exists - use it. |
1162 context_ext = Handle<JSObject>(context->extension()); | 1182 context_ext = Handle<JSObject>(context->extension()); |
1163 } else { | 1183 } else { |
1164 // The function context's extension context does not exists - allocate | 1184 // The function context's extension context does not exists - allocate |
1165 // it. | 1185 // it. |
1166 context_ext = Factory::NewJSObject(Top::context_extension_function()); | 1186 context_ext = Factory::NewJSObject(Top::context_extension_function()); |
1167 // And store it in the extension slot. | 1187 // And store it in the extension slot. |
1168 context->set_extension(*context_ext); | 1188 context->set_extension(*context_ext); |
1169 } | 1189 } |
1170 ASSERT(*context_ext != NULL); | 1190 ASSERT(*context_ext != NULL); |
1171 | 1191 |
1172 // Declare the property by setting it to the initial value if provided, | 1192 // Declare the property by setting it to the initial value if provided, |
1173 // or undefined, and use the correct mode (e.g. READ_ONLY attribute for | 1193 // or undefined, and use the correct mode (e.g. READ_ONLY attribute for |
1174 // constant declarations). | 1194 // constant declarations). |
1175 ASSERT(!context_ext->HasLocalProperty(*name)); | 1195 ASSERT(!context_ext->HasLocalProperty(*name)); |
1176 Handle<Object> value(Heap::undefined_value()); | 1196 Handle<Object> value(Heap::undefined_value()); |
1177 if (*initial_value != NULL) value = initial_value; | 1197 if (*initial_value != NULL) value = initial_value; |
1178 SetProperty(context_ext, name, value, mode); | 1198 Handle<Object> result = SetProperty(context_ext, name, value, mode); |
1179 ASSERT(context_ext->GetLocalPropertyAttribute(*name) == mode); | 1199 if (result.is_null()) return Failure::Exception(); |
1180 } | 1200 } |
1181 | 1201 |
1182 return Heap::undefined_value(); | 1202 return Heap::undefined_value(); |
1183 } | 1203 } |
1184 | 1204 |
1185 | 1205 |
1186 static MaybeObject* Runtime_InitializeVarGlobal(Arguments args) { | 1206 static MaybeObject* Runtime_InitializeVarGlobal(Arguments args) { |
1187 NoHandleAllocation nha; | 1207 NoHandleAllocation nha; |
1188 | 1208 |
1189 // Determine if we need to assign to the variable if it already | 1209 // Determine if we need to assign to the variable if it already |
(...skipping 2458 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3648 // Check if this is an element. | 3668 // Check if this is an element. |
3649 uint32_t index; | 3669 uint32_t index; |
3650 bool is_element = name->AsArrayIndex(&index); | 3670 bool is_element = name->AsArrayIndex(&index); |
3651 | 3671 |
3652 // Special case for elements if any of the flags are true. | 3672 // Special case for elements if any of the flags are true. |
3653 // If elements are in fast case we always implicitly assume that: | 3673 // If elements are in fast case we always implicitly assume that: |
3654 // DONT_DELETE: false, DONT_ENUM: false, READ_ONLY: false. | 3674 // DONT_DELETE: false, DONT_ENUM: false, READ_ONLY: false. |
3655 if (((unchecked & (DONT_DELETE | DONT_ENUM | READ_ONLY)) != 0) && | 3675 if (((unchecked & (DONT_DELETE | DONT_ENUM | READ_ONLY)) != 0) && |
3656 is_element) { | 3676 is_element) { |
3657 // Normalize the elements to enable attributes on the property. | 3677 // Normalize the elements to enable attributes on the property. |
| 3678 if (js_object->IsJSGlobalProxy()) { |
| 3679 Handle<Object> proto(js_object->GetPrototype()); |
| 3680 // If proxy is detached, ignore the assignment. Alternatively, |
| 3681 // we could throw an exception. |
| 3682 if (proto->IsNull()) return *obj_value; |
| 3683 js_object = Handle<JSObject>::cast(proto); |
| 3684 } |
3658 NormalizeElements(js_object); | 3685 NormalizeElements(js_object); |
3659 Handle<NumberDictionary> dictionary(js_object->element_dictionary()); | 3686 Handle<NumberDictionary> dictionary(js_object->element_dictionary()); |
3660 // Make sure that we never go back to fast case. | 3687 // Make sure that we never go back to fast case. |
3661 dictionary->set_requires_slow_elements(); | 3688 dictionary->set_requires_slow_elements(); |
3662 PropertyDetails details = PropertyDetails(attr, NORMAL); | 3689 PropertyDetails details = PropertyDetails(attr, NORMAL); |
3663 NumberDictionarySet(dictionary, index, obj_value, details); | 3690 NumberDictionarySet(dictionary, index, obj_value, details); |
| 3691 return *obj_value; |
3664 } | 3692 } |
3665 | 3693 |
3666 LookupResult result; | 3694 LookupResult result; |
3667 js_object->LookupRealNamedProperty(*name, &result); | 3695 js_object->LookupRealNamedProperty(*name, &result); |
3668 | 3696 |
3669 // Take special care when attributes are different and there is already | 3697 // Take special care when attributes are different and there is already |
3670 // a property. For simplicity we normalize the property which enables us | 3698 // a property. For simplicity we normalize the property which enables us |
3671 // to not worry about changing the instance_descriptor and creating a new | 3699 // to not worry about changing the instance_descriptor and creating a new |
3672 // map. The current version of SetObjectProperty does not handle attributes | 3700 // map. The current version of SetObjectProperty does not handle attributes |
3673 // correctly in the case where a property is a field and is reset with | 3701 // correctly in the case where a property is a field and is reset with |
3674 // new attributes. | 3702 // new attributes. |
3675 if (result.IsProperty() && | 3703 if (result.IsProperty() && |
3676 (attr != result.GetAttributes() || result.type() == CALLBACKS)) { | 3704 (attr != result.GetAttributes() || result.type() == CALLBACKS)) { |
3677 // New attributes - normalize to avoid writing to instance descriptor | 3705 // New attributes - normalize to avoid writing to instance descriptor |
| 3706 if (js_object->IsJSGlobalProxy()) { |
| 3707 // Since the result is a property, the prototype will exist so |
| 3708 // we don't have to check for null. |
| 3709 js_object = Handle<JSObject>(JSObject::cast(js_object->GetPrototype())); |
| 3710 } |
3678 NormalizeProperties(js_object, CLEAR_INOBJECT_PROPERTIES, 0); | 3711 NormalizeProperties(js_object, CLEAR_INOBJECT_PROPERTIES, 0); |
3679 // Use IgnoreAttributes version since a readonly property may be | 3712 // Use IgnoreAttributes version since a readonly property may be |
3680 // overridden and SetProperty does not allow this. | 3713 // overridden and SetProperty does not allow this. |
3681 return js_object->SetLocalPropertyIgnoreAttributes(*name, | 3714 return js_object->SetLocalPropertyIgnoreAttributes(*name, |
3682 *obj_value, | 3715 *obj_value, |
3683 attr); | 3716 attr); |
3684 } | 3717 } |
3685 | 3718 |
3686 return Runtime::SetObjectProperty(js_object, name, obj_value, attr); | 3719 return Runtime::SetObjectProperty(js_object, name, obj_value, attr); |
3687 } | 3720 } |
(...skipping 3628 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7316 | 7349 |
7317 int index; | 7350 int index; |
7318 PropertyAttributes attributes; | 7351 PropertyAttributes attributes; |
7319 ContextLookupFlags flags = FOLLOW_CHAINS; | 7352 ContextLookupFlags flags = FOLLOW_CHAINS; |
7320 Handle<Object> holder = context->Lookup(name, flags, &index, &attributes); | 7353 Handle<Object> holder = context->Lookup(name, flags, &index, &attributes); |
7321 | 7354 |
7322 if (index >= 0) { | 7355 if (index >= 0) { |
7323 if (holder->IsContext()) { | 7356 if (holder->IsContext()) { |
7324 // Ignore if read_only variable. | 7357 // Ignore if read_only variable. |
7325 if ((attributes & READ_ONLY) == 0) { | 7358 if ((attributes & READ_ONLY) == 0) { |
7326 Handle<Context>::cast(holder)->set(index, *value); | 7359 // Context is a fixed array and set cannot fail. |
| 7360 Context::cast(*holder)->set(index, *value); |
7327 } | 7361 } |
7328 } else { | 7362 } else { |
7329 ASSERT((attributes & READ_ONLY) == 0); | 7363 ASSERT((attributes & READ_ONLY) == 0); |
7330 Handle<JSObject>::cast(holder)->SetElement(index, *value)-> | 7364 Handle<Object> result = |
7331 ToObjectUnchecked(); | 7365 SetElement(Handle<JSObject>::cast(holder), index, value); |
| 7366 if (result.is_null()) { |
| 7367 ASSERT(Top::has_pending_exception()); |
| 7368 return Failure::Exception(); |
| 7369 } |
7332 } | 7370 } |
7333 return *value; | 7371 return *value; |
7334 } | 7372 } |
7335 | 7373 |
7336 // Slow case: The property is not in a FixedArray context. | 7374 // Slow case: The property is not in a FixedArray context. |
7337 // It is either in an JSObject extension context or it was not found. | 7375 // It is either in an JSObject extension context or it was not found. |
7338 Handle<JSObject> context_ext; | 7376 Handle<JSObject> context_ext; |
7339 | 7377 |
7340 if (!holder.is_null()) { | 7378 if (!holder.is_null()) { |
7341 // The property exists in the extension context. | 7379 // The property exists in the extension context. |
7342 context_ext = Handle<JSObject>::cast(holder); | 7380 context_ext = Handle<JSObject>::cast(holder); |
7343 } else { | 7381 } else { |
7344 // The property was not found. It needs to be stored in the global context. | 7382 // The property was not found. It needs to be stored in the global context. |
7345 ASSERT(attributes == ABSENT); | 7383 ASSERT(attributes == ABSENT); |
7346 attributes = NONE; | 7384 attributes = NONE; |
7347 context_ext = Handle<JSObject>(Top::context()->global()); | 7385 context_ext = Handle<JSObject>(Top::context()->global()); |
7348 } | 7386 } |
7349 | 7387 |
7350 // Set the property, but ignore if read_only variable on the context | 7388 // Set the property, but ignore if read_only variable on the context |
7351 // extension object itself. | 7389 // extension object itself. |
7352 if ((attributes & READ_ONLY) == 0 || | 7390 if ((attributes & READ_ONLY) == 0 || |
7353 (context_ext->GetLocalPropertyAttribute(*name) == ABSENT)) { | 7391 (context_ext->GetLocalPropertyAttribute(*name) == ABSENT)) { |
7354 Handle<Object> set = SetProperty(context_ext, name, value, NONE); | 7392 Handle<Object> result = SetProperty(context_ext, name, value, NONE); |
7355 if (set.is_null()) { | 7393 if (result.is_null()) { |
7356 // Failure::Exception is converted to a null handle in the | 7394 // Failure::Exception is converted to a null handle in the |
7357 // handle-based methods such as SetProperty. We therefore need | 7395 // handle-based methods such as SetProperty. We therefore need |
7358 // to convert null handles back to exceptions. | 7396 // to convert null handles back to exceptions. |
7359 ASSERT(Top::has_pending_exception()); | 7397 ASSERT(Top::has_pending_exception()); |
7360 return Failure::Exception(); | 7398 return Failure::Exception(); |
7361 } | 7399 } |
7362 } | 7400 } |
7363 return *value; | 7401 return *value; |
7364 } | 7402 } |
7365 | 7403 |
(...skipping 3647 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11013 } else { | 11051 } else { |
11014 // Handle last resort GC and make sure to allow future allocations | 11052 // Handle last resort GC and make sure to allow future allocations |
11015 // to grow the heap without causing GCs (if possible). | 11053 // to grow the heap without causing GCs (if possible). |
11016 Counters::gc_last_resort_from_js.Increment(); | 11054 Counters::gc_last_resort_from_js.Increment(); |
11017 Heap::CollectAllGarbage(false); | 11055 Heap::CollectAllGarbage(false); |
11018 } | 11056 } |
11019 } | 11057 } |
11020 | 11058 |
11021 | 11059 |
11022 } } // namespace v8::internal | 11060 } } // namespace v8::internal |
OLD | NEW |