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

Side by Side Diff: src/objects.cc

Issue 7566004: Move element deletion into element handlers (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: white space tweaks Created 9 years, 4 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.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 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 3122 matching lines...) Expand 10 before | Expand all | Expand 10 after
3133 return *v8::Utils::OpenHandle(*result); 3133 return *v8::Utils::OpenHandle(*result);
3134 } 3134 }
3135 } 3135 }
3136 MaybeObject* raw_result = 3136 MaybeObject* raw_result =
3137 this_handle->DeletePropertyPostInterceptor(*name_handle, NORMAL_DELETION); 3137 this_handle->DeletePropertyPostInterceptor(*name_handle, NORMAL_DELETION);
3138 RETURN_IF_SCHEDULED_EXCEPTION(isolate); 3138 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
3139 return raw_result; 3139 return raw_result;
3140 } 3140 }
3141 3141
3142 3142
3143 MaybeObject* JSObject::DeleteElementPostInterceptor(uint32_t index,
3144 DeleteMode mode) {
3145 ASSERT(!HasExternalArrayElements());
3146 switch (GetElementsKind()) {
3147 case FAST_ELEMENTS: {
3148 Object* obj;
3149 { MaybeObject* maybe_obj = EnsureWritableFastElements();
3150 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
3151 }
3152 uint32_t length = IsJSArray() ?
3153 static_cast<uint32_t>(Smi::cast(JSArray::cast(this)->length())->value()) :
3154 static_cast<uint32_t>(FixedArray::cast(elements())->length());
3155 if (index < length) {
3156 FixedArray::cast(elements())->set_the_hole(index);
3157 }
3158 break;
3159 }
3160 case DICTIONARY_ELEMENTS: {
3161 NumberDictionary* dictionary = element_dictionary();
3162 int entry = dictionary->FindEntry(index);
3163 if (entry != NumberDictionary::kNotFound) {
3164 Object* deleted = dictionary->DeleteProperty(entry, mode);
3165 if (deleted == GetHeap()->true_value()) {
3166 MaybeObject* maybe_elements = dictionary->Shrink(index);
3167 FixedArray* new_elements = NULL;
3168 if (!maybe_elements->To(&new_elements)) {
3169 return maybe_elements;
3170 }
3171 set_elements(new_elements);
3172 }
3173 return deleted;
3174 }
3175 break;
3176 }
3177 default:
3178 UNREACHABLE();
3179 break;
3180 }
3181 return GetHeap()->true_value();
3182 }
3183
3184
3185 MaybeObject* JSObject::DeleteElementWithInterceptor(uint32_t index) { 3143 MaybeObject* JSObject::DeleteElementWithInterceptor(uint32_t index) {
3186 Isolate* isolate = GetIsolate(); 3144 Isolate* isolate = GetIsolate();
3187 Heap* heap = isolate->heap(); 3145 Heap* heap = isolate->heap();
3188 // Make sure that the top context does not change when doing 3146 // Make sure that the top context does not change when doing
3189 // callbacks or interceptor calls. 3147 // callbacks or interceptor calls.
3190 AssertNoContextChange ncc; 3148 AssertNoContextChange ncc;
3191 HandleScope scope(isolate); 3149 HandleScope scope(isolate);
3192 Handle<InterceptorInfo> interceptor(GetIndexedInterceptor()); 3150 Handle<InterceptorInfo> interceptor(GetIndexedInterceptor());
3193 if (interceptor->deleter()->IsUndefined()) return heap->false_value(); 3151 if (interceptor->deleter()->IsUndefined()) return heap->false_value();
3194 v8::IndexedPropertyDeleter deleter = 3152 v8::IndexedPropertyDeleter deleter =
3195 v8::ToCData<v8::IndexedPropertyDeleter>(interceptor->deleter()); 3153 v8::ToCData<v8::IndexedPropertyDeleter>(interceptor->deleter());
3196 Handle<JSObject> this_handle(this); 3154 Handle<JSObject> this_handle(this);
3197 LOG(isolate, 3155 LOG(isolate,
3198 ApiIndexedPropertyAccess("interceptor-indexed-delete", this, index)); 3156 ApiIndexedPropertyAccess("interceptor-indexed-delete", this, index));
3199 CustomArguments args(isolate, interceptor->data(), this, this); 3157 CustomArguments args(isolate, interceptor->data(), this, this);
3200 v8::AccessorInfo info(args.end()); 3158 v8::AccessorInfo info(args.end());
3201 v8::Handle<v8::Boolean> result; 3159 v8::Handle<v8::Boolean> result;
3202 { 3160 {
3203 // Leaving JavaScript. 3161 // Leaving JavaScript.
3204 VMState state(isolate, EXTERNAL); 3162 VMState state(isolate, EXTERNAL);
3205 result = deleter(index, info); 3163 result = deleter(index, info);
3206 } 3164 }
3207 RETURN_IF_SCHEDULED_EXCEPTION(isolate); 3165 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
3208 if (!result.IsEmpty()) { 3166 if (!result.IsEmpty()) {
3209 ASSERT(result->IsBoolean()); 3167 ASSERT(result->IsBoolean());
3210 return *v8::Utils::OpenHandle(*result); 3168 return *v8::Utils::OpenHandle(*result);
3211 } 3169 }
3212 MaybeObject* raw_result = 3170 MaybeObject* raw_result = GetElementsAccessor()->Delete(*this_handle,
3213 this_handle->DeleteElementPostInterceptor(index, NORMAL_DELETION); 3171 index,
3172 NORMAL_DELETION);
3214 RETURN_IF_SCHEDULED_EXCEPTION(isolate); 3173 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
3215 return raw_result; 3174 return raw_result;
3216 } 3175 }
3217 3176
3218 3177
3219 MaybeObject* JSObject::DeleteFastElement(uint32_t index) {
3220 ASSERT(HasFastElements() || HasFastArgumentsElements());
3221 Heap* heap = GetHeap();
3222 FixedArray* backing_store = FixedArray::cast(elements());
3223 if (backing_store->map() == heap->non_strict_arguments_elements_map()) {
3224 backing_store = FixedArray::cast(backing_store->get(1));
3225 } else {
3226 Object* writable;
3227 MaybeObject* maybe = EnsureWritableFastElements();
3228 if (!maybe->ToObject(&writable)) return maybe;
3229 backing_store = FixedArray::cast(writable);
3230 }
3231 uint32_t length = static_cast<uint32_t>(
3232 IsJSArray()
3233 ? Smi::cast(JSArray::cast(this)->length())->value()
3234 : backing_store->length());
3235 if (index < length) {
3236 backing_store->set_the_hole(index);
3237 // If an old space backing store is larger than a certain size and
3238 // has too few used values, normalize it.
3239 // To avoid doing the check on every delete we require at least
3240 // one adjacent hole to the value being deleted.
3241 Object* hole = heap->the_hole_value();
3242 const int kMinLengthForSparsenessCheck = 64;
3243 if (backing_store->length() >= kMinLengthForSparsenessCheck &&
3244 !heap->InNewSpace(backing_store) &&
3245 ((index > 0 && backing_store->get(index - 1) == hole) ||
3246 (index + 1 < length && backing_store->get(index + 1) == hole))) {
3247 int num_used = 0;
3248 for (int i = 0; i < backing_store->length(); ++i) {
3249 if (backing_store->get(i) != hole) ++num_used;
3250 // Bail out early if more than 1/4 is used.
3251 if (4 * num_used > backing_store->length()) break;
3252 }
3253 if (4 * num_used <= backing_store->length()) {
3254 MaybeObject* result = NormalizeElements();
3255 if (result->IsFailure()) return result;
3256 }
3257 }
3258 }
3259 return heap->true_value();
3260 }
3261
3262
3263 MaybeObject* JSObject::DeleteDictionaryElement(uint32_t index,
3264 DeleteMode mode) {
3265 Isolate* isolate = GetIsolate();
3266 Heap* heap = isolate->heap();
3267 FixedArray* backing_store = FixedArray::cast(elements());
3268 bool is_arguments =
3269 (GetElementsKind() == JSObject::NON_STRICT_ARGUMENTS_ELEMENTS);
3270 if (is_arguments) {
3271 backing_store = FixedArray::cast(backing_store->get(1));
3272 }
3273 NumberDictionary* dictionary = NumberDictionary::cast(backing_store);
3274 int entry = dictionary->FindEntry(index);
3275 if (entry != NumberDictionary::kNotFound) {
3276 Object* result = dictionary->DeleteProperty(entry, mode);
3277 if (result == heap->true_value()) {
3278 MaybeObject* maybe_elements = dictionary->Shrink(index);
3279 FixedArray* new_elements = NULL;
3280 if (!maybe_elements->To(&new_elements)) {
3281 return maybe_elements;
3282 }
3283 if (is_arguments) {
3284 FixedArray::cast(elements())->set(1, new_elements);
3285 } else {
3286 set_elements(new_elements);
3287 }
3288 }
3289 if (mode == STRICT_DELETION && result == heap->false_value()) {
3290 // In strict mode, attempting to delete a non-configurable property
3291 // throws an exception.
3292 HandleScope scope(isolate);
3293 Handle<Object> holder(this);
3294 Handle<Object> name = isolate->factory()->NewNumberFromUint(index);
3295 Handle<Object> args[2] = { name, holder };
3296 Handle<Object> error =
3297 isolate->factory()->NewTypeError("strict_delete_property",
3298 HandleVector(args, 2));
3299 return isolate->Throw(*error);
3300 }
3301 }
3302 return heap->true_value();
3303 }
3304
3305
3306 MaybeObject* JSObject::DeleteElement(uint32_t index, DeleteMode mode) { 3178 MaybeObject* JSObject::DeleteElement(uint32_t index, DeleteMode mode) {
3307 Isolate* isolate = GetIsolate(); 3179 Isolate* isolate = GetIsolate();
3308 // Check access rights if needed. 3180 // Check access rights if needed.
3309 if (IsAccessCheckNeeded() && 3181 if (IsAccessCheckNeeded() &&
3310 !isolate->MayIndexedAccess(this, index, v8::ACCESS_DELETE)) { 3182 !isolate->MayIndexedAccess(this, index, v8::ACCESS_DELETE)) {
3311 isolate->ReportFailedAccessCheck(this, v8::ACCESS_DELETE); 3183 isolate->ReportFailedAccessCheck(this, v8::ACCESS_DELETE);
3312 return isolate->heap()->false_value(); 3184 return isolate->heap()->false_value();
3313 } 3185 }
3314 3186
3315 if (IsJSGlobalProxy()) { 3187 if (IsJSGlobalProxy()) {
3316 Object* proto = GetPrototype(); 3188 Object* proto = GetPrototype();
3317 if (proto->IsNull()) return isolate->heap()->false_value(); 3189 if (proto->IsNull()) return isolate->heap()->false_value();
3318 ASSERT(proto->IsJSGlobalObject()); 3190 ASSERT(proto->IsJSGlobalObject());
3319 return JSGlobalObject::cast(proto)->DeleteElement(index, mode); 3191 return JSGlobalObject::cast(proto)->DeleteElement(index, mode);
3320 } 3192 }
3321 3193
3322 if (HasIndexedInterceptor()) { 3194 if (HasIndexedInterceptor()) {
3323 // Skip interceptor if forcing deletion. 3195 // Skip interceptor if forcing deletion.
3324 return (mode == FORCE_DELETION) 3196 if (mode != FORCE_DELETION) {
3325 ? DeleteElementPostInterceptor(index, FORCE_DELETION) 3197 return DeleteElementWithInterceptor(index);
3326 : DeleteElementWithInterceptor(index); 3198 }
3199 mode = JSReceiver::FORCE_DELETION;
3327 } 3200 }
3328 3201
3329 switch (GetElementsKind()) { 3202 return GetElementsAccessor()->Delete(this, index, mode);
3330 case FAST_ELEMENTS:
3331 return DeleteFastElement(index);
3332
3333 case DICTIONARY_ELEMENTS:
3334 return DeleteDictionaryElement(index, mode);
3335
3336 case FAST_DOUBLE_ELEMENTS: {
3337 int length = IsJSArray()
3338 ? Smi::cast(JSArray::cast(this)->length())->value()
3339 : FixedDoubleArray::cast(elements())->length();
3340 if (index < static_cast<uint32_t>(length)) {
3341 FixedDoubleArray::cast(elements())->set_the_hole(index);
3342 }
3343 break;
3344 }
3345 case EXTERNAL_PIXEL_ELEMENTS:
3346 case EXTERNAL_BYTE_ELEMENTS:
3347 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
3348 case EXTERNAL_SHORT_ELEMENTS:
3349 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
3350 case EXTERNAL_INT_ELEMENTS:
3351 case EXTERNAL_UNSIGNED_INT_ELEMENTS:
3352 case EXTERNAL_FLOAT_ELEMENTS:
3353 case EXTERNAL_DOUBLE_ELEMENTS:
3354 // Pixel and external array elements cannot be deleted. Just
3355 // silently ignore here.
3356 break;
3357
3358 case NON_STRICT_ARGUMENTS_ELEMENTS: {
3359 FixedArray* parameter_map = FixedArray::cast(elements());
3360 uint32_t length = parameter_map->length();
3361 Object* probe =
3362 index < (length - 2) ? parameter_map->get(index + 2) : NULL;
3363 if (probe != NULL && !probe->IsTheHole()) {
3364 // TODO(kmillikin): We could check if this was the last aliased
3365 // parameter, and revert to normal elements in that case. That
3366 // would enable GC of the context.
3367 parameter_map->set_the_hole(index + 2);
3368 } else {
3369 FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
3370 if (arguments->IsDictionary()) {
3371 return DeleteDictionaryElement(index, mode);
3372 } else {
3373 return DeleteFastElement(index);
3374 }
3375 }
3376 break;
3377 }
3378 }
3379 return isolate->heap()->true_value();
3380 } 3203 }
3381 3204
3382 3205
3383 MaybeObject* JSReceiver::DeleteProperty(String* name, DeleteMode mode) { 3206 MaybeObject* JSReceiver::DeleteProperty(String* name, DeleteMode mode) {
3384 if (IsJSProxy()) { 3207 if (IsJSProxy()) {
3385 return JSProxy::cast(this)->DeletePropertyWithHandler(name, mode); 3208 return JSProxy::cast(this)->DeletePropertyWithHandler(name, mode);
3386 } else { 3209 } else {
3387 return JSObject::cast(this)->DeleteProperty(name, mode); 3210 return JSObject::cast(this)->DeleteProperty(name, mode);
3388 } 3211 }
3389 } 3212 }
(...skipping 8505 matching lines...) Expand 10 before | Expand all | Expand 10 after
11895 if (break_point_objects()->IsUndefined()) return 0; 11718 if (break_point_objects()->IsUndefined()) return 0;
11896 // Single break point. 11719 // Single break point.
11897 if (!break_point_objects()->IsFixedArray()) return 1; 11720 if (!break_point_objects()->IsFixedArray()) return 1;
11898 // Multiple break points. 11721 // Multiple break points.
11899 return FixedArray::cast(break_point_objects())->length(); 11722 return FixedArray::cast(break_point_objects())->length();
11900 } 11723 }
11901 #endif 11724 #endif
11902 11725
11903 11726
11904 } } // namespace v8::internal 11727 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/objects.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698