};
-// 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
}
~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.
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&);
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();
#include "debug.h"
#include "deoptimizer.h"
#include "execution.h"
+#include "global-handles.h"
#include "jsregexp.h"
#include "liveedit.h"
#include "parser.h"
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;
// 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);
}
}
// 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_;