| OLD | NEW |
| 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 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 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 212 return *result; | 212 return *result; |
| 213 } | 213 } |
| 214 | 214 |
| 215 | 215 |
| 216 // Only deal with CALLBACKS and INTERCEPTOR | 216 // Only deal with CALLBACKS and INTERCEPTOR |
| 217 Object* JSObject::GetPropertyWithFailedAccessCheck( | 217 Object* JSObject::GetPropertyWithFailedAccessCheck( |
| 218 Object* receiver, | 218 Object* receiver, |
| 219 LookupResult* result, | 219 LookupResult* result, |
| 220 String* name, | 220 String* name, |
| 221 PropertyAttributes* attributes) { | 221 PropertyAttributes* attributes) { |
| 222 if (result->IsValid()) { | 222 if (result->IsProperty()) { |
| 223 switch (result->type()) { | 223 switch (result->type()) { |
| 224 case CALLBACKS: { | 224 case CALLBACKS: { |
| 225 // Only allow API accessors. | 225 // Only allow API accessors. |
| 226 Object* obj = result->GetCallbackObject(); | 226 Object* obj = result->GetCallbackObject(); |
| 227 if (obj->IsAccessorInfo()) { | 227 if (obj->IsAccessorInfo()) { |
| 228 AccessorInfo* info = AccessorInfo::cast(obj); | 228 AccessorInfo* info = AccessorInfo::cast(obj); |
| 229 if (info->all_can_read()) { | 229 if (info->all_can_read()) { |
| 230 *attributes = result->GetAttributes(); | 230 *attributes = result->GetAttributes(); |
| 231 return GetPropertyWithCallback(receiver, | 231 return GetPropertyWithCallback(receiver, |
| 232 result->GetCallbackObject(), | 232 result->GetCallbackObject(), |
| 233 name, | 233 name, |
| 234 result->holder()); | 234 result->holder()); |
| 235 } | 235 } |
| 236 } | 236 } |
| 237 break; | 237 break; |
| 238 } | 238 } |
| 239 case NORMAL: | 239 case NORMAL: |
| 240 case FIELD: | 240 case FIELD: |
| 241 case CONSTANT_FUNCTION: { | 241 case CONSTANT_FUNCTION: { |
| 242 // Search ALL_CAN_READ accessors in prototype chain. | 242 // Search ALL_CAN_READ accessors in prototype chain. |
| 243 LookupResult r; | 243 LookupResult r; |
| 244 result->holder()->LookupRealNamedPropertyInPrototypes(name, &r); | 244 result->holder()->LookupRealNamedPropertyInPrototypes(name, &r); |
| 245 if (r.IsValid()) { | 245 if (r.IsProperty()) { |
| 246 return GetPropertyWithFailedAccessCheck(receiver, | 246 return GetPropertyWithFailedAccessCheck(receiver, |
| 247 &r, | 247 &r, |
| 248 name, | 248 name, |
| 249 attributes); | 249 attributes); |
| 250 } | 250 } |
| 251 break; | 251 break; |
| 252 } | 252 } |
| 253 case INTERCEPTOR: { | 253 case INTERCEPTOR: { |
| 254 // If the object has an interceptor, try real named properties. | 254 // If the object has an interceptor, try real named properties. |
| 255 // No access check in GetPropertyAttributeWithInterceptor. | 255 // No access check in GetPropertyAttributeWithInterceptor. |
| 256 LookupResult r; | 256 LookupResult r; |
| 257 result->holder()->LookupRealNamedProperty(name, &r); | 257 result->holder()->LookupRealNamedProperty(name, &r); |
| 258 if (r.IsValid()) { | 258 if (r.IsProperty()) { |
| 259 return GetPropertyWithFailedAccessCheck(receiver, | 259 return GetPropertyWithFailedAccessCheck(receiver, |
| 260 &r, | 260 &r, |
| 261 name, | 261 name, |
| 262 attributes); | 262 attributes); |
| 263 } | 263 } |
| 264 } | |
| 265 default: { | |
| 266 break; | 264 break; |
| 267 } | 265 } |
| 266 default: |
| 267 UNREACHABLE(); |
| 268 } | 268 } |
| 269 } | 269 } |
| 270 | 270 |
| 271 // No accessible property found. | 271 // No accessible property found. |
| 272 *attributes = ABSENT; | 272 *attributes = ABSENT; |
| 273 Top::ReportFailedAccessCheck(this, v8::ACCESS_GET); | 273 Top::ReportFailedAccessCheck(this, v8::ACCESS_GET); |
| 274 return Heap::undefined_value(); | 274 return Heap::undefined_value(); |
| 275 } | 275 } |
| 276 | 276 |
| 277 | 277 |
| 278 PropertyAttributes JSObject::GetPropertyAttributeWithFailedAccessCheck( | 278 PropertyAttributes JSObject::GetPropertyAttributeWithFailedAccessCheck( |
| 279 Object* receiver, | 279 Object* receiver, |
| 280 LookupResult* result, | 280 LookupResult* result, |
| 281 String* name, | 281 String* name, |
| 282 bool continue_search) { | 282 bool continue_search) { |
| 283 if (result->IsValid()) { | 283 if (result->IsProperty()) { |
| 284 switch (result->type()) { | 284 switch (result->type()) { |
| 285 case CALLBACKS: { | 285 case CALLBACKS: { |
| 286 // Only allow API accessors. | 286 // Only allow API accessors. |
| 287 Object* obj = result->GetCallbackObject(); | 287 Object* obj = result->GetCallbackObject(); |
| 288 if (obj->IsAccessorInfo()) { | 288 if (obj->IsAccessorInfo()) { |
| 289 AccessorInfo* info = AccessorInfo::cast(obj); | 289 AccessorInfo* info = AccessorInfo::cast(obj); |
| 290 if (info->all_can_read()) { | 290 if (info->all_can_read()) { |
| 291 return result->GetAttributes(); | 291 return result->GetAttributes(); |
| 292 } | 292 } |
| 293 } | 293 } |
| 294 break; | 294 break; |
| 295 } | 295 } |
| 296 | 296 |
| 297 case NORMAL: | 297 case NORMAL: |
| 298 case FIELD: | 298 case FIELD: |
| 299 case CONSTANT_FUNCTION: { | 299 case CONSTANT_FUNCTION: { |
| 300 if (!continue_search) break; | 300 if (!continue_search) break; |
| 301 // Search ALL_CAN_READ accessors in prototype chain. | 301 // Search ALL_CAN_READ accessors in prototype chain. |
| 302 LookupResult r; | 302 LookupResult r; |
| 303 result->holder()->LookupRealNamedPropertyInPrototypes(name, &r); | 303 result->holder()->LookupRealNamedPropertyInPrototypes(name, &r); |
| 304 if (r.IsValid()) { | 304 if (r.IsProperty()) { |
| 305 return GetPropertyAttributeWithFailedAccessCheck(receiver, | 305 return GetPropertyAttributeWithFailedAccessCheck(receiver, |
| 306 &r, | 306 &r, |
| 307 name, | 307 name, |
| 308 continue_search); | 308 continue_search); |
| 309 } | 309 } |
| 310 break; | 310 break; |
| 311 } | 311 } |
| 312 | 312 |
| 313 case INTERCEPTOR: { | 313 case INTERCEPTOR: { |
| 314 // If the object has an interceptor, try real named properties. | 314 // If the object has an interceptor, try real named properties. |
| 315 // No access check in GetPropertyAttributeWithInterceptor. | 315 // No access check in GetPropertyAttributeWithInterceptor. |
| 316 LookupResult r; | 316 LookupResult r; |
| 317 if (continue_search) { | 317 if (continue_search) { |
| 318 result->holder()->LookupRealNamedProperty(name, &r); | 318 result->holder()->LookupRealNamedProperty(name, &r); |
| 319 } else { | 319 } else { |
| 320 result->holder()->LocalLookupRealNamedProperty(name, &r); | 320 result->holder()->LocalLookupRealNamedProperty(name, &r); |
| 321 } | 321 } |
| 322 if (r.IsValid()) { | 322 if (r.IsProperty()) { |
| 323 return GetPropertyAttributeWithFailedAccessCheck(receiver, | 323 return GetPropertyAttributeWithFailedAccessCheck(receiver, |
| 324 &r, | 324 &r, |
| 325 name, | 325 name, |
| 326 continue_search); | 326 continue_search); |
| 327 } | 327 } |
| 328 break; | 328 break; |
| 329 } | 329 } |
| 330 | 330 |
| 331 default: { | 331 default: |
| 332 break; | 332 UNREACHABLE(); |
| 333 } | |
| 334 } | 333 } |
| 335 } | 334 } |
| 336 | 335 |
| 337 Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS); | 336 Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS); |
| 338 return ABSENT; | 337 return ABSENT; |
| 339 } | 338 } |
| 340 | 339 |
| 341 | 340 |
| 342 Object* JSObject::GetNormalizedProperty(LookupResult* result) { | 341 Object* JSObject::GetNormalizedProperty(LookupResult* result) { |
| 343 ASSERT(!HasFastProperties()); | 342 ASSERT(!HasFastProperties()); |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 449 // Make sure that the top context does not change when doing | 448 // Make sure that the top context does not change when doing |
| 450 // callbacks or interceptor calls. | 449 // callbacks or interceptor calls. |
| 451 AssertNoContextChange ncc; | 450 AssertNoContextChange ncc; |
| 452 | 451 |
| 453 // Traverse the prototype chain from the current object (this) to | 452 // Traverse the prototype chain from the current object (this) to |
| 454 // the holder and check for access rights. This avoid traversing the | 453 // the holder and check for access rights. This avoid traversing the |
| 455 // objects more than once in case of interceptors, because the | 454 // objects more than once in case of interceptors, because the |
| 456 // holder will always be the interceptor holder and the search may | 455 // holder will always be the interceptor holder and the search may |
| 457 // only continue with a current object just after the interceptor | 456 // only continue with a current object just after the interceptor |
| 458 // holder in the prototype chain. | 457 // holder in the prototype chain. |
| 459 Object* last = result->IsValid() ? result->holder() : Heap::null_value(); | 458 Object* last = result->IsProperty() ? result->holder() : Heap::null_value(); |
| 460 for (Object* current = this; true; current = current->GetPrototype()) { | 459 for (Object* current = this; true; current = current->GetPrototype()) { |
| 461 if (current->IsAccessCheckNeeded()) { | 460 if (current->IsAccessCheckNeeded()) { |
| 462 // Check if we're allowed to read from the current object. Note | 461 // Check if we're allowed to read from the current object. Note |
| 463 // that even though we may not actually end up loading the named | 462 // that even though we may not actually end up loading the named |
| 464 // property from the current object, we still check that we have | 463 // property from the current object, we still check that we have |
| 465 // access to it. | 464 // access to it. |
| 466 JSObject* checked = JSObject::cast(current); | 465 JSObject* checked = JSObject::cast(current); |
| 467 if (!Top::MayNamedAccess(checked, name, v8::ACCESS_GET)) { | 466 if (!Top::MayNamedAccess(checked, name, v8::ACCESS_GET)) { |
| 468 return checked->GetPropertyWithFailedAccessCheck(receiver, | 467 return checked->GetPropertyWithFailedAccessCheck(receiver, |
| 469 result, | 468 result, |
| (...skipping 931 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1401 return AddSlowProperty(name, value, attributes); | 1400 return AddSlowProperty(name, value, attributes); |
| 1402 } | 1401 } |
| 1403 | 1402 |
| 1404 | 1403 |
| 1405 Object* JSObject::SetPropertyPostInterceptor(String* name, | 1404 Object* JSObject::SetPropertyPostInterceptor(String* name, |
| 1406 Object* value, | 1405 Object* value, |
| 1407 PropertyAttributes attributes) { | 1406 PropertyAttributes attributes) { |
| 1408 // Check local property, ignore interceptor. | 1407 // Check local property, ignore interceptor. |
| 1409 LookupResult result; | 1408 LookupResult result; |
| 1410 LocalLookupRealNamedProperty(name, &result); | 1409 LocalLookupRealNamedProperty(name, &result); |
| 1411 if (result.IsValid()) return SetProperty(&result, name, value, attributes); | 1410 if (result.IsFound()) { |
| 1412 // Add real property. | 1411 // An existing property, a map transition or a null descriptor was |
| 1412 // found. Use set property to handle all these cases. |
| 1413 return SetProperty(&result, name, value, attributes); |
| 1414 } |
| 1415 // Add a new real property. |
| 1413 return AddProperty(name, value, attributes); | 1416 return AddProperty(name, value, attributes); |
| 1414 } | 1417 } |
| 1415 | 1418 |
| 1416 | 1419 |
| 1417 Object* JSObject::ReplaceSlowProperty(String* name, | 1420 Object* JSObject::ReplaceSlowProperty(String* name, |
| 1418 Object* value, | 1421 Object* value, |
| 1419 PropertyAttributes attributes) { | 1422 PropertyAttributes attributes) { |
| 1420 StringDictionary* dictionary = property_dictionary(); | 1423 StringDictionary* dictionary = property_dictionary(); |
| 1421 int old_index = dictionary->FindEntry(name); | 1424 int old_index = dictionary->FindEntry(name); |
| 1422 int new_enumeration_index = 0; // 0 means "Use the next available index." | 1425 int new_enumeration_index = 0; // 0 means "Use the next available index." |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1634 return *value_handle; | 1637 return *value_handle; |
| 1635 } | 1638 } |
| 1636 | 1639 |
| 1637 | 1640 |
| 1638 void JSObject::LookupCallbackSetterInPrototypes(String* name, | 1641 void JSObject::LookupCallbackSetterInPrototypes(String* name, |
| 1639 LookupResult* result) { | 1642 LookupResult* result) { |
| 1640 for (Object* pt = GetPrototype(); | 1643 for (Object* pt = GetPrototype(); |
| 1641 pt != Heap::null_value(); | 1644 pt != Heap::null_value(); |
| 1642 pt = pt->GetPrototype()) { | 1645 pt = pt->GetPrototype()) { |
| 1643 JSObject::cast(pt)->LocalLookupRealNamedProperty(name, result); | 1646 JSObject::cast(pt)->LocalLookupRealNamedProperty(name, result); |
| 1644 if (result->IsValid()) { | 1647 if (result->IsProperty()) { |
| 1645 if (!result->IsTransitionType() && result->IsReadOnly()) { | 1648 if (result->IsReadOnly()) { |
| 1646 result->NotFound(); | 1649 result->NotFound(); |
| 1647 return; | 1650 return; |
| 1648 } | 1651 } |
| 1649 if (result->type() == CALLBACKS) { | 1652 if (result->type() == CALLBACKS) { |
| 1650 return; | 1653 return; |
| 1651 } | 1654 } |
| 1652 } | 1655 } |
| 1653 } | 1656 } |
| 1654 result->NotFound(); | 1657 result->NotFound(); |
| 1655 } | 1658 } |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1696 LookupResult* result) { | 1699 LookupResult* result) { |
| 1697 if (IsJSGlobalProxy()) { | 1700 if (IsJSGlobalProxy()) { |
| 1698 Object* proto = GetPrototype(); | 1701 Object* proto = GetPrototype(); |
| 1699 if (proto->IsNull()) return result->NotFound(); | 1702 if (proto->IsNull()) return result->NotFound(); |
| 1700 ASSERT(proto->IsJSGlobalObject()); | 1703 ASSERT(proto->IsJSGlobalObject()); |
| 1701 return JSObject::cast(proto)->LocalLookupRealNamedProperty(name, result); | 1704 return JSObject::cast(proto)->LocalLookupRealNamedProperty(name, result); |
| 1702 } | 1705 } |
| 1703 | 1706 |
| 1704 if (HasFastProperties()) { | 1707 if (HasFastProperties()) { |
| 1705 LookupInDescriptor(name, result); | 1708 LookupInDescriptor(name, result); |
| 1706 if (result->IsValid()) { | 1709 if (result->IsFound()) { |
| 1710 // A property, a map transition or a null descriptor was found. |
| 1711 // We return all of these result types because |
| 1712 // LocalLookupRealNamedProperty is used when setting properties |
| 1713 // where map transitions and null descriptors are handled. |
| 1707 ASSERT(result->holder() == this && result->type() != NORMAL); | 1714 ASSERT(result->holder() == this && result->type() != NORMAL); |
| 1708 // Disallow caching for uninitialized constants. These can only | 1715 // Disallow caching for uninitialized constants. These can only |
| 1709 // occur as fields. | 1716 // occur as fields. |
| 1710 if (result->IsReadOnly() && result->type() == FIELD && | 1717 if (result->IsReadOnly() && result->type() == FIELD && |
| 1711 FastPropertyAt(result->GetFieldIndex())->IsTheHole()) { | 1718 FastPropertyAt(result->GetFieldIndex())->IsTheHole()) { |
| 1712 result->DisallowCaching(); | 1719 result->DisallowCaching(); |
| 1713 } | 1720 } |
| 1714 return; | 1721 return; |
| 1715 } | 1722 } |
| 1716 } else { | 1723 } else { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1745 LookupRealNamedPropertyInPrototypes(name, result); | 1752 LookupRealNamedPropertyInPrototypes(name, result); |
| 1746 } | 1753 } |
| 1747 | 1754 |
| 1748 | 1755 |
| 1749 void JSObject::LookupRealNamedPropertyInPrototypes(String* name, | 1756 void JSObject::LookupRealNamedPropertyInPrototypes(String* name, |
| 1750 LookupResult* result) { | 1757 LookupResult* result) { |
| 1751 for (Object* pt = GetPrototype(); | 1758 for (Object* pt = GetPrototype(); |
| 1752 pt != Heap::null_value(); | 1759 pt != Heap::null_value(); |
| 1753 pt = JSObject::cast(pt)->GetPrototype()) { | 1760 pt = JSObject::cast(pt)->GetPrototype()) { |
| 1754 JSObject::cast(pt)->LocalLookupRealNamedProperty(name, result); | 1761 JSObject::cast(pt)->LocalLookupRealNamedProperty(name, result); |
| 1755 if (result->IsValid()) { | 1762 if (result->IsProperty() && (result->type() != INTERCEPTOR)) return; |
| 1756 switch (result->type()) { | |
| 1757 case NORMAL: | |
| 1758 case FIELD: | |
| 1759 case CONSTANT_FUNCTION: | |
| 1760 case CALLBACKS: | |
| 1761 return; | |
| 1762 default: break; | |
| 1763 } | |
| 1764 } | |
| 1765 } | 1763 } |
| 1766 result->NotFound(); | 1764 result->NotFound(); |
| 1767 } | 1765 } |
| 1768 | 1766 |
| 1769 | 1767 |
| 1770 // We only need to deal with CALLBACKS and INTERCEPTORS | 1768 // We only need to deal with CALLBACKS and INTERCEPTORS |
| 1771 Object* JSObject::SetPropertyWithFailedAccessCheck(LookupResult* result, | 1769 Object* JSObject::SetPropertyWithFailedAccessCheck(LookupResult* result, |
| 1772 String* name, | 1770 String* name, |
| 1773 Object* value) { | 1771 Object* value) { |
| 1774 if (!result->IsProperty()) { | 1772 if (!result->IsProperty()) { |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1840 if (proto->IsNull()) return value; | 1838 if (proto->IsNull()) return value; |
| 1841 ASSERT(proto->IsJSGlobalObject()); | 1839 ASSERT(proto->IsJSGlobalObject()); |
| 1842 return JSObject::cast(proto)->SetProperty(result, name, value, attributes); | 1840 return JSObject::cast(proto)->SetProperty(result, name, value, attributes); |
| 1843 } | 1841 } |
| 1844 | 1842 |
| 1845 if (!result->IsProperty() && !IsJSContextExtensionObject()) { | 1843 if (!result->IsProperty() && !IsJSContextExtensionObject()) { |
| 1846 // We could not find a local property so let's check whether there is an | 1844 // We could not find a local property so let's check whether there is an |
| 1847 // accessor that wants to handle the property. | 1845 // accessor that wants to handle the property. |
| 1848 LookupResult accessor_result; | 1846 LookupResult accessor_result; |
| 1849 LookupCallbackSetterInPrototypes(name, &accessor_result); | 1847 LookupCallbackSetterInPrototypes(name, &accessor_result); |
| 1850 if (accessor_result.IsValid()) { | 1848 if (accessor_result.IsProperty()) { |
| 1851 return SetPropertyWithCallback(accessor_result.GetCallbackObject(), | 1849 return SetPropertyWithCallback(accessor_result.GetCallbackObject(), |
| 1852 name, | 1850 name, |
| 1853 value, | 1851 value, |
| 1854 accessor_result.holder()); | 1852 accessor_result.holder()); |
| 1855 } | 1853 } |
| 1856 } | 1854 } |
| 1857 if (result->IsNotFound()) { | 1855 if (!result->IsFound()) { |
| 1856 // Neither properties nor transitions found. |
| 1858 return AddProperty(name, value, attributes); | 1857 return AddProperty(name, value, attributes); |
| 1859 } | 1858 } |
| 1860 if (result->IsReadOnly() && result->IsProperty()) return value; | 1859 if (result->IsReadOnly() && result->IsProperty()) return value; |
| 1861 // This is a real property that is not read-only, or it is a | 1860 // This is a real property that is not read-only, or it is a |
| 1862 // transition or null descriptor and there are no setters in the prototypes. | 1861 // transition or null descriptor and there are no setters in the prototypes. |
| 1863 switch (result->type()) { | 1862 switch (result->type()) { |
| 1864 case NORMAL: | 1863 case NORMAL: |
| 1865 return SetNormalizedProperty(result, value); | 1864 return SetNormalizedProperty(result, value); |
| 1866 case FIELD: | 1865 case FIELD: |
| 1867 return FastPropertyAtPut(result->GetFieldIndex(), value); | 1866 return FastPropertyAtPut(result->GetFieldIndex(), value); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1906 // callback setter removed. The two lines looking up the LookupResult | 1905 // callback setter removed. The two lines looking up the LookupResult |
| 1907 // result are also added. If one of the functions is changed, the other | 1906 // result are also added. If one of the functions is changed, the other |
| 1908 // should be. | 1907 // should be. |
| 1909 Object* JSObject::IgnoreAttributesAndSetLocalProperty( | 1908 Object* JSObject::IgnoreAttributesAndSetLocalProperty( |
| 1910 String* name, | 1909 String* name, |
| 1911 Object* value, | 1910 Object* value, |
| 1912 PropertyAttributes attributes) { | 1911 PropertyAttributes attributes) { |
| 1913 // Make sure that the top context does not change when doing callbacks or | 1912 // Make sure that the top context does not change when doing callbacks or |
| 1914 // interceptor calls. | 1913 // interceptor calls. |
| 1915 AssertNoContextChange ncc; | 1914 AssertNoContextChange ncc; |
| 1916 // ADDED TO CLONE | 1915 LookupResult result; |
| 1917 LookupResult result_struct; | 1916 LocalLookup(name, &result); |
| 1918 LocalLookup(name, &result_struct); | |
| 1919 LookupResult* result = &result_struct; | |
| 1920 // END ADDED TO CLONE | |
| 1921 // Check access rights if needed. | 1917 // Check access rights if needed. |
| 1922 if (IsAccessCheckNeeded() | 1918 if (IsAccessCheckNeeded() |
| 1923 && !Top::MayNamedAccess(this, name, v8::ACCESS_SET)) { | 1919 && !Top::MayNamedAccess(this, name, v8::ACCESS_SET)) { |
| 1924 return SetPropertyWithFailedAccessCheck(result, name, value); | 1920 return SetPropertyWithFailedAccessCheck(&result, name, value); |
| 1925 } | 1921 } |
| 1926 | 1922 |
| 1927 if (IsJSGlobalProxy()) { | 1923 if (IsJSGlobalProxy()) { |
| 1928 Object* proto = GetPrototype(); | 1924 Object* proto = GetPrototype(); |
| 1929 if (proto->IsNull()) return value; | 1925 if (proto->IsNull()) return value; |
| 1930 ASSERT(proto->IsJSGlobalObject()); | 1926 ASSERT(proto->IsJSGlobalObject()); |
| 1931 return JSObject::cast(proto)->IgnoreAttributesAndSetLocalProperty( | 1927 return JSObject::cast(proto)->IgnoreAttributesAndSetLocalProperty( |
| 1932 name, | 1928 name, |
| 1933 value, | 1929 value, |
| 1934 attributes); | 1930 attributes); |
| 1935 } | 1931 } |
| 1936 | 1932 |
| 1937 // Check for accessor in prototype chain removed here in clone. | 1933 // Check for accessor in prototype chain removed here in clone. |
| 1938 if (result->IsNotFound()) { | 1934 if (!result.IsFound()) { |
| 1935 // Neither properties nor transitions found. |
| 1939 return AddProperty(name, value, attributes); | 1936 return AddProperty(name, value, attributes); |
| 1940 } | 1937 } |
| 1938 PropertyDetails details = PropertyDetails(attributes, NORMAL); |
| 1939 |
| 1941 // Check of IsReadOnly removed from here in clone. | 1940 // Check of IsReadOnly removed from here in clone. |
| 1942 switch (result->type()) { | 1941 switch (result.type()) { |
| 1943 case NORMAL: | 1942 case NORMAL: |
| 1944 return SetNormalizedProperty(result, value); | 1943 return SetNormalizedProperty(name, value, details); |
| 1945 case FIELD: | 1944 case FIELD: |
| 1946 return FastPropertyAtPut(result->GetFieldIndex(), value); | 1945 return FastPropertyAtPut(result.GetFieldIndex(), value); |
| 1947 case MAP_TRANSITION: | 1946 case MAP_TRANSITION: |
| 1948 if (attributes == result->GetAttributes()) { | 1947 if (attributes == result.GetAttributes()) { |
| 1949 // Only use map transition if the attributes match. | 1948 // Only use map transition if the attributes match. |
| 1950 return AddFastPropertyUsingMap(result->GetTransitionMap(), | 1949 return AddFastPropertyUsingMap(result.GetTransitionMap(), |
| 1951 name, | 1950 name, |
| 1952 value); | 1951 value); |
| 1953 } | 1952 } |
| 1954 return ConvertDescriptorToField(name, value, attributes); | 1953 return ConvertDescriptorToField(name, value, attributes); |
| 1955 case CONSTANT_FUNCTION: | 1954 case CONSTANT_FUNCTION: |
| 1956 // Only replace the function if necessary. | 1955 // Only replace the function if necessary. |
| 1957 if (value == result->GetConstantFunction()) return value; | 1956 if (value == result.GetConstantFunction()) return value; |
| 1958 // Preserve the attributes of this existing property. | 1957 // Preserve the attributes of this existing property. |
| 1959 attributes = result->GetAttributes(); | 1958 attributes = result.GetAttributes(); |
| 1960 return ConvertDescriptorToField(name, value, attributes); | 1959 return ConvertDescriptorToField(name, value, attributes); |
| 1961 case CALLBACKS: | 1960 case CALLBACKS: |
| 1962 case INTERCEPTOR: | 1961 case INTERCEPTOR: |
| 1963 // Override callback in clone | 1962 // Override callback in clone |
| 1964 return ConvertDescriptorToField(name, value, attributes); | 1963 return ConvertDescriptorToField(name, value, attributes); |
| 1965 case CONSTANT_TRANSITION: | 1964 case CONSTANT_TRANSITION: |
| 1966 // Replace with a MAP_TRANSITION to a new map with a FIELD, even | 1965 // Replace with a MAP_TRANSITION to a new map with a FIELD, even |
| 1967 // if the value is a function. | 1966 // if the value is a function. |
| 1968 return ConvertDescriptorToFieldAndMapTransition(name, value, attributes); | 1967 return ConvertDescriptorToFieldAndMapTransition(name, value, attributes); |
| 1969 case NULL_DESCRIPTOR: | 1968 case NULL_DESCRIPTOR: |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2065 String* name, | 2064 String* name, |
| 2066 bool continue_search) { | 2065 bool continue_search) { |
| 2067 // Check access rights if needed. | 2066 // Check access rights if needed. |
| 2068 if (IsAccessCheckNeeded() && | 2067 if (IsAccessCheckNeeded() && |
| 2069 !Top::MayNamedAccess(this, name, v8::ACCESS_HAS)) { | 2068 !Top::MayNamedAccess(this, name, v8::ACCESS_HAS)) { |
| 2070 return GetPropertyAttributeWithFailedAccessCheck(receiver, | 2069 return GetPropertyAttributeWithFailedAccessCheck(receiver, |
| 2071 result, | 2070 result, |
| 2072 name, | 2071 name, |
| 2073 continue_search); | 2072 continue_search); |
| 2074 } | 2073 } |
| 2075 if (result->IsValid()) { | 2074 if (result->IsProperty()) { |
| 2076 switch (result->type()) { | 2075 switch (result->type()) { |
| 2077 case NORMAL: // fall through | 2076 case NORMAL: // fall through |
| 2078 case FIELD: | 2077 case FIELD: |
| 2079 case CONSTANT_FUNCTION: | 2078 case CONSTANT_FUNCTION: |
| 2080 case CALLBACKS: | 2079 case CALLBACKS: |
| 2081 return result->GetAttributes(); | 2080 return result->GetAttributes(); |
| 2082 case INTERCEPTOR: | 2081 case INTERCEPTOR: |
| 2083 return result->holder()-> | 2082 return result->holder()-> |
| 2084 GetPropertyAttributeWithInterceptor(receiver, name, continue_search); | 2083 GetPropertyAttributeWithInterceptor(receiver, name, continue_search); |
| 2085 case MAP_TRANSITION: | |
| 2086 case CONSTANT_TRANSITION: | |
| 2087 case NULL_DESCRIPTOR: | |
| 2088 return ABSENT; | |
| 2089 default: | 2084 default: |
| 2090 UNREACHABLE(); | 2085 UNREACHABLE(); |
| 2091 break; | |
| 2092 } | 2086 } |
| 2093 } | 2087 } |
| 2094 return ABSENT; | 2088 return ABSENT; |
| 2095 } | 2089 } |
| 2096 | 2090 |
| 2097 | 2091 |
| 2098 PropertyAttributes JSObject::GetLocalPropertyAttribute(String* name) { | 2092 PropertyAttributes JSObject::GetLocalPropertyAttribute(String* name) { |
| 2099 // Check whether the name is an array index. | 2093 // Check whether the name is an array index. |
| 2100 uint32_t index = 0; | 2094 uint32_t index = 0; |
| 2101 if (name->AsArrayIndex(&index)) { | 2095 if (name->AsArrayIndex(&index)) { |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2254 #endif | 2248 #endif |
| 2255 | 2249 |
| 2256 return this; | 2250 return this; |
| 2257 } | 2251 } |
| 2258 | 2252 |
| 2259 | 2253 |
| 2260 Object* JSObject::DeletePropertyPostInterceptor(String* name, DeleteMode mode) { | 2254 Object* JSObject::DeletePropertyPostInterceptor(String* name, DeleteMode mode) { |
| 2261 // Check local property, ignore interceptor. | 2255 // Check local property, ignore interceptor. |
| 2262 LookupResult result; | 2256 LookupResult result; |
| 2263 LocalLookupRealNamedProperty(name, &result); | 2257 LocalLookupRealNamedProperty(name, &result); |
| 2264 if (!result.IsValid()) return Heap::true_value(); | 2258 if (!result.IsProperty()) return Heap::true_value(); |
| 2265 | 2259 |
| 2266 // Normalize object if needed. | 2260 // Normalize object if needed. |
| 2267 Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); | 2261 Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); |
| 2268 if (obj->IsFailure()) return obj; | 2262 if (obj->IsFailure()) return obj; |
| 2269 | 2263 |
| 2270 return DeleteNormalizedProperty(name, mode); | 2264 return DeleteNormalizedProperty(name, mode); |
| 2271 } | 2265 } |
| 2272 | 2266 |
| 2273 | 2267 |
| 2274 Object* JSObject::DeletePropertyWithInterceptor(String* name) { | 2268 Object* JSObject::DeletePropertyWithInterceptor(String* name) { |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2438 ASSERT(proto->IsJSGlobalObject()); | 2432 ASSERT(proto->IsJSGlobalObject()); |
| 2439 return JSGlobalObject::cast(proto)->DeleteProperty(name, mode); | 2433 return JSGlobalObject::cast(proto)->DeleteProperty(name, mode); |
| 2440 } | 2434 } |
| 2441 | 2435 |
| 2442 uint32_t index = 0; | 2436 uint32_t index = 0; |
| 2443 if (name->AsArrayIndex(&index)) { | 2437 if (name->AsArrayIndex(&index)) { |
| 2444 return DeleteElement(index, mode); | 2438 return DeleteElement(index, mode); |
| 2445 } else { | 2439 } else { |
| 2446 LookupResult result; | 2440 LookupResult result; |
| 2447 LocalLookup(name, &result); | 2441 LocalLookup(name, &result); |
| 2448 if (!result.IsValid()) return Heap::true_value(); | 2442 if (!result.IsProperty()) return Heap::true_value(); |
| 2449 // Ignore attributes if forcing a deletion. | 2443 // Ignore attributes if forcing a deletion. |
| 2450 if (result.IsDontDelete() && mode != FORCE_DELETION) { | 2444 if (result.IsDontDelete() && mode != FORCE_DELETION) { |
| 2451 return Heap::false_value(); | 2445 return Heap::false_value(); |
| 2452 } | 2446 } |
| 2453 // Check for interceptor. | 2447 // Check for interceptor. |
| 2454 if (result.type() == INTERCEPTOR) { | 2448 if (result.type() == INTERCEPTOR) { |
| 2455 // Skip interceptor if forcing a deletion. | 2449 // Skip interceptor if forcing a deletion. |
| 2456 if (mode == FORCE_DELETION) { | 2450 if (mode == FORCE_DELETION) { |
| 2457 return DeletePropertyPostInterceptor(name, mode); | 2451 return DeletePropertyPostInterceptor(name, mode); |
| 2458 } | 2452 } |
| (...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2668 LocalLookupRealNamedProperty(name, result); | 2662 LocalLookupRealNamedProperty(name, result); |
| 2669 } | 2663 } |
| 2670 | 2664 |
| 2671 | 2665 |
| 2672 void JSObject::Lookup(String* name, LookupResult* result) { | 2666 void JSObject::Lookup(String* name, LookupResult* result) { |
| 2673 // Ecma-262 3rd 8.6.2.4 | 2667 // Ecma-262 3rd 8.6.2.4 |
| 2674 for (Object* current = this; | 2668 for (Object* current = this; |
| 2675 current != Heap::null_value(); | 2669 current != Heap::null_value(); |
| 2676 current = JSObject::cast(current)->GetPrototype()) { | 2670 current = JSObject::cast(current)->GetPrototype()) { |
| 2677 JSObject::cast(current)->LocalLookup(name, result); | 2671 JSObject::cast(current)->LocalLookup(name, result); |
| 2678 if (result->IsValid() && !result->IsTransitionType()) return; | 2672 if (result->IsProperty()) return; |
| 2679 } | 2673 } |
| 2680 result->NotFound(); | 2674 result->NotFound(); |
| 2681 } | 2675 } |
| 2682 | 2676 |
| 2683 | 2677 |
| 2684 // Search object and it's prototype chain for callback properties. | 2678 // Search object and it's prototype chain for callback properties. |
| 2685 void JSObject::LookupCallback(String* name, LookupResult* result) { | 2679 void JSObject::LookupCallback(String* name, LookupResult* result) { |
| 2686 for (Object* current = this; | 2680 for (Object* current = this; |
| 2687 current != Heap::null_value(); | 2681 current != Heap::null_value(); |
| 2688 current = JSObject::cast(current)->GetPrototype()) { | 2682 current = JSObject::cast(current)->GetPrototype()) { |
| 2689 JSObject::cast(current)->LocalLookupRealNamedProperty(name, result); | 2683 JSObject::cast(current)->LocalLookupRealNamedProperty(name, result); |
| 2690 if (result->IsValid() && result->type() == CALLBACKS) return; | 2684 if (result->IsProperty() && result->type() == CALLBACKS) return; |
| 2691 } | 2685 } |
| 2692 result->NotFound(); | 2686 result->NotFound(); |
| 2693 } | 2687 } |
| 2694 | 2688 |
| 2695 | 2689 |
| 2696 Object* JSObject::DefineGetterSetter(String* name, | 2690 Object* JSObject::DefineGetterSetter(String* name, |
| 2697 PropertyAttributes attributes) { | 2691 PropertyAttributes attributes) { |
| 2698 // Make sure that the top context does not change when doing callbacks or | 2692 // Make sure that the top context does not change when doing callbacks or |
| 2699 // interceptor calls. | 2693 // interceptor calls. |
| 2700 AssertNoContextChange ncc; | 2694 AssertNoContextChange ncc; |
| 2701 | 2695 |
| 2702 // Check access rights if needed. | 2696 // Check access rights if needed. |
| 2703 if (IsAccessCheckNeeded() && | 2697 if (IsAccessCheckNeeded() && |
| 2704 !Top::MayNamedAccess(this, name, v8::ACCESS_SET)) { | 2698 !Top::MayNamedAccess(this, name, v8::ACCESS_SET)) { |
| 2705 Top::ReportFailedAccessCheck(this, v8::ACCESS_SET); | 2699 Top::ReportFailedAccessCheck(this, v8::ACCESS_SET); |
| 2706 return Heap::undefined_value(); | 2700 return Heap::undefined_value(); |
| 2707 } | 2701 } |
| 2708 | 2702 |
| 2709 // Try to flatten before operating on the string. | 2703 // Try to flatten before operating on the string. |
| 2710 name->TryFlattenIfNotFlat(); | 2704 name->TryFlattenIfNotFlat(); |
| 2711 | 2705 |
| 2712 // Check if there is an API defined callback object which prohibits | 2706 // Check if there is an API defined callback object which prohibits |
| 2713 // callback overwriting in this object or it's prototype chain. | 2707 // callback overwriting in this object or it's prototype chain. |
| 2714 // This mechanism is needed for instance in a browser setting, where | 2708 // This mechanism is needed for instance in a browser setting, where |
| 2715 // certain accessors such as window.location should not be allowed | 2709 // certain accessors such as window.location should not be allowed |
| 2716 // to be overwritten because allowing overwriting could potentially | 2710 // to be overwritten because allowing overwriting could potentially |
| 2717 // cause security problems. | 2711 // cause security problems. |
| 2718 LookupResult callback_result; | 2712 LookupResult callback_result; |
| 2719 LookupCallback(name, &callback_result); | 2713 LookupCallback(name, &callback_result); |
| 2720 if (callback_result.IsValid()) { | 2714 if (callback_result.IsFound()) { |
| 2721 Object* obj = callback_result.GetCallbackObject(); | 2715 Object* obj = callback_result.GetCallbackObject(); |
| 2722 if (obj->IsAccessorInfo() && | 2716 if (obj->IsAccessorInfo() && |
| 2723 AccessorInfo::cast(obj)->prohibits_overwriting()) { | 2717 AccessorInfo::cast(obj)->prohibits_overwriting()) { |
| 2724 return Heap::undefined_value(); | 2718 return Heap::undefined_value(); |
| 2725 } | 2719 } |
| 2726 } | 2720 } |
| 2727 | 2721 |
| 2728 uint32_t index; | 2722 uint32_t index; |
| 2729 bool is_element = name->AsArrayIndex(&index); | 2723 bool is_element = name->AsArrayIndex(&index); |
| 2730 if (is_element && IsJSArray()) return Heap::undefined_value(); | 2724 if (is_element && IsJSArray()) return Heap::undefined_value(); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 2761 break; | 2755 break; |
| 2762 } | 2756 } |
| 2763 default: | 2757 default: |
| 2764 UNREACHABLE(); | 2758 UNREACHABLE(); |
| 2765 break; | 2759 break; |
| 2766 } | 2760 } |
| 2767 } else { | 2761 } else { |
| 2768 // Lookup the name. | 2762 // Lookup the name. |
| 2769 LookupResult result; | 2763 LookupResult result; |
| 2770 LocalLookup(name, &result); | 2764 LocalLookup(name, &result); |
| 2771 if (result.IsValid()) { | 2765 if (result.IsProperty()) { |
| 2772 if (result.IsReadOnly()) return Heap::undefined_value(); | 2766 if (result.IsReadOnly()) return Heap::undefined_value(); |
| 2773 if (result.type() == CALLBACKS) { | 2767 if (result.type() == CALLBACKS) { |
| 2774 Object* obj = result.GetCallbackObject(); | 2768 Object* obj = result.GetCallbackObject(); |
| 2775 if (obj->IsFixedArray()) { | 2769 if (obj->IsFixedArray()) { |
| 2770 // The object might be in fast mode even though it has |
| 2771 // a getter/setter. |
| 2772 Object* ok = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); |
| 2773 if (ok->IsFailure()) return ok; |
| 2774 |
| 2776 PropertyDetails details = PropertyDetails(attributes, CALLBACKS); | 2775 PropertyDetails details = PropertyDetails(attributes, CALLBACKS); |
| 2777 SetNormalizedProperty(name, obj, details); | 2776 SetNormalizedProperty(name, obj, details); |
| 2778 return obj; | 2777 return obj; |
| 2779 } | 2778 } |
| 2780 } | 2779 } |
| 2781 } | 2780 } |
| 2782 } | 2781 } |
| 2783 | 2782 |
| 2784 // Allocate the fixed array to hold getter and setter. | 2783 // Allocate the fixed array to hold getter and setter. |
| 2785 Object* structure = Heap::AllocateFixedArray(2, TENURED); | 2784 Object* structure = Heap::AllocateFixedArray(2, TENURED); |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2878 } | 2877 } |
| 2879 } | 2878 } |
| 2880 } | 2879 } |
| 2881 } | 2880 } |
| 2882 } else { | 2881 } else { |
| 2883 for (Object* obj = this; | 2882 for (Object* obj = this; |
| 2884 obj != Heap::null_value(); | 2883 obj != Heap::null_value(); |
| 2885 obj = JSObject::cast(obj)->GetPrototype()) { | 2884 obj = JSObject::cast(obj)->GetPrototype()) { |
| 2886 LookupResult result; | 2885 LookupResult result; |
| 2887 JSObject::cast(obj)->LocalLookup(name, &result); | 2886 JSObject::cast(obj)->LocalLookup(name, &result); |
| 2888 if (result.IsValid()) { | 2887 if (result.IsProperty()) { |
| 2889 if (result.IsReadOnly()) return Heap::undefined_value(); | 2888 if (result.IsReadOnly()) return Heap::undefined_value(); |
| 2890 if (result.type() == CALLBACKS) { | 2889 if (result.type() == CALLBACKS) { |
| 2891 Object* obj = result.GetCallbackObject(); | 2890 Object* obj = result.GetCallbackObject(); |
| 2892 if (obj->IsFixedArray()) { | 2891 if (obj->IsFixedArray()) { |
| 2893 return FixedArray::cast(obj)->get(accessor_index); | 2892 return FixedArray::cast(obj)->get(accessor_index); |
| 2894 } | 2893 } |
| 2895 } | 2894 } |
| 2896 } | 2895 } |
| 2897 } | 2896 } |
| 2898 } | 2897 } |
| (...skipping 1847 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4746 } | 4745 } |
| 4747 return instance_size; | 4746 return instance_size; |
| 4748 } | 4747 } |
| 4749 | 4748 |
| 4750 | 4749 |
| 4751 int SharedFunctionInfo::CalculateInObjectProperties() { | 4750 int SharedFunctionInfo::CalculateInObjectProperties() { |
| 4752 return (CalculateInstanceSize() - JSObject::kHeaderSize) / kPointerSize; | 4751 return (CalculateInstanceSize() - JSObject::kHeaderSize) / kPointerSize; |
| 4753 } | 4752 } |
| 4754 | 4753 |
| 4755 | 4754 |
| 4755 bool SharedFunctionInfo::CanGenerateInlineConstructor(Object* prototype) { |
| 4756 // Check the basic conditions for generating inline constructor code. |
| 4757 if (!FLAG_inline_new |
| 4758 || !has_only_simple_this_property_assignments() |
| 4759 || this_property_assignments_count() == 0) { |
| 4760 return false; |
| 4761 } |
| 4762 |
| 4763 // If the prototype is null inline constructors cause no problems. |
| 4764 if (!prototype->IsJSObject()) { |
| 4765 ASSERT(prototype->IsNull()); |
| 4766 return true; |
| 4767 } |
| 4768 |
| 4769 // Traverse the proposed prototype chain looking for setters for properties of |
| 4770 // the same names as are set by the inline constructor. |
| 4771 for (Object* obj = prototype; |
| 4772 obj != Heap::null_value(); |
| 4773 obj = obj->GetPrototype()) { |
| 4774 JSObject* js_object = JSObject::cast(obj); |
| 4775 for (int i = 0; i < this_property_assignments_count(); i++) { |
| 4776 LookupResult result; |
| 4777 String* name = GetThisPropertyAssignmentName(i); |
| 4778 js_object->LocalLookupRealNamedProperty(name, &result); |
| 4779 if (result.IsProperty() && result.type() == CALLBACKS) { |
| 4780 return false; |
| 4781 } |
| 4782 } |
| 4783 } |
| 4784 |
| 4785 return true; |
| 4786 } |
| 4787 |
| 4788 |
| 4756 void SharedFunctionInfo::SetThisPropertyAssignmentsInfo( | 4789 void SharedFunctionInfo::SetThisPropertyAssignmentsInfo( |
| 4757 bool only_simple_this_property_assignments, | 4790 bool only_simple_this_property_assignments, |
| 4758 FixedArray* assignments) { | 4791 FixedArray* assignments) { |
| 4759 set_compiler_hints(BooleanBit::set(compiler_hints(), | 4792 set_compiler_hints(BooleanBit::set(compiler_hints(), |
| 4760 kHasOnlySimpleThisPropertyAssignments, | 4793 kHasOnlySimpleThisPropertyAssignments, |
| 4761 only_simple_this_property_assignments)); | 4794 only_simple_this_property_assignments)); |
| 4762 set_this_property_assignments(assignments); | 4795 set_this_property_assignments(assignments); |
| 4763 set_this_property_assignments_count(assignments->length() / 3); | 4796 set_this_property_assignments_count(assignments->length() / 3); |
| 4764 } | 4797 } |
| 4765 | 4798 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4801 | 4834 |
| 4802 | 4835 |
| 4803 Object* SharedFunctionInfo::GetThisPropertyAssignmentConstant(int index) { | 4836 Object* SharedFunctionInfo::GetThisPropertyAssignmentConstant(int index) { |
| 4804 ASSERT(!IsThisPropertyAssignmentArgument(index)); | 4837 ASSERT(!IsThisPropertyAssignmentArgument(index)); |
| 4805 Object* obj = | 4838 Object* obj = |
| 4806 FixedArray::cast(this_property_assignments())->get(index * 3 + 2); | 4839 FixedArray::cast(this_property_assignments())->get(index * 3 + 2); |
| 4807 return obj; | 4840 return obj; |
| 4808 } | 4841 } |
| 4809 | 4842 |
| 4810 | 4843 |
| 4811 | |
| 4812 // Support function for printing the source code to a StringStream | 4844 // Support function for printing the source code to a StringStream |
| 4813 // without any allocation in the heap. | 4845 // without any allocation in the heap. |
| 4814 void SharedFunctionInfo::SourceCodePrint(StringStream* accumulator, | 4846 void SharedFunctionInfo::SourceCodePrint(StringStream* accumulator, |
| 4815 int max_length) { | 4847 int max_length) { |
| 4816 // For some native functions there is no source. | 4848 // For some native functions there is no source. |
| 4817 if (script()->IsUndefined() || | 4849 if (script()->IsUndefined() || |
| 4818 Script::cast(script())->source()->IsUndefined()) { | 4850 Script::cast(script())->source()->IsUndefined()) { |
| 4819 accumulator->Add("<No Source>"); | 4851 accumulator->Add("<No Source>"); |
| 4820 return; | 4852 return; |
| 4821 } | 4853 } |
| (...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5199 | 5231 |
| 5200 static Object* ArrayLengthRangeError() { | 5232 static Object* ArrayLengthRangeError() { |
| 5201 HandleScope scope; | 5233 HandleScope scope; |
| 5202 return Top::Throw(*Factory::NewRangeError("invalid_array_length", | 5234 return Top::Throw(*Factory::NewRangeError("invalid_array_length", |
| 5203 HandleVector<Object>(NULL, 0))); | 5235 HandleVector<Object>(NULL, 0))); |
| 5204 } | 5236 } |
| 5205 | 5237 |
| 5206 | 5238 |
| 5207 Object* JSObject::SetElementsLength(Object* len) { | 5239 Object* JSObject::SetElementsLength(Object* len) { |
| 5208 // We should never end in here with a pixel or external array. | 5240 // We should never end in here with a pixel or external array. |
| 5209 ASSERT(!HasPixelElements() && !HasExternalArrayElements()); | 5241 ASSERT(AllowsSetElementsLength()); |
| 5210 | 5242 |
| 5211 Object* smi_length = len->ToSmi(); | 5243 Object* smi_length = len->ToSmi(); |
| 5212 if (smi_length->IsSmi()) { | 5244 if (smi_length->IsSmi()) { |
| 5213 int value = Smi::cast(smi_length)->value(); | 5245 int value = Smi::cast(smi_length)->value(); |
| 5214 if (value < 0) return ArrayLengthRangeError(); | 5246 if (value < 0) return ArrayLengthRangeError(); |
| 5215 switch (GetElementsKind()) { | 5247 switch (GetElementsKind()) { |
| 5216 case FAST_ELEMENTS: { | 5248 case FAST_ELEMENTS: { |
| 5217 int old_capacity = FixedArray::cast(elements())->length(); | 5249 int old_capacity = FixedArray::cast(elements())->length(); |
| 5218 if (value <= old_capacity) { | 5250 if (value <= old_capacity) { |
| 5219 if (IsJSArray()) { | 5251 if (IsJSArray()) { |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5279 // set only element to len. | 5311 // set only element to len. |
| 5280 Object* obj = Heap::AllocateFixedArray(1); | 5312 Object* obj = Heap::AllocateFixedArray(1); |
| 5281 if (obj->IsFailure()) return obj; | 5313 if (obj->IsFailure()) return obj; |
| 5282 FixedArray::cast(obj)->set(0, len); | 5314 FixedArray::cast(obj)->set(0, len); |
| 5283 if (IsJSArray()) JSArray::cast(this)->set_length(Smi::FromInt(1)); | 5315 if (IsJSArray()) JSArray::cast(this)->set_length(Smi::FromInt(1)); |
| 5284 set_elements(FixedArray::cast(obj)); | 5316 set_elements(FixedArray::cast(obj)); |
| 5285 return this; | 5317 return this; |
| 5286 } | 5318 } |
| 5287 | 5319 |
| 5288 | 5320 |
| 5321 Object* JSObject::SetPrototype(Object* value, |
| 5322 bool skip_hidden_prototypes) { |
| 5323 // Silently ignore the change if value is not a JSObject or null. |
| 5324 // SpiderMonkey behaves this way. |
| 5325 if (!value->IsJSObject() && !value->IsNull()) return value; |
| 5326 |
| 5327 // Before we can set the prototype we need to be sure |
| 5328 // prototype cycles are prevented. |
| 5329 // It is sufficient to validate that the receiver is not in the new prototype |
| 5330 // chain. |
| 5331 for (Object* pt = value; pt != Heap::null_value(); pt = pt->GetPrototype()) { |
| 5332 if (JSObject::cast(pt) == this) { |
| 5333 // Cycle detected. |
| 5334 HandleScope scope; |
| 5335 return Top::Throw(*Factory::NewError("cyclic_proto", |
| 5336 HandleVector<Object>(NULL, 0))); |
| 5337 } |
| 5338 } |
| 5339 |
| 5340 JSObject* real_receiver = this; |
| 5341 |
| 5342 if (skip_hidden_prototypes) { |
| 5343 // Find the first object in the chain whose prototype object is not |
| 5344 // hidden and set the new prototype on that object. |
| 5345 Object* current_proto = real_receiver->GetPrototype(); |
| 5346 while (current_proto->IsJSObject() && |
| 5347 JSObject::cast(current_proto)->map()->is_hidden_prototype()) { |
| 5348 real_receiver = JSObject::cast(current_proto); |
| 5349 current_proto = current_proto->GetPrototype(); |
| 5350 } |
| 5351 } |
| 5352 |
| 5353 // Set the new prototype of the object. |
| 5354 Object* new_map = real_receiver->map()->CopyDropTransitions(); |
| 5355 if (new_map->IsFailure()) return new_map; |
| 5356 Map::cast(new_map)->set_prototype(value); |
| 5357 real_receiver->set_map(Map::cast(new_map)); |
| 5358 |
| 5359 return value; |
| 5360 } |
| 5361 |
| 5362 |
| 5289 bool JSObject::HasElementPostInterceptor(JSObject* receiver, uint32_t index) { | 5363 bool JSObject::HasElementPostInterceptor(JSObject* receiver, uint32_t index) { |
| 5290 switch (GetElementsKind()) { | 5364 switch (GetElementsKind()) { |
| 5291 case FAST_ELEMENTS: { | 5365 case FAST_ELEMENTS: { |
| 5292 uint32_t length = IsJSArray() ? | 5366 uint32_t length = IsJSArray() ? |
| 5293 static_cast<uint32_t> | 5367 static_cast<uint32_t> |
| 5294 (Smi::cast(JSArray::cast(this)->length())->value()) : | 5368 (Smi::cast(JSArray::cast(this)->length())->value()) : |
| 5295 static_cast<uint32_t>(FixedArray::cast(elements())->length()); | 5369 static_cast<uint32_t>(FixedArray::cast(elements())->length()); |
| 5296 if ((index < length) && | 5370 if ((index < length) && |
| 5297 !FixedArray::cast(elements())->get(index)->IsTheHole()) { | 5371 !FixedArray::cast(elements())->get(index)->IsTheHole()) { |
| 5298 return true; | 5372 return true; |
| (...skipping 797 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6096 return InterceptorInfo::cast(result); | 6170 return InterceptorInfo::cast(result); |
| 6097 } | 6171 } |
| 6098 | 6172 |
| 6099 | 6173 |
| 6100 Object* JSObject::GetPropertyPostInterceptor(JSObject* receiver, | 6174 Object* JSObject::GetPropertyPostInterceptor(JSObject* receiver, |
| 6101 String* name, | 6175 String* name, |
| 6102 PropertyAttributes* attributes) { | 6176 PropertyAttributes* attributes) { |
| 6103 // Check local property in holder, ignore interceptor. | 6177 // Check local property in holder, ignore interceptor. |
| 6104 LookupResult result; | 6178 LookupResult result; |
| 6105 LocalLookupRealNamedProperty(name, &result); | 6179 LocalLookupRealNamedProperty(name, &result); |
| 6106 if (result.IsValid()) return GetProperty(receiver, &result, name, attributes); | 6180 if (result.IsProperty()) { |
| 6181 return GetProperty(receiver, &result, name, attributes); |
| 6182 } |
| 6107 // Continue searching via the prototype chain. | 6183 // Continue searching via the prototype chain. |
| 6108 Object* pt = GetPrototype(); | 6184 Object* pt = GetPrototype(); |
| 6109 *attributes = ABSENT; | 6185 *attributes = ABSENT; |
| 6110 if (pt == Heap::null_value()) return Heap::undefined_value(); | 6186 if (pt == Heap::null_value()) return Heap::undefined_value(); |
| 6111 return pt->GetPropertyWithReceiver(receiver, name, attributes); | 6187 return pt->GetPropertyWithReceiver(receiver, name, attributes); |
| 6112 } | 6188 } |
| 6113 | 6189 |
| 6114 | 6190 |
| 6115 Object* JSObject::GetLocalPropertyPostInterceptor( | 6191 Object* JSObject::GetLocalPropertyPostInterceptor( |
| 6116 JSObject* receiver, | 6192 JSObject* receiver, |
| 6117 String* name, | 6193 String* name, |
| 6118 PropertyAttributes* attributes) { | 6194 PropertyAttributes* attributes) { |
| 6119 // Check local property in holder, ignore interceptor. | 6195 // Check local property in holder, ignore interceptor. |
| 6120 LookupResult result; | 6196 LookupResult result; |
| 6121 LocalLookupRealNamedProperty(name, &result); | 6197 LocalLookupRealNamedProperty(name, &result); |
| 6122 if (!result.IsValid()) return Heap::undefined_value(); | 6198 if (result.IsProperty()) { |
| 6123 return GetProperty(receiver, &result, name, attributes); | 6199 return GetProperty(receiver, &result, name, attributes); |
| 6200 } |
| 6201 return Heap::undefined_value(); |
| 6124 } | 6202 } |
| 6125 | 6203 |
| 6126 | 6204 |
| 6127 Object* JSObject::GetPropertyWithInterceptor( | 6205 Object* JSObject::GetPropertyWithInterceptor( |
| 6128 JSObject* receiver, | 6206 JSObject* receiver, |
| 6129 String* name, | 6207 String* name, |
| 6130 PropertyAttributes* attributes) { | 6208 PropertyAttributes* attributes) { |
| 6131 InterceptorInfo* interceptor = GetNamedInterceptor(); | 6209 InterceptorInfo* interceptor = GetNamedInterceptor(); |
| 6132 HandleScope scope; | 6210 HandleScope scope; |
| 6133 Handle<JSObject> receiver_handle(receiver); | 6211 Handle<JSObject> receiver_handle(receiver); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6165 bool JSObject::HasRealNamedProperty(String* key) { | 6243 bool JSObject::HasRealNamedProperty(String* key) { |
| 6166 // Check access rights if needed. | 6244 // Check access rights if needed. |
| 6167 if (IsAccessCheckNeeded() && | 6245 if (IsAccessCheckNeeded() && |
| 6168 !Top::MayNamedAccess(this, key, v8::ACCESS_HAS)) { | 6246 !Top::MayNamedAccess(this, key, v8::ACCESS_HAS)) { |
| 6169 Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS); | 6247 Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS); |
| 6170 return false; | 6248 return false; |
| 6171 } | 6249 } |
| 6172 | 6250 |
| 6173 LookupResult result; | 6251 LookupResult result; |
| 6174 LocalLookupRealNamedProperty(key, &result); | 6252 LocalLookupRealNamedProperty(key, &result); |
| 6175 if (result.IsValid()) { | 6253 return result.IsProperty() && (result.type() != INTERCEPTOR); |
| 6176 switch (result.type()) { | |
| 6177 case NORMAL: // fall through. | |
| 6178 case FIELD: // fall through. | |
| 6179 case CALLBACKS: // fall through. | |
| 6180 case CONSTANT_FUNCTION: | |
| 6181 return true; | |
| 6182 case INTERCEPTOR: | |
| 6183 case MAP_TRANSITION: | |
| 6184 case CONSTANT_TRANSITION: | |
| 6185 case NULL_DESCRIPTOR: | |
| 6186 return false; | |
| 6187 default: | |
| 6188 UNREACHABLE(); | |
| 6189 } | |
| 6190 } | |
| 6191 | |
| 6192 return false; | |
| 6193 } | 6254 } |
| 6194 | 6255 |
| 6195 | 6256 |
| 6196 bool JSObject::HasRealElementProperty(uint32_t index) { | 6257 bool JSObject::HasRealElementProperty(uint32_t index) { |
| 6197 // Check access rights if needed. | 6258 // Check access rights if needed. |
| 6198 if (IsAccessCheckNeeded() && | 6259 if (IsAccessCheckNeeded() && |
| 6199 !Top::MayIndexedAccess(this, index, v8::ACCESS_HAS)) { | 6260 !Top::MayIndexedAccess(this, index, v8::ACCESS_HAS)) { |
| 6200 Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS); | 6261 Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS); |
| 6201 return false; | 6262 return false; |
| 6202 } | 6263 } |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6244 bool JSObject::HasRealNamedCallbackProperty(String* key) { | 6305 bool JSObject::HasRealNamedCallbackProperty(String* key) { |
| 6245 // Check access rights if needed. | 6306 // Check access rights if needed. |
| 6246 if (IsAccessCheckNeeded() && | 6307 if (IsAccessCheckNeeded() && |
| 6247 !Top::MayNamedAccess(this, key, v8::ACCESS_HAS)) { | 6308 !Top::MayNamedAccess(this, key, v8::ACCESS_HAS)) { |
| 6248 Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS); | 6309 Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS); |
| 6249 return false; | 6310 return false; |
| 6250 } | 6311 } |
| 6251 | 6312 |
| 6252 LookupResult result; | 6313 LookupResult result; |
| 6253 LocalLookupRealNamedProperty(key, &result); | 6314 LocalLookupRealNamedProperty(key, &result); |
| 6254 return result.IsValid() && (result.type() == CALLBACKS); | 6315 return result.IsProperty() && (result.type() == CALLBACKS); |
| 6255 } | 6316 } |
| 6256 | 6317 |
| 6257 | 6318 |
| 6258 int JSObject::NumberOfLocalProperties(PropertyAttributes filter) { | 6319 int JSObject::NumberOfLocalProperties(PropertyAttributes filter) { |
| 6259 if (HasFastProperties()) { | 6320 if (HasFastProperties()) { |
| 6260 DescriptorArray* descs = map()->instance_descriptors(); | 6321 DescriptorArray* descs = map()->instance_descriptors(); |
| 6261 int result = 0; | 6322 int result = 0; |
| 6262 for (int i = 0; i < descs->number_of_descriptors(); i++) { | 6323 for (int i = 0; i < descs->number_of_descriptors(); i++) { |
| 6263 PropertyDetails details = descs->GetDetails(i); | 6324 PropertyDetails details = descs->GetDetails(i); |
| 6264 if (details.IsProperty() && (details.attributes() & filter) == 0) { | 6325 if (details.IsProperty() && (details.attributes() & filter) == 0) { |
| (...skipping 1968 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8233 if (break_point_objects()->IsUndefined()) return 0; | 8294 if (break_point_objects()->IsUndefined()) return 0; |
| 8234 // Single beak point. | 8295 // Single beak point. |
| 8235 if (!break_point_objects()->IsFixedArray()) return 1; | 8296 if (!break_point_objects()->IsFixedArray()) return 1; |
| 8236 // Multiple break points. | 8297 // Multiple break points. |
| 8237 return FixedArray::cast(break_point_objects())->length(); | 8298 return FixedArray::cast(break_point_objects())->length(); |
| 8238 } | 8299 } |
| 8239 #endif | 8300 #endif |
| 8240 | 8301 |
| 8241 | 8302 |
| 8242 } } // namespace v8::internal | 8303 } } // namespace v8::internal |
| OLD | NEW |