Handlify JSObject::NormalizeProperties method.

R=verwaest@chromium.org

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16862 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
mstarzinger@chromium.org 2013-09-20 11:37:02 +00:00
parent 3dd88c4067
commit 35142b817f
3 changed files with 62 additions and 89 deletions

View File

@ -4348,12 +4348,12 @@ PropertyAttributes JSObject::GetElementAttributeWithoutInterceptor(
} }
MaybeObject* NormalizedMapCache::Get(JSObject* obj, Handle<Map> NormalizedMapCache::Get(Handle<NormalizedMapCache> cache,
PropertyNormalizationMode mode) { Handle<JSObject> obj,
Isolate* isolate = obj->GetIsolate(); PropertyNormalizationMode mode) {
Map* fast = obj->map(); Map* fast = obj->map();
int index = fast->Hash() % kEntries; int index = fast->Hash() % kEntries;
Object* result = get(index); Object* result = cache->get(index);
if (result->IsMap() && if (result->IsMap() &&
Map::cast(result)->EquivalentToForNormalization(fast, mode)) { Map::cast(result)->EquivalentToForNormalization(fast, mode)) {
#ifdef VERIFY_HEAP #ifdef VERIFY_HEAP
@ -4382,18 +4382,17 @@ MaybeObject* NormalizedMapCache::Get(JSObject* obj,
} }
} }
#endif #endif
return result; return handle(Map::cast(result));
} }
{ MaybeObject* maybe_result = Isolate* isolate = cache->GetIsolate();
fast->CopyNormalized(mode, SHARED_NORMALIZED_MAP); Handle<Map> map = Map::CopyNormalized(handle(fast), mode,
if (!maybe_result->ToObject(&result)) return maybe_result; SHARED_NORMALIZED_MAP);
} ASSERT(map->is_dictionary_map());
ASSERT(Map::cast(result)->is_dictionary_map()); cache->set(index, *map);
set(index, result);
isolate->counters()->normalized_maps()->Increment(); isolate->counters()->normalized_maps()->Increment();
return result; return map;
} }
@ -4426,65 +4425,55 @@ void HeapObject::UpdateMapCodeCache(Handle<HeapObject> object,
void JSObject::NormalizeProperties(Handle<JSObject> object, void JSObject::NormalizeProperties(Handle<JSObject> object,
PropertyNormalizationMode mode, PropertyNormalizationMode mode,
int expected_additional_properties) { int expected_additional_properties) {
CALL_HEAP_FUNCTION_VOID(object->GetIsolate(), if (!object->HasFastProperties()) return;
object->NormalizeProperties(
mode, expected_additional_properties));
}
MaybeObject* JSObject::NormalizeProperties(PropertyNormalizationMode mode,
int expected_additional_properties) {
if (!HasFastProperties()) return this;
// The global object is always normalized. // The global object is always normalized.
ASSERT(!IsGlobalObject()); ASSERT(!object->IsGlobalObject());
// JSGlobalProxy must never be normalized // JSGlobalProxy must never be normalized
ASSERT(!IsJSGlobalProxy()); ASSERT(!object->IsJSGlobalProxy());
Map* map_of_this = map(); Isolate* isolate = object->GetIsolate();
HandleScope scope(isolate);
Handle<Map> map(object->map());
// Allocate new content. // Allocate new content.
int real_size = map_of_this->NumberOfOwnDescriptors(); int real_size = map->NumberOfOwnDescriptors();
int property_count = real_size; int property_count = real_size;
if (expected_additional_properties > 0) { if (expected_additional_properties > 0) {
property_count += expected_additional_properties; property_count += expected_additional_properties;
} else { } else {
property_count += 2; // Make space for two more properties. property_count += 2; // Make space for two more properties.
} }
NameDictionary* dictionary; Handle<NameDictionary> dictionary =
MaybeObject* maybe_dictionary = isolate->factory()->NewNameDictionary(property_count);
NameDictionary::Allocate(GetHeap(), property_count);
if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
DescriptorArray* descs = map_of_this->instance_descriptors(); Handle<DescriptorArray> descs(map->instance_descriptors());
for (int i = 0; i < real_size; i++) { for (int i = 0; i < real_size; i++) {
PropertyDetails details = descs->GetDetails(i); PropertyDetails details = descs->GetDetails(i);
switch (details.type()) { switch (details.type()) {
case CONSTANT: { case CONSTANT: {
Handle<Name> key(descs->GetKey(i));
Handle<Object> value(descs->GetConstant(i), isolate);
PropertyDetails d = PropertyDetails( PropertyDetails d = PropertyDetails(
details.attributes(), NORMAL, i + 1); details.attributes(), NORMAL, i + 1);
Object* value = descs->GetConstant(i); dictionary = NameDictionaryAdd(dictionary, key, value, d);
MaybeObject* maybe_dictionary =
dictionary->Add(descs->GetKey(i), value, d);
if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
break; break;
} }
case FIELD: { case FIELD: {
Handle<Name> key(descs->GetKey(i));
Handle<Object> value(
object->RawFastPropertyAt(descs->GetFieldIndex(i)), isolate);
PropertyDetails d = PropertyDetails d =
PropertyDetails(details.attributes(), NORMAL, i + 1); PropertyDetails(details.attributes(), NORMAL, i + 1);
Object* value = RawFastPropertyAt(descs->GetFieldIndex(i)); dictionary = NameDictionaryAdd(dictionary, key, value, d);
MaybeObject* maybe_dictionary =
dictionary->Add(descs->GetKey(i), value, d);
if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
break; break;
} }
case CALLBACKS: { case CALLBACKS: {
Object* value = descs->GetCallbacksObject(i); Handle<Name> key(descs->GetKey(i));
Handle<Object> value(descs->GetCallbacksObject(i), isolate);
PropertyDetails d = PropertyDetails( PropertyDetails d = PropertyDetails(
details.attributes(), CALLBACKS, i + 1); details.attributes(), CALLBACKS, i + 1);
MaybeObject* maybe_dictionary = dictionary = NameDictionaryAdd(dictionary, key, value, d);
dictionary->Add(descs->GetKey(i), value, d);
if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
break; break;
} }
case INTERCEPTOR: case INTERCEPTOR:
@ -4498,62 +4487,52 @@ MaybeObject* JSObject::NormalizeProperties(PropertyNormalizationMode mode,
} }
} }
Heap* current_heap = GetHeap();
// Copy the next enumeration index from instance descriptor. // Copy the next enumeration index from instance descriptor.
dictionary->SetNextEnumerationIndex(real_size + 1); dictionary->SetNextEnumerationIndex(real_size + 1);
Map* new_map; Handle<NormalizedMapCache> cache(
MaybeObject* maybe_map = isolate->context()->native_context()->normalized_map_cache());
current_heap->isolate()->context()->native_context()-> Handle<Map> new_map = NormalizedMapCache::Get(cache, object, mode);
normalized_map_cache()->Get(this, mode);
if (!maybe_map->To(&new_map)) return maybe_map;
ASSERT(new_map->is_dictionary_map()); ASSERT(new_map->is_dictionary_map());
// We have now successfully allocated all the necessary objects. // From here on we cannot fail and we shouldn't GC anymore.
// Changes can now be made with the guarantee that all of them take effect. DisallowHeapAllocation no_allocation;
// Resize the object in the heap if necessary. // Resize the object in the heap if necessary.
int new_instance_size = new_map->instance_size(); int new_instance_size = new_map->instance_size();
int instance_size_delta = map_of_this->instance_size() - new_instance_size; int instance_size_delta = map->instance_size() - new_instance_size;
ASSERT(instance_size_delta >= 0); ASSERT(instance_size_delta >= 0);
current_heap->CreateFillerObjectAt(this->address() + new_instance_size, isolate->heap()->CreateFillerObjectAt(object->address() + new_instance_size,
instance_size_delta); instance_size_delta);
if (Marking::IsBlack(Marking::MarkBitFrom(this))) { if (Marking::IsBlack(Marking::MarkBitFrom(*object))) {
MemoryChunk::IncrementLiveBytesFromMutator(this->address(), MemoryChunk::IncrementLiveBytesFromMutator(object->address(),
-instance_size_delta); -instance_size_delta);
} }
set_map(new_map); object->set_map(*new_map);
map_of_this->NotifyLeafMapLayoutChange(); map->NotifyLeafMapLayoutChange();
set_properties(dictionary); object->set_properties(*dictionary);
current_heap->isolate()->counters()->props_to_dictionary()->Increment(); isolate->counters()->props_to_dictionary()->Increment();
#ifdef DEBUG #ifdef DEBUG
if (FLAG_trace_normalization) { if (FLAG_trace_normalization) {
PrintF("Object properties have been normalized:\n"); PrintF("Object properties have been normalized:\n");
Print(); object->Print();
} }
#endif #endif
return this;
} }
void JSObject::TransformToFastProperties(Handle<JSObject> object, void JSObject::TransformToFastProperties(Handle<JSObject> object,
int unused_property_fields) { int unused_property_fields) {
if (object->HasFastProperties()) return;
ASSERT(!object->IsGlobalObject());
CALL_HEAP_FUNCTION_VOID( CALL_HEAP_FUNCTION_VOID(
object->GetIsolate(), object->GetIsolate(),
object->TransformToFastProperties(unused_property_fields)); object->property_dictionary()->TransformPropertiesToFastFor(
} *object, unused_property_fields));
MaybeObject* JSObject::TransformToFastProperties(int unused_property_fields) {
if (HasFastProperties()) return this;
ASSERT(!IsGlobalObject());
return property_dictionary()->
TransformPropertiesToFastFor(this, unused_property_fields);
} }

View File

@ -2486,10 +2486,6 @@ class JSObject: public JSReceiver {
PropertyNormalizationMode mode, PropertyNormalizationMode mode,
int expected_additional_properties); int expected_additional_properties);
MUST_USE_RESULT MaybeObject* NormalizeProperties(
PropertyNormalizationMode mode,
int expected_additional_properties);
// Convert and update the elements backing store to be a // Convert and update the elements backing store to be a
// SeededNumberDictionary dictionary. Returns the backing after conversion. // SeededNumberDictionary dictionary. Returns the backing after conversion.
static Handle<SeededNumberDictionary> NormalizeElements( static Handle<SeededNumberDictionary> NormalizeElements(
@ -2498,13 +2494,9 @@ class JSObject: public JSReceiver {
MUST_USE_RESULT MaybeObject* NormalizeElements(); MUST_USE_RESULT MaybeObject* NormalizeElements();
// Transform slow named properties to fast variants. // Transform slow named properties to fast variants.
// Returns failure if allocation failed.
static void TransformToFastProperties(Handle<JSObject> object, static void TransformToFastProperties(Handle<JSObject> object,
int unused_property_fields); int unused_property_fields);
MUST_USE_RESULT MaybeObject* TransformToFastProperties(
int unused_property_fields);
// Access fast-case object properties at index. // Access fast-case object properties at index.
MUST_USE_RESULT inline MaybeObject* FastPropertyAt( MUST_USE_RESULT inline MaybeObject* FastPropertyAt(
Representation representation, Representation representation,
@ -2537,9 +2529,6 @@ class JSObject: public JSReceiver {
// Check whether this object references another object // Check whether this object references another object
bool ReferencesObject(Object* obj); bool ReferencesObject(Object* obj);
// Casting.
static inline JSObject* cast(Object* obj);
// Disalow further properties to be added to the object. // Disalow further properties to be added to the object.
static Handle<Object> PreventExtensions(Handle<JSObject> object); static Handle<Object> PreventExtensions(Handle<JSObject> object);
MUST_USE_RESULT MaybeObject* PreventExtensions(); MUST_USE_RESULT MaybeObject* PreventExtensions();
@ -2554,6 +2543,9 @@ class JSObject: public JSReceiver {
static Handle<JSObject> Copy(Handle<JSObject> object); static Handle<JSObject> Copy(Handle<JSObject> object);
static Handle<JSObject> DeepCopy(Handle<JSObject> object); static Handle<JSObject> DeepCopy(Handle<JSObject> object);
// Casting.
static inline JSObject* cast(Object* obj);
// Dispatched behavior. // Dispatched behavior.
void JSObjectShortPrint(StringStream* accumulator); void JSObjectShortPrint(StringStream* accumulator);
DECLARE_PRINTER(JSObject) DECLARE_PRINTER(JSObject)
@ -4231,8 +4223,9 @@ class NormalizedMapCache: public FixedArray {
public: public:
static const int kEntries = 64; static const int kEntries = 64;
MUST_USE_RESULT MaybeObject* Get(JSObject* object, static Handle<Map> Get(Handle<NormalizedMapCache> cache,
PropertyNormalizationMode mode); Handle<JSObject> object,
PropertyNormalizationMode mode);
void Clear(); void Clear();

View File

@ -5923,12 +5923,13 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetArgumentsProperty) {
RUNTIME_FUNCTION(MaybeObject*, Runtime_ToFastProperties) { RUNTIME_FUNCTION(MaybeObject*, Runtime_ToFastProperties) {
SealHandleScope shs(isolate); HandleScope scope(isolate);
ASSERT(args.length() == 1); ASSERT(args.length() == 1);
Object* object = args[0]; CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
return (object->IsJSObject() && !object->IsGlobalObject()) if (object->IsJSObject() && !object->IsGlobalObject()) {
? JSObject::cast(object)->TransformToFastProperties(0) JSObject::TransformToFastProperties(Handle<JSObject>::cast(object), 0);
: object; }
return *object;
} }