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

Side by Side Diff: src/objects.cc

Issue 10386166: Revert r11496. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 8 years, 7 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') | test/mjsunit/accessor-map-sharing.js » ('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 4399 matching lines...) Expand 10 before | Expand all | Expand 10 after
4410 accessors->SetComponents(getter, setter); 4410 accessors->SetComponents(getter, setter);
4411 4411
4412 return SetElementCallback(index, accessors, attributes); 4412 return SetElementCallback(index, accessors, attributes);
4413 } 4413 }
4414 4414
4415 4415
4416 MaybeObject* JSObject::CreateAccessorPairFor(String* name) { 4416 MaybeObject* JSObject::CreateAccessorPairFor(String* name) {
4417 LookupResult result(GetHeap()->isolate()); 4417 LookupResult result(GetHeap()->isolate());
4418 LocalLookupRealNamedProperty(name, &result); 4418 LocalLookupRealNamedProperty(name, &result);
4419 if (result.IsProperty() && result.type() == CALLBACKS) { 4419 if (result.IsProperty() && result.type() == CALLBACKS) {
4420 // Note that the result can actually have IsDontDelete() == true when we 4420 ASSERT(!result.IsDontDelete());
4421 // e.g. have to fall back to the slow case while adding a setter after
4422 // successfully reusing a map transition for a getter. Nevertheless, this is
4423 // OK, because the assertion only holds for the whole addition of both
4424 // accessors, not for the addition of each part. See first comment in
4425 // DefinePropertyAccessor below.
4426 Object* obj = result.GetCallbackObject(); 4421 Object* obj = result.GetCallbackObject();
4427 if (obj->IsAccessorPair()) { 4422 if (obj->IsAccessorPair()) {
4428 return AccessorPair::cast(obj)->CopyWithoutTransitions(); 4423 return AccessorPair::cast(obj)->CopyWithoutTransitions();
4429 } 4424 }
4430 } 4425 }
4431 return GetHeap()->AllocateAccessorPair(); 4426 return GetHeap()->AllocateAccessorPair();
4432 } 4427 }
4433 4428
4434 4429
4435 MaybeObject* JSObject::DefinePropertyAccessor(String* name, 4430 MaybeObject* JSObject::DefinePropertyAccessor(String* name,
4436 Object* getter, 4431 Object* getter,
4437 Object* setter, 4432 Object* setter,
4438 PropertyAttributes attributes) { 4433 PropertyAttributes attributes) {
4439 // We could assert that the property is configurable here, but we would need
4440 // to do a lookup, which seems to be a bit of overkill.
4441 Heap* heap = GetHeap();
4442 bool only_attribute_changes = getter->IsNull() && setter->IsNull();
4443 if (HasFastProperties() && !only_attribute_changes) {
4444 MaybeObject* getterOk = heap->undefined_value();
4445 if (!getter->IsNull()) {
4446 getterOk = DefineFastAccessor(name, ACCESSOR_GETTER, getter, attributes);
4447 if (getterOk->IsFailure()) return getterOk;
4448 }
4449
4450 MaybeObject* setterOk = heap->undefined_value();
4451 if (getterOk != heap->null_value() && !setter->IsNull()) {
4452 setterOk = DefineFastAccessor(name, ACCESSOR_SETTER, setter, attributes);
4453 if (setterOk->IsFailure()) return setterOk;
4454 }
4455
4456 if (getterOk != heap->null_value() && setterOk != heap->null_value()) {
4457 return heap->undefined_value();
4458 }
4459 }
4460
4461 AccessorPair* accessors; 4434 AccessorPair* accessors;
4462 { MaybeObject* maybe_accessors = CreateAccessorPairFor(name); 4435 { MaybeObject* maybe_accessors = CreateAccessorPairFor(name);
4463 if (!maybe_accessors->To(&accessors)) return maybe_accessors; 4436 if (!maybe_accessors->To(&accessors)) return maybe_accessors;
4464 } 4437 }
4465 accessors->SetComponents(getter, setter); 4438 accessors->SetComponents(getter, setter);
4466 return SetPropertyCallback(name, accessors, attributes); 4439 return SetPropertyCallback(name, accessors, attributes);
4467 } 4440 }
4468 4441
4469 4442
4470 bool JSObject::CanSetCallback(String* name) { 4443 bool JSObject::CanSetCallback(String* name) {
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
4600 4573
4601 if (!CanSetCallback(name)) return isolate->heap()->undefined_value(); 4574 if (!CanSetCallback(name)) return isolate->heap()->undefined_value();
4602 4575
4603 uint32_t index = 0; 4576 uint32_t index = 0;
4604 return name->AsArrayIndex(&index) ? 4577 return name->AsArrayIndex(&index) ?
4605 DefineElementAccessor(index, getter, setter, attributes) : 4578 DefineElementAccessor(index, getter, setter, attributes) :
4606 DefinePropertyAccessor(name, getter, setter, attributes); 4579 DefinePropertyAccessor(name, getter, setter, attributes);
4607 } 4580 }
4608 4581
4609 4582
4610 static MaybeObject* CreateFreshAccessor(JSObject* obj,
4611 String* name,
4612 AccessorComponent component,
4613 Object* accessor,
4614 PropertyAttributes attributes) {
4615 // step 1: create a new getter/setter pair with only the accessor in it
4616 Heap* heap = obj->GetHeap();
4617 AccessorPair* accessors2;
4618 { MaybeObject* maybe_accessors2 = heap->AllocateAccessorPair();
4619 if (!maybe_accessors2->To(&accessors2)) return maybe_accessors2;
4620 }
4621 accessors2->set(component, accessor);
4622
4623 // step 2: create a copy of the descriptors, incl. the new getter/setter pair
4624 Map* map1 = obj->map();
4625 CallbacksDescriptor callbacks_descr2(name, accessors2, attributes);
4626 DescriptorArray* descriptors2;
4627 { MaybeObject* maybe_descriptors2 =
4628 map1->instance_descriptors()->CopyInsert(&callbacks_descr2,
4629 REMOVE_TRANSITIONS);
4630 if (!maybe_descriptors2->To(&descriptors2)) return maybe_descriptors2;
4631 }
4632
4633 // step 3: create a new map with the new descriptors
4634 Map* map2;
4635 { MaybeObject* maybe_map2 = map1->CopyDropDescriptors();
4636 if (!maybe_map2->To(&map2)) return maybe_map2;
4637 }
4638 map2->set_instance_descriptors(descriptors2);
4639
4640 // step 4: create a new getter/setter pair with a transition to the new map
4641 AccessorPair* accessors1;
4642 { MaybeObject* maybe_accessors1 = heap->AllocateAccessorPair();
4643 if (!maybe_accessors1->To(&accessors1)) return maybe_accessors1;
4644 }
4645 accessors1->set(component, map2);
4646
4647 // step 5: create a copy of the descriptors, incl. the new getter/setter pair
4648 // with the transition
4649 CallbacksDescriptor callbacks_descr1(name, accessors1, attributes);
4650 DescriptorArray* descriptors1;
4651 { MaybeObject* maybe_descriptors1 =
4652 map1->instance_descriptors()->CopyInsert(&callbacks_descr1,
4653 KEEP_TRANSITIONS);
4654 if (!maybe_descriptors1->To(&descriptors1)) return maybe_descriptors1;
4655 }
4656
4657 // step 6: everything went well so far, so we make our changes visible
4658 obj->set_map(map2);
4659 map1->set_instance_descriptors(descriptors1);
4660 map2->SetBackPointer(map1);
4661 return obj;
4662 }
4663
4664
4665 static bool TransitionToSameAccessor(Object* map,
4666 String* name,
4667 AccessorComponent component,
4668 Object* accessor,
4669 PropertyAttributes attributes ) {
4670 DescriptorArray* descs = Map::cast(map)->instance_descriptors();
4671 int number = descs->SearchWithCache(name);
4672 ASSERT(number != DescriptorArray::kNotFound);
4673 Object* target_accessor =
4674 AccessorPair::cast(descs->GetCallbacksObject(number))->get(component);
4675 PropertyAttributes target_attributes = descs->GetDetails(number).attributes();
4676 return target_accessor == accessor && target_attributes == attributes;
4677 }
4678
4679
4680 static MaybeObject* NewCallbackTransition(JSObject* obj,
4681 String* name,
4682 AccessorComponent component,
4683 Object* accessor,
4684 PropertyAttributes attributes,
4685 AccessorPair* accessors2) {
4686 // step 1: copy the old getter/setter pair and set the new accessor
4687 AccessorPair* accessors3;
4688 { MaybeObject* maybe_accessors3 = accessors2->CopyWithoutTransitions();
4689 if (!maybe_accessors3->To(&accessors3)) return maybe_accessors3;
4690 }
4691 accessors3->set(component, accessor);
4692
4693 // step 2: create a copy of the descriptors, incl. the new getter/setter pair
4694 Map* map2 = obj->map();
4695 CallbacksDescriptor callbacks_descr3(name, accessors3, attributes);
4696 DescriptorArray* descriptors3;
4697 { MaybeObject* maybe_descriptors3 =
4698 map2->instance_descriptors()->CopyInsert(&callbacks_descr3,
4699 REMOVE_TRANSITIONS);
4700 if (!maybe_descriptors3->To(&descriptors3)) return maybe_descriptors3;
4701 }
4702
4703 // step 3: create a new map with the new descriptors
4704 Map* map3;
4705 { MaybeObject* maybe_map3 = map2->CopyDropDescriptors();
4706 if (!maybe_map3->To(&map3)) return maybe_map3;
4707 }
4708 map3->set_instance_descriptors(descriptors3);
4709
4710 // step 4: everything went well so far, so we make our changes visible
4711 obj->set_map(map3);
4712 accessors2->set(component, map3);
4713 map3->SetBackPointer(map2);
4714 return obj;
4715 }
4716
4717
4718 MaybeObject* JSObject::DefineFastAccessor(String* name,
4719 AccessorComponent component,
4720 Object* accessor,
4721 PropertyAttributes attributes) {
4722 ASSERT(accessor->IsSpecFunction() || accessor->IsUndefined());
4723 LookupResult result(GetIsolate());
4724 LocalLookup(name, &result);
4725
4726 // If we have a new property, create a fresh accessor plus a transition to it.
4727 if (!result.IsFound()) {
4728 return CreateFreshAccessor(this, name, component, accessor, attributes);
4729 }
4730
4731 // If the property is not a JavaScript accessor, fall back to the slow case.
4732 if (result.type() != CALLBACKS) return GetHeap()->null_value();
4733 Object* callback_value = result.GetValue();
4734 if (!callback_value->IsAccessorPair()) return GetHeap()->null_value();
4735 AccessorPair* accessors = AccessorPair::cast(callback_value);
4736
4737 // Follow a callback transition, if there is a fitting one.
4738 Object* entry = accessors->get(component);
4739 if (entry->IsMap() &&
4740 TransitionToSameAccessor(entry, name, component, accessor, attributes)) {
4741 set_map(Map::cast(entry));
4742 return this;
4743 }
4744
4745 // When we re-add the same accessor again, there is nothing to do.
4746 if (entry == accessor && result.GetAttributes() == attributes) return this;
4747
4748 // Only the other accessor has been set so far, create a new transition.
4749 if (entry->IsTheHole()) {
4750 return NewCallbackTransition(this,
4751 name,
4752 component,
4753 accessor,
4754 attributes,
4755 accessors);
4756 }
4757
4758 // Nothing from the above worked, so we have to fall back to the slow case.
4759 return GetHeap()->null_value();
4760 }
4761
4762
4763 MaybeObject* JSObject::DefineAccessor(AccessorInfo* info) { 4583 MaybeObject* JSObject::DefineAccessor(AccessorInfo* info) {
4764 Isolate* isolate = GetIsolate(); 4584 Isolate* isolate = GetIsolate();
4765 String* name = String::cast(info->name()); 4585 String* name = String::cast(info->name());
4766 // Check access rights if needed. 4586 // Check access rights if needed.
4767 if (IsAccessCheckNeeded() && 4587 if (IsAccessCheckNeeded() &&
4768 !isolate->MayNamedAccess(this, name, v8::ACCESS_SET)) { 4588 !isolate->MayNamedAccess(this, name, v8::ACCESS_SET)) {
4769 isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET); 4589 isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET);
4770 return isolate->heap()->undefined_value(); 4590 return isolate->heap()->undefined_value();
4771 } 4591 }
4772 4592
(...skipping 1347 matching lines...) Expand 10 before | Expand all | Expand 10 after
6120 { MaybeObject* maybe_copy = heap->AllocateAccessorPair(); 5940 { MaybeObject* maybe_copy = heap->AllocateAccessorPair();
6121 if (!maybe_copy->To(&copy)) return maybe_copy; 5941 if (!maybe_copy->To(&copy)) return maybe_copy;
6122 } 5942 }
6123 copy->set_getter(getter()->IsMap() ? heap->the_hole_value() : getter()); 5943 copy->set_getter(getter()->IsMap() ? heap->the_hole_value() : getter());
6124 copy->set_setter(setter()->IsMap() ? heap->the_hole_value() : setter()); 5944 copy->set_setter(setter()->IsMap() ? heap->the_hole_value() : setter());
6125 return copy; 5945 return copy;
6126 } 5946 }
6127 5947
6128 5948
6129 Object* AccessorPair::GetComponent(AccessorComponent component) { 5949 Object* AccessorPair::GetComponent(AccessorComponent component) {
6130 Object* accessor = get(component); 5950 Object* accessor = (component == ACCESSOR_GETTER) ? getter() : setter();
6131 return accessor->IsTheHole() ? GetHeap()->undefined_value() : accessor; 5951 return accessor->IsTheHole() ? GetHeap()->undefined_value() : accessor;
6132 } 5952 }
6133 5953
6134 5954
6135 MaybeObject* DeoptimizationInputData::Allocate(int deopt_entry_count, 5955 MaybeObject* DeoptimizationInputData::Allocate(int deopt_entry_count,
6136 PretenureFlag pretenure) { 5956 PretenureFlag pretenure) {
6137 ASSERT(deopt_entry_count > 0); 5957 ASSERT(deopt_entry_count > 0);
6138 return HEAP->AllocateFixedArray(LengthFor(deopt_entry_count), 5958 return HEAP->AllocateFixedArray(LengthFor(deopt_entry_count),
6139 pretenure); 5959 pretenure);
6140 } 5960 }
6141 5961
(...skipping 6969 matching lines...) Expand 10 before | Expand all | Expand 10 after
13111 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); 12931 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER);
13112 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); 12932 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER);
13113 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); 12933 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER);
13114 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); 12934 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER);
13115 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); 12935 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER);
13116 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); 12936 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER);
13117 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); 12937 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER);
13118 } 12938 }
13119 12939
13120 } } // namespace v8::internal 12940 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/objects.h ('k') | test/mjsunit/accessor-map-sharing.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698