Author: [email protected]
Date: Wed Mar 11 04:26:09 2009
New Revision: 1488
Modified:
branches/experimental/global/src/objects-inl.h
branches/experimental/global/src/objects.cc
branches/experimental/global/src/objects.h
branches/experimental/global/src/property.h
branches/experimental/global/src/runtime.cc
Log:
Changed runtime system to preserve the global property cells for deleted
properties
and then reuse them for reintroduced global properties.
Review URL: http://codereview.chromium.org/42066
Modified: branches/experimental/global/src/objects-inl.h
==============================================================================
--- branches/experimental/global/src/objects-inl.h (original)
+++ branches/experimental/global/src/objects-inl.h Wed Mar 11 04:26:09 2009
@@ -52,6 +52,13 @@
}
+PropertyDetails PropertyDetails::AsDeleted() {
+ PropertyDetails d(DONT_ENUM, NORMAL);
+ Smi* smi = Smi::FromInt(AsSmi()->value() | DeletedField::encode(1));
+ return PropertyDetails(smi);
+}
+
+
#define CAST_ACCESSOR(type) \
type* type::cast(Object* object) { \
ASSERT(object->Is##type()); \
Modified: branches/experimental/global/src/objects.cc
==============================================================================
--- branches/experimental/global/src/objects.cc (original)
+++ branches/experimental/global/src/objects.cc Wed Mar 11 04:26:09 2009
@@ -435,7 +435,7 @@
PropertyDetails details) {
ASSERT(!HasFastProperties());
int entry = property_dictionary()->FindStringEntry(name);
- if (entry == -1) {
+ if (entry == Dictionary::kNotFound) {
Object* store_value = value;
if (IsJSGlobalObject()) {
store_value = Heap::AllocateJSGlobalPropertyCell(value);
@@ -456,7 +456,7 @@
JSGlobalPropertyCell::cast(property_dictionary()->ValueAt(entry));
cell->set_value(value);
// Please note we have to update the property details.
- property_dictionary()->SetStringEntry(entry, name, cell, details);
+ property_dictionary()->DetailsAtPut(entry, details);
} else {
property_dictionary()->SetStringEntry(entry, name, value, details);
}
@@ -464,6 +464,27 @@
}
+Object* JSObject::DeleteNormalizedProperty(String* name) {
+ ASSERT(!HasFastProperties());
+ Dictionary* dictionary = property_dictionary();
+ int entry = dictionary->FindStringEntry(name);
+ if (entry != Dictionary::kNotFound) {
+ PropertyDetails details = dictionary->DetailsAt(entry);
+ if (details.IsDontDelete()) return Heap::false_value();
+ // If we have a global object set the cell to the hole.
+ if (IsJSGlobalObject()) {
+ JSGlobalPropertyCell* cell =
+ JSGlobalPropertyCell::cast(dictionary->ValueAt(entry));
+ cell->set_value(Heap::the_hole_value());
+ dictionary->DetailsAtPut(entry, details.AsDeleted());
+ } else {
+ return dictionary->DeleteProperty(entry);
+ }
+ }
+ return Heap::true_value();
+}
+
+
Object* Object::GetProperty(Object* receiver,
LookupResult* result,
String* name,
@@ -1323,19 +1344,27 @@
Object* JSObject::AddSlowProperty(String* name,
Object* value,
PropertyAttributes attributes) {
- PropertyDetails details = PropertyDetails(attributes, NORMAL);
+ ASSERT(!HasFastProperties());
+ Dictionary* dict = property_dictionary();
Object* store_value = value;
if (IsJSGlobalObject()) {
+ // In case name is an orphaned property reuse the cell.
+ int entry = dict->FindStringEntry(name);
+ if (entry != Dictionary::kNotFound) {
+ store_value = dict->ValueAt(entry);
+ JSGlobalPropertyCell::cast(store_value)->set_value(value);
+ PropertyDetails details = PropertyDetails(attributes, NORMAL);
+ dict->SetStringEntry(entry, name, store_value, details);
+ return value;
+ }
store_value = Heap::AllocateJSGlobalPropertyCell(value);
if (store_value->IsFailure()) return store_value;
+ JSGlobalPropertyCell::cast(store_value)->set_value(value);
}
- Object* result = property_dictionary()->AddStringEntry(name,
- store_value,
- details);
+ PropertyDetails details = PropertyDetails(attributes, NORMAL);
+ Object* result = dict->AddStringEntry(name, store_value, details);
if (result->IsFailure()) return result;
- if (property_dictionary() != result) {
- set_properties(Dictionary::cast(result));
- }
+ if (dict != result) set_properties(Dictionary::cast(result));
return value;
}
@@ -1643,11 +1672,16 @@
}
} else {
int entry = property_dictionary()->FindStringEntry(name);
- if (entry != DescriptorArray::kNotFound) {
+ if (entry != Dictionary::kNotFound) {
// Make sure to disallow caching for uninitialized constants
// found in the dictionary-mode objects.
Object* value = property_dictionary()->ValueAt(entry);
if (IsJSGlobalObject()) {
+ PropertyDetails d = property_dictionary()->DetailsAt(entry);
+ if (d.IsDeleted()) {
+ result->NotFound();
+ return;
+ }
value = JSGlobalPropertyCell::cast(value)->value();
}
if (value->IsTheHole()) {
@@ -2185,12 +2219,7 @@
Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES);
if (obj->IsFailure()) return obj;
- ASSERT(!HasFastProperties());
- // Attempt to remove the property from the property dictionary.
- Dictionary* dictionary = property_dictionary();
- int entry = dictionary->FindStringEntry(name);
- if (entry != -1) return dictionary->DeleteProperty(entry);
- return Heap::true_value();
+ return DeleteNormalizedProperty(name);
}
@@ -2238,7 +2267,7 @@
ASSERT(!HasFastElements());
Dictionary* dictionary = element_dictionary();
int entry = dictionary->FindNumberEntry(index);
- if (entry != -1) return dictionary->DeleteProperty(entry);
+ if (entry != Dictionary::kNotFound) return
dictionary->DeleteProperty(entry);
return Heap::true_value();
}
@@ -2305,7 +2334,9 @@
} else {
Dictionary* dictionary = element_dictionary();
int entry = dictionary->FindNumberEntry(index);
- if (entry != -1) return dictionary->DeleteProperty(entry);
+ if (entry != Dictionary::kNotFound) {
+ return dictionary->DeleteProperty(entry);
+ }
}
return Heap::true_value();
}
@@ -2348,10 +2379,7 @@
Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES);
if (obj->IsFailure()) return obj;
// Make sure the properties are normalized before removing the entry.
- Dictionary* dictionary = property_dictionary();
- int entry = dictionary->FindStringEntry(name);
- if (entry != -1) return dictionary->DeleteProperty(entry);
- return Heap::true_value();
+ return DeleteNormalizedProperty(name);
}
}
@@ -5061,7 +5089,9 @@
return true;
}
} else {
- if (element_dictionary()->FindNumberEntry(index) != -1) return true;
+ if (element_dictionary()->FindNumberEntry(index) !=
Dictionary::kNotFound) {
+ return true;
+ }
}
// Handle [] on String objects.
@@ -5136,7 +5166,8 @@
return (index < length) &&
!FixedArray::cast(elements())->get(index)->IsTheHole();
} else {
- return element_dictionary()->FindNumberEntry(index) != -1;
+ return element_dictionary()->FindNumberEntry(index)
+ != Dictionary::kNotFound;
}
}
@@ -5162,7 +5193,9 @@
if ((index < length) &&
!FixedArray::cast(elements())->get(index)->IsTheHole()) return
true;
} else {
- if (element_dictionary()->FindNumberEntry(index) != -1) return true;
+ if (element_dictionary()->FindNumberEntry(index) !=
Dictionary::kNotFound) {
+ return true;
+ }
}
// Handle [] on String objects.
@@ -5370,7 +5403,7 @@
} else {
Dictionary* dictionary = element_dictionary();
int entry = dictionary->FindNumberEntry(index);
- if (entry != -1) {
+ if (entry != Dictionary::kNotFound) {
return dictionary->ValueAt(entry);
}
}
@@ -5440,7 +5473,7 @@
} else {
Dictionary* dictionary = element_dictionary();
int entry = dictionary->FindNumberEntry(index);
- if (entry != -1) {
+ if (entry != Dictionary::kNotFound) {
return dictionary->ValueAt(entry);
}
}
@@ -5700,7 +5733,8 @@
return (index < length) &&
!FixedArray::cast(elements())->get(index)->IsTheHole();
}
- return element_dictionary()->FindNumberEntry(index) != -1;
+ return element_dictionary()->FindNumberEntry(index)
+ != Dictionary::kNotFound;
}
@@ -6231,7 +6265,7 @@
template <int prefix_size, int element_size>
int HashTable<prefix_size, element_size>::FindEntry(HashTableKey* key) {
uint32_t nof = NumberOfElements();
- if (nof == 0) return -1; // Bail out if empty.
+ if (nof == 0) return kNotFound; // Bail out if empty.
uint32_t capacity = Capacity();
uint32_t hash = key->Hash();
@@ -6241,17 +6275,17 @@
uint32_t passed_elements = 0;
if (!element->IsNull()) {
if (!element->IsUndefined() && key->IsMatch(element)) return entry;
- if (++passed_elements == nof) return -1;
+ if (++passed_elements == nof) return kNotFound;
}
for (uint32_t i = 1; !element->IsUndefined(); i++) {
entry = GetProbe(hash, i, capacity);
element = KeyAt(entry);
if (!element->IsNull()) {
if (!element->IsUndefined() && key->IsMatch(element)) return entry;
- if (++passed_elements == nof) return -1;
+ if (++passed_elements == nof) return kNotFound;
}
}
- return -1;
+ return kNotFound;
}
@@ -6328,7 +6362,7 @@
bool SymbolTable::LookupSymbolIfExists(String* string, String** symbol) {
SymbolKey key(string);
int entry = FindEntry(&key);
- if (entry == -1) {
+ if (entry == kNotFound) {
return false;
} else {
String* result = String::cast(KeyAt(entry));
@@ -6349,7 +6383,7 @@
int entry = FindEntry(key);
// Symbol already in table.
- if (entry != -1) {
+ if (entry != kNotFound) {
*s = KeyAt(entry);
return this;
}
@@ -6379,7 +6413,7 @@
Object* CompilationCacheTable::Lookup(String* src) {
StringKey key(src);
int entry = FindEntry(&key);
- if (entry == -1) return Heap::undefined_value();
+ if (entry == kNotFound) return Heap::undefined_value();
return get(EntryToIndex(entry) + 1);
}
@@ -6387,7 +6421,7 @@
Object* CompilationCacheTable::LookupEval(String* src, Context* context) {
StringSharedKey key(src, context->closure()->shared());
int entry = FindEntry(&key);
- if (entry == -1) return Heap::undefined_value();
+ if (entry == kNotFound) return Heap::undefined_value();
return get(EntryToIndex(entry) + 1);
}
@@ -6396,7 +6430,7 @@
JSRegExp::Flags flags) {
RegExpKey key(src, flags);
int entry = FindEntry(&key);
- if (entry == -1) return Heap::undefined_value();
+ if (entry == kNotFound) return Heap::undefined_value();
return get(EntryToIndex(entry) + 1);
}
@@ -6546,7 +6580,7 @@
Object* MapCache::Lookup(FixedArray* array) {
SymbolsKey key(array);
int entry = FindEntry(&key);
- if (entry == -1) return Heap::undefined_value();
+ if (entry == kNotFound) return Heap::undefined_value();
return get(EntryToIndex(entry) + 1);
}
@@ -6568,7 +6602,7 @@
int LookupCache::Lookup(Map* map, String* name) {
MapNameKey key(map, name);
int entry = FindEntry(&key);
- if (entry == -1) return kNotFound;
+ if (entry == kNotFound) return kNotFound;
return Smi::cast(get(EntryToIndex(entry) + 1))->value();
}
@@ -6719,7 +6753,7 @@
int entry = FindEntry(key);
// If the entry is present set the value;
- if (entry != -1) {
+ if (entry != kNotFound) {
ValueAtPut(entry, value);
return this;
}
@@ -6794,7 +6828,7 @@
Object* value,
PropertyDetails details) {
StringKey k(key);
- SLOW_ASSERT(FindEntry(&k) == -1);
+ SLOW_ASSERT(FindEntry(&k) == kNotFound);
return Add(&k, value, details);
}
@@ -6804,7 +6838,7 @@
PropertyDetails details) {
NumberKey k(key);
UpdateMaxNumberKey(key);
- SLOW_ASSERT(FindEntry(&k) == -1);
+ SLOW_ASSERT(FindEntry(&k) == kNotFound);
return Add(&k, value, details);
}
Modified: branches/experimental/global/src/objects.h
==============================================================================
--- branches/experimental/global/src/objects.h (original)
+++ branches/experimental/global/src/objects.h Wed Mar 11 04:26:09 2009
@@ -148,20 +148,23 @@
int index() { return IndexField::decode(value_); }
+ inline PropertyDetails AsDeleted();
+
static bool IsValidIndex(int index) { return
IndexField::is_valid(index); }
bool IsReadOnly() { return (attributes() & READ_ONLY) != 0; }
bool IsDontDelete() { return (attributes() & DONT_DELETE) != 0; }
bool IsDontEnum() { return (attributes() & DONT_ENUM) != 0; }
+ bool IsDeleted() { return DeletedField::decode(value_) != 0;}
// Bit fields in value_ (type, shift, size). Must be public so the
// constants can be embedded in generated code.
class TypeField: public BitField<PropertyType, 0, 3> {};
class AttributesField: public BitField<PropertyAttributes, 3, 3> {};
- class IndexField: public BitField<uint32_t, 6, 31-6> {};
+ class DeletedField: public BitField<uint32_t, 6, 1> {};
+ class IndexField: public BitField<uint32_t, 7, 31-7> {};
static const int kInitialIndex = 1;
-
private:
uint32_t value_;
};
@@ -1191,6 +1194,9 @@
Object* value,
PropertyDetails details);
+ // Deletes the named property in a normalized object.
+ Object* DeleteNormalizedProperty(String* name);
+
// Sets a property that currently has lazy loading.
Object* SetLazyProperty(LookupResult* result,
String* name,
@@ -1838,6 +1844,9 @@
static const int kElementsStartOffset =
kHeaderSize + kElementsStartIndex * kPointerSize;
+ // Constant used for denoting a absent entry.
+ static const int kNotFound = -1;
+
protected:
// Find entry for key otherwise return -1.
int FindEntry(HashTableKey* key);
@@ -1933,9 +1942,6 @@
int Lookup(Map* map, String* name);
Object* Put(Map* map, String* name, int offset);
static inline LookupCache* cast(Object* obj);
-
- // Constant returned by Lookup when the key was not found.
- static const int kNotFound = -1;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(LookupCache);
Modified: branches/experimental/global/src/property.h
==============================================================================
--- branches/experimental/global/src/property.h (original)
+++ branches/experimental/global/src/property.h Wed Mar 11 04:26:09 2009
@@ -229,6 +229,7 @@
bool IsReadOnly() { return details_.IsReadOnly(); }
bool IsDontDelete() { return details_.IsDontDelete(); }
bool IsDontEnum() { return details_.IsDontEnum(); }
+ bool IsDeleted() { return details_.IsDeleted(); }
bool IsValid() { return lookup_type_ != NOT_FOUND; }
bool IsNotFound() { return lookup_type_ == NOT_FOUND; }
Modified: branches/experimental/global/src/runtime.cc
==============================================================================
--- branches/experimental/global/src/runtime.cc (original)
+++ branches/experimental/global/src/runtime.cc Wed Mar 11 04:26:09 2009
@@ -1879,7 +1879,7 @@
// Attempt dictionary lookup.
Dictionary* dictionary = receiver->property_dictionary();
int entry = dictionary->FindStringEntry(key);
- if ((entry != DescriptorArray::kNotFound) &&
+ if ((entry != Dictionary::kNotFound) &&
(dictionary->DetailsAt(entry).type() == NORMAL)) {
Object* value = dictionary->ValueAt(entry);
if (receiver->IsJSGlobalObject()) {
--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---