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

Side by Side Diff: src/runtime.cc

Issue 234913003: Allow allocation and GC in access check callbacks. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: added TODOs, addressed comments Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/objects.cc ('k') | test/cctest/test-api.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 1698 matching lines...) Expand 10 before | Expand all | Expand 10 after
1709 1709
1710 1710
1711 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPrototype) { 1711 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPrototype) {
1712 HandleScope scope(isolate); 1712 HandleScope scope(isolate);
1713 ASSERT(args.length() == 1); 1713 ASSERT(args.length() == 1);
1714 CONVERT_ARG_HANDLE_CHECKED(Object, obj, 0); 1714 CONVERT_ARG_HANDLE_CHECKED(Object, obj, 0);
1715 // We don't expect access checks to be needed on JSProxy objects. 1715 // We don't expect access checks to be needed on JSProxy objects.
1716 ASSERT(!obj->IsAccessCheckNeeded() || obj->IsJSObject()); 1716 ASSERT(!obj->IsAccessCheckNeeded() || obj->IsJSObject());
1717 do { 1717 do {
1718 if (obj->IsAccessCheckNeeded() && 1718 if (obj->IsAccessCheckNeeded() &&
1719 !isolate->MayNamedAccessWrapper(Handle<JSObject>::cast(obj), 1719 !isolate->MayNamedAccess(Handle<JSObject>::cast(obj),
1720 isolate->factory()->proto_string(), 1720 isolate->factory()->proto_string(),
1721 v8::ACCESS_GET)) { 1721 v8::ACCESS_GET)) {
1722 isolate->ReportFailedAccessCheckWrapper(Handle<JSObject>::cast(obj), 1722 isolate->ReportFailedAccessCheck(Handle<JSObject>::cast(obj),
1723 v8::ACCESS_GET); 1723 v8::ACCESS_GET);
1724 RETURN_IF_SCHEDULED_EXCEPTION(isolate); 1724 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
1725 return isolate->heap()->undefined_value(); 1725 return isolate->heap()->undefined_value();
1726 } 1726 }
1727 obj = handle(obj->GetPrototype(isolate), isolate); 1727 obj = handle(obj->GetPrototype(isolate), isolate);
1728 } while (obj->IsJSObject() && 1728 } while (obj->IsJSObject() &&
1729 JSObject::cast(*obj)->map()->is_hidden_prototype()); 1729 JSObject::cast(*obj)->map()->is_hidden_prototype());
1730 return *obj; 1730 return *obj;
1731 } 1731 }
1732 1732
1733 1733
1734 static inline Object* GetPrototypeSkipHiddenPrototypes(Isolate* isolate, 1734 static inline Object* GetPrototypeSkipHiddenPrototypes(Isolate* isolate,
1735 Object* receiver) { 1735 Object* receiver) {
1736 Object* current = receiver->GetPrototype(isolate); 1736 Object* current = receiver->GetPrototype(isolate);
1737 while (current->IsJSObject() && 1737 while (current->IsJSObject() &&
1738 JSObject::cast(current)->map()->is_hidden_prototype()) { 1738 JSObject::cast(current)->map()->is_hidden_prototype()) {
1739 current = current->GetPrototype(isolate); 1739 current = current->GetPrototype(isolate);
1740 } 1740 }
1741 return current; 1741 return current;
1742 } 1742 }
1743 1743
1744 1744
1745 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetPrototype) { 1745 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetPrototype) {
1746 HandleScope scope(isolate); 1746 HandleScope scope(isolate);
1747 ASSERT(args.length() == 2); 1747 ASSERT(args.length() == 2);
1748 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0); 1748 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
1749 CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1); 1749 CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1);
1750 if (obj->IsAccessCheckNeeded() && 1750 if (obj->IsAccessCheckNeeded() &&
1751 !isolate->MayNamedAccessWrapper(obj, 1751 !isolate->MayNamedAccess(
1752 isolate->factory()->proto_string(), 1752 obj, isolate->factory()->proto_string(), v8::ACCESS_SET)) {
1753 v8::ACCESS_SET)) { 1753 isolate->ReportFailedAccessCheck(obj, v8::ACCESS_SET);
1754 isolate->ReportFailedAccessCheckWrapper(obj, v8::ACCESS_SET);
1755 RETURN_IF_SCHEDULED_EXCEPTION(isolate); 1754 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
1756 return isolate->heap()->undefined_value(); 1755 return isolate->heap()->undefined_value();
1757 } 1756 }
1758 if (obj->map()->is_observed()) { 1757 if (obj->map()->is_observed()) {
1759 Handle<Object> old_value( 1758 Handle<Object> old_value(
1760 GetPrototypeSkipHiddenPrototypes(isolate, *obj), isolate); 1759 GetPrototypeSkipHiddenPrototypes(isolate, *obj), isolate);
1761 1760
1762 Handle<Object> result = JSObject::SetPrototype(obj, prototype, true); 1761 Handle<Object> result = JSObject::SetPrototype(obj, prototype, true);
1763 RETURN_IF_EMPTY_HANDLE(isolate, result); 1762 RETURN_IF_EMPTY_HANDLE(isolate, result);
1764 1763
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
1843 }; 1842 };
1844 1843
1845 1844
1846 static AccessCheckResult CheckPropertyAccess(Handle<JSObject> obj, 1845 static AccessCheckResult CheckPropertyAccess(Handle<JSObject> obj,
1847 Handle<Name> name, 1846 Handle<Name> name,
1848 v8::AccessType access_type) { 1847 v8::AccessType access_type) {
1849 uint32_t index; 1848 uint32_t index;
1850 if (name->AsArrayIndex(&index)) { 1849 if (name->AsArrayIndex(&index)) {
1851 // TODO(1095): we should traverse hidden prototype hierachy as well. 1850 // TODO(1095): we should traverse hidden prototype hierachy as well.
1852 if (CheckGenericAccess( 1851 if (CheckGenericAccess(
1853 obj, obj, index, access_type, &Isolate::MayIndexedAccessWrapper)) { 1852 obj, obj, index, access_type, &Isolate::MayIndexedAccess)) {
1854 return ACCESS_ALLOWED; 1853 return ACCESS_ALLOWED;
1855 } 1854 }
1856 1855
1857 obj->GetIsolate()->ReportFailedAccessCheckWrapper(obj, access_type); 1856 obj->GetIsolate()->ReportFailedAccessCheck(obj, access_type);
1858 return ACCESS_FORBIDDEN; 1857 return ACCESS_FORBIDDEN;
1859 } 1858 }
1860 1859
1861 Isolate* isolate = obj->GetIsolate(); 1860 Isolate* isolate = obj->GetIsolate();
1862 LookupResult lookup(isolate); 1861 LookupResult lookup(isolate);
1863 obj->LocalLookup(*name, &lookup, true); 1862 obj->LocalLookup(*name, &lookup, true);
1864 1863
1865 if (!lookup.IsProperty()) return ACCESS_ABSENT; 1864 if (!lookup.IsProperty()) return ACCESS_ABSENT;
1866 Handle<JSObject> holder(lookup.holder(), isolate); 1865 Handle<JSObject> holder(lookup.holder(), isolate);
1867 if (CheckGenericAccess<Handle<Object> >( 1866 if (CheckGenericAccess<Handle<Object> >(
1868 obj, holder, name, access_type, &Isolate::MayNamedAccessWrapper)) { 1867 obj, holder, name, access_type, &Isolate::MayNamedAccess)) {
1869 return ACCESS_ALLOWED; 1868 return ACCESS_ALLOWED;
1870 } 1869 }
1871 1870
1872 // Access check callback denied the access, but some properties 1871 // Access check callback denied the access, but some properties
1873 // can have a special permissions which override callbacks descision 1872 // can have a special permissions which override callbacks descision
1874 // (currently see v8::AccessControl). 1873 // (currently see v8::AccessControl).
1875 // API callbacks can have per callback access exceptions. 1874 // API callbacks can have per callback access exceptions.
1876 switch (lookup.type()) { 1875 switch (lookup.type()) {
1877 case CALLBACKS: 1876 case CALLBACKS:
1878 if (CheckAccessException(lookup.GetCallbackObject(), access_type)) { 1877 if (CheckAccessException(lookup.GetCallbackObject(), access_type)) {
1879 return ACCESS_ALLOWED; 1878 return ACCESS_ALLOWED;
1880 } 1879 }
1881 break; 1880 break;
1882 case INTERCEPTOR: 1881 case INTERCEPTOR:
1883 // If the object has an interceptor, try real named properties. 1882 // If the object has an interceptor, try real named properties.
1884 // Overwrite the result to fetch the correct property later. 1883 // Overwrite the result to fetch the correct property later.
1885 holder->LookupRealNamedProperty(*name, &lookup); 1884 holder->LookupRealNamedProperty(*name, &lookup);
1886 if (lookup.IsProperty() && lookup.IsPropertyCallbacks()) { 1885 if (lookup.IsProperty() && lookup.IsPropertyCallbacks()) {
1887 if (CheckAccessException(lookup.GetCallbackObject(), access_type)) { 1886 if (CheckAccessException(lookup.GetCallbackObject(), access_type)) {
1888 return ACCESS_ALLOWED; 1887 return ACCESS_ALLOWED;
1889 } 1888 }
1890 } 1889 }
1891 break; 1890 break;
1892 default: 1891 default:
1893 break; 1892 break;
1894 } 1893 }
1895 1894
1896 isolate->ReportFailedAccessCheckWrapper(obj, access_type); 1895 isolate->ReportFailedAccessCheck(obj, access_type);
1897 return ACCESS_FORBIDDEN; 1896 return ACCESS_FORBIDDEN;
1898 } 1897 }
1899 1898
1900 1899
1901 // Enumerator used as indices into the array returned from GetOwnProperty 1900 // Enumerator used as indices into the array returned from GetOwnProperty
1902 enum PropertyDescriptorIndices { 1901 enum PropertyDescriptorIndices {
1903 IS_ACCESSOR_INDEX, 1902 IS_ACCESSOR_INDEX,
1904 VALUE_INDEX, 1903 VALUE_INDEX,
1905 GETTER_INDEX, 1904 GETTER_INDEX,
1906 SETTER_INDEX, 1905 SETTER_INDEX,
(...skipping 3898 matching lines...) Expand 10 before | Expand all | Expand 10 after
5805 } 5804 }
5806 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0); 5805 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
5807 CONVERT_SMI_ARG_CHECKED(filter_value, 1); 5806 CONVERT_SMI_ARG_CHECKED(filter_value, 1);
5808 PropertyAttributes filter = static_cast<PropertyAttributes>(filter_value); 5807 PropertyAttributes filter = static_cast<PropertyAttributes>(filter_value);
5809 5808
5810 // Skip the global proxy as it has no properties and always delegates to the 5809 // Skip the global proxy as it has no properties and always delegates to the
5811 // real global object. 5810 // real global object.
5812 if (obj->IsJSGlobalProxy()) { 5811 if (obj->IsJSGlobalProxy()) {
5813 // Only collect names if access is permitted. 5812 // Only collect names if access is permitted.
5814 if (obj->IsAccessCheckNeeded() && 5813 if (obj->IsAccessCheckNeeded() &&
5815 !isolate->MayNamedAccessWrapper(obj, 5814 !isolate->MayNamedAccess(
5816 isolate->factory()->undefined_value(), 5815 obj, isolate->factory()->undefined_value(), v8::ACCESS_KEYS)) {
5817 v8::ACCESS_KEYS)) { 5816 isolate->ReportFailedAccessCheck(obj, v8::ACCESS_KEYS);
5818 isolate->ReportFailedAccessCheckWrapper(obj, v8::ACCESS_KEYS);
5819 RETURN_IF_SCHEDULED_EXCEPTION(isolate); 5817 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
5820 return *isolate->factory()->NewJSArray(0); 5818 return *isolate->factory()->NewJSArray(0);
5821 } 5819 }
5822 obj = Handle<JSObject>(JSObject::cast(obj->GetPrototype())); 5820 obj = Handle<JSObject>(JSObject::cast(obj->GetPrototype()));
5823 } 5821 }
5824 5822
5825 // Find the number of objects making up this. 5823 // Find the number of objects making up this.
5826 int length = LocalPrototypeChainLength(*obj); 5824 int length = LocalPrototypeChainLength(*obj);
5827 5825
5828 // Find the number of local properties for each of the objects. 5826 // Find the number of local properties for each of the objects.
5829 ScopedVector<int> local_property_count(length); 5827 ScopedVector<int> local_property_count(length);
5830 int total_property_count = 0; 5828 int total_property_count = 0;
5831 Handle<JSObject> jsproto = obj; 5829 Handle<JSObject> jsproto = obj;
5832 for (int i = 0; i < length; i++) { 5830 for (int i = 0; i < length; i++) {
5833 // Only collect names if access is permitted. 5831 // Only collect names if access is permitted.
5834 if (jsproto->IsAccessCheckNeeded() && 5832 if (jsproto->IsAccessCheckNeeded() &&
5835 !isolate->MayNamedAccessWrapper(jsproto, 5833 !isolate->MayNamedAccess(
5836 isolate->factory()->undefined_value(), 5834 jsproto, isolate->factory()->undefined_value(), v8::ACCESS_KEYS)) {
5837 v8::ACCESS_KEYS)) { 5835 isolate->ReportFailedAccessCheck(jsproto, v8::ACCESS_KEYS);
5838 isolate->ReportFailedAccessCheckWrapper(jsproto, v8::ACCESS_KEYS);
5839 RETURN_IF_SCHEDULED_EXCEPTION(isolate); 5836 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
5840 return *isolate->factory()->NewJSArray(0); 5837 return *isolate->factory()->NewJSArray(0);
5841 } 5838 }
5842 int n; 5839 int n;
5843 n = jsproto->NumberOfLocalProperties(filter); 5840 n = jsproto->NumberOfLocalProperties(filter);
5844 local_property_count[i] = n; 5841 local_property_count[i] = n;
5845 total_property_count += n; 5842 total_property_count += n;
5846 if (i < length - 1) { 5843 if (i < length - 1) {
5847 jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype())); 5844 jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
5848 } 5845 }
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
5978 5975
5979 RUNTIME_FUNCTION(MaybeObject*, Runtime_LocalKeys) { 5976 RUNTIME_FUNCTION(MaybeObject*, Runtime_LocalKeys) {
5980 HandleScope scope(isolate); 5977 HandleScope scope(isolate);
5981 ASSERT_EQ(args.length(), 1); 5978 ASSERT_EQ(args.length(), 1);
5982 CONVERT_ARG_CHECKED(JSObject, raw_object, 0); 5979 CONVERT_ARG_CHECKED(JSObject, raw_object, 0);
5983 Handle<JSObject> object(raw_object); 5980 Handle<JSObject> object(raw_object);
5984 5981
5985 if (object->IsJSGlobalProxy()) { 5982 if (object->IsJSGlobalProxy()) {
5986 // Do access checks before going to the global object. 5983 // Do access checks before going to the global object.
5987 if (object->IsAccessCheckNeeded() && 5984 if (object->IsAccessCheckNeeded() &&
5988 !isolate->MayNamedAccessWrapper(object, 5985 !isolate->MayNamedAccess(
5989 isolate->factory()->undefined_value(), 5986 object, isolate->factory()->undefined_value(), v8::ACCESS_KEYS)) {
5990 v8::ACCESS_KEYS)) { 5987 isolate->ReportFailedAccessCheck(object, v8::ACCESS_KEYS);
5991 isolate->ReportFailedAccessCheckWrapper(object, v8::ACCESS_KEYS);
5992 RETURN_IF_SCHEDULED_EXCEPTION(isolate); 5988 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
5993 return *isolate->factory()->NewJSArray(0); 5989 return *isolate->factory()->NewJSArray(0);
5994 } 5990 }
5995 5991
5996 Handle<Object> proto(object->GetPrototype(), isolate); 5992 Handle<Object> proto(object->GetPrototype(), isolate);
5997 // If proxy is detached we simply return an empty array. 5993 // If proxy is detached we simply return an empty array.
5998 if (proto->IsNull()) return *isolate->factory()->NewJSArray(0); 5994 if (proto->IsNull()) return *isolate->factory()->NewJSArray(0);
5999 object = Handle<JSObject>::cast(proto); 5995 object = Handle<JSObject>::cast(proto);
6000 } 5996 }
6001 5997
(...skipping 8897 matching lines...) Expand 10 before | Expand all | Expand 10 after
14899 14895
14900 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsAccessAllowedForObserver) { 14896 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsAccessAllowedForObserver) {
14901 HandleScope scope(isolate); 14897 HandleScope scope(isolate);
14902 ASSERT(args.length() == 3); 14898 ASSERT(args.length() == 3);
14903 CONVERT_ARG_HANDLE_CHECKED(JSFunction, observer, 0); 14899 CONVERT_ARG_HANDLE_CHECKED(JSFunction, observer, 0);
14904 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 1); 14900 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 1);
14905 ASSERT(object->map()->is_access_check_needed()); 14901 ASSERT(object->map()->is_access_check_needed());
14906 Handle<Object> key = args.at<Object>(2); 14902 Handle<Object> key = args.at<Object>(2);
14907 SaveContext save(isolate); 14903 SaveContext save(isolate);
14908 isolate->set_context(observer->context()); 14904 isolate->set_context(observer->context());
14909 if (!isolate->MayNamedAccessWrapper(object, 14905 if (!isolate->MayNamedAccess(
14910 isolate->factory()->undefined_value(), 14906 object, isolate->factory()->undefined_value(), v8::ACCESS_KEYS)) {
14911 v8::ACCESS_KEYS)) {
14912 return isolate->heap()->false_value(); 14907 return isolate->heap()->false_value();
14913 } 14908 }
14914 bool access_allowed = false; 14909 bool access_allowed = false;
14915 uint32_t index = 0; 14910 uint32_t index = 0;
14916 if (key->ToArrayIndex(&index) || 14911 if (key->ToArrayIndex(&index) ||
14917 (key->IsString() && String::cast(*key)->AsArrayIndex(&index))) { 14912 (key->IsString() && String::cast(*key)->AsArrayIndex(&index))) {
14918 access_allowed = 14913 access_allowed =
14919 isolate->MayIndexedAccessWrapper(object, index, v8::ACCESS_GET) && 14914 isolate->MayIndexedAccess(object, index, v8::ACCESS_GET) &&
14920 isolate->MayIndexedAccessWrapper(object, index, v8::ACCESS_HAS); 14915 isolate->MayIndexedAccess(object, index, v8::ACCESS_HAS);
14921 } else { 14916 } else {
14922 access_allowed = 14917 access_allowed =
14923 isolate->MayNamedAccessWrapper(object, key, v8::ACCESS_GET) && 14918 isolate->MayNamedAccess(object, key, v8::ACCESS_GET) &&
14924 isolate->MayNamedAccessWrapper(object, key, v8::ACCESS_HAS); 14919 isolate->MayNamedAccess(object, key, v8::ACCESS_HAS);
14925 } 14920 }
14926 return isolate->heap()->ToBoolean(access_allowed); 14921 return isolate->heap()->ToBoolean(access_allowed);
14927 } 14922 }
14928 14923
14929 14924
14930 static MaybeObject* ArrayConstructorCommon(Isolate* isolate, 14925 static MaybeObject* ArrayConstructorCommon(Isolate* isolate,
14931 Handle<JSFunction> constructor, 14926 Handle<JSFunction> constructor,
14932 Handle<AllocationSite> site, 14927 Handle<AllocationSite> site,
14933 Arguments* caller_args) { 14928 Arguments* caller_args) {
14934 Factory* factory = isolate->factory(); 14929 Factory* factory = isolate->factory();
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after
15172 } 15167 }
15173 } 15168 }
15174 15169
15175 15170
15176 void Runtime::OutOfMemory() { 15171 void Runtime::OutOfMemory() {
15177 Heap::FatalProcessOutOfMemory("CALL_AND_RETRY_LAST", true); 15172 Heap::FatalProcessOutOfMemory("CALL_AND_RETRY_LAST", true);
15178 UNREACHABLE(); 15173 UNREACHABLE();
15179 } 15174 }
15180 15175
15181 } } // namespace v8::internal 15176 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/objects.cc ('k') | test/cctest/test-api.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698