| Index: src/objects.cc
|
| ===================================================================
|
| --- src/objects.cc (revision 12582)
|
| +++ src/objects.cc (working copy)
|
| @@ -11478,7 +11478,7 @@
|
| for (int i = 0; i < capacity; i++) {
|
| uint32_t from_index = EntryToIndex(i);
|
| Object* k = get(from_index);
|
| - if (IsKey(k)) {
|
| + if (IsKey(k) && !k->IsNull()) {
|
| uint32_t hash = HashTable<Shape, Key>::HashForObject(key, k);
|
| uint32_t insertion_index =
|
| EntryToIndex(new_table->FindInsertionEntry(hash));
|
| @@ -11573,6 +11573,8 @@
|
|
|
| template class HashTable<CompilationCacheShape, HashTableKey*>;
|
|
|
| +template class HashTable<ShortTermJSONEvalCacheShape, HashTableKey*>;
|
| +
|
| template class HashTable<MapCacheShape, HashTableKey*>;
|
|
|
| template class HashTable<ObjectHashTableShape<1>, Object*>;
|
| @@ -12365,7 +12367,7 @@
|
| int scope_position) {
|
| StringSharedKey key(src,
|
| context->closure()->shared(),
|
| - value->language_mode(),
|
| + value->language_mode() ? STRICT_MODE : CLASSIC_MODE,
|
| scope_position);
|
| Object* obj;
|
| { MaybeObject* maybe_obj = EnsureCapacity(1, &key);
|
| @@ -12409,6 +12411,24 @@
|
| }
|
|
|
|
|
| +MaybeObject* CompilationCacheTable::PutRaw(Object* key,
|
| + SharedFunctionInfo* value,
|
| + HashTableKey* hasher) {
|
| + Object* obj;
|
| + { MaybeObject* maybe_obj = EnsureCapacity(1, hasher);
|
| + if (!maybe_obj->ToObject(&obj)) return maybe_obj;
|
| + }
|
| +
|
| + CompilationCacheTable* cache =
|
| + reinterpret_cast<CompilationCacheTable*>(obj);
|
| + int entry = cache->FindInsertionEntry(hasher->HashForObject(key));
|
| + cache->set(EntryToIndex(entry), key);
|
| + cache->set(EntryToIndex(entry) + 1, value);
|
| + cache->ElementAdded();
|
| + return cache;
|
| +}
|
| +
|
| +
|
| void CompilationCacheTable::Remove(Object* value) {
|
| Object* the_hole_value = GetHeap()->the_hole_value();
|
| for (int entry = 0, size = Capacity(); entry < size; entry++) {
|
| @@ -12424,6 +12444,189 @@
|
| }
|
|
|
|
|
| +MaybeObject* ShortTermJSONEvalCacheTable::Allocate() {
|
| + ShortTermJSONEvalCacheTable* table;
|
| + { MaybeObject* maybe_table =
|
| + HashTable<ShortTermJSONEvalCacheShape,
|
| + HashTableKey*>::Allocate(max_entries(),
|
| + USE_DEFAULT_MINIMUM_CAPACITY,
|
| + TENURED);
|
| + if (!maybe_table->To<ShortTermJSONEvalCacheTable>(&table))
|
| + return maybe_table;
|
| + }
|
| +
|
| + Smi* zero = Smi::FromInt(0);
|
| + table->set(ShortTermJSONEvalCacheShape::kTotalSourceSizeIndex, zero);
|
| + table->set(ShortTermJSONEvalCacheShape::kAgeIndex, zero);
|
| + return table;
|
| +}
|
| +
|
| +
|
| +int ShortTermJSONEvalCacheTable::total_source_size() {
|
| + Object* size = get(ShortTermJSONEvalCacheShape::kTotalSourceSizeIndex);
|
| + return Smi::cast(size)->value();
|
| +}
|
| +
|
| +
|
| +void ShortTermJSONEvalCacheTable::set_total_source_size(int size) {
|
| + set(ShortTermJSONEvalCacheShape::kTotalSourceSizeIndex, Smi::FromInt(size));
|
| +}
|
| +
|
| +
|
| +Object* ShortTermJSONEvalCacheTable::Lookup(String* src) {
|
| + // Try to find the eval in the cache
|
| + StringKey key(src);
|
| + int entry = FindEntry(&key);
|
| + if (entry == kNotFound) {
|
| + return GetHeap()->undefined_value();
|
| + }
|
| +
|
| + // Reset the age of the entry
|
| + int value_index = EntryToIndex(entry) + 1;
|
| + int age_index = value_index + 1;
|
| + set(age_index, NextAge());
|
| +
|
| + return get(value_index);
|
| +}
|
| +
|
| +
|
| +MaybeObject* ShortTermJSONEvalCacheTable::Put(String* src,
|
| + SharedFunctionInfo* value) {
|
| + int size = ValueSize(value);
|
| + if (size >= max_total_source_size()) {
|
| + return this;
|
| + }
|
| + ASSERT(value->code()->kind() == Code::FUNCTION);
|
| +
|
| + // Reserve space for this element.
|
| + Reserve(size);
|
| + ASSERT(total_source_size() + size <= max_total_source_size());
|
| + ASSERT(NumberOfElements() + 1 <= max_entries());
|
| +
|
| + // Create the key
|
| + StringKey key(src);
|
| + Object* k;
|
| + { MaybeObject* maybe_k = key.AsObject();
|
| + if (!maybe_k->ToObject(&k)) return maybe_k;
|
| + }
|
| +
|
| + // Reallocate and rehash the table if we've gone stale.
|
| + ShortTermJSONEvalCacheTable* table;
|
| + {
|
| + MaybeObject* maybe_t = EnsureCapacity(1, &key);
|
| + if (!maybe_t->To<ShortTermJSONEvalCacheTable>(&table)) return maybe_t;
|
| + }
|
| +
|
| + // Add the new entry
|
| + uint32_t entry = table->FindInsertionEntry(key.Hash());
|
| + int index = table->EntryToIndex(entry);
|
| + Smi* age = table->NextAge();
|
| + table->set(index, k);
|
| + table->set(index+1, value);
|
| + table->set(index+2, age);
|
| + table->ElementAdded();
|
| +
|
| + table->set_total_source_size(total_source_size() + size);
|
| +
|
| + return table;
|
| +}
|
| +
|
| +
|
| +void ShortTermJSONEvalCacheTable::Remove(Object* value) {
|
| + int elements_removed = 0;
|
| + int source_size_removed = 0;
|
| + for (int entry = 0, size = Capacity(); entry < size; entry++) {
|
| + int key_index = EntryToIndex(entry);
|
| + int value_index = key_index + 1;
|
| + if (get(value_index) == value) {
|
| + set_the_hole(key_index);
|
| + set_the_hole(value_index);
|
| + elements_removed += 1;
|
| + source_size_removed = ValueSize(SharedFunctionInfo::cast(value));
|
| + }
|
| + }
|
| + ElementsRemoved(elements_removed);
|
| + set_total_source_size(total_source_size() - source_size_removed);
|
| +}
|
| +
|
| +
|
| +int ShortTermJSONEvalCacheTable::ValueSize(SharedFunctionInfo* value) {
|
| + return value->end_position() - value->start_position();
|
| +}
|
| +
|
| +
|
| +void ShortTermJSONEvalCacheTable::Reserve(int size) {
|
| + ASSERT(0 <= size && size < max_total_source_size());
|
| + while (NumberOfElements() == max_entries() ||
|
| + total_source_size() + size > max_total_source_size()) {
|
| + RemoveOldest();
|
| + }
|
| +}
|
| +
|
| +int ShortTermJSONEvalCacheTable::max_entries() {
|
| + ASSERT(FLAG_json_eval_cache_max_entries > 0);
|
| + return FLAG_json_eval_cache_max_entries;
|
| +}
|
| +
|
| +int ShortTermJSONEvalCacheTable::max_total_source_size() {
|
| + ASSERT(FLAG_json_eval_cache_max_size > 0);
|
| + return FLAG_json_eval_cache_max_size;
|
| +}
|
| +
|
| +
|
| +void ShortTermJSONEvalCacheTable::RemoveOldest() {
|
| + ASSERT(NumberOfElements() > 0);
|
| +
|
| + // Locate the oldest element. Smaller age values indicate older elements.
|
| + int oldest_age = -1;
|
| + int oldest_entry = -1;
|
| + for (int entry = 0, size = Capacity(); entry < size; entry++) {
|
| + int key_index = EntryToIndex(entry);
|
| + if (get(key_index)->IsTheHole() || get(key_index)->IsUndefined()) continue;
|
| + int age_index = key_index + 2;
|
| + int age = Smi::cast(get(age_index))->value();
|
| + if (oldest_entry == -1 || age < oldest_age) {
|
| + oldest_entry = entry;
|
| + oldest_age = age;
|
| + }
|
| + }
|
| +
|
| + // Remove the element from this table.
|
| + int oldest_key_index = EntryToIndex(oldest_entry);
|
| + int oldest_value_index = oldest_key_index + 1;
|
| + int oldest_age_index = oldest_key_index + 2;
|
| + SharedFunctionInfo* value = SharedFunctionInfo::cast(get(oldest_value_index));
|
| + int size = ValueSize(value);
|
| + set_total_source_size(total_source_size() - size);
|
| + set_the_hole(oldest_key_index);
|
| + set_the_hole(oldest_value_index);
|
| + set_the_hole(oldest_age_index);
|
| + ElementRemoved();
|
| +}
|
| +
|
| +
|
| +int ShortTermJSONEvalCacheTable::current_age() {
|
| + return Smi::cast(get(ShortTermJSONEvalCacheShape::kAgeIndex))->value();
|
| +}
|
| +
|
| +
|
| +void ShortTermJSONEvalCacheTable::set_current_age(int age) {
|
| + set(ShortTermJSONEvalCacheShape::kAgeIndex, Smi::FromInt(age));
|
| +}
|
| +
|
| +
|
| +Smi* ShortTermJSONEvalCacheTable::NextAge() {
|
| + // We need to protect against overflowing to non-Smi values here.
|
| + // If we reach the maximum Smi value, we roll over to 0. This will
|
| + // make old age values invalid, but this is unlikely to ever happen
|
| + // since age is reset when the browser goes idle.
|
| + int age = current_age();
|
| + int next_age = age == Smi::kMaxValue ? 0 : age + 1;
|
| + set_current_age(next_age);
|
| + return Smi::FromInt(age);
|
| +}
|
| +
|
| +
|
| // SymbolsKey used for HashTable where key is array of symbols.
|
| class SymbolsKey : public HashTableKey {
|
| public:
|
|
|