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:
parent
3dd88c4067
commit
35142b817f
117
src/objects.cc
117
src/objects.cc
@ -4348,12 +4348,12 @@ PropertyAttributes JSObject::GetElementAttributeWithoutInterceptor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
MaybeObject* NormalizedMapCache::Get(JSObject* obj,
|
Handle<Map> NormalizedMapCache::Get(Handle<NormalizedMapCache> cache,
|
||||||
|
Handle<JSObject> obj,
|
||||||
PropertyNormalizationMode mode) {
|
PropertyNormalizationMode mode) {
|
||||||
Isolate* isolate = obj->GetIsolate();
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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,7 +4223,8 @@ 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,
|
||||||
|
Handle<JSObject> object,
|
||||||
PropertyNormalizationMode mode);
|
PropertyNormalizationMode mode);
|
||||||
|
|
||||||
void Clear();
|
void Clear();
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user