Commit 20739610 authored by dcarney@chromium.org's avatar dcarney@chromium.org

introduce eternal handles

R=mstarzinger@chromium.org
BUG=

Review URL: https://codereview.chromium.org/21133006

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16045 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent a50827e0
......@@ -5451,7 +5451,7 @@ class Internals {
static const int kNullValueRootIndex = 7;
static const int kTrueValueRootIndex = 8;
static const int kFalseValueRootIndex = 9;
static const int kEmptyStringRootIndex = 135;
static const int kEmptyStringRootIndex = 133;
static const int kNodeClassIdOffset = 1 * kApiPointerSize;
static const int kNodeFlagsOffset = 1 * kApiPointerSize + 3;
......
......@@ -141,35 +141,37 @@ void Utils::AsciiToUChar(const char* source,
}
// static
v8::Local<v8::ObjectTemplate> Utils::GetTemplate(v8::Isolate* isolate) {
i::Isolate* internal = reinterpret_cast<i::Isolate*>(isolate);
if (internal->heap()->i18n_template_one() ==
internal->heap()->the_hole_value()) {
v8::Local<v8::ObjectTemplate> raw_template(v8::ObjectTemplate::New());
raw_template->SetInternalFieldCount(1);
internal->heap()
->SetI18nTemplateOne(*v8::Utils::OpenHandle(*raw_template));
static v8::Local<v8::ObjectTemplate> ToLocal(i::Handle<i::Object> handle) {
return v8::Utils::ToLocal(i::Handle<i::ObjectTemplateInfo>::cast(handle));
}
template<int internal_fields, i::EternalHandles::SingletonHandle field>
static v8::Local<v8::ObjectTemplate> GetEternal(v8::Isolate* external) {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(external);
if (isolate->eternal_handles()->Exists(field)) {
return ToLocal(isolate->eternal_handles()->GetSingleton(field));
}
v8::Local<v8::ObjectTemplate> raw_template(v8::ObjectTemplate::New());
raw_template->SetInternalFieldCount(internal_fields);
return ToLocal(
isolate->eternal_handles()->CreateSingleton(
isolate,
*v8::Utils::OpenHandle(*raw_template),
field));
}
return v8::Utils::ToLocal(i::Handle<i::ObjectTemplateInfo>::cast(
internal->factory()->i18n_template_one()));
// static
v8::Local<v8::ObjectTemplate> Utils::GetTemplate(v8::Isolate* isolate) {
return GetEternal<1, i::EternalHandles::I18N_TEMPLATE_ONE>(isolate);
}
// static
v8::Local<v8::ObjectTemplate> Utils::GetTemplate2(v8::Isolate* isolate) {
i::Isolate* internal = reinterpret_cast<i::Isolate*>(isolate);
if (internal->heap()->i18n_template_two() ==
internal->heap()->the_hole_value()) {
v8::Local<v8::ObjectTemplate> raw_template(v8::ObjectTemplate::New());
raw_template->SetInternalFieldCount(2);
internal->heap()
->SetI18nTemplateTwo(*v8::Utils::OpenHandle(*raw_template));
}
return v8::Utils::ToLocal(i::Handle<i::ObjectTemplateInfo>::cast(
internal->factory()->i18n_template_two()));
return GetEternal<2, i::EternalHandles::I18N_TEMPLATE_TWO>(isolate);
}
} // namespace v8_i18n
......@@ -1250,4 +1250,67 @@ void GlobalHandles::ComputeObjectGroupsAndImplicitReferences() {
}
EternalHandles::EternalHandles() : size_(0) {
for (unsigned i = 0; i < ARRAY_SIZE(singleton_handles_); i++) {
singleton_handles_[i] = kInvalidIndex;
}
}
EternalHandles::~EternalHandles() {
for (int i = 0; i < blocks_.length(); i++) delete blocks_[i];
}
void EternalHandles::IterateAllRoots(ObjectVisitor* visitor) {
int limit = size_;
for (int i = 0; i < blocks_.length(); i++) {
ASSERT(limit > 0);
Object** block = blocks_[i];
visitor->VisitPointers(block, block + Min(limit, kSize));
limit -= kSize;
}
}
void EternalHandles::IterateNewSpaceRoots(ObjectVisitor* visitor) {
for (int i = 0; i < new_space_indices_.length(); i++) {
visitor->VisitPointer(GetLocation(new_space_indices_[i]));
}
}
void EternalHandles::PostGarbageCollectionProcessing(Heap* heap) {
int last = 0;
for (int i = 0; i < new_space_indices_.length(); i++) {
int index = new_space_indices_[i];
if (heap->InNewSpace(*GetLocation(index))) {
new_space_indices_[last++] = index;
}
}
new_space_indices_.Rewind(last);
}
int EternalHandles::Create(Isolate* isolate, Object* object) {
if (object == NULL) return kInvalidIndex;
ASSERT_NE(isolate->heap()->the_hole_value(), object);
int block = size_ >> kShift;
int offset = size_ & kMask;
// need to resize
if (offset == 0) {
Object** next_block = new Object*[kSize];
Object* the_hole = isolate->heap()->the_hole_value();
MemsetPointer(next_block, the_hole, kSize);
blocks_.Add(next_block);
}
ASSERT_EQ(isolate->heap()->the_hole_value(), blocks_[block][offset]);
blocks_[block][offset] = object;
if (isolate->heap()->InNewSpace(object)) {
new_space_indices_.Add(size_);
}
return size_++;
}
} } // namespace v8::internal
......@@ -31,6 +31,7 @@
#include "../include/v8.h"
#include "../include/v8-profiler.h"
#include "handles.h"
#include "list.h"
#include "v8utils.h"
......@@ -381,6 +382,76 @@ class GlobalHandles {
};
class EternalHandles {
public:
enum SingletonHandle {
I18N_TEMPLATE_ONE,
I18N_TEMPLATE_TWO,
NUMBER_OF_SINGLETON_HANDLES
};
EternalHandles();
~EternalHandles();
int NumberOfHandles() { return size_; }
// Create an EternalHandle, returning the index.
int Create(Isolate* isolate, Object* object);
// Grab the handle for an existing EternalHandle.
inline Handle<Object> Get(int index) {
return Handle<Object>(GetLocation(index));
}
// Grab the handle for an existing SingletonHandle.
inline Handle<Object> GetSingleton(SingletonHandle singleton) {
ASSERT(Exists(singleton));
return Get(singleton_handles_[singleton]);
}
// Checks whether a SingletonHandle has been assigned.
inline bool Exists(SingletonHandle singleton) {
return singleton_handles_[singleton] != kInvalidIndex;
}
// Assign a SingletonHandle to an empty slot and returns the handle.
Handle<Object> CreateSingleton(Isolate* isolate,
Object* object,
SingletonHandle singleton) {
ASSERT(singleton_handles_[singleton] == kInvalidIndex);
singleton_handles_[singleton] = Create(isolate, object);
return Get(singleton_handles_[singleton]);
}
// Iterates over all handles.
void IterateAllRoots(ObjectVisitor* visitor);
// Iterates over all handles which might be in new space.
void IterateNewSpaceRoots(ObjectVisitor* visitor);
// Rebuilds new space list.
void PostGarbageCollectionProcessing(Heap* heap);
private:
static const int kInvalidIndex = -1;
static const int kShift = 8;
static const int kSize = 1 << kShift;
static const int kMask = 0xff;
// Gets the slot for an index
inline Object** GetLocation(int index) {
ASSERT(index >= 0 && index < size_);
return &blocks_[index >> kShift][index & kMask];
}
int size_;
List<Object**> blocks_;
List<int> new_space_indices_;
int singleton_handles_[NUMBER_OF_SINGLETON_HANDLES];
DISALLOW_COPY_AND_ASSIGN(EternalHandles);
};
} } // namespace v8::internal
#endif // V8_GLOBAL_HANDLES_H_
......@@ -1014,6 +1014,8 @@ bool Heap::PerformGarbageCollection(GarbageCollector collector,
}
gc_post_processing_depth_--;
isolate_->eternal_handles()->PostGarbageCollectionProcessing(this);
// Update relocatables.
Relocatable::PostGarbageCollectionProcessing();
......@@ -3218,9 +3220,6 @@ bool Heap::CreateInitialObjects() {
}
set_observed_symbol(Symbol::cast(obj));
set_i18n_template_one(the_hole_value());
set_i18n_template_two(the_hole_value());
// Handling of script id generation is in Factory::NewScript.
set_last_script_id(Smi::FromInt(v8::Script::kNoScriptId));
......@@ -6608,6 +6607,14 @@ void Heap::IterateStrongRoots(ObjectVisitor* v, VisitMode mode) {
}
v->Synchronize(VisitorSynchronization::kGlobalHandles);
// Iterate over eternal handles.
if (mode == VISIT_ALL_IN_SCAVENGE) {
isolate_->eternal_handles()->IterateNewSpaceRoots(v);
} else {
isolate_->eternal_handles()->IterateAllRoots(v);
}
v->Synchronize(VisitorSynchronization::kEternalHandles);
// Iterate over pointers being held by inactive threads.
isolate_->thread_manager()->Iterate(v);
v->Synchronize(VisitorSynchronization::kThreadManager);
......
......@@ -189,9 +189,7 @@ namespace internal {
V(Symbol, elements_transition_symbol, ElementsTransitionSymbol) \
V(SeededNumberDictionary, empty_slow_element_dictionary, \
EmptySlowElementDictionary) \
V(Symbol, observed_symbol, ObservedSymbol) \
V(HeapObject, i18n_template_one, I18nTemplateOne) \
V(HeapObject, i18n_template_two, I18nTemplateTwo)
V(Symbol, observed_symbol, ObservedSymbol)
#define ROOT_LIST(V) \
STRONG_ROOT_LIST(V) \
......@@ -1302,12 +1300,6 @@ class Heap {
ASSERT((callback == NULL) ^ (global_gc_epilogue_callback_ == NULL));
global_gc_epilogue_callback_ = callback;
}
void SetI18nTemplateOne(ObjectTemplateInfo* tmpl) {
set_i18n_template_one(tmpl);
}
void SetI18nTemplateTwo(ObjectTemplateInfo* tmpl) {
set_i18n_template_two(tmpl);
}
// Heap root getters. We have versions with and without type::cast() here.
// You can't use type::cast during GC because the assert fails.
......
......@@ -1774,6 +1774,7 @@ Isolate::Isolate()
inner_pointer_to_code_cache_(NULL),
write_iterator_(NULL),
global_handles_(NULL),
eternal_handles_(NULL),
context_switcher_(NULL),
thread_manager_(NULL),
fp_stubs_generated_(false),
......@@ -2052,6 +2053,8 @@ Isolate::~Isolate() {
code_range_ = NULL;
delete global_handles_;
global_handles_ = NULL;
delete eternal_handles_;
eternal_handles_ = NULL;
delete string_stream_debug_object_cache_;
string_stream_debug_object_cache_ = NULL;
......@@ -2183,6 +2186,7 @@ bool Isolate::Init(Deserializer* des) {
inner_pointer_to_code_cache_ = new InnerPointerToCodeCache(this);
write_iterator_ = new ConsStringIteratorOp();
global_handles_ = new GlobalHandles(this);
eternal_handles_ = new EternalHandles();
bootstrapper_ = new Bootstrapper(this);
handle_scope_implementer_ = new HandleScopeImplementer(this);
stub_cache_ = new StubCache(this);
......
......@@ -922,6 +922,8 @@ class Isolate {
GlobalHandles* global_handles() { return global_handles_; }
EternalHandles* eternal_handles() { return eternal_handles_; }
ThreadManager* thread_manager() { return thread_manager_; }
ContextSwitcher* context_switcher() { return context_switcher_; }
......@@ -1295,6 +1297,7 @@ class Isolate {
InnerPointerToCodeCache* inner_pointer_to_code_cache_;
ConsStringIteratorOp* write_iterator_;
GlobalHandles* global_handles_;
EternalHandles* eternal_handles_;
ContextSwitcher* context_switcher_;
ThreadManager* thread_manager_;
RuntimeState runtime_state_;
......
......@@ -10067,6 +10067,7 @@ class BreakPointInfo: public Struct {
V(kHandleScope, "handlescope", "(Handle scope)") \
V(kBuiltins, "builtins", "(Builtins)") \
V(kGlobalHandles, "globalhandles", "(Global handles)") \
V(kEternalHandles, "eternalhandles", "(Eternal handles)") \
V(kThreadManager, "threadmanager", "(Thread manager)") \
V(kExtensions, "Extensions", "(Extensions)")
......
......@@ -1304,6 +1304,7 @@ void StartupSerializer::SerializeStrongReferences() {
// No active or weak handles.
CHECK(isolate->handle_scope_implementer()->blocks()->is_empty());
CHECK_EQ(0, isolate->global_handles()->NumberOfWeakHandles());
CHECK_EQ(0, isolate->eternal_handles()->NumberOfHandles());
// We don't support serializing installed extensions.
CHECK(!isolate->has_installed_extensions());
......
......@@ -469,3 +469,37 @@ TEST(RandomMutation) {
// clear everything
data.RemoveAll();
}
TEST(EternalHandles) {
CcTest::InitializeVM();
Isolate* isolate = Isolate::Current();
v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
EternalHandles* eternals = isolate->eternal_handles();
// Create a number of handles that will not be on a block boundary
const int kArrayLength = 2048-1;
int indices[kArrayLength];
CHECK_EQ(0, eternals->NumberOfHandles());
for (int i = 0; i < kArrayLength; i++) {
HandleScope scope(isolate);
v8::Handle<v8::Object> object = v8::Object::New();
object->Set(i, v8::Integer::New(i, v8_isolate));
indices[i] = eternals->Create(isolate, *v8::Utils::OpenHandle(*object));
}
isolate->heap()->CollectAllAvailableGarbage();
for (int i = 0; i < kArrayLength; i++) {
HandleScope scope(isolate);
v8::Handle<v8::Value> local = v8::Utils::ToLocal(eternals->Get(i));
v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(local);
v8::Handle<v8::Value> value = object->Get(i);
CHECK(value->IsInt32());
CHECK_EQ(i, value->Int32Value());
}
CHECK_EQ(kArrayLength, eternals->NumberOfHandles());
}
......@@ -208,7 +208,7 @@ KNOWN_MAPS = {
KNOWN_OBJECTS = {
("OLD_POINTER_SPACE", 0x08081): "NullValue",
("OLD_POINTER_SPACE", 0x08091): "UndefinedValue",
("OLD_POINTER_SPACE", 0x080a1): "I18nTemplateTwo",
("OLD_POINTER_SPACE", 0x080a1): "InstanceofCacheMap",
("OLD_POINTER_SPACE", 0x080b1): "TrueValue",
("OLD_POINTER_SPACE", 0x080c1): "FalseValue",
("OLD_POINTER_SPACE", 0x080d1): "UninitializedValue",
......@@ -247,6 +247,6 @@ KNOWN_OBJECTS = {
("OLD_DATA_SPACE", 0x082c9): "EmptyExternalPixelArray",
("OLD_DATA_SPACE", 0x082d5): "InfinityValue",
("OLD_DATA_SPACE", 0x082e1): "MinusZeroValue",
("CODE_SPACE", 0x0eb41): "JsConstructEntryCode",
("CODE_SPACE", 0x177a1): "JsEntryCode",
("CODE_SPACE", 0x0e801): "JsConstructEntryCode",
("CODE_SPACE", 0x176e1): "JsEntryCode",
}
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