| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 959 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 970 // Recursively traverses hidden prototypes if property is not found | 970 // Recursively traverses hidden prototypes if property is not found |
| 971 static void GetOwnPropertyImplementation(JSObject* obj, | 971 static void GetOwnPropertyImplementation(JSObject* obj, |
| 972 String* name, | 972 String* name, |
| 973 LookupResult* result) { | 973 LookupResult* result) { |
| 974 obj->LocalLookupRealNamedProperty(name, result); | 974 obj->LocalLookupRealNamedProperty(name, result); |
| 975 | 975 |
| 976 if (result->IsFound()) return; | 976 if (result->IsFound()) return; |
| 977 | 977 |
| 978 Object* proto = obj->GetPrototype(); | 978 Object* proto = obj->GetPrototype(); |
| 979 if (proto->IsJSObject() && | 979 if (proto->IsJSObject() && |
| 980 JSObject::cast(proto)->map()->is_hidden_prototype()) | 980 JSObject::cast(proto)->map()->is_hidden_prototype()) { |
| 981 GetOwnPropertyImplementation(JSObject::cast(proto), | 981 GetOwnPropertyImplementation(JSObject::cast(proto), |
| 982 name, result); | 982 name, result); |
| 983 } |
| 983 } | 984 } |
| 984 | 985 |
| 985 | 986 |
| 986 static bool CheckAccessException(LookupResult* result, | 987 static bool CheckAccessException(Object* callback, |
| 987 v8::AccessType access_type) { | 988 v8::AccessType access_type) { |
| 988 if (result->type() == CALLBACKS) { | 989 if (callback->IsAccessorInfo()) { |
| 989 Object* callback = result->GetCallbackObject(); | 990 AccessorInfo* info = AccessorInfo::cast(callback); |
| 990 if (callback->IsAccessorInfo()) { | 991 return |
| 991 AccessorInfo* info = AccessorInfo::cast(callback); | 992 (access_type == v8::ACCESS_HAS && |
| 992 bool can_access = | 993 (info->all_can_read() || info->all_can_write())) || |
| 993 (access_type == v8::ACCESS_HAS && | 994 (access_type == v8::ACCESS_GET && info->all_can_read()) || |
| 994 (info->all_can_read() || info->all_can_write())) || | 995 (access_type == v8::ACCESS_SET && info->all_can_write()); |
| 995 (access_type == v8::ACCESS_GET && info->all_can_read()) || | |
| 996 (access_type == v8::ACCESS_SET && info->all_can_write()); | |
| 997 return can_access; | |
| 998 } | |
| 999 } | 996 } |
| 1000 | |
| 1001 return false; | 997 return false; |
| 1002 } | 998 } |
| 1003 | 999 |
| 1004 | 1000 |
| 1005 static bool CheckAccess(JSObject* obj, | 1001 template<class Key> |
| 1006 String* name, | 1002 static bool CheckGenericAccess( |
| 1007 LookupResult* result, | 1003 JSObject* receiver, |
| 1008 v8::AccessType access_type) { | 1004 JSObject* holder, |
| 1009 ASSERT(result->IsProperty()); | 1005 Key key, |
| 1006 v8::AccessType access_type, |
| 1007 bool (Isolate::*mayAccess)(JSObject*, Key, v8::AccessType)) { |
| 1008 Isolate* isolate = receiver->GetIsolate(); |
| 1009 for (JSObject* current = receiver; |
| 1010 true; |
| 1011 current = JSObject::cast(current->GetPrototype())) { |
| 1012 if (current->IsAccessCheckNeeded() && |
| 1013 !(isolate->*mayAccess)(current, key, access_type)) { |
| 1014 return false; |
| 1015 } |
| 1016 if (current == holder) break; |
| 1017 } |
| 1018 return true; |
| 1019 } |
| 1010 | 1020 |
| 1011 JSObject* holder = result->holder(); | |
| 1012 JSObject* current = obj; | |
| 1013 Isolate* isolate = obj->GetIsolate(); | |
| 1014 while (true) { | |
| 1015 if (current->IsAccessCheckNeeded() && | |
| 1016 !isolate->MayNamedAccess(current, name, access_type)) { | |
| 1017 // Access check callback denied the access, but some properties | |
| 1018 // can have a special permissions which override callbacks descision | |
| 1019 // (currently see v8::AccessControl). | |
| 1020 break; | |
| 1021 } | |
| 1022 | 1021 |
| 1023 if (current == holder) { | 1022 static bool CheckElementAccess( |
| 1024 return true; | 1023 JSObject* obj, |
| 1025 } | 1024 uint32_t index, |
| 1026 | 1025 v8::AccessType access_type) { |
| 1027 current = JSObject::cast(current->GetPrototype()); | 1026 // TODO(1095): we should traverse hidden prototype hierachy as well. |
| 1027 if (CheckGenericAccess( |
| 1028 obj, obj, index, access_type, &Isolate::MayIndexedAccess)) { |
| 1029 return true; |
| 1028 } | 1030 } |
| 1029 | 1031 |
| 1032 obj->GetIsolate()->ReportFailedAccessCheck(obj, access_type); |
| 1033 return false; |
| 1034 } |
| 1035 |
| 1036 |
| 1037 static bool CheckPropertyAccess( |
| 1038 JSObject* obj, |
| 1039 String* name, |
| 1040 v8::AccessType access_type) { |
| 1041 uint32_t index; |
| 1042 if (name->AsArrayIndex(&index)) { |
| 1043 return CheckElementAccess(obj, index, access_type); |
| 1044 } |
| 1045 |
| 1046 LookupResult lookup(obj->GetIsolate()); |
| 1047 obj->LocalLookup(name, &lookup); |
| 1048 |
| 1049 if (CheckGenericAccess<Object*>( |
| 1050 obj, lookup.holder(), name, access_type, &Isolate::MayNamedAccess)) { |
| 1051 return true; |
| 1052 } |
| 1053 |
| 1054 // Access check callback denied the access, but some properties |
| 1055 // can have a special permissions which override callbacks descision |
| 1056 // (currently see v8::AccessControl). |
| 1030 // API callbacks can have per callback access exceptions. | 1057 // API callbacks can have per callback access exceptions. |
| 1031 switch (result->type()) { | 1058 switch (lookup.type()) { |
| 1032 case CALLBACKS: { | 1059 case CALLBACKS: |
| 1033 if (CheckAccessException(result, access_type)) { | 1060 if (CheckAccessException(lookup.GetCallbackObject(), access_type)) { |
| 1034 return true; | 1061 return true; |
| 1035 } | 1062 } |
| 1036 break; | 1063 break; |
| 1037 } | 1064 case INTERCEPTOR: |
| 1038 case INTERCEPTOR: { | |
| 1039 // If the object has an interceptor, try real named properties. | 1065 // If the object has an interceptor, try real named properties. |
| 1040 // Overwrite the result to fetch the correct property later. | 1066 // Overwrite the result to fetch the correct property later. |
| 1041 holder->LookupRealNamedProperty(name, result); | 1067 lookup.holder()->LookupRealNamedProperty(name, &lookup); |
| 1042 if (result->IsProperty()) { | 1068 if (lookup.IsProperty() && lookup.IsPropertyCallbacks()) { |
| 1043 if (CheckAccessException(result, access_type)) { | 1069 if (CheckAccessException(lookup.GetCallbackObject(), access_type)) { |
| 1044 return true; | 1070 return true; |
| 1045 } | 1071 } |
| 1046 } | 1072 } |
| 1047 break; | 1073 break; |
| 1048 } | |
| 1049 default: | 1074 default: |
| 1050 break; | 1075 break; |
| 1051 } | 1076 } |
| 1052 | 1077 |
| 1053 isolate->ReportFailedAccessCheck(current, access_type); | 1078 obj->GetIsolate()->ReportFailedAccessCheck(obj, access_type); |
| 1054 return false; | 1079 return false; |
| 1055 } | 1080 } |
| 1056 | 1081 |
| 1057 | 1082 |
| 1058 // TODO(1095): we should traverse hidden prototype hierachy as well. | |
| 1059 static bool CheckElementAccess(JSObject* obj, | |
| 1060 uint32_t index, | |
| 1061 v8::AccessType access_type) { | |
| 1062 if (obj->IsAccessCheckNeeded() && | |
| 1063 !obj->GetIsolate()->MayIndexedAccess(obj, index, access_type)) { | |
| 1064 return false; | |
| 1065 } | |
| 1066 | |
| 1067 return true; | |
| 1068 } | |
| 1069 | |
| 1070 | |
| 1071 // Enumerator used as indices into the array returned from GetOwnProperty | 1083 // Enumerator used as indices into the array returned from GetOwnProperty |
| 1072 enum PropertyDescriptorIndices { | 1084 enum PropertyDescriptorIndices { |
| 1073 IS_ACCESSOR_INDEX, | 1085 IS_ACCESSOR_INDEX, |
| 1074 VALUE_INDEX, | 1086 VALUE_INDEX, |
| 1075 GETTER_INDEX, | 1087 GETTER_INDEX, |
| 1076 SETTER_INDEX, | 1088 SETTER_INDEX, |
| 1077 WRITABLE_INDEX, | 1089 WRITABLE_INDEX, |
| 1078 ENUMERABLE_INDEX, | 1090 ENUMERABLE_INDEX, |
| 1079 CONFIGURABLE_INDEX, | 1091 CONFIGURABLE_INDEX, |
| 1080 DESCRIPTOR_SIZE | 1092 DESCRIPTOR_SIZE |
| 1081 }; | 1093 }; |
| 1082 | 1094 |
| 1083 | 1095 |
| 1084 static MaybeObject* GetOwnProperty(Isolate* isolate, | 1096 static MaybeObject* GetOwnProperty(Isolate* isolate, |
| 1085 Handle<JSObject> obj, | 1097 Handle<JSObject> obj, |
| 1086 Handle<String> name) { | 1098 Handle<String> name) { |
| 1087 Heap* heap = isolate->heap(); | 1099 Heap* heap = isolate->heap(); |
| 1100 PropertyAttributes attrs = obj->GetLocalPropertyAttribute(*name); |
| 1101 if (attrs == ABSENT) return heap->undefined_value(); |
| 1102 AccessorPair* accessors = obj->GetLocalPropertyAccessorPair(*name); |
| 1103 |
| 1088 Handle<FixedArray> elms = isolate->factory()->NewFixedArray(DESCRIPTOR_SIZE); | 1104 Handle<FixedArray> elms = isolate->factory()->NewFixedArray(DESCRIPTOR_SIZE); |
| 1089 Handle<JSArray> desc = isolate->factory()->NewJSArrayWithElements(elms); | 1105 elms->set(ENUMERABLE_INDEX, heap->ToBoolean((attrs & DONT_ENUM) == 0)); |
| 1090 LookupResult result(isolate); | 1106 elms->set(CONFIGURABLE_INDEX, heap->ToBoolean((attrs & DONT_DELETE) == 0)); |
| 1091 // This could be an element. | 1107 elms->set(IS_ACCESSOR_INDEX, heap->ToBoolean(accessors != NULL)); |
| 1092 uint32_t index; | |
| 1093 if (name->AsArrayIndex(&index)) { | |
| 1094 switch (obj->GetLocalElementKind(index)) { | |
| 1095 case JSObject::UNDEFINED_ELEMENT: | |
| 1096 return heap->undefined_value(); | |
| 1097 | 1108 |
| 1098 case JSObject::STRING_CHARACTER_ELEMENT: { | 1109 if (accessors == NULL) { |
| 1099 // Special handling of string objects according to ECMAScript 5 | 1110 elms->set(WRITABLE_INDEX, heap->ToBoolean((attrs & READ_ONLY) == 0)); |
| 1100 // 15.5.5.2. Note that this might be a string object with elements | 1111 // GetProperty does access check. |
| 1101 // other than the actual string value. This is covered by the | 1112 elms->set(VALUE_INDEX, *GetProperty(obj, name)); |
| 1102 // subsequent cases. | 1113 } else { |
| 1103 Handle<JSValue> js_value = Handle<JSValue>::cast(obj); | 1114 // Access checks are performed for both accessors separately. |
| 1104 Handle<String> str(String::cast(js_value->value())); | 1115 // When they fail, the respective field is not set in the descriptor. |
| 1105 Handle<String> substr = SubString(str, index, index + 1, NOT_TENURED); | 1116 Object* getter = accessors->GetComponent(ACCESSOR_GETTER); |
| 1106 | 1117 Object* setter = accessors->GetComponent(ACCESSOR_SETTER); |
| 1107 elms->set(IS_ACCESSOR_INDEX, heap->false_value()); | 1118 if (!getter->IsMap() && CheckPropertyAccess(*obj, *name, v8::ACCESS_GET)) { |
| 1108 elms->set(VALUE_INDEX, *substr); | 1119 elms->set(GETTER_INDEX, getter); |
| 1109 elms->set(WRITABLE_INDEX, heap->false_value()); | 1120 } |
| 1110 elms->set(ENUMERABLE_INDEX, heap->true_value()); | 1121 if (!setter->IsMap() && CheckPropertyAccess(*obj, *name, v8::ACCESS_SET)) { |
| 1111 elms->set(CONFIGURABLE_INDEX, heap->false_value()); | 1122 elms->set(SETTER_INDEX, setter); |
| 1112 return *desc; | |
| 1113 } | |
| 1114 | |
| 1115 case JSObject::INTERCEPTED_ELEMENT: | |
| 1116 case JSObject::FAST_ELEMENT: { | |
| 1117 elms->set(IS_ACCESSOR_INDEX, heap->false_value()); | |
| 1118 Handle<Object> value = Object::GetElement(obj, index); | |
| 1119 RETURN_IF_EMPTY_HANDLE(isolate, value); | |
| 1120 elms->set(VALUE_INDEX, *value); | |
| 1121 elms->set(WRITABLE_INDEX, heap->true_value()); | |
| 1122 elms->set(ENUMERABLE_INDEX, heap->true_value()); | |
| 1123 elms->set(CONFIGURABLE_INDEX, heap->true_value()); | |
| 1124 return *desc; | |
| 1125 } | |
| 1126 | |
| 1127 case JSObject::DICTIONARY_ELEMENT: { | |
| 1128 Handle<JSObject> holder = obj; | |
| 1129 if (obj->IsJSGlobalProxy()) { | |
| 1130 Object* proto = obj->GetPrototype(); | |
| 1131 if (proto->IsNull()) return heap->undefined_value(); | |
| 1132 ASSERT(proto->IsJSGlobalObject()); | |
| 1133 holder = Handle<JSObject>(JSObject::cast(proto)); | |
| 1134 } | |
| 1135 FixedArray* elements = FixedArray::cast(holder->elements()); | |
| 1136 SeededNumberDictionary* dictionary = NULL; | |
| 1137 if (elements->map() == heap->non_strict_arguments_elements_map()) { | |
| 1138 dictionary = SeededNumberDictionary::cast(elements->get(1)); | |
| 1139 } else { | |
| 1140 dictionary = SeededNumberDictionary::cast(elements); | |
| 1141 } | |
| 1142 int entry = dictionary->FindEntry(index); | |
| 1143 ASSERT(entry != SeededNumberDictionary::kNotFound); | |
| 1144 PropertyDetails details = dictionary->DetailsAt(entry); | |
| 1145 switch (details.type()) { | |
| 1146 case CALLBACKS: { | |
| 1147 // This is an accessor property with getter and/or setter. | |
| 1148 AccessorPair* accessors = | |
| 1149 AccessorPair::cast(dictionary->ValueAt(entry)); | |
| 1150 elms->set(IS_ACCESSOR_INDEX, heap->true_value()); | |
| 1151 if (CheckElementAccess(*obj, index, v8::ACCESS_GET)) { | |
| 1152 elms->set(GETTER_INDEX, accessors->GetComponent(ACCESSOR_GETTER)); | |
| 1153 } | |
| 1154 if (CheckElementAccess(*obj, index, v8::ACCESS_SET)) { | |
| 1155 elms->set(SETTER_INDEX, accessors->GetComponent(ACCESSOR_SETTER)); | |
| 1156 } | |
| 1157 break; | |
| 1158 } | |
| 1159 case NORMAL: { | |
| 1160 // This is a data property. | |
| 1161 elms->set(IS_ACCESSOR_INDEX, heap->false_value()); | |
| 1162 Handle<Object> value = Object::GetElement(obj, index); | |
| 1163 ASSERT(!value.is_null()); | |
| 1164 elms->set(VALUE_INDEX, *value); | |
| 1165 elms->set(WRITABLE_INDEX, heap->ToBoolean(!details.IsReadOnly())); | |
| 1166 break; | |
| 1167 } | |
| 1168 default: | |
| 1169 UNREACHABLE(); | |
| 1170 break; | |
| 1171 } | |
| 1172 elms->set(ENUMERABLE_INDEX, heap->ToBoolean(!details.IsDontEnum())); | |
| 1173 elms->set(CONFIGURABLE_INDEX, heap->ToBoolean(!details.IsDontDelete())); | |
| 1174 return *desc; | |
| 1175 } | |
| 1176 } | 1123 } |
| 1177 } | 1124 } |
| 1178 | 1125 |
| 1179 // Use recursive implementation to also traverse hidden prototypes | 1126 return *isolate->factory()->NewJSArrayWithElements(elms); |
| 1180 GetOwnPropertyImplementation(*obj, *name, &result); | |
| 1181 | |
| 1182 if (!result.IsProperty()) { | |
| 1183 return heap->undefined_value(); | |
| 1184 } | |
| 1185 | |
| 1186 if (!CheckAccess(*obj, *name, &result, v8::ACCESS_HAS)) { | |
| 1187 return heap->false_value(); | |
| 1188 } | |
| 1189 | |
| 1190 elms->set(ENUMERABLE_INDEX, heap->ToBoolean(!result.IsDontEnum())); | |
| 1191 elms->set(CONFIGURABLE_INDEX, heap->ToBoolean(!result.IsDontDelete())); | |
| 1192 | |
| 1193 bool is_js_accessor = result.IsPropertyCallbacks() && | |
| 1194 (result.GetCallbackObject()->IsAccessorPair()); | |
| 1195 | |
| 1196 if (is_js_accessor) { | |
| 1197 // __defineGetter__/__defineSetter__ callback. | |
| 1198 elms->set(IS_ACCESSOR_INDEX, heap->true_value()); | |
| 1199 | |
| 1200 AccessorPair* accessors = AccessorPair::cast(result.GetCallbackObject()); | |
| 1201 Object* getter = accessors->GetComponent(ACCESSOR_GETTER); | |
| 1202 if (!getter->IsMap() && CheckAccess(*obj, *name, &result, v8::ACCESS_GET)) { | |
| 1203 elms->set(GETTER_INDEX, getter); | |
| 1204 } | |
| 1205 Object* setter = accessors->GetComponent(ACCESSOR_SETTER); | |
| 1206 if (!setter->IsMap() && CheckAccess(*obj, *name, &result, v8::ACCESS_SET)) { | |
| 1207 elms->set(SETTER_INDEX, setter); | |
| 1208 } | |
| 1209 } else { | |
| 1210 elms->set(IS_ACCESSOR_INDEX, heap->false_value()); | |
| 1211 elms->set(WRITABLE_INDEX, heap->ToBoolean(!result.IsReadOnly())); | |
| 1212 | |
| 1213 PropertyAttributes attrs; | |
| 1214 Object* value; | |
| 1215 // GetProperty will check access and report any violations. | |
| 1216 { MaybeObject* maybe_value = obj->GetProperty(*obj, &result, *name, &attrs); | |
| 1217 if (!maybe_value->ToObject(&value)) return maybe_value; | |
| 1218 } | |
| 1219 elms->set(VALUE_INDEX, value); | |
| 1220 } | |
| 1221 | |
| 1222 return *desc; | |
| 1223 } | 1127 } |
| 1224 | 1128 |
| 1225 | 1129 |
| 1226 // Returns an array with the property description: | 1130 // Returns an array with the property description: |
| 1227 // if args[1] is not a property on args[0] | 1131 // if args[1] is not a property on args[0] |
| 1228 // returns undefined | 1132 // returns undefined |
| 1229 // if args[1] is a data property on args[0] | 1133 // if args[1] is a data property on args[0] |
| 1230 // [false, value, Writeable, Enumerable, Configurable] | 1134 // [false, value, Writeable, Enumerable, Configurable] |
| 1231 // if args[1] is an accessor on args[0] | 1135 // if args[1] is an accessor on args[0] |
| 1232 // [true, GetFunction, SetFunction, Enumerable, Configurable] | 1136 // [true, GetFunction, SetFunction, Enumerable, Configurable] |
| (...skipping 3487 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4720 } | 4624 } |
| 4721 | 4625 |
| 4722 | 4626 |
| 4723 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsPropertyEnumerable) { | 4627 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsPropertyEnumerable) { |
| 4724 NoHandleAllocation ha; | 4628 NoHandleAllocation ha; |
| 4725 ASSERT(args.length() == 2); | 4629 ASSERT(args.length() == 2); |
| 4726 | 4630 |
| 4727 CONVERT_ARG_CHECKED(JSObject, object, 0); | 4631 CONVERT_ARG_CHECKED(JSObject, object, 0); |
| 4728 CONVERT_ARG_CHECKED(String, key, 1); | 4632 CONVERT_ARG_CHECKED(String, key, 1); |
| 4729 | 4633 |
| 4730 uint32_t index; | |
| 4731 if (key->AsArrayIndex(&index)) { | |
| 4732 JSObject::LocalElementKind type = object->GetLocalElementKind(index); | |
| 4733 switch (type) { | |
| 4734 case JSObject::UNDEFINED_ELEMENT: | |
| 4735 case JSObject::STRING_CHARACTER_ELEMENT: | |
| 4736 return isolate->heap()->false_value(); | |
| 4737 case JSObject::INTERCEPTED_ELEMENT: | |
| 4738 case JSObject::FAST_ELEMENT: | |
| 4739 return isolate->heap()->true_value(); | |
| 4740 case JSObject::DICTIONARY_ELEMENT: { | |
| 4741 if (object->IsJSGlobalProxy()) { | |
| 4742 Object* proto = object->GetPrototype(); | |
| 4743 if (proto->IsNull()) { | |
| 4744 return isolate->heap()->false_value(); | |
| 4745 } | |
| 4746 ASSERT(proto->IsJSGlobalObject()); | |
| 4747 object = JSObject::cast(proto); | |
| 4748 } | |
| 4749 FixedArray* elements = FixedArray::cast(object->elements()); | |
| 4750 SeededNumberDictionary* dictionary = NULL; | |
| 4751 if (elements->map() == | |
| 4752 isolate->heap()->non_strict_arguments_elements_map()) { | |
| 4753 dictionary = SeededNumberDictionary::cast(elements->get(1)); | |
| 4754 } else { | |
| 4755 dictionary = SeededNumberDictionary::cast(elements); | |
| 4756 } | |
| 4757 int entry = dictionary->FindEntry(index); | |
| 4758 ASSERT(entry != SeededNumberDictionary::kNotFound); | |
| 4759 PropertyDetails details = dictionary->DetailsAt(entry); | |
| 4760 return isolate->heap()->ToBoolean(!details.IsDontEnum()); | |
| 4761 } | |
| 4762 } | |
| 4763 } | |
| 4764 | |
| 4765 PropertyAttributes att = object->GetLocalPropertyAttribute(key); | 4634 PropertyAttributes att = object->GetLocalPropertyAttribute(key); |
| 4766 return isolate->heap()->ToBoolean(att != ABSENT && (att & DONT_ENUM) == 0); | 4635 return isolate->heap()->ToBoolean(att != ABSENT && (att & DONT_ENUM) == 0); |
| 4767 } | 4636 } |
| 4768 | 4637 |
| 4769 | 4638 |
| 4770 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPropertyNames) { | 4639 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPropertyNames) { |
| 4771 HandleScope scope(isolate); | 4640 HandleScope scope(isolate); |
| 4772 ASSERT(args.length() == 1); | 4641 ASSERT(args.length() == 1); |
| 4773 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0); | 4642 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0); |
| 4774 bool threw = false; | 4643 bool threw = false; |
| (...skipping 8646 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 13421 // Handle last resort GC and make sure to allow future allocations | 13290 // Handle last resort GC and make sure to allow future allocations |
| 13422 // to grow the heap without causing GCs (if possible). | 13291 // to grow the heap without causing GCs (if possible). |
| 13423 isolate->counters()->gc_last_resort_from_js()->Increment(); | 13292 isolate->counters()->gc_last_resort_from_js()->Increment(); |
| 13424 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, | 13293 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, |
| 13425 "Runtime::PerformGC"); | 13294 "Runtime::PerformGC"); |
| 13426 } | 13295 } |
| 13427 } | 13296 } |
| 13428 | 13297 |
| 13429 | 13298 |
| 13430 } } // namespace v8::internal | 13299 } } // namespace v8::internal |
| OLD | NEW |