| Index: src/objects.cc
|
| ===================================================================
|
| --- src/objects.cc (revision 645)
|
| +++ src/objects.cc (working copy)
|
| @@ -333,7 +333,7 @@
|
| // Check if we're allowed to read from the current object. Note
|
| // that even though we may not actually end up loading the named
|
| // property from the current object, we still check that we have
|
| - // access to the it.
|
| + // access to it.
|
| JSObject* checked = JSObject::cast(current);
|
| if (!Top::MayNamedAccess(checked, name, v8::ACCESS_GET)) {
|
| return checked->GetPropertyWithFailedAccessCheck(receiver,
|
| @@ -3968,10 +3968,12 @@
|
| } else {
|
| payload = v8::internal::HashField(GetHash(), false);
|
| }
|
| - return (payload & 0x00FFFFFF) | (length_ << String::kShortLengthShift);
|
| + return (payload & ((1 << String::kShortLengthShift) - 1)) |
|
| + (length_ << String::kShortLengthShift);
|
| } else if (length_ <= String::kMaxMediumStringSize) {
|
| uint32_t payload = v8::internal::HashField(GetHash(), false);
|
| - return (payload & 0x0000FFFF) | (length_ << String::kMediumLengthShift);
|
| + return (payload & ((1 << String::kMediumLengthShift) - 1)) |
|
| + (length_ << String::kMediumLengthShift);
|
| } else {
|
| return v8::internal::HashField(length_, false);
|
| }
|
| @@ -4050,6 +4052,67 @@
|
| }
|
|
|
|
|
| +void Map::CreateBackPointers() {
|
| + DescriptorArray* descriptors = instance_descriptors();
|
| + for (DescriptorReader r(descriptors); !r.eos(); r.advance()) {
|
| + if (r.type() == MAP_TRANSITION) {
|
| + // Get target.
|
| + Map* target = Map::cast(r.GetValue());
|
| +#ifdef DEBUG
|
| + // Verify target.
|
| + Object* source_prototype = prototype();
|
| + Object* target_prototype = target->prototype();
|
| + ASSERT(source_prototype->IsJSObject() ||
|
| + source_prototype->IsMap() ||
|
| + source_prototype->IsNull());
|
| + ASSERT(target_prototype->IsJSObject() ||
|
| + target_prototype->IsNull());
|
| + ASSERT(source_prototype->IsMap() ||
|
| + source_prototype == target_prototype);
|
| +#endif
|
| + // Point target back to source. set_prototype() will not let us set
|
| + // the prototype to a map, as we do here.
|
| + *RawField(target, kPrototypeOffset) = this;
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +void Map::ClearNonLiveTransitions(Object* real_prototype) {
|
| + // Live DescriptorArray objects will be marked, so we must use
|
| + // low-level accessors to get and modify their data.
|
| + DescriptorArray* d = reinterpret_cast<DescriptorArray*>(
|
| + *RawField(this, Map::kInstanceDescriptorsOffset));
|
| + if (d == Heap::empty_descriptor_array()) return;
|
| + Smi* NullDescriptorDetails =
|
| + PropertyDetails(NONE, NULL_DESCRIPTOR).AsSmi();
|
| + FixedArray* contents = reinterpret_cast<FixedArray*>(
|
| + d->get(DescriptorArray::kContentArrayIndex));
|
| + ASSERT(contents->length() >= 2);
|
| + for (int i = 0; i < contents->length(); i += 2) {
|
| + // If the pair (value, details) is a map transition,
|
| + // check if the target is live. If not, null the descriptor.
|
| + // Also drop the back pointer for that map transition, so that this
|
| + // map is not reached again by following a back pointer from a
|
| + // non-live object.
|
| + PropertyDetails details(Smi::cast(contents->get(i + 1)));
|
| + if (details.type() == MAP_TRANSITION) {
|
| + Map* target = reinterpret_cast<Map*>(contents->get(i));
|
| + ASSERT(target->IsHeapObject());
|
| + if (!target->IsMarked()) {
|
| + ASSERT(target->IsMap());
|
| + contents->set(i + 1, NullDescriptorDetails, SKIP_WRITE_BARRIER);
|
| + contents->set(i, Heap::null_value(), SKIP_WRITE_BARRIER);
|
| + ASSERT(target->prototype() == this ||
|
| + target->prototype() == real_prototype);
|
| + // Getter prototype() is read-only, set_prototype() has side effects.
|
| + *RawField(target, Map::kPrototypeOffset) = real_prototype;
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| void Map::MapIterateBody(ObjectVisitor* v) {
|
| // Assumes all Object* members are contiguously allocated!
|
| IteratePointers(v, kPrototypeOffset, kCodeCacheOffset + kPointerSize);
|
| @@ -5749,7 +5812,7 @@
|
| int n, HashTableKey* key) {
|
| int capacity = Capacity();
|
| int nof = NumberOfElements() + n;
|
| - // Make sure 20% is free
|
| + // Make sure 25% is free
|
| if (nof + (nof >> 2) <= capacity) return this;
|
|
|
| Object* obj = Allocate(nof * 2);
|
|
|