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

Side by Side Diff: src/objects.cc

Issue 10784014: Removed transitions from the accessor pair descriptors. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Addressed comments Created 8 years, 5 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') | src/objects-debug.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 2841 matching lines...) Expand 10 before | Expand all | Expand 10 after
2852 *value, 2852 *value,
2853 result->holder(), 2853 result->holder(),
2854 strict_mode); 2854 strict_mode);
2855 } 2855 }
2856 case INTERCEPTOR: 2856 case INTERCEPTOR:
2857 return self->SetPropertyWithInterceptor(*name, 2857 return self->SetPropertyWithInterceptor(*name,
2858 *value, 2858 *value,
2859 attributes, 2859 attributes,
2860 strict_mode); 2860 strict_mode);
2861 case TRANSITION: { 2861 case TRANSITION: {
2862 Object* transition = result->GetTransitionValue(); 2862 Map* transition_map = result->GetTransitionTarget();
2863 2863
2864 if (transition->IsAccessorPair()) {
2865 ASSERT(!AccessorPair::cast(transition)->ContainsAccessor());
2866 return ConvertDescriptorToField(*name, *value, attributes);
2867 }
2868
2869 Map* transition_map = Map::cast(transition);
2870 DescriptorArray* descriptors = transition_map->instance_descriptors(); 2864 DescriptorArray* descriptors = transition_map->instance_descriptors();
2871 int descriptor = descriptors->LastAdded(); 2865 int descriptor = descriptors->LastAdded();
2872 PropertyDetails details = descriptors->GetDetails(descriptor); 2866 PropertyDetails details = descriptors->GetDetails(descriptor);
2873 ASSERT(details.type() == FIELD || details.type() == CONSTANT_FUNCTION);
2874 2867
2875 if (details.type() == FIELD) { 2868 if (details.type() == FIELD) {
2876 if (attributes == details.attributes()) { 2869 if (attributes == details.attributes()) {
2877 int field_index = descriptors->GetFieldIndex(descriptor); 2870 int field_index = descriptors->GetFieldIndex(descriptor);
2878 return self->AddFastPropertyUsingMap(transition_map, 2871 return self->AddFastPropertyUsingMap(transition_map,
2879 *name, 2872 *name,
2880 *value, 2873 *value,
2881 field_index); 2874 field_index);
2882 } 2875 }
2883 return self->ConvertDescriptorToField(*name, *value, attributes); 2876 return self->ConvertDescriptorToField(*name, *value, attributes);
2877 } else if (details.type() == CALLBACKS) {
2878 return ConvertDescriptorToField(*name, *value, attributes);
2884 } 2879 }
2885 2880
2886 // Is transition to CONSTANT_FUNCTION. 2881 ASSERT(details.type() == CONSTANT_FUNCTION);
2882
2887 Object* constant_function = descriptors->GetValue(descriptor); 2883 Object* constant_function = descriptors->GetValue(descriptor);
2888 // If the same constant function is being added we can simply 2884 // If the same constant function is being added we can simply
2889 // transition to the target map. 2885 // transition to the target map.
2890 if (constant_function == *value) { 2886 if (constant_function == *value) {
2891 self->set_map(transition_map); 2887 self->set_map(transition_map);
2892 return constant_function; 2888 return constant_function;
2893 } 2889 }
2894 // Otherwise, replace with a map transition to a new map with a FIELD, 2890 // Otherwise, replace with a map transition to a new map with a FIELD,
2895 // even if the value is a constant function. 2891 // even if the value is a constant function.
2896 return ConvertTransitionToMapTransition( 2892 return ConvertTransitionToMapTransition(
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
2976 // Only replace the function if necessary. 2972 // Only replace the function if necessary.
2977 if (value == result.GetConstantFunction()) return value; 2973 if (value == result.GetConstantFunction()) return value;
2978 // Preserve the attributes of this existing property. 2974 // Preserve the attributes of this existing property.
2979 attributes = result.GetAttributes(); 2975 attributes = result.GetAttributes();
2980 return ConvertDescriptorToField(name, value, attributes); 2976 return ConvertDescriptorToField(name, value, attributes);
2981 case CALLBACKS: 2977 case CALLBACKS:
2982 case INTERCEPTOR: 2978 case INTERCEPTOR:
2983 // Override callback in clone 2979 // Override callback in clone
2984 return ConvertDescriptorToField(name, value, attributes); 2980 return ConvertDescriptorToField(name, value, attributes);
2985 case TRANSITION: { 2981 case TRANSITION: {
2986 Object* transition = result.GetTransitionValue(); 2982 Map* transition_map = result.GetTransitionTarget();
2987 2983
2988 if (transition->IsAccessorPair()) {
2989 ASSERT(!AccessorPair::cast(transition)->ContainsAccessor());
2990 return ConvertDescriptorToField(name, value, attributes);
2991 }
2992
2993 Map* transition_map = Map::cast(transition);
2994 DescriptorArray* descriptors = transition_map->instance_descriptors(); 2984 DescriptorArray* descriptors = transition_map->instance_descriptors();
2995 int descriptor = descriptors->LastAdded(); 2985 int descriptor = descriptors->LastAdded();
2996 PropertyDetails details = descriptors->GetDetails(descriptor); 2986 PropertyDetails details = descriptors->GetDetails(descriptor);
2997 ASSERT(details.type() == FIELD || details.type() == CONSTANT_FUNCTION);
2998 2987
2999 if (details.type() == FIELD) { 2988 if (details.type() == FIELD) {
3000 if (attributes == details.attributes()) { 2989 if (attributes == details.attributes()) {
3001 int field_index = descriptors->GetFieldIndex(descriptor); 2990 int field_index = descriptors->GetFieldIndex(descriptor);
3002 return AddFastPropertyUsingMap(transition_map, 2991 return AddFastPropertyUsingMap(transition_map,
3003 name, 2992 name,
3004 value, 2993 value,
3005 field_index); 2994 field_index);
3006 } 2995 }
3007 return ConvertDescriptorToField(name, value, attributes); 2996 return ConvertDescriptorToField(name, value, attributes);
2997 } else if (details.type() == CALLBACKS) {
2998 return ConvertDescriptorToField(name, value, attributes);
3008 } 2999 }
3009 3000
3010 // Was transition to CONSTANT_FUNCTION. Replace with a map transition to a 3001 ASSERT(details.type() == CONSTANT_FUNCTION);
3011 // new map with a FIELD, even if the value is a function. 3002
3003 // Replace transition to CONSTANT FUNCTION with a map transition to a new
3004 // map with a FIELD, even if the value is a function.
3012 return ConvertTransitionToMapTransition( 3005 return ConvertTransitionToMapTransition(
3013 result.GetTransitionIndex(), name, value, attributes); 3006 result.GetTransitionIndex(), name, value, attributes);
3014 } 3007 }
3015 case HANDLER: 3008 case HANDLER:
3016 case NONEXISTENT: 3009 case NONEXISTENT:
3017 UNREACHABLE(); 3010 UNREACHABLE();
3018 } 3011 }
3019 UNREACHABLE(); // keep the compiler happy 3012 UNREACHABLE(); // keep the compiler happy
3020 return value; 3013 return value;
3021 } 3014 }
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after
3287 PropertyDetails d = 3280 PropertyDetails d =
3288 PropertyDetails(details.attributes(), NORMAL, details.index()); 3281 PropertyDetails(details.attributes(), NORMAL, details.index());
3289 Object* value = FastPropertyAt(descs->GetFieldIndex(i)); 3282 Object* value = FastPropertyAt(descs->GetFieldIndex(i));
3290 MaybeObject* maybe_dictionary = 3283 MaybeObject* maybe_dictionary =
3291 dictionary->Add(descs->GetKey(i), value, d); 3284 dictionary->Add(descs->GetKey(i), value, d);
3292 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary; 3285 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
3293 break; 3286 break;
3294 } 3287 }
3295 case CALLBACKS: { 3288 case CALLBACKS: {
3296 Object* value = descs->GetCallbacksObject(i); 3289 Object* value = descs->GetCallbacksObject(i);
3297 if (value->IsAccessorPair()) {
3298 MaybeObject* maybe_copy =
3299 AccessorPair::cast(value)->CopyWithoutTransitions();
3300 if (!maybe_copy->To(&value)) return maybe_copy;
3301 }
3302 MaybeObject* maybe_dictionary = 3290 MaybeObject* maybe_dictionary =
3303 dictionary->Add(descs->GetKey(i), value, details); 3291 dictionary->Add(descs->GetKey(i), value, details);
3304 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary; 3292 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
3305 break; 3293 break;
3306 } 3294 }
3307 case INTERCEPTOR: 3295 case INTERCEPTOR:
3308 break; 3296 break;
3309 case HANDLER: 3297 case HANDLER:
3310 case NORMAL: 3298 case NORMAL:
3311 case TRANSITION: 3299 case TRANSITION:
(...skipping 912 matching lines...) Expand 10 before | Expand all | Expand 10 after
4224 } 4212 }
4225 4213
4226 4214
4227 // Search object and its prototype chain for callback properties. 4215 // Search object and its prototype chain for callback properties.
4228 void JSObject::LookupCallback(String* name, LookupResult* result) { 4216 void JSObject::LookupCallback(String* name, LookupResult* result) {
4229 Heap* heap = GetHeap(); 4217 Heap* heap = GetHeap();
4230 for (Object* current = this; 4218 for (Object* current = this;
4231 current != heap->null_value() && current->IsJSObject(); 4219 current != heap->null_value() && current->IsJSObject();
4232 current = JSObject::cast(current)->GetPrototype()) { 4220 current = JSObject::cast(current)->GetPrototype()) {
4233 JSObject::cast(current)->LocalLookupRealNamedProperty(name, result); 4221 JSObject::cast(current)->LocalLookupRealNamedProperty(name, result);
4234 if (result->IsCallbacks()) return; 4222 if (result->IsPropertyCallbacks()) return;
4235 } 4223 }
4236 result->NotFound(); 4224 result->NotFound();
4237 } 4225 }
4238 4226
4239 4227
4240 // Try to update an accessor in an elements dictionary. Return true if the 4228 // Try to update an accessor in an elements dictionary. Return true if the
4241 // update succeeded, and false otherwise. 4229 // update succeeded, and false otherwise.
4242 static bool UpdateGetterSetterInDictionary( 4230 static bool UpdateGetterSetterInDictionary(
4243 SeededNumberDictionary* dictionary, 4231 SeededNumberDictionary* dictionary,
4244 uint32_t index, 4232 uint32_t index,
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
4336 LocalLookupRealNamedProperty(name, &result); 4324 LocalLookupRealNamedProperty(name, &result);
4337 if (result.IsPropertyCallbacks()) { 4325 if (result.IsPropertyCallbacks()) {
4338 // Note that the result can actually have IsDontDelete() == true when we 4326 // Note that the result can actually have IsDontDelete() == true when we
4339 // e.g. have to fall back to the slow case while adding a setter after 4327 // e.g. have to fall back to the slow case while adding a setter after
4340 // successfully reusing a map transition for a getter. Nevertheless, this is 4328 // successfully reusing a map transition for a getter. Nevertheless, this is
4341 // OK, because the assertion only holds for the whole addition of both 4329 // OK, because the assertion only holds for the whole addition of both
4342 // accessors, not for the addition of each part. See first comment in 4330 // accessors, not for the addition of each part. See first comment in
4343 // DefinePropertyAccessor below. 4331 // DefinePropertyAccessor below.
4344 Object* obj = result.GetCallbackObject(); 4332 Object* obj = result.GetCallbackObject();
4345 if (obj->IsAccessorPair()) { 4333 if (obj->IsAccessorPair()) {
4346 return AccessorPair::cast(obj)->CopyWithoutTransitions(); 4334 return AccessorPair::cast(obj)->Copy();
4347 } 4335 }
4348 } 4336 }
4349 return GetHeap()->AllocateAccessorPair(); 4337 return GetHeap()->AllocateAccessorPair();
4350 } 4338 }
4351 4339
4352 4340
4353 MaybeObject* JSObject::DefinePropertyAccessor(String* name, 4341 MaybeObject* JSObject::DefinePropertyAccessor(String* name,
4354 Object* getter, 4342 Object* getter,
4355 Object* setter, 4343 Object* setter,
4356 PropertyAttributes attributes) { 4344 PropertyAttributes attributes) {
(...skipping 13 matching lines...) Expand all
4370 setterOk = DefineFastAccessor(name, ACCESSOR_SETTER, setter, attributes); 4358 setterOk = DefineFastAccessor(name, ACCESSOR_SETTER, setter, attributes);
4371 if (setterOk->IsFailure()) return setterOk; 4359 if (setterOk->IsFailure()) return setterOk;
4372 } 4360 }
4373 4361
4374 if (getterOk != heap->null_value() && setterOk != heap->null_value()) { 4362 if (getterOk != heap->null_value() && setterOk != heap->null_value()) {
4375 return heap->undefined_value(); 4363 return heap->undefined_value();
4376 } 4364 }
4377 } 4365 }
4378 4366
4379 AccessorPair* accessors; 4367 AccessorPair* accessors;
4380 { MaybeObject* maybe_accessors = CreateAccessorPairFor(name); 4368 MaybeObject* maybe_accessors = CreateAccessorPairFor(name);
4381 if (!maybe_accessors->To(&accessors)) return maybe_accessors; 4369 if (!maybe_accessors->To(&accessors)) return maybe_accessors;
4382 } 4370
4383 accessors->SetComponents(getter, setter); 4371 accessors->SetComponents(getter, setter);
4384 return SetPropertyCallback(name, accessors, attributes); 4372 return SetPropertyCallback(name, accessors, attributes);
4385 } 4373 }
4386 4374
4387 4375
4388 bool JSObject::CanSetCallback(String* name) { 4376 bool JSObject::CanSetCallback(String* name) {
4389 ASSERT(!IsAccessCheckNeeded() || 4377 ASSERT(!IsAccessCheckNeeded() ||
4390 GetIsolate()->MayNamedAccess(this, name, v8::ACCESS_SET)); 4378 GetIsolate()->MayNamedAccess(this, name, v8::ACCESS_SET));
4391 4379
4392 // Check if there is an API defined callback object which prohibits 4380 // Check if there is an API defined callback object which prohibits
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
4444 } 4432 }
4445 4433
4446 return GetHeap()->undefined_value(); 4434 return GetHeap()->undefined_value();
4447 } 4435 }
4448 4436
4449 4437
4450 MaybeObject* JSObject::SetPropertyCallback(String* name, 4438 MaybeObject* JSObject::SetPropertyCallback(String* name,
4451 Object* structure, 4439 Object* structure,
4452 PropertyAttributes attributes) { 4440 PropertyAttributes attributes) {
4453 // Normalize object to make this operation simple. 4441 // Normalize object to make this operation simple.
4454 { MaybeObject* maybe_ok = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); 4442 MaybeObject* maybe_ok = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
4455 if (maybe_ok->IsFailure()) return maybe_ok; 4443 if (maybe_ok->IsFailure()) return maybe_ok;
4456 }
4457 4444
4458 // For the global object allocate a new map to invalidate the global inline 4445 // For the global object allocate a new map to invalidate the global inline
4459 // caches which have a global property cell reference directly in the code. 4446 // caches which have a global property cell reference directly in the code.
4460 if (IsGlobalObject()) { 4447 if (IsGlobalObject()) {
4461 Map* new_map; 4448 Map* new_map;
4462 { MaybeObject* maybe_new_map = map()->CopyDropDescriptors(); 4449 MaybeObject* maybe_new_map = map()->CopyDropDescriptors();
4463 if (!maybe_new_map->To(&new_map)) return maybe_new_map; 4450 if (!maybe_new_map->To(&new_map)) return maybe_new_map;
4464 } 4451
4465 set_map(new_map); 4452 set_map(new_map);
4466 // When running crankshaft, changing the map is not enough. We 4453 // When running crankshaft, changing the map is not enough. We
4467 // need to deoptimize all functions that rely on this global 4454 // need to deoptimize all functions that rely on this global
4468 // object. 4455 // object.
4469 Deoptimizer::DeoptimizeGlobalObject(this); 4456 Deoptimizer::DeoptimizeGlobalObject(this);
4470 } 4457 }
4471 4458
4472 // Update the dictionary with the new CALLBACKS property. 4459 // Update the dictionary with the new CALLBACKS property.
4473 PropertyDetails details = PropertyDetails(attributes, CALLBACKS); 4460 PropertyDetails details = PropertyDetails(attributes, CALLBACKS);
4474 { MaybeObject* maybe_ok = SetNormalizedProperty(name, structure, details); 4461 maybe_ok = SetNormalizedProperty(name, structure, details);
4475 if (maybe_ok->IsFailure()) return maybe_ok; 4462 if (maybe_ok->IsFailure()) return maybe_ok;
4476 }
4477 4463
4478 return GetHeap()->undefined_value(); 4464 return GetHeap()->undefined_value();
4479 } 4465 }
4480 4466
4481 4467
4482 void JSObject::DefineAccessor(Handle<JSObject> object, 4468 void JSObject::DefineAccessor(Handle<JSObject> object,
4483 Handle<String> name, 4469 Handle<String> name,
4484 Handle<Object> getter, 4470 Handle<Object> getter,
4485 Handle<Object> setter, 4471 Handle<Object> setter,
4486 PropertyAttributes attributes) { 4472 PropertyAttributes attributes) {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
4518 4504
4519 if (!CanSetCallback(name)) return isolate->heap()->undefined_value(); 4505 if (!CanSetCallback(name)) return isolate->heap()->undefined_value();
4520 4506
4521 uint32_t index = 0; 4507 uint32_t index = 0;
4522 return name->AsArrayIndex(&index) ? 4508 return name->AsArrayIndex(&index) ?
4523 DefineElementAccessor(index, getter, setter, attributes) : 4509 DefineElementAccessor(index, getter, setter, attributes) :
4524 DefinePropertyAccessor(name, getter, setter, attributes); 4510 DefinePropertyAccessor(name, getter, setter, attributes);
4525 } 4511 }
4526 4512
4527 4513
4528 static MaybeObject* CreateFreshAccessor(JSObject* obj, 4514 static MaybeObject* TryAccessorTransition(JSObject* self,
4529 String* name, 4515 Map* transitioned_map,
4530 AccessorComponent component, 4516 String* name,
4531 Object* accessor, 4517 AccessorComponent component,
4532 PropertyAttributes attributes) { 4518 Object* accessor,
4533 // step 1: create a new getter/setter pair with only the accessor in it 4519 PropertyAttributes attributes) {
4534 Heap* heap = obj->GetHeap(); 4520 DescriptorArray* descs = transitioned_map->instance_descriptors();
4535 AccessorPair* accessors2; 4521 int number = descs->LastAdded();
4536 { MaybeObject* maybe_accessors2 = heap->AllocateAccessorPair(); 4522 PropertyDetails details = descs->GetDetails(number);
4537 if (!maybe_accessors2->To(&accessors2)) return maybe_accessors2;
4538 }
4539 accessors2->set(component, accessor);
4540 4523
4541 // step 2: create a copy of the descriptors, incl. the new getter/setter pair 4524 // If the transition target was not callbacks, fall back to the slow case.
4542 Map* map1 = obj->map(); 4525 if (details.type() != CALLBACKS) return self->GetHeap()->null_value();
4543 CallbacksDescriptor callbacks_descr2(name, accessors2, attributes, 0); 4526
4544 DescriptorArray* descriptors2; 4527 Object* target_accessor =
4545 { MaybeObject* maybe_descriptors2 = 4528 AccessorPair::cast(descs->GetCallbacksObject(number))->get(component);
4546 map1->instance_descriptors()->CopyAdd(&callbacks_descr2); 4529 PropertyAttributes target_attributes = details.attributes();
4547 if (!maybe_descriptors2->To(&descriptors2)) return maybe_descriptors2; 4530
4531 // Reuse transition if adding same accessor with same attributes.
4532 if (target_accessor == accessor && target_attributes == attributes) {
4533 self->set_map(transitioned_map);
4534 return self;
4548 } 4535 }
4549 4536
4550 // step 3: create a new map with the new descriptors 4537 // If either not the same accessor, or not the same attributes, fall back to
4551 Map* map2; 4538 // the slow case.
4552 { MaybeObject* maybe_map2 = map1->CopyReplaceDescriptors(descriptors2); 4539 return self->GetHeap()->null_value();
4553 if (!maybe_map2->To(&map2)) return maybe_map2;
4554 }
4555
4556 // step 4: create a new getter/setter pair with a transition to the new map
4557 AccessorPair* accessors1;
4558 { MaybeObject* maybe_accessors1 = heap->AllocateAccessorPair();
4559 if (!maybe_accessors1->To(&accessors1)) return maybe_accessors1;
4560 }
4561 accessors1->set(component, map2);
4562
4563 // step 5: create a copy of the descriptors, incl. the new getter/setter pair
4564 // with the transition
4565 TransitionArray* new_transitions;
4566 { MaybeObject* maybe_new_transitions = map1->AddTransition(name, accessors1);
4567 if (!maybe_new_transitions->To(&new_transitions)) {
4568 return maybe_new_transitions;
4569 }
4570 }
4571
4572 // step 6: everything went well so far, so we make our changes visible
4573 { MaybeObject* transition_added = map1->set_transitions(new_transitions);
4574 if (transition_added->IsFailure()) return transition_added;
4575 }
4576
4577 map2->SetBackPointer(map1);
4578 obj->set_map(map2);
4579 return obj;
4580 } 4540 }
4581 4541
4582 4542
4583 static bool TransitionToSameAccessor(Object* map,
4584 String* name,
4585 AccessorComponent component,
4586 Object* accessor,
4587 PropertyAttributes attributes ) {
4588 Map* transitioned_map = Map::cast(map);
4589 DescriptorArray* descs = transitioned_map->instance_descriptors();
4590 int number = descs->LastAdded();
4591 Object* target_accessor =
4592 AccessorPair::cast(descs->GetCallbacksObject(number))->get(component);
4593 PropertyAttributes target_attributes = descs->GetDetails(number).attributes();
4594 return target_accessor == accessor && target_attributes == attributes;
4595 }
4596
4597
4598 static MaybeObject* NewCallbackTransition(JSObject* obj, 4543 static MaybeObject* NewCallbackTransition(JSObject* obj,
4599 String* name, 4544 String* name,
4600 AccessorComponent component, 4545 AccessorComponent component,
4601 Object* accessor, 4546 Object* accessor,
4602 PropertyAttributes attributes, 4547 PropertyAttributes attributes,
4603 AccessorPair* accessors2) { 4548 AccessorPair* new_accessors) {
4604 // step 1: copy the old getter/setter pair and set the new accessor 4549 // step 1: create a copy of the descriptors, incl. the new getter/setter pair
4605 AccessorPair* accessors3; 4550 Map* old_map = obj->map();
4606 { MaybeObject* maybe_accessors3 = accessors2->CopyWithoutTransitions(); 4551 CallbacksDescriptor new_accessors_desc(name, new_accessors, attributes);
4607 if (!maybe_accessors3->To(&accessors3)) return maybe_accessors3; 4552 DescriptorArray* descriptors;
4608 } 4553 MaybeObject* maybe_descriptors =
4609 accessors3->set(component, accessor); 4554 old_map->instance_descriptors()->CopyInsert(&new_accessors_desc);
4555 if (!maybe_descriptors->To(&descriptors)) return maybe_descriptors;
4610 4556
4611 // step 2: create a copy of the descriptors, incl. the new getter/setter pair 4557 // step 2: create a new map with the new descriptors
4612 Map* map2 = obj->map(); 4558 Map* new_map;
4613 CallbacksDescriptor callbacks_descr3(name, accessors3, attributes, 0); 4559 MaybeObject* maybe_new_map = old_map->CopyReplaceDescriptors(descriptors);
4614 DescriptorArray* descriptors3; 4560 if (!maybe_new_map->To(&new_map)) return maybe_new_map;
4615 { MaybeObject* maybe_descriptors3 =
4616 map2->instance_descriptors()->CopyInsert(&callbacks_descr3);
4617 if (!maybe_descriptors3->To(&descriptors3)) return maybe_descriptors3;
4618 }
4619 4561
4620 // step 3: create a new map with the new descriptors 4562 // step 3: add a new transition to the new map
4621 Map* map3; 4563 TransitionArray* transitions;
4622 { MaybeObject* maybe_map3 = map2->CopyReplaceDescriptors(descriptors3); 4564 MaybeObject* maybe_transitions = old_map->AddTransition(name, new_map);
4623 if (!maybe_map3->To(&map3)) return maybe_map3; 4565 if (!maybe_transitions->To(&transitions)) return maybe_transitions;
4624 }
4625 4566
4626 // step 4: add a new transition to the new map 4567 // step 4: everything went well so far, so we make our changes visible
4627 TransitionArray* new_transitions; 4568 MaybeObject* transition_added = old_map->set_transitions(transitions);
4628 { MaybeObject* maybe_transitions = map2->AddTransition(name, accessors2); 4569 if (transition_added->IsFailure()) return transition_added;
4629 if (!maybe_transitions->To(&new_transitions)) return maybe_transitions;
4630 }
4631 4570
4632 // step 5: everything went well so far, so we make our changes visible 4571 new_map->SetBackPointer(old_map);
4633 { MaybeObject* transition_added = map2->set_transitions(new_transitions); 4572 obj->set_map(new_map);
4634 if (transition_added->IsFailure()) return transition_added;
4635 }
4636
4637 map3->SetBackPointer(map2);
4638 obj->set_map(map3);
4639 accessors2->set(component, map3);
4640 return obj; 4573 return obj;
4641 } 4574 }
4642 4575
4643 4576
4644 MaybeObject* JSObject::DefineFastAccessor(String* name, 4577 MaybeObject* JSObject::DefineFastAccessor(String* name,
4645 AccessorComponent component, 4578 AccessorComponent component,
4646 Object* accessor, 4579 Object* accessor,
4647 PropertyAttributes attributes) { 4580 PropertyAttributes attributes) {
4648 ASSERT(accessor->IsSpecFunction() || accessor->IsUndefined()); 4581 ASSERT(accessor->IsSpecFunction() || accessor->IsUndefined());
4649 LookupResult result(GetIsolate()); 4582 LookupResult result(GetIsolate());
4650 LocalLookup(name, &result); 4583 LocalLookup(name, &result);
4651 4584
4652 // If we have a new property, create a fresh accessor plus a transition to it. 4585 if (result.IsFound()
4653 if (!result.IsFound()) { 4586 && !result.IsPropertyCallbacks()
4654 return CreateFreshAccessor(this, name, component, accessor, attributes); 4587 && !result.IsTransition()) return GetHeap()->null_value();
4588
4589 // Return success if the same accessor with the same attributes already exist.
4590 AccessorPair* source_accessors = NULL;
4591 if (result.IsPropertyCallbacks()) {
4592 Object* callback_value = result.GetCallbackObject();
4593 if (callback_value->IsAccessorPair()) {
4594 source_accessors = AccessorPair::cast(callback_value);
4595 Object* entry = source_accessors->get(component);
4596 if (entry == accessor && result.GetAttributes() == attributes) {
4597 return this;
4598 }
4599 }
4655 } 4600 }
4656 4601
4657 // If the property is not a JavaScript accessor, fall back to the slow case. 4602 // If not, lookup a transition.
4658 if (!result.IsCallbacks()) return GetHeap()->null_value(); 4603 map()->LookupTransition(this, name, &result);
4659 4604
4660 Object* callback_value = result.GetCallbackObject(); 4605 // If there is a transition, try to follow it.
4661 if (!callback_value->IsAccessorPair()) return GetHeap()->null_value(); 4606 if (result.IsFound()) {
4662 AccessorPair* accessors = AccessorPair::cast(callback_value); 4607 Map* target = result.GetTransitionTarget();
4663 4608 return TryAccessorTransition(
4664 // Follow a callback transition, if there is a fitting one. 4609 this, target, name, component, accessor, attributes);
4665 Object* entry = accessors->get(component);
4666 if (entry->IsMap() &&
4667 TransitionToSameAccessor(entry, name, component, accessor, attributes)) {
4668 set_map(Map::cast(entry));
4669 return this;
4670 } 4610 }
4671 4611
4672 if (entry == accessor && result.GetAttributes() == attributes) return this; 4612 // If there is no transition yet, add a transition to the a new accessor pair
4613 // containing the accessor.
4614 AccessorPair* accessors;
4615 MaybeObject* maybe_accessors;
4673 4616
4674 // Only the other accessor has been set so far, create a new transition. 4617 // Allocate a new pair if there were no source accessors. Otherwise, copy the
4675 if (entry->IsTheHole()) { 4618 // pair and modify the accessor.
4676 return NewCallbackTransition(this, 4619 if (source_accessors != NULL) {
4677 name, 4620 maybe_accessors = source_accessors->Copy();
4678 component, 4621 } else {
4679 accessor, 4622 maybe_accessors = GetHeap()->AllocateAccessorPair();
4680 attributes,
4681 accessors);
4682 } 4623 }
4624 if (!maybe_accessors->To(&accessors)) return maybe_accessors;
4625 accessors->set(component, accessor);
4683 4626
4684 // Nothing from the above worked, so we have to fall back to the slow case. 4627 return NewCallbackTransition(this,
4685 return GetHeap()->null_value(); 4628 name,
4629 component,
4630 accessor,
4631 attributes,
4632 accessors);
4686 } 4633 }
4687 4634
4688 4635
4689 MaybeObject* JSObject::DefineAccessor(AccessorInfo* info) { 4636 MaybeObject* JSObject::DefineAccessor(AccessorInfo* info) {
4690 Isolate* isolate = GetIsolate(); 4637 Isolate* isolate = GetIsolate();
4691 String* name = String::cast(info->name()); 4638 String* name = String::cast(info->name());
4692 // Check access rights if needed. 4639 // Check access rights if needed.
4693 if (IsAccessCheckNeeded() && 4640 if (IsAccessCheckNeeded() &&
4694 !isolate->MayNamedAccess(this, name, v8::ACCESS_SET)) { 4641 !isolate->MayNamedAccess(this, name, v8::ACCESS_SET)) {
4695 isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET); 4642 isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET);
(...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after
5005 ASSERT(!IsIterating()); 4952 ASSERT(!IsIterating());
5006 *TransitionArrayHeader() = Smi::FromInt(0); 4953 *TransitionArrayHeader() = Smi::FromInt(0);
5007 } 4954 }
5008 4955
5009 bool IsIterating() { 4956 bool IsIterating() {
5010 return (*TransitionArrayHeader())->IsSmi(); 4957 return (*TransitionArrayHeader())->IsSmi();
5011 } 4958 }
5012 4959
5013 Map* Next() { 4960 Map* Next() {
5014 ASSERT(IsIterating()); 4961 ASSERT(IsIterating());
5015 // Attention, tricky index manipulation ahead: Two consecutive indices are 4962 int index = Smi::cast(*TransitionArrayHeader())->value();
5016 // assigned to each descriptor. Most descriptors directly advance to the
5017 // next descriptor by adding 2 to the index. The exceptions are the
5018 // CALLBACKS entries: An even index means we look at its getter, and an odd
5019 // index means we look at its setter.
5020 int raw_index = Smi::cast(*TransitionArrayHeader())->value();
5021 int index = raw_index / 2;
5022 int number_of_transitions = transition_array_->number_of_transitions(); 4963 int number_of_transitions = transition_array_->number_of_transitions();
5023 while (index < number_of_transitions) { 4964 while (index < number_of_transitions) {
5024 Object* value = transition_array_->GetValue(index); 4965 *TransitionArrayHeader() = Smi::FromInt(index + 1);
5025 4966 return transition_array_->GetTarget(index);
5026 if (value->IsMap()) {
5027 *TransitionArrayHeader() = Smi::FromInt(raw_index + 2);
5028 return static_cast<Map*>(value);
5029 }
5030
5031 ASSERT(value->IsAccessorPair());
5032
5033 // We might have a map transition in a getter or in a setter.
5034 AccessorPair* accessors = static_cast<AccessorPair*>(value);
5035 Object* accessor;
5036 if ((raw_index & 1) == 0) {
5037 accessor = accessors->setter();
5038 } else {
5039 ++index;
5040 accessor = accessors->getter();
5041 }
5042 ++raw_index;
5043 if (accessor->IsMap()) {
5044 *TransitionArrayHeader() = Smi::FromInt(raw_index);
5045 return static_cast<Map*>(accessor);
5046 }
5047 } 4967 }
5048 4968
5049 if (index == transition_array_->number_of_transitions() && 4969 if (index == number_of_transitions &&
5050 transition_array_->HasElementsTransition()) { 4970 transition_array_->HasElementsTransition()) {
5051 Map* elements_transition = transition_array_->elements_transition(); 4971 Map* elements_transition = transition_array_->elements_transition();
5052 *TransitionArrayHeader() = Smi::FromInt(raw_index + 2); 4972 *TransitionArrayHeader() = Smi::FromInt(index + 1);
5053 return elements_transition; 4973 return elements_transition;
5054 } 4974 }
5055 *TransitionArrayHeader() = transition_array_->GetHeap()->fixed_array_map(); 4975 *TransitionArrayHeader() = transition_array_->GetHeap()->fixed_array_map();
5056 return NULL; 4976 return NULL;
5057 } 4977 }
5058 4978
5059 private: 4979 private:
5060 Object** TransitionArrayHeader() { 4980 Object** TransitionArrayHeader() {
5061 return HeapObject::RawField(transition_array_, TransitionArray::kMapOffset); 4981 return HeapObject::RawField(transition_array_, TransitionArray::kMapOffset);
5062 } 4982 }
(...skipping 716 matching lines...) Expand 10 before | Expand all | Expand 10 after
5779 set(kLastAddedIndex, bridge_storage); 5699 set(kLastAddedIndex, bridge_storage);
5780 } 5700 }
5781 } 5701 }
5782 5702
5783 5703
5784 static bool InsertionPointFound(String* key1, String* key2) { 5704 static bool InsertionPointFound(String* key1, String* key2) {
5785 return key1->Hash() > key2->Hash() || key1 == key2; 5705 return key1->Hash() > key2->Hash() || key1 == key2;
5786 } 5706 }
5787 5707
5788 5708
5789 void DescriptorArray::CopyFrom(Handle<DescriptorArray> dst, 5709 void DescriptorArray::CopyFrom(int dst_index,
5790 int dst_index, 5710 DescriptorArray* src,
5791 Handle<DescriptorArray> src,
5792 int src_index, 5711 int src_index,
5793 const WhitenessWitness& witness) { 5712 const WhitenessWitness& witness) {
5794 CALL_HEAP_FUNCTION_VOID(dst->GetIsolate(),
5795 dst->CopyFrom(dst_index, *src, src_index, witness));
5796 }
5797
5798
5799 MaybeObject* DescriptorArray::CopyFrom(int dst_index,
5800 DescriptorArray* src,
5801 int src_index,
5802 const WhitenessWitness& witness) {
5803 Object* value = src->GetValue(src_index); 5713 Object* value = src->GetValue(src_index);
5804 PropertyDetails details = src->GetDetails(src_index); 5714 PropertyDetails details = src->GetDetails(src_index);
5805 if (details.type() == CALLBACKS && value->IsAccessorPair()) {
5806 MaybeObject* maybe_copy =
5807 AccessorPair::cast(value)->CopyWithoutTransitions();
5808 if (!maybe_copy->To(&value)) return maybe_copy;
5809 }
5810 Descriptor desc(src->GetKey(src_index), value, details); 5715 Descriptor desc(src->GetKey(src_index), value, details);
5811 Set(dst_index, &desc, witness); 5716 Set(dst_index, &desc, witness);
5812 return this;
5813 } 5717 }
5814 5718
5815 MaybeObject* DescriptorArray::CopyReplace(Descriptor* descriptor, 5719 MaybeObject* DescriptorArray::CopyReplace(Descriptor* descriptor,
5816 int insertion_index) { 5720 int insertion_index) {
5817 ASSERT(0 <= insertion_index && insertion_index < number_of_descriptors()); 5721 ASSERT(0 <= insertion_index && insertion_index < number_of_descriptors());
5818 5722
5819 // Ensure the key is a symbol. 5723 // Ensure the key is a symbol.
5820 { MaybeObject* maybe_result = descriptor->KeyToSymbol(); 5724 { MaybeObject* maybe_result = descriptor->KeyToSymbol();
5821 if (maybe_result->IsFailure()) return maybe_result; 5725 if (maybe_result->IsFailure()) return maybe_result;
5822 } 5726 }
5823 5727
5824 int size = number_of_descriptors(); 5728 int size = number_of_descriptors();
5825 5729
5826 DescriptorArray* new_descriptors; 5730 DescriptorArray* new_descriptors;
5827 { MaybeObject* maybe_result = Allocate(size, MAY_BE_SHARED); 5731 { MaybeObject* maybe_result = Allocate(size, MAY_BE_SHARED);
5828 if (!maybe_result->To(&new_descriptors)) return maybe_result; 5732 if (!maybe_result->To(&new_descriptors)) return maybe_result;
5829 } 5733 }
5830 5734
5831 FixedArray::WhitenessWitness witness(new_descriptors); 5735 FixedArray::WhitenessWitness witness(new_descriptors);
5832 5736
5833 // Copy the descriptors, replacing a descriptor. 5737 // Copy the descriptors, replacing a descriptor.
5834 for (int index = 0; index < size; ++index) { 5738 for (int index = 0; index < size; ++index) {
5835 if (index == insertion_index) continue; 5739 if (index == insertion_index) continue;
5836 MaybeObject* copy_result = 5740 new_descriptors->CopyFrom(index, this, index, witness);
5837 new_descriptors->CopyFrom(index, this, index, witness);
5838 if (copy_result->IsFailure()) return copy_result;
5839 } 5741 }
5840 5742
5841 descriptor->SetEnumerationIndex(GetDetails(insertion_index).index()); 5743 descriptor->SetEnumerationIndex(GetDetails(insertion_index).index());
5842 new_descriptors->Set(insertion_index, descriptor, witness); 5744 new_descriptors->Set(insertion_index, descriptor, witness);
5843 new_descriptors->SetLastAdded(LastAdded()); 5745 new_descriptors->SetLastAdded(LastAdded());
5844 5746
5845 SLOW_ASSERT(new_descriptors->IsSortedNoDuplicates()); 5747 SLOW_ASSERT(new_descriptors->IsSortedNoDuplicates());
5846 5748
5847 return new_descriptors; 5749 return new_descriptors;
5848 } 5750 }
5849 5751
5850 5752
5851 MaybeObject* DescriptorArray::CopyInsert(Descriptor* descriptor) { 5753 MaybeObject* DescriptorArray::CopyInsert(Descriptor* descriptor) {
5852 // Ensure the key is a symbol. 5754 // Ensure the key is a symbol.
5853 { MaybeObject* maybe_result = descriptor->KeyToSymbol(); 5755 MaybeObject* maybe_result = descriptor->KeyToSymbol();
5854 if (maybe_result->IsFailure()) return maybe_result; 5756 if (maybe_result->IsFailure()) return maybe_result;
5855 }
5856 5757
5857 // We replace the key if it is already present. 5758 // We replace the key if it is already present.
5858 int index = SearchWithCache(descriptor->GetKey()); 5759 int index = SearchWithCache(descriptor->GetKey());
5859 if (index == kNotFound) return CopyAdd(descriptor); 5760 if (index == kNotFound) return CopyAdd(descriptor);
5860 return CopyReplace(descriptor, index); 5761 return CopyReplace(descriptor, index);
5861 } 5762 }
5862 5763
5863 5764
5864 MaybeObject* DescriptorArray::CopyAdd(Descriptor* descriptor) { 5765 MaybeObject* DescriptorArray::CopyAdd(Descriptor* descriptor) {
5865 // Ensure the key is a symbol. 5766 // Ensure the key is a symbol.
5866 { MaybeObject* maybe_result = descriptor->KeyToSymbol(); 5767 MaybeObject* maybe_result = descriptor->KeyToSymbol();
5867 if (maybe_result->IsFailure()) return maybe_result; 5768 if (maybe_result->IsFailure()) return maybe_result;
5868 }
5869 5769
5870 String* key = descriptor->GetKey(); 5770 String* key = descriptor->GetKey();
5871 ASSERT(Search(key) == kNotFound); 5771 ASSERT(Search(key) == kNotFound);
5872 5772
5873 int new_size = number_of_descriptors() + 1; 5773 int new_size = number_of_descriptors() + 1;
5874 5774
5875 DescriptorArray* new_descriptors; 5775 DescriptorArray* new_descriptors;
5876 { MaybeObject* maybe_result = Allocate(new_size, MAY_BE_SHARED); 5776 MaybeObject* maybe_descriptors = Allocate(new_size, MAY_BE_SHARED);
5877 if (!maybe_result->To(&new_descriptors)) return maybe_result; 5777 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
5878 }
5879 5778
5880 FixedArray::WhitenessWitness witness(new_descriptors); 5779 FixedArray::WhitenessWitness witness(new_descriptors);
5881 5780
5882 // Copy the descriptors, inserting a descriptor. 5781 // Copy the descriptors, inserting a descriptor.
5883 int insertion_index = -1; 5782 int insertion_index = -1;
5884 int to = 0; 5783 int to = 0;
5885 for (int from = 0; from < number_of_descriptors(); ++from) { 5784 for (int from = 0; from < number_of_descriptors(); ++from) {
5886 if (insertion_index < 0 && InsertionPointFound(GetKey(from), key)) { 5785 if (insertion_index < 0 && InsertionPointFound(GetKey(from), key)) {
5887 insertion_index = to++; 5786 insertion_index = to++;
5888 } 5787 }
5889 MaybeObject* copy_result = 5788 new_descriptors->CopyFrom(to++, this, from, witness);
5890 new_descriptors->CopyFrom(to++, this, from, witness);
5891 if (copy_result->IsFailure()) return copy_result;
5892 } 5789 }
5893 if (insertion_index < 0) insertion_index = to++; 5790 if (insertion_index < 0) insertion_index = to++;
5894 5791
5895 ASSERT(to == new_descriptors->number_of_descriptors()); 5792 ASSERT(to == new_descriptors->number_of_descriptors());
5896 5793
5897 ASSERT(new_size == NextEnumerationIndex()); 5794 ASSERT(new_size == NextEnumerationIndex());
5898 descriptor->SetEnumerationIndex(new_size); 5795 descriptor->SetEnumerationIndex(new_size);
5899 new_descriptors->Set(insertion_index, descriptor, witness); 5796 new_descriptors->Set(insertion_index, descriptor, witness);
5900 new_descriptors->SetLastAdded(insertion_index); 5797 new_descriptors->SetLastAdded(insertion_index);
5901 5798
5902 SLOW_ASSERT(new_descriptors->IsSortedNoDuplicates()); 5799 SLOW_ASSERT(new_descriptors->IsSortedNoDuplicates());
5903 5800
5904 return new_descriptors; 5801 return new_descriptors;
5905 } 5802 }
5906 5803
5907 5804
5908 MaybeObject* DescriptorArray::Copy(SharedMode shared_mode) { 5805 MaybeObject* DescriptorArray::Copy(SharedMode shared_mode) {
5909 // Allocate the new descriptor array. 5806 // Allocate the new descriptor array.
5910 int number_of_descriptors = this->number_of_descriptors(); 5807 int number_of_descriptors = this->number_of_descriptors();
5911 DescriptorArray* new_descriptors; 5808 DescriptorArray* new_descriptors;
5912 { MaybeObject* maybe_result = Allocate(number_of_descriptors, 5809 MaybeObject* maybe_result = Allocate(number_of_descriptors, shared_mode);
5913 shared_mode); 5810 if (!maybe_result->To(&new_descriptors)) return maybe_result;
5914 if (!maybe_result->To(&new_descriptors)) return maybe_result;
5915 }
5916 5811
5917 // Copy the content. 5812 // Copy the content.
5918 if (number_of_descriptors > 0) { 5813 if (number_of_descriptors > 0) {
5919 FixedArray::WhitenessWitness witness(new_descriptors); 5814 FixedArray::WhitenessWitness witness(new_descriptors);
5920 for (int i = 0; i < number_of_descriptors; i++) { 5815 for (int i = 0; i < number_of_descriptors; i++) {
5921 MaybeObject* copy_result = 5816 new_descriptors->CopyFrom(i, this, i, witness);
5922 new_descriptors->CopyFrom(i, this, i, witness);
5923 if (copy_result->IsFailure()) return copy_result;
5924 } 5817 }
5925 new_descriptors->SetLastAdded(LastAdded()); 5818 new_descriptors->SetLastAdded(LastAdded());
5926 } 5819 }
5927 5820
5928 return new_descriptors; 5821 return new_descriptors;
5929 } 5822 }
5930 5823
5931 // We need the whiteness witness since sort will reshuffle the entries in the 5824 // We need the whiteness witness since sort will reshuffle the entries in the
5932 // descriptor array. If the descriptor array were to be black, the shuffling 5825 // descriptor array. If the descriptor array were to be black, the shuffling
5933 // would move a slot that was already recorded as pointing into an evacuation 5826 // would move a slot that was already recorded as pointing into an evacuation
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
6013 UNREACHABLE(); 5906 UNREACHABLE();
6014 } 5907 }
6015 5908
6016 5909
6017 void DescriptorArray::Sort(const WhitenessWitness& witness) { 5910 void DescriptorArray::Sort(const WhitenessWitness& witness) {
6018 SortUnchecked(witness); 5911 SortUnchecked(witness);
6019 SLOW_ASSERT(IsSortedNoDuplicates()); 5912 SLOW_ASSERT(IsSortedNoDuplicates());
6020 } 5913 }
6021 5914
6022 5915
6023 MaybeObject* AccessorPair::CopyWithoutTransitions() { 5916 MaybeObject* AccessorPair::Copy() {
6024 Heap* heap = GetHeap(); 5917 Heap* heap = GetHeap();
6025 AccessorPair* copy; 5918 AccessorPair* copy;
6026 { MaybeObject* maybe_copy = heap->AllocateAccessorPair(); 5919 MaybeObject* maybe_copy = heap->AllocateAccessorPair();
6027 if (!maybe_copy->To(&copy)) return maybe_copy; 5920 if (!maybe_copy->To(&copy)) return maybe_copy;
6028 } 5921
6029 copy->set_getter(getter()->IsMap() ? heap->the_hole_value() : getter()); 5922 copy->set_getter(getter());
6030 copy->set_setter(setter()->IsMap() ? heap->the_hole_value() : setter()); 5923 copy->set_setter(setter());
6031 return copy; 5924 return copy;
6032 } 5925 }
6033 5926
6034 5927
6035 Object* AccessorPair::GetComponent(AccessorComponent component) { 5928 Object* AccessorPair::GetComponent(AccessorComponent component) {
6036 Object* accessor = get(component); 5929 Object* accessor = get(component);
6037 return accessor->IsTheHole() ? GetHeap()->undefined_value() : accessor; 5930 return accessor->IsTheHole() ? GetHeap()->undefined_value() : accessor;
6038 } 5931 }
6039 5932
6040 5933
(...skipping 1265 matching lines...) Expand 10 before | Expand all | Expand 10 after
7306 // Return true in case a back pointer has been cleared and false otherwise. 7199 // Return true in case a back pointer has been cleared and false otherwise.
7307 static bool ClearBackPointer(Heap* heap, Object* target) { 7200 static bool ClearBackPointer(Heap* heap, Object* target) {
7308 ASSERT(target->IsMap()); 7201 ASSERT(target->IsMap());
7309 Map* map = Map::cast(target); 7202 Map* map = Map::cast(target);
7310 if (Marking::MarkBitFrom(map).Get()) return false; 7203 if (Marking::MarkBitFrom(map).Get()) return false;
7311 map->SetBackPointer(heap->undefined_value(), SKIP_WRITE_BARRIER); 7204 map->SetBackPointer(heap->undefined_value(), SKIP_WRITE_BARRIER);
7312 return true; 7205 return true;
7313 } 7206 }
7314 7207
7315 7208
7316 static bool ClearAccessorComponent(Heap* heap,
7317 AccessorPair* accessors,
7318 AccessorComponent component) {
7319 Object* component_value = accessors->get(component);
7320 if (!component_value->IsMap()) return true;
7321 if (ClearBackPointer(heap, component_value)) {
7322 accessors->set(component, heap->the_hole_value());
7323 return true;
7324 }
7325 return false;
7326 }
7327
7328
7329 static bool ClearNonLiveTransition(Heap* heap,
7330 TransitionArray* t,
7331 int transition_index) {
7332 // If the value is a map, check if the target is live. If not, clear the
7333 // transition. Also drop the back pointer for that map transition, so that
7334 // this map is not reached again by following a back pointer from that
7335 // non-live map.
7336 Object* value = t->GetValue(transition_index);
7337 if (value->IsMap()) {
7338 return ClearBackPointer(heap, t->GetValue(transition_index));
7339 }
7340
7341 ASSERT(value->IsAccessorPair());
7342
7343 AccessorPair* accessors = AccessorPair::cast(value);
7344 bool getter = ClearAccessorComponent(heap, accessors, ACCESSOR_GETTER);
7345 bool setter = ClearAccessorComponent(heap, accessors, ACCESSOR_SETTER);
7346 return getter && setter;
7347 }
7348
7349
7350 // TODO(mstarzinger): This method should be moved into MarkCompactCollector, 7209 // TODO(mstarzinger): This method should be moved into MarkCompactCollector,
7351 // because it cannot be called from outside the GC and we already have methods 7210 // because it cannot be called from outside the GC and we already have methods
7352 // depending on the transitions layout in the GC anyways. 7211 // depending on the transitions layout in the GC anyways.
7353 void Map::ClearNonLiveTransitions(Heap* heap) { 7212 void Map::ClearNonLiveTransitions(Heap* heap) {
7354 // If there are no transitions to be cleared, return. 7213 // If there are no transitions to be cleared, return.
7355 // TODO(verwaest) Should be an assert, otherwise back pointers are not 7214 // TODO(verwaest) Should be an assert, otherwise back pointers are not
7356 // properly cleared. 7215 // properly cleared.
7357 if (!HasTransitionArray()) return; 7216 if (!HasTransitionArray()) return;
7358 7217
7359 TransitionArray* t = transitions(); 7218 TransitionArray* t = transitions();
7360 7219
7361 int transition_index = 0; 7220 int transition_index = 0;
7362 7221
7363 // Compact all live descriptors to the left. 7222 // Compact all live descriptors to the left.
7364 for (int i = 0; i < t->number_of_transitions(); ++i) { 7223 for (int i = 0; i < t->number_of_transitions(); ++i) {
7365 if (!ClearNonLiveTransition(heap, t, i)) { 7224 if (!ClearBackPointer(heap, t->GetTarget(i))) {
7366 if (i != transition_index) { 7225 if (i != transition_index) {
7367 String* key = t->GetKey(i); 7226 String* key = t->GetKey(i);
7368 Object* value = t->GetValue(i); 7227 Map* target = t->GetTarget(i);
7369 t->SetKey(transition_index, key); 7228 t->SetKey(transition_index, key);
7370 t->SetValue(transition_index, value); 7229 t->SetTarget(transition_index, target);
7371 MarkCompactCollector* collector = heap->mark_compact_collector(); 7230 MarkCompactCollector* collector = heap->mark_compact_collector();
7372 Object** key_slot = t->GetKeySlot(transition_index); 7231 Object** key_slot = t->GetKeySlot(transition_index);
7373 collector->RecordSlot(key_slot, key_slot, key); 7232 collector->RecordSlot(key_slot, key_slot, key);
7374 Object** value_slot = t->GetValueSlot(transition_index); 7233 Object** target_slot = t->GetTargetSlot(transition_index);
7375 collector->RecordSlot(value_slot, value_slot, value); 7234 collector->RecordSlot(target_slot, target_slot, target);
7376 } 7235 }
7377 transition_index++; 7236 transition_index++;
7378 } 7237 }
7379 } 7238 }
7380 7239
7381 if (t->HasElementsTransition() && 7240 if (t->HasElementsTransition() &&
7382 ClearBackPointer(heap, t->elements_transition())) { 7241 ClearBackPointer(heap, t->elements_transition())) {
7383 t->ClearElementsTransition(); 7242 t->ClearElementsTransition();
7384 } else { 7243 } else {
7385 // If there are no transitions to be cleared, return. 7244 // If there are no transitions to be cleared, return.
(...skipping 3079 matching lines...) Expand 10 before | Expand all | Expand 10 after
10465 Isolate* isolate = GetIsolate(); 10324 Isolate* isolate = GetIsolate();
10466 if (IsAccessCheckNeeded()) { 10325 if (IsAccessCheckNeeded()) {
10467 if (!isolate->MayNamedAccess(this, key, v8::ACCESS_HAS)) { 10326 if (!isolate->MayNamedAccess(this, key, v8::ACCESS_HAS)) {
10468 isolate->ReportFailedAccessCheck(this, v8::ACCESS_HAS); 10327 isolate->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
10469 return false; 10328 return false;
10470 } 10329 }
10471 } 10330 }
10472 10331
10473 LookupResult result(isolate); 10332 LookupResult result(isolate);
10474 LocalLookupRealNamedProperty(key, &result); 10333 LocalLookupRealNamedProperty(key, &result);
10475 return result.IsCallbacks(); 10334 return result.IsPropertyCallbacks();
10476 } 10335 }
10477 10336
10478 10337
10479 int JSObject::NumberOfLocalProperties(PropertyAttributes filter) { 10338 int JSObject::NumberOfLocalProperties(PropertyAttributes filter) {
10480 return HasFastProperties() ? 10339 return HasFastProperties() ?
10481 map()->NumberOfDescribedProperties(filter) : 10340 map()->NumberOfDescribedProperties(filter) :
10482 property_dictionary()->NumberOfElementsFilterAttributes(filter); 10341 property_dictionary()->NumberOfElementsFilterAttributes(filter);
10483 } 10342 }
10484 10343
10485 10344
(...skipping 2203 matching lines...) Expand 10 before | Expand all | Expand 10 after
12689 } 12548 }
12690 12549
12691 // Fill in the instance descriptor and the fields. 12550 // Fill in the instance descriptor and the fields.
12692 int next_descriptor = 0; 12551 int next_descriptor = 0;
12693 int current_offset = 0; 12552 int current_offset = 0;
12694 for (int i = 0; i < capacity; i++) { 12553 for (int i = 0; i < capacity; i++) {
12695 Object* k = KeyAt(i); 12554 Object* k = KeyAt(i);
12696 if (IsKey(k)) { 12555 if (IsKey(k)) {
12697 Object* value = ValueAt(i); 12556 Object* value = ValueAt(i);
12698 // Ensure the key is a symbol before writing into the instance descriptor. 12557 // Ensure the key is a symbol before writing into the instance descriptor.
12699 Object* key; 12558 String* key;
12700 { MaybeObject* maybe_key = heap->LookupSymbol(String::cast(k)); 12559 MaybeObject* maybe_key = heap->LookupSymbol(String::cast(k));
12701 if (!maybe_key->ToObject(&key)) return maybe_key; 12560 if (!maybe_key->To(&key)) return maybe_key;
12702 } 12561
12703 PropertyDetails details = DetailsAt(i); 12562 PropertyDetails details = DetailsAt(i);
12704 PropertyType type = details.type(); 12563 PropertyType type = details.type();
12705 12564
12706 if (value->IsJSFunction() && !heap->InNewSpace(value)) { 12565 if (value->IsJSFunction() && !heap->InNewSpace(value)) {
12707 ConstantFunctionDescriptor d(String::cast(key), 12566 ConstantFunctionDescriptor d(key,
12708 JSFunction::cast(value), 12567 JSFunction::cast(value),
12709 details.attributes(), 12568 details.attributes(),
12710 details.index()); 12569 details.index());
12711 descriptors->Set(next_descriptor, &d, witness); 12570 descriptors->Set(next_descriptor, &d, witness);
12712 } else if (type == NORMAL) { 12571 } else if (type == NORMAL) {
12713 if (current_offset < inobject_props) { 12572 if (current_offset < inobject_props) {
12714 obj->InObjectPropertyAtPut(current_offset, 12573 obj->InObjectPropertyAtPut(current_offset,
12715 value, 12574 value,
12716 UPDATE_WRITE_BARRIER); 12575 UPDATE_WRITE_BARRIER);
12717 } else { 12576 } else {
12718 int offset = current_offset - inobject_props; 12577 int offset = current_offset - inobject_props;
12719 FixedArray::cast(fields)->set(offset, value); 12578 FixedArray::cast(fields)->set(offset, value);
12720 } 12579 }
12721 FieldDescriptor d(String::cast(key), 12580 FieldDescriptor d(key,
12722 current_offset++, 12581 current_offset++,
12723 details.attributes(), 12582 details.attributes(),
12724 details.index()); 12583 details.index());
12725 descriptors->Set(next_descriptor, &d, witness); 12584 descriptors->Set(next_descriptor, &d, witness);
12726 } else if (type == CALLBACKS) { 12585 } else if (type == CALLBACKS) {
12727 if (value->IsAccessorPair()) { 12586 CallbacksDescriptor d(key,
12728 MaybeObject* maybe_copy =
12729 AccessorPair::cast(value)->CopyWithoutTransitions();
12730 if (!maybe_copy->To(&value)) return maybe_copy;
12731 }
12732 CallbacksDescriptor d(String::cast(key),
12733 value, 12587 value,
12734 details.attributes(), 12588 details.attributes(),
12735 details.index()); 12589 details.index());
12736 descriptors->Set(next_descriptor, &d, witness); 12590 descriptors->Set(next_descriptor, &d, witness);
12737 } else { 12591 } else {
12738 UNREACHABLE(); 12592 UNREACHABLE();
12739 } 12593 }
12740 ++next_descriptor; 12594 ++next_descriptor;
12741 } 12595 }
12742 } 12596 }
12743 ASSERT(current_offset == number_of_fields); 12597 ASSERT(current_offset == number_of_fields);
12744 12598
12745 descriptors->Sort(witness); 12599 descriptors->Sort(witness);
12746 // Allocate new map. 12600 // Allocate new map.
12747 Map* new_map; 12601 Map* new_map;
12748 { MaybeObject* maybe_new_map = 12602 MaybeObject* maybe_new_map = obj->map()->CopyReplaceDescriptors(descriptors);
12749 obj->map()->CopyReplaceDescriptors(descriptors); 12603 if (!maybe_new_map->To(&new_map)) return maybe_new_map;
12750 if (!maybe_new_map->To(&new_map)) return maybe_new_map;
12751 }
12752 12604
12753 new_map->set_unused_property_fields(unused_property_fields); 12605 new_map->set_unused_property_fields(unused_property_fields);
12754 12606
12755 // Transform the object. 12607 // Transform the object.
12756 obj->set_map(new_map); 12608 obj->set_map(new_map);
12757 12609
12758 obj->set_properties(FixedArray::cast(fields)); 12610 obj->set_properties(FixedArray::cast(fields));
12759 ASSERT(obj->IsJSObject()); 12611 ASSERT(obj->IsJSObject());
12760 12612
12761 // Check that it really works. 12613 // Check that it really works.
(...skipping 500 matching lines...) Expand 10 before | Expand all | Expand 10 after
13262 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); 13114 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER);
13263 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); 13115 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER);
13264 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); 13116 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER);
13265 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); 13117 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER);
13266 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); 13118 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER);
13267 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); 13119 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER);
13268 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); 13120 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER);
13269 } 13121 }
13270 13122
13271 } } // namespace v8::internal 13123 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/objects-debug.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698