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 4395 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4406 accessors->SetComponents(getter, setter); | 4406 accessors->SetComponents(getter, setter); |
4407 | 4407 |
4408 return SetElementCallback(index, accessors, attributes); | 4408 return SetElementCallback(index, accessors, attributes); |
4409 } | 4409 } |
4410 | 4410 |
4411 | 4411 |
4412 MaybeObject* JSObject::CreateAccessorPairFor(String* name) { | 4412 MaybeObject* JSObject::CreateAccessorPairFor(String* name) { |
4413 LookupResult result(GetHeap()->isolate()); | 4413 LookupResult result(GetHeap()->isolate()); |
4414 LocalLookupRealNamedProperty(name, &result); | 4414 LocalLookupRealNamedProperty(name, &result); |
4415 if (result.IsProperty() && result.type() == CALLBACKS) { | 4415 if (result.IsProperty() && result.type() == CALLBACKS) { |
4416 ASSERT(!result.IsDontDelete()); | 4416 // Note that the result can actually have IsDontDelete() == true when we |
4417 // e.g. have to fall back to the slow case while adding a setter after | |
4418 // successfully reusing a map transition for a getter. Nevertheless, this is | |
4419 // OK, because the assertion only holds for the whole addition of both | |
4420 // accessors, not for the addition of each part. | |
4417 Object* obj = result.GetCallbackObject(); | 4421 Object* obj = result.GetCallbackObject(); |
4418 if (obj->IsAccessorPair()) { | 4422 if (obj->IsAccessorPair()) { |
4419 return AccessorPair::cast(obj)->CopyWithoutTransitions(); | 4423 return AccessorPair::cast(obj)->CopyWithoutTransitions(); |
4420 } | 4424 } |
4421 } | 4425 } |
4422 return GetHeap()->AllocateAccessorPair(); | 4426 return GetHeap()->AllocateAccessorPair(); |
4423 } | 4427 } |
4424 | 4428 |
4425 | 4429 |
4426 MaybeObject* JSObject::DefinePropertyAccessor(String* name, | 4430 MaybeObject* JSObject::DefinePropertyAccessor(String* name, |
4427 Object* getter, | 4431 Object* getter, |
4428 Object* setter, | 4432 Object* setter, |
4429 PropertyAttributes attributes) { | 4433 PropertyAttributes attributes) { |
4434 bool only_attribute_changes = getter->IsNull() && setter->IsNull(); | |
4435 if (HasFastProperties() && !only_attribute_changes) { | |
4436 MaybeObject* getterOk = GetHeap()->undefined_value(); | |
Michael Starzinger
2012/05/02 13:30:14
Can we move the result of "GetHeap()" into a local
Sven Panne
2012/05/03 09:39:02
Done for the occurrences where it is actually used
| |
4437 if (!getter->IsNull()) { | |
4438 getterOk = DefineFastAccessor(name, ACCESSOR_GETTER, getter, attributes); | |
4439 if (getterOk->IsFailure()) return getterOk; | |
4440 } | |
4441 | |
4442 MaybeObject* setterOk = GetHeap()->undefined_value(); | |
4443 if (getterOk != GetHeap()->null_value() && !setter->IsNull()) { | |
4444 setterOk = DefineFastAccessor(name, ACCESSOR_SETTER, setter, attributes); | |
4445 if (setterOk->IsFailure()) return setterOk; | |
4446 } | |
4447 | |
4448 if (getterOk != GetHeap()->null_value() && | |
4449 setterOk != GetHeap()->null_value()) { | |
4450 return GetHeap()->undefined_value(); | |
4451 } | |
4452 } | |
4453 | |
4430 AccessorPair* accessors; | 4454 AccessorPair* accessors; |
4431 { MaybeObject* maybe_accessors = CreateAccessorPairFor(name); | 4455 { MaybeObject* maybe_accessors = CreateAccessorPairFor(name); |
4432 if (!maybe_accessors->To(&accessors)) return maybe_accessors; | 4456 if (!maybe_accessors->To(&accessors)) return maybe_accessors; |
4433 } | 4457 } |
4434 accessors->SetComponents(getter, setter); | 4458 accessors->SetComponents(getter, setter); |
4435 return SetPropertyCallback(name, accessors, attributes); | 4459 return SetPropertyCallback(name, accessors, attributes); |
4436 } | 4460 } |
4437 | 4461 |
4438 | 4462 |
4439 bool JSObject::CanSetCallback(String* name) { | 4463 bool JSObject::CanSetCallback(String* name) { |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4569 | 4593 |
4570 if (!CanSetCallback(name)) return isolate->heap()->undefined_value(); | 4594 if (!CanSetCallback(name)) return isolate->heap()->undefined_value(); |
4571 | 4595 |
4572 uint32_t index = 0; | 4596 uint32_t index = 0; |
4573 return name->AsArrayIndex(&index) ? | 4597 return name->AsArrayIndex(&index) ? |
4574 DefineElementAccessor(index, getter, setter, attributes) : | 4598 DefineElementAccessor(index, getter, setter, attributes) : |
4575 DefinePropertyAccessor(name, getter, setter, attributes); | 4599 DefinePropertyAccessor(name, getter, setter, attributes); |
4576 } | 4600 } |
4577 | 4601 |
4578 | 4602 |
4603 static bool TransitionToSameAccessor(Object* map, | |
4604 String* name, | |
4605 AccessorComponent component, | |
4606 Object* accessor, | |
4607 PropertyAttributes attributes ) { | |
4608 DescriptorArray* descs = Map::cast(map)->instance_descriptors(); | |
4609 int number = descs->SearchWithCache(name); | |
4610 ASSERT(number != DescriptorArray::kNotFound); | |
4611 Object* target_accessor = | |
4612 AccessorPair::cast(descs->GetCallbacksObject(number))->get(component); | |
4613 PropertyAttributes target_attributes = descs->GetDetails(number).attributes(); | |
4614 return target_accessor == accessor && target_attributes == attributes; | |
4615 } | |
4616 | |
4617 | |
4618 MaybeObject* JSObject::DefineFastAccessor(String* name, | |
4619 AccessorComponent component, | |
4620 Object* accessor, | |
4621 PropertyAttributes attributes) { | |
4622 LookupResult result(GetIsolate()); | |
4623 LocalLookup(name, &result); | |
4624 | |
4625 // If we have a new property, create a fresh accessor plus a transition to it. | |
4626 if (!result.IsFound()) { | |
4627 return CreateFreshAccessor(name, component, accessor, attributes); | |
4628 } | |
4629 | |
4630 // If the property is not a JavaScript accessor, fall back to the slow case. | |
4631 if (result.type() != CALLBACKS) return GetHeap()->null_value(); | |
4632 Object* callback_value = result.GetValue(); | |
4633 if (!callback_value->IsAccessorPair()) return GetHeap()->null_value(); | |
4634 AccessorPair* accessors = AccessorPair::cast(callback_value); | |
4635 | |
4636 // Follow a callback transition, if there is a fitting one. | |
4637 Object* entry = accessors->get(component); | |
4638 if (entry->IsMap() && | |
4639 TransitionToSameAccessor(entry, name, component, accessor, attributes)) { | |
4640 set_map(Map::cast(entry)); | |
4641 return this; | |
4642 } | |
4643 | |
4644 // When we re-add the same accessor again, there is nothing to do. | |
4645 if (entry == accessor && result.GetAttributes() == attributes) return this; | |
4646 | |
4647 // Only the other accessor has been set so far, create a new transition. | |
4648 if (entry->IsTheHole()) { | |
4649 return NewCallbackTrans(name, component, accessor, attributes, accessors); | |
Michael Starzinger
2012/05/02 13:30:14
Can we add an assertion to the top of this method
Sven Panne
2012/05/03 09:39:02
I'll add a slightly stronger assertion, checking t
| |
4650 } | |
4651 | |
4652 // Nothing from the above worked, so we have to fall back to the slow case. | |
4653 return GetHeap()->null_value(); | |
4654 } | |
4655 | |
4656 | |
4657 MaybeObject* JSObject::CreateFreshAccessor(String* name, | |
Michael Starzinger
2012/05/02 13:30:14
Can we turn this method into a static helper that
Sven Panne
2012/05/03 09:39:02
As discussed offline, let's just simply pass 'this
| |
4658 AccessorComponent component, | |
4659 Object* accessor, | |
4660 PropertyAttributes attributes) { | |
4661 // step 1: create a new getter/setter pair with only the accessor in it | |
4662 AccessorPair* accessors2; | |
4663 { MaybeObject* maybe_accessors2 = GetHeap()->AllocateAccessorPair(); | |
4664 if (!maybe_accessors2->To(&accessors2)) return maybe_accessors2; | |
4665 } | |
4666 accessors2->set(component, accessor); | |
4667 | |
4668 // step 2: create a copy of the descriptors, incl. the new getter/setter pair | |
4669 Map* map1 = map(); | |
4670 CallbacksDescriptor callbacks_descr2(name, accessors2, attributes); | |
4671 DescriptorArray* descriptors2; | |
4672 { MaybeObject* maybe_descriptors2 = | |
4673 map1->instance_descriptors()->CopyInsert(&callbacks_descr2, | |
4674 REMOVE_TRANSITIONS); | |
4675 if (!maybe_descriptors2->To(&descriptors2)) return maybe_descriptors2; | |
4676 } | |
4677 | |
4678 // step 3: create a new map with the new descriptors | |
4679 Map* map2; | |
4680 { MaybeObject* maybe_map2 = map1->CopyDropDescriptors(); | |
4681 if (!maybe_map2->To(&map2)) return maybe_map2; | |
4682 } | |
4683 map2->set_instance_descriptors(descriptors2); | |
4684 | |
4685 // step 4: create a new getter/setter pair with a transition to the new map | |
4686 AccessorPair* accessors1; | |
4687 { MaybeObject* maybe_accessors1 = GetHeap()->AllocateAccessorPair(); | |
4688 if (!maybe_accessors1->To(&accessors1)) return maybe_accessors1; | |
4689 } | |
4690 accessors1->set(component, map2); | |
4691 | |
4692 // step 5: create a copy of the descriptors, incl. the new getter/setter pair | |
4693 // with the transition | |
4694 CallbacksDescriptor callbacks_descr1(name, accessors1, attributes); | |
4695 DescriptorArray* descriptors1; | |
4696 { MaybeObject* maybe_descriptors1 = | |
4697 map1->instance_descriptors()->CopyInsert(&callbacks_descr1, | |
4698 KEEP_TRANSITIONS); | |
4699 if (!maybe_descriptors1->To(&descriptors1)) return maybe_descriptors1; | |
4700 } | |
4701 | |
4702 // step 6: everything went well so far, so we make our changes visible | |
4703 set_map(map2); | |
4704 map1->set_instance_descriptors(descriptors1); | |
4705 return this; | |
4706 } | |
4707 | |
4708 | |
4709 MaybeObject* JSObject::NewCallbackTrans(String* name, | |
Michael Starzinger
2012/05/02 13:30:14
Likewise. Also the full name "NewCallbackTransitio
Sven Panne
2012/05/03 09:39:02
It was because of our 80-column limit. :-) Done.
| |
4710 AccessorComponent component, | |
4711 Object* accessor, | |
4712 PropertyAttributes attributes, | |
4713 AccessorPair* accessors2) { | |
4714 // step 1: copy the old getter/setter pair and set the new accessor | |
4715 AccessorPair* accessors3; | |
4716 { MaybeObject* maybe_accessors3 = accessors2->CopyWithoutTransitions(); | |
4717 if (!maybe_accessors3->To(&accessors3)) return maybe_accessors3; | |
4718 } | |
4719 accessors3->set(component, accessor); | |
4720 | |
4721 // step 2: create a copy of the descriptors, incl. the new getter/setter pair | |
4722 Map* map2 = map(); | |
4723 CallbacksDescriptor callbacks_descr3(name, accessors3, attributes); | |
4724 DescriptorArray* descriptors3; | |
4725 { MaybeObject* maybe_descriptors3 = | |
4726 map2->instance_descriptors()->CopyInsert(&callbacks_descr3, | |
4727 REMOVE_TRANSITIONS); | |
4728 if (!maybe_descriptors3->To(&descriptors3)) return maybe_descriptors3; | |
4729 } | |
4730 | |
4731 // step 3: create a new map with the new descriptors | |
4732 Map* map3; | |
4733 { MaybeObject* maybe_map3 = map2->CopyDropDescriptors(); | |
4734 if (!maybe_map3->To(&map3)) return maybe_map3; | |
4735 } | |
4736 map3->set_instance_descriptors(descriptors3); | |
4737 | |
4738 // step 4: everything went well so far, so we make our changes visible | |
4739 set_map(map3); | |
4740 accessors2->set(component, map3); | |
4741 return this; | |
4742 } | |
4743 | |
4744 | |
4579 MaybeObject* JSObject::DefineAccessor(AccessorInfo* info) { | 4745 MaybeObject* JSObject::DefineAccessor(AccessorInfo* info) { |
4580 Isolate* isolate = GetIsolate(); | 4746 Isolate* isolate = GetIsolate(); |
4581 String* name = String::cast(info->name()); | 4747 String* name = String::cast(info->name()); |
4582 // Check access rights if needed. | 4748 // Check access rights if needed. |
4583 if (IsAccessCheckNeeded() && | 4749 if (IsAccessCheckNeeded() && |
4584 !isolate->MayNamedAccess(this, name, v8::ACCESS_SET)) { | 4750 !isolate->MayNamedAccess(this, name, v8::ACCESS_SET)) { |
4585 isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET); | 4751 isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET); |
4586 return isolate->heap()->undefined_value(); | 4752 return isolate->heap()->undefined_value(); |
4587 } | 4753 } |
4588 | 4754 |
(...skipping 1343 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5932 { MaybeObject* maybe_copy = heap->AllocateAccessorPair(); | 6098 { MaybeObject* maybe_copy = heap->AllocateAccessorPair(); |
5933 if (!maybe_copy->To(©)) return maybe_copy; | 6099 if (!maybe_copy->To(©)) return maybe_copy; |
5934 } | 6100 } |
5935 copy->set_getter(getter()->IsMap() ? heap->the_hole_value() : getter()); | 6101 copy->set_getter(getter()->IsMap() ? heap->the_hole_value() : getter()); |
5936 copy->set_setter(setter()->IsMap() ? heap->the_hole_value() : setter()); | 6102 copy->set_setter(setter()->IsMap() ? heap->the_hole_value() : setter()); |
5937 return copy; | 6103 return copy; |
5938 } | 6104 } |
5939 | 6105 |
5940 | 6106 |
5941 Object* AccessorPair::GetComponent(AccessorComponent component) { | 6107 Object* AccessorPair::GetComponent(AccessorComponent component) { |
5942 Object* accessor = (component == ACCESSOR_GETTER) ? getter() : setter(); | 6108 Object* accessor = get(component); |
5943 return accessor->IsTheHole() ? GetHeap()->undefined_value() : accessor; | 6109 return accessor->IsTheHole() ? GetHeap()->undefined_value() : accessor; |
5944 } | 6110 } |
5945 | 6111 |
5946 | 6112 |
5947 MaybeObject* DeoptimizationInputData::Allocate(int deopt_entry_count, | 6113 MaybeObject* DeoptimizationInputData::Allocate(int deopt_entry_count, |
5948 PretenureFlag pretenure) { | 6114 PretenureFlag pretenure) { |
5949 ASSERT(deopt_entry_count > 0); | 6115 ASSERT(deopt_entry_count > 0); |
5950 return HEAP->AllocateFixedArray(LengthFor(deopt_entry_count), | 6116 return HEAP->AllocateFixedArray(LengthFor(deopt_entry_count), |
5951 pretenure); | 6117 pretenure); |
5952 } | 6118 } |
5953 | 6119 |
(...skipping 7010 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
12964 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); | 13130 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); |
12965 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); | 13131 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); |
12966 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); | 13132 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); |
12967 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); | 13133 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); |
12968 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); | 13134 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); |
12969 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); | 13135 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); |
12970 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); | 13136 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); |
12971 } | 13137 } |
12972 | 13138 |
12973 } } // namespace v8::internal | 13139 } } // namespace v8::internal |
OLD | NEW |