Make HashMap a template class to specify the allocation policy.

The old HashMap class had an explicit member to determine the allocation
policy. The template version matches the approach used already for
lists.

Cleanup some include dependencies and unnecessary forward declarations.

Cleanup some dead code from isolate.h and replace some HEAP macros
with GetHeap().
Review URL: https://chromiumcodereview.appspot.com/9372106

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@10806 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 7d4b78ac
# Copyright 2011 the V8 project authors. All rights reserved.
# Copyright 2012 the V8 project authors. All rights reserved.
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
......@@ -78,7 +78,6 @@ SOURCES = {
fast-dtoa.cc
fixed-dtoa.cc
handles.cc
hashmap.cc
heap-profiler.cc
heap.cc
hydrogen.cc
......@@ -246,7 +245,6 @@ PREPARSER_SOURCES = {
dtoa.cc
fast-dtoa.cc
fixed-dtoa.cc
hashmap.cc
preparse-data.cc
preparser.cc
preparser-api.cc
......
......@@ -237,8 +237,8 @@ bool IsEqualNumber(void* first, void* second) {
void ObjectLiteral::CalculateEmitStore() {
HashMap properties(&IsEqualString);
HashMap elements(&IsEqualNumber);
ZoneHashMap properties(&IsEqualString);
ZoneHashMap elements(&IsEqualNumber);
for (int i = this->properties()->length() - 1; i >= 0; i--) {
ObjectLiteral::Property* property = this->properties()->at(i);
Literal* literal = property->key();
......@@ -249,7 +249,7 @@ void ObjectLiteral::CalculateEmitStore() {
}
uint32_t hash;
HashMap* table;
ZoneHashMap* table;
void* key;
Factory* factory = Isolate::Current()->factory();
if (handle->IsSymbol()) {
......
......@@ -214,13 +214,12 @@ class Genesis BASE_EMBEDDED {
};
class ExtensionStates {
public:
public:
ExtensionStates();
ExtensionTraversalState get_state(RegisteredExtension* extension);
void set_state(RegisteredExtension* extension,
ExtensionTraversalState state);
private:
Allocator allocator_;
private:
HashMap map_;
DISALLOW_COPY_AND_ASSIGN(ExtensionStates);
};
......@@ -1961,9 +1960,7 @@ static bool MatchRegisteredExtensions(void* key1, void* key2) {
}
Genesis::ExtensionStates::ExtensionStates()
: allocator_(),
map_(MatchRegisteredExtensions, &allocator_, 8)
{}
: map_(MatchRegisteredExtensions, 8) { }
Genesis::ExtensionTraversalState Genesis::ExtensionStates::get_state(
RegisteredExtension* extension) {
......
// Copyright 2011 the V8 project authors. All rights reserved.
// Copyright 2012 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
......@@ -31,8 +31,6 @@
namespace v8 {
namespace internal {
class HashMap;
// The compilation cache consists of several generational sub-caches which uses
// this class as a base class. A sub-cache contains a compilation cache tables
// for each generation of the sub-cache. Since the same source code string has
......
// Copyright 2010 the V8 project authors. All rights reserved.
// Copyright 2012 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
......@@ -41,7 +41,6 @@ class CodeEntry;
class CodeMap;
class CpuProfile;
class CpuProfilesCollection;
class HashMap;
class ProfileGenerator;
class TokenEnumerator;
......
// Copyright 2008 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../include/v8stdint.h"
#include "globals.h"
#include "checks.h"
#include "utils.h"
#include "allocation.h"
#include "hashmap.h"
namespace v8 {
namespace internal {
Allocator* HashMap::DefaultAllocator = ::new Allocator();
HashMap::HashMap(MatchFun match,
Allocator* allocator,
uint32_t initial_capacity) {
allocator_ = allocator;
match_ = match;
Initialize(initial_capacity);
}
HashMap::~HashMap() {
if (allocator_) {
allocator_->Delete(map_);
}
}
HashMap::Entry* HashMap::Lookup(void* key, uint32_t hash, bool insert) {
// Find a matching entry.
Entry* p = Probe(key, hash);
if (p->key != NULL) {
return p;
}
// No entry found; insert one if necessary.
if (insert) {
p->key = key;
p->value = NULL;
p->hash = hash;
occupancy_++;
// Grow the map if we reached >= 80% occupancy.
if (occupancy_ + occupancy_/4 >= capacity_) {
Resize();
p = Probe(key, hash);
}
return p;
}
// No entry found and none inserted.
return NULL;
}
void HashMap::Remove(void* key, uint32_t hash) {
// Lookup the entry for the key to remove.
Entry* p = Probe(key, hash);
if (p->key == NULL) {
// Key not found nothing to remove.
return;
}
// To remove an entry we need to ensure that it does not create an empty
// entry that will cause the search for another entry to stop too soon. If all
// the entries between the entry to remove and the next empty slot have their
// initial position inside this interval, clearing the entry to remove will
// not break the search. If, while searching for the next empty entry, an
// entry is encountered which does not have its initial position between the
// entry to remove and the position looked at, then this entry can be moved to
// the place of the entry to remove without breaking the search for it. The
// entry made vacant by this move is now the entry to remove and the process
// starts over.
// Algorithm from http://en.wikipedia.org/wiki/Open_addressing.
// This guarantees loop termination as there is at least one empty entry so
// eventually the removed entry will have an empty entry after it.
ASSERT(occupancy_ < capacity_);
// p is the candidate entry to clear. q is used to scan forwards.
Entry* q = p; // Start at the entry to remove.
while (true) {
// Move q to the next entry.
q = q + 1;
if (q == map_end()) {
q = map_;
}
// All entries between p and q have their initial position between p and q
// and the entry p can be cleared without breaking the search for these
// entries.
if (q->key == NULL) {
break;
}
// Find the initial position for the entry at position q.
Entry* r = map_ + (q->hash & (capacity_ - 1));
// If the entry at position q has its initial position outside the range
// between p and q it can be moved forward to position p and will still be
// found. There is now a new candidate entry for clearing.
if ((q > p && (r <= p || r > q)) ||
(q < p && (r <= p && r > q))) {
*p = *q;
p = q;
}
}
// Clear the entry which is allowed to en emptied.
p->key = NULL;
occupancy_--;
}
void HashMap::Clear() {
// Mark all entries as empty.
const Entry* end = map_end();
for (Entry* p = map_; p < end; p++) {
p->key = NULL;
}
occupancy_ = 0;
}
HashMap::Entry* HashMap::Start() const {
return Next(map_ - 1);
}
HashMap::Entry* HashMap::Next(Entry* p) const {
const Entry* end = map_end();
ASSERT(map_ - 1 <= p && p < end);
for (p++; p < end; p++) {
if (p->key != NULL) {
return p;
}
}
return NULL;
}
HashMap::Entry* HashMap::Probe(void* key, uint32_t hash) {
ASSERT(key != NULL);
ASSERT(IsPowerOf2(capacity_));
Entry* p = map_ + (hash & (capacity_ - 1));
const Entry* end = map_end();
ASSERT(map_ <= p && p < end);
ASSERT(occupancy_ < capacity_); // Guarantees loop termination.
while (p->key != NULL && (hash != p->hash || !match_(key, p->key))) {
p++;
if (p >= end) {
p = map_;
}
}
return p;
}
void HashMap::Initialize(uint32_t capacity) {
ASSERT(IsPowerOf2(capacity));
map_ = reinterpret_cast<Entry*>(allocator_->New(capacity * sizeof(Entry)));
if (map_ == NULL) {
v8::internal::FatalProcessOutOfMemory("HashMap::Initialize");
return;
}
capacity_ = capacity;
Clear();
}
void HashMap::Resize() {
Entry* map = map_;
uint32_t n = occupancy_;
// Allocate larger map.
Initialize(capacity_ * 2);
// Rehash all current entries.
for (Entry* p = map; n > 0; p++) {
if (p->key != NULL) {
Lookup(p->key, p->hash, true)->value = p->value;
n--;
}
}
// Delete old map.
allocator_->Delete(map);
}
} } // namespace v8::internal
// Copyright 2011 the V8 project authors. All rights reserved.
// Copyright 2012 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
......@@ -29,34 +29,22 @@
#define V8_HASHMAP_H_
#include "allocation.h"
#include "checks.h"
#include "utils.h"
namespace v8 {
namespace internal {
// Allocator defines the memory allocator interface
// used by HashMap and implements a default allocator.
class Allocator BASE_EMBEDDED {
public:
virtual ~Allocator() {}
virtual void* New(size_t size) { return Malloced::New(size); }
virtual void Delete(void* p) { Malloced::Delete(p); }
};
class HashMap {
template<class AllocationPolicy>
class TemplateHashMap {
public:
static Allocator* DefaultAllocator;
typedef bool (*MatchFun) (void* key1, void* key2);
// initial_capacity is the size of the initial hash map;
// it must be a power of 2 (and thus must not be 0).
explicit HashMap(MatchFun match,
Allocator* allocator = DefaultAllocator,
uint32_t initial_capacity = 8);
TemplateHashMap(MatchFun match, uint32_t initial_capacity = 8);
~HashMap();
~TemplateHashMap();
// HashMap entries are (key, value, hash) triplets.
// Some clients may not need to use the value slot
......@@ -100,7 +88,6 @@ class HashMap {
Entry* Next(Entry* p) const;
private:
Allocator* allocator_;
MatchFun match_;
Entry* map_;
uint32_t capacity_;
......@@ -112,6 +99,196 @@ class HashMap {
void Resize();
};
typedef TemplateHashMap<FreeStoreAllocationPolicy> HashMap;
template<class P>
TemplateHashMap<P>::TemplateHashMap(MatchFun match,
uint32_t initial_capacity) {
match_ = match;
Initialize(initial_capacity);
}
template<class P>
TemplateHashMap<P>::~TemplateHashMap() {
P::Delete(map_);
}
template<class P>
struct TemplateHashMap<P>::Entry* TemplateHashMap<P>::Lookup(
void* key, uint32_t hash, bool insert) {
// Find a matching entry.
Entry* p = Probe(key, hash);
if (p->key != NULL) {
return p;
}
// No entry found; insert one if necessary.
if (insert) {
p->key = key;
p->value = NULL;
p->hash = hash;
occupancy_++;
// Grow the map if we reached >= 80% occupancy.
if (occupancy_ + occupancy_/4 >= capacity_) {
Resize();
p = Probe(key, hash);
}
return p;
}
// No entry found and none inserted.
return NULL;
}
template<class P>
void TemplateHashMap<P>::Remove(void* key, uint32_t hash) {
// Lookup the entry for the key to remove.
Entry* p = Probe(key, hash);
if (p->key == NULL) {
// Key not found nothing to remove.
return;
}
// To remove an entry we need to ensure that it does not create an empty
// entry that will cause the search for another entry to stop too soon. If all
// the entries between the entry to remove and the next empty slot have their
// initial position inside this interval, clearing the entry to remove will
// not break the search. If, while searching for the next empty entry, an
// entry is encountered which does not have its initial position between the
// entry to remove and the position looked at, then this entry can be moved to
// the place of the entry to remove without breaking the search for it. The
// entry made vacant by this move is now the entry to remove and the process
// starts over.
// Algorithm from http://en.wikipedia.org/wiki/Open_addressing.
// This guarantees loop termination as there is at least one empty entry so
// eventually the removed entry will have an empty entry after it.
ASSERT(occupancy_ < capacity_);
// p is the candidate entry to clear. q is used to scan forwards.
Entry* q = p; // Start at the entry to remove.
while (true) {
// Move q to the next entry.
q = q + 1;
if (q == map_end()) {
q = map_;
}
// All entries between p and q have their initial position between p and q
// and the entry p can be cleared without breaking the search for these
// entries.
if (q->key == NULL) {
break;
}
// Find the initial position for the entry at position q.
Entry* r = map_ + (q->hash & (capacity_ - 1));
// If the entry at position q has its initial position outside the range
// between p and q it can be moved forward to position p and will still be
// found. There is now a new candidate entry for clearing.
if ((q > p && (r <= p || r > q)) ||
(q < p && (r <= p && r > q))) {
*p = *q;
p = q;
}
}
// Clear the entry which is allowed to en emptied.
p->key = NULL;
occupancy_--;
}
template<class P>
void TemplateHashMap<P>::Clear() {
// Mark all entries as empty.
const Entry* end = map_end();
for (Entry* p = map_; p < end; p++) {
p->key = NULL;
}
occupancy_ = 0;
}
template<class P>
struct TemplateHashMap<P>::Entry* TemplateHashMap<P>::Start() const {
return Next(map_ - 1);
}
template<class P>
struct TemplateHashMap<P>::Entry* TemplateHashMap<P>::Next(Entry* p) const {
const Entry* end = map_end();
ASSERT(map_ - 1 <= p && p < end);
for (p++; p < end; p++) {
if (p->key != NULL) {
return p;
}
}
return NULL;
}
template<class P>
struct TemplateHashMap<P>::Entry* TemplateHashMap<P>::Probe(void* key,
uint32_t hash) {
ASSERT(key != NULL);
ASSERT(IsPowerOf2(capacity_));
Entry* p = map_ + (hash & (capacity_ - 1));
const Entry* end = map_end();
ASSERT(map_ <= p && p < end);
ASSERT(occupancy_ < capacity_); // Guarantees loop termination.
while (p->key != NULL && (hash != p->hash || !match_(key, p->key))) {
p++;
if (p >= end) {
p = map_;
}
}
return p;
}
template<class P>
void TemplateHashMap<P>::Initialize(uint32_t capacity) {
ASSERT(IsPowerOf2(capacity));
map_ = reinterpret_cast<Entry*>(P::New(capacity * sizeof(Entry)));
if (map_ == NULL) {
v8::internal::FatalProcessOutOfMemory("HashMap::Initialize");
return;
}
capacity_ = capacity;
Clear();
}
template<class P>
void TemplateHashMap<P>::Resize() {
Entry* map = map_;
uint32_t n = occupancy_;
// Allocate larger map.
Initialize(capacity_ * 2);
// Rehash all current entries.
for (Entry* p = map; n > 0; p++) {
if (p->key != NULL) {
Lookup(p->key, p->hash, true)->value = p->value;
n--;
}
}
// Delete old map.
P::Delete(map);
}
} } // namespace v8::internal
......
......@@ -38,6 +38,7 @@
#include "frames.h"
#include "global-handles.h"
#include "handles.h"
#include "hashmap.h"
#include "heap.h"
#include "regexp-stack.h"
#include "runtime-profiler.h"
......@@ -280,23 +281,6 @@ class ThreadLocalTop BASE_EMBEDDED {
Address try_catch_handler_address_;
};
#if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_MIPS)
#define ISOLATE_PLATFORM_INIT_LIST(V) \
/* VirtualFrame::SpilledScope state */ \
V(bool, is_virtual_frame_in_spilled_scope, false) \
/* CodeGenerator::EmitNamedStore state */ \
V(int, inlined_write_barrier_size, -1)
#if !defined(__arm__) && !defined(__mips__)
class HashMap;
#endif
#else
#define ISOLATE_PLATFORM_INIT_LIST(V)
#endif
#ifdef ENABLE_DEBUGGER_SUPPORT
......@@ -367,7 +351,6 @@ typedef List<HeapObject*, PreallocatedStorage> DebugObjectCache;
V(uint64_t, enabled_cpu_features, 0) \
V(CpuProfiler*, cpu_profiler, NULL) \
V(HeapProfiler*, heap_profiler, NULL) \
ISOLATE_PLATFORM_INIT_LIST(V) \
ISOLATE_DEBUGGER_INIT_LIST(V)
class Isolate {
......
// Copyright 2011 the V8 project authors. All rights reserved.
// Copyright 2012 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
......@@ -71,7 +71,6 @@ namespace internal {
// tick profiler requires code events, so --prof implies --log-code.
// Forward declarations.
class HashMap;
class LogMessageBuilder;
class Profiler;
class Semaphore;
......
......@@ -3331,7 +3331,7 @@ void Map::set_prototype(Object* value, WriteBarrierMode mode) {
DescriptorArray* Map::instance_descriptors() {
Object* object = READ_FIELD(this, kInstanceDescriptorsOrBitField3Offset);
if (object->IsSmi()) {
return HEAP->empty_descriptor_array();
return GetHeap()->empty_descriptor_array();
} else {
return DescriptorArray::cast(object);
}
......@@ -3645,7 +3645,7 @@ BOOL_ACCESSORS(SharedFunctionInfo,
bool SharedFunctionInfo::IsInobjectSlackTrackingInProgress() {
return initial_map() != HEAP->undefined_value();
return initial_map() != GetHeap()->undefined_value();
}
......
// Copyright 2011 the V8 project authors. All rights reserved.
// Copyright 2012 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
......@@ -28,6 +28,7 @@
#ifndef V8_PREPARSER_H
#define V8_PREPARSER_H
#include "hashmap.h"
#include "token.h"
#include "scanner.h"
......
......@@ -39,26 +39,6 @@
namespace v8 {
namespace internal {
// ----------------------------------------------------------------------------
// A Zone allocator for use with LocalsMap.
// TODO(isolates): It is probably worth it to change the Allocator class to
// take a pointer to an isolate.
class ZoneAllocator: public Allocator {
public:
/* nothing to do */
virtual ~ZoneAllocator() {}
virtual void* New(size_t size) { return ZONE->New(static_cast<int>(size)); }
/* ignored - Zone is freed in one fell swoop */
virtual void Delete(void* p) {}
};
static ZoneAllocator* LocalsMapAllocator = ::new ZoneAllocator();
// ----------------------------------------------------------------------------
// Implementation of LocalsMap
//
......@@ -77,7 +57,7 @@ static bool Match(void* key1, void* key2) {
}
VariableMap::VariableMap() : HashMap(Match, LocalsMapAllocator, 8) {}
VariableMap::VariableMap() : ZoneHashMap(Match, 8) {}
VariableMap::~VariableMap() {}
......@@ -88,7 +68,7 @@ Variable* VariableMap::Declare(
bool is_valid_lhs,
Variable::Kind kind,
InitializationFlag initialization_flag) {
HashMap::Entry* p = HashMap::Lookup(name.location(), name->Hash(), true);
Entry* p = ZoneHashMap::Lookup(name.location(), name->Hash(), true);
if (p->value == NULL) {
// The variable has not been declared yet -> insert it.
ASSERT(p->key == name.location());
......@@ -104,7 +84,7 @@ Variable* VariableMap::Declare(
Variable* VariableMap::Lookup(Handle<String> name) {
HashMap::Entry* p = HashMap::Lookup(name.location(), name->Hash(), false);
Entry* p = ZoneHashMap::Lookup(name.location(), name->Hash(), false);
if (p != NULL) {
ASSERT(*reinterpret_cast<String**>(p->key) == *name);
ASSERT(p->value != NULL);
......
......@@ -29,7 +29,7 @@
#define V8_SCOPES_H_
#include "ast.h"
#include "hashmap.h"
#include "zone.h"
namespace v8 {
namespace internal {
......@@ -38,7 +38,7 @@ class CompilationInfo;
// A hash map to support fast variable declaration and lookup.
class VariableMap: public HashMap {
class VariableMap: public ZoneHashMap {
public:
VariableMap();
......
......@@ -30,6 +30,7 @@
#include "allocation.h"
#include "checks.h"
#include "hashmap.h"
#include "globals.h"
#include "list.h"
#include "splay-tree.h"
......@@ -239,6 +240,8 @@ class ZoneSplayTree: public SplayTree<Config, ZoneListAllocationPolicy> {
};
typedef TemplateHashMap<ZoneListAllocationPolicy> ZoneHashMap;
} } // namespace v8::internal
#endif // V8_ZONE_H_
......@@ -325,7 +325,6 @@
'../../src/handles-inl.h',
'../../src/handles.cc',
'../../src/handles.h',
'../../src/hashmap.cc',
'../../src/hashmap.h',
'../../src/heap-inl.h',
'../../src/heap.cc',
......@@ -923,7 +922,6 @@
'../../src/fixed-dtoa.cc',
'../../src/fixed-dtoa.h',
'../../src/globals.h',
'../../src/hashmap.cc',
'../../src/hashmap.h',
'../../src/list-inl.h',
'../../src/list.h',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment