| 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 4399 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 Loading... |
| 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 Loading... |
| 6120 { MaybeObject* maybe_copy = heap->AllocateAccessorPair(); | 5940 { MaybeObject* maybe_copy = heap->AllocateAccessorPair(); |
| 6121 if (!maybe_copy->To(©)) return maybe_copy; | 5941 if (!maybe_copy->To(©)) 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 Loading... |
| 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 |
| OLD | NEW |