Commit 6475f8d7 authored by lrn@chromium.org's avatar lrn@chromium.org

Remove HandleCell and use GlobalHandle and HandleScope::Escape instead.

Added HandleScope::Escape to HandleScope to allow exiting a value
from a scope.

Review URL: http://codereview.chromium.org/6594075

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6993 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 97aecae1
......@@ -51,16 +51,6 @@ inline T* Handle<T>::operator*() const {
}
template <typename T>
HandleCell<T>::HandleCell(T* value)
: location_(HandleScope::CreateHandle(value)) { }
template <typename T>
HandleCell<T>::HandleCell(Handle<T> value)
: location_(HandleScope::CreateHandle(*value)) { }
#ifdef DEBUG
inline NoHandleAllocation::NoHandleAllocation() {
v8::ImplementationUtilities::HandleScopeData* current =
......
......@@ -93,55 +93,6 @@ class Handle {
};
// A handle-scope based variable. The value stored in the variable can change
// over time. The value stored in the variable at any time is a root
// for garbage collection.
// The variable is backed by the current HandleScope.
template <typename T>
class HandleCell {
public:
// Create a new HandleCell holding the given value.
explicit HandleCell(Handle<T> value);
explicit HandleCell(T* value);
// Create an alias of an existing HandleCell.
explicit HandleCell(const HandleCell<T>& value)
: location_(value.location_) { }
INLINE(T* operator->() const) { return operator*(); }
INLINE(T* operator*() const) {
return *location_;
}
INLINE(void operator=(T* value)) {
*location_ = value;
}
INLINE(void operator=(Handle<T> value)) {
*location_ = *value;
}
INLINE(void operator=(const HandleCell<T>& value)) {
*location_ = *value.location_;
}
// Extract the value of the variable and cast it to a give type.
// This is typically used for calling methods on a more specialized type.
template <typename S>
inline S* cast() {
S::cast(*location_);
return *reinterpret_cast<S**>(location_);
}
Handle<T> ToHandle() const {
return Handle<T>(*location_);
}
private:
// Prevent implicit constructor from being created.
HandleCell();
T** location_;
};
// A stack-allocated class that governs a number of local handles.
// After a handle scope has been created, all local handles will be
// allocated within that handle scope until either the handle scope is
......@@ -161,15 +112,7 @@ class HandleScope {
}
~HandleScope() {
current_.next = prev_next_;
current_.level--;
if (current_.limit != prev_limit_) {
current_.limit = prev_limit_;
DeleteExtensions();
}
#ifdef DEBUG
ZapRange(prev_next_, prev_limit_);
#endif
CloseScope();
}
// Counts the number of allocated handles.
......@@ -197,6 +140,26 @@ class HandleScope {
static Address current_limit_address();
static Address current_level_address();
// Closes the HandleScope (invalidating all handles
// created in the scope of the HandleScope) and returns
// a Handle backed by the parent scope holding the
// value of the argument handle.
template <typename T>
Handle<T> CloseAndEscape(Handle<T> handle_value) {
T* value = *handle_value;
// Throw away all handles in the current scope.
CloseScope();
// Allocate one handle in the parent scope.
ASSERT(current_.level > 0);
Handle<T> result(CreateHandle<T>(value));
// Reinitialize the current scope (so that it's ready
// to be used or closed again).
prev_next_ = current_.next;
prev_limit_ = current_.limit;
current_.level++;
return result;
}
private:
// Prevent heap allocation or illegal handle scopes.
HandleScope(const HandleScope&);
......@@ -204,9 +167,23 @@ class HandleScope {
void* operator new(size_t size);
void operator delete(void* size_t);
inline void CloseScope() {
current_.next = prev_next_;
current_.level--;
if (current_.limit != prev_limit_) {
current_.limit = prev_limit_;
DeleteExtensions();
}
#ifdef DEBUG
ZapRange(prev_next_, prev_limit_);
#endif
}
static v8::ImplementationUtilities::HandleScopeData current_;
Object** const prev_next_;
Object** const prev_limit_;
// Holds values on entry. The prev_next_ value is never NULL
// on_entry, but is set to NULL when this scope is closed.
Object** prev_next_;
Object** prev_limit_;
// Extend the handle scope making room for more handles.
static internal::Object** Extend();
......
......@@ -40,6 +40,7 @@
#include "debug.h"
#include "deoptimizer.h"
#include "execution.h"
#include "global-handles.h"
#include "jsregexp.h"
#include "liveedit.h"
#include "parser.h"
......@@ -8041,10 +8042,14 @@ class ArrayConcatVisitor {
public:
ArrayConcatVisitor(Handle<FixedArray> storage,
bool fast_elements) :
storage_(storage),
storage_(Handle<FixedArray>::cast(GlobalHandles::Create(*storage))),
index_offset_(0u),
fast_elements_(fast_elements) { }
~ArrayConcatVisitor() {
clear_storage();
}
void visit(uint32_t i, Handle<Object> elm) {
if (i >= JSObject::kMaxElementCount - index_offset_) return;
uint32_t index = index_offset_ + i;
......@@ -8062,11 +8067,13 @@ class ArrayConcatVisitor {
// Fall-through to dictionary mode.
}
ASSERT(!fast_elements_);
Handle<NumberDictionary> dict(storage_.cast<NumberDictionary>());
Handle<NumberDictionary> dict(NumberDictionary::cast(*storage_));
Handle<NumberDictionary> result =
Factory::DictionaryAtNumberPut(dict, index, elm);
if (!result.is_identical_to(dict)) {
storage_ = Handle<FixedArray>::cast(result);
// Dictionary needed to grow.
clear_storage();
set_storage(*result);
}
}
......@@ -8098,23 +8105,35 @@ class ArrayConcatVisitor {
// Convert storage to dictionary mode.
void SetDictionaryMode(uint32_t index) {
ASSERT(fast_elements_);
Handle<FixedArray> current_storage(storage_.ToHandle());
HandleCell<NumberDictionary> slow_storage(
Handle<FixedArray> current_storage(*storage_);
Handle<NumberDictionary> slow_storage(
Factory::NewNumberDictionary(current_storage->length()));
uint32_t current_length = static_cast<uint32_t>(current_storage->length());
for (uint32_t i = 0; i < current_length; i++) {
HandleScope loop_scope;
Handle<Object> element(current_storage->get(i));
if (!element->IsTheHole()) {
slow_storage =
Factory::DictionaryAtNumberPut(slow_storage.ToHandle(), i, element);
Handle<NumberDictionary> new_storage =
Factory::DictionaryAtNumberPut(slow_storage, i, element);
if (!new_storage.is_identical_to(slow_storage)) {
slow_storage = loop_scope.CloseAndEscape(new_storage);
}
}
}
storage_ = slow_storage.cast<FixedArray>();
clear_storage();
set_storage(*slow_storage);
fast_elements_ = false;
}
HandleCell<FixedArray> storage_;
inline void clear_storage() {
GlobalHandles::Destroy(Handle<Object>::cast(storage_).location());
}
inline void set_storage(FixedArray* storage) {
storage_ = Handle<FixedArray>::cast(GlobalHandles::Create(storage));
}
Handle<FixedArray> storage_; // Always a global handle.
// Index after last seen index. Always less than or equal to
// JSObject::kMaxElementCount.
uint32_t index_offset_;
......
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