Index: src/objects.cc |
=================================================================== |
--- src/objects.cc (revision 1049) |
+++ src/objects.cc (working copy) |
@@ -43,6 +43,22 @@ |
namespace v8 { namespace internal { |
+#define FIELD_ADDR(p, offset) \ |
+ (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag) |
+ |
+ |
+#define WRITE_FIELD(p, offset, value) \ |
+ (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value) |
+ |
+ |
+#define WRITE_INT_FIELD(p, offset, value) \ |
+ (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)) = value) |
+ |
+ |
+#define WRITE_BARRIER(object, offset) \ |
+ Heap::RecordWrite(object->address(), offset); |
+ |
+ |
// Getters and setters are stored in a fixed array property. These are |
// constants for their indices. |
const int kGetterIndex = 0; |
@@ -1040,7 +1056,7 @@ |
// Normalize the object if the name is not a real identifier. |
StringInputBuffer buffer(name); |
if (!Scanner::IsIdentifier(&buffer)) { |
- Object* obj = NormalizeProperties(); |
+ Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES); |
if (obj->IsFailure()) return obj; |
return AddSlowProperty(name, value, attributes); |
} |
@@ -1078,7 +1094,7 @@ |
if (map()->unused_property_fields() == 0) { |
if (properties()->length() > kMaxFastProperties) { |
- Object* obj = NormalizeProperties(); |
+ Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES); |
if (obj->IsFailure()) return obj; |
return AddSlowProperty(name, value, attributes); |
} |
@@ -1180,7 +1196,7 @@ |
} else { |
// Normalize the object to prevent very large instance descriptors. |
// This eliminates unwanted N^2 allocation and lookup behavior. |
- Object* obj = NormalizeProperties(); |
+ Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES); |
if (obj->IsFailure()) return obj; |
} |
} |
@@ -1253,7 +1269,7 @@ |
PropertyAttributes attributes) { |
if (map()->unused_property_fields() == 0 && |
properties()->length() > kMaxFastProperties) { |
- Object* obj = NormalizeProperties(); |
+ Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES); |
if (obj->IsFailure()) return obj; |
return ReplaceSlowProperty(name, new_value, attributes); |
} |
@@ -1848,7 +1864,7 @@ |
} |
-Object* JSObject::NormalizeProperties() { |
+Object* JSObject::NormalizeProperties(PropertyNormalizationMode mode) { |
if (!HasFastProperties()) return this; |
// Allocate new content |
@@ -1908,13 +1924,33 @@ |
// Allocate new map. |
obj = map()->Copy(); |
if (obj->IsFailure()) return obj; |
+ Map* new_map = Map::cast(obj); |
+ // Clear inobject properties if needed by adjusting the instance |
+ // size and putting in a filler or byte array instead of the |
+ // inobject properties. |
+ if (mode == CLEAR_INOBJECT_PROPERTIES && map()->inobject_properties() > 0) { |
+ int instance_size_delta = map()->inobject_properties() * kPointerSize; |
+ int new_instance_size = map()->instance_size() - instance_size_delta; |
+ new_map->set_inobject_properties(0); |
+ new_map->set_instance_size(new_instance_size); |
+ if (instance_size_delta == kPointerSize) { |
+ WRITE_FIELD(this, new_instance_size, Heap::one_word_filler_map()); |
+ } else { |
+ int byte_array_length = ByteArray::LengthFor(instance_size_delta); |
+ int byte_array_length_offset = new_instance_size + kPointerSize; |
+ WRITE_FIELD(this, new_instance_size, Heap::byte_array_map()); |
+ WRITE_INT_FIELD(this, byte_array_length_offset, byte_array_length); |
+ } |
+ WRITE_BARRIER(this, new_instance_size); |
+ } |
+ new_map->set_unused_property_fields(0); |
+ |
// We have now sucessfully allocated all the necessary objects. |
// Changes can now be made with the guarantee that all of them take effect. |
- set_map(Map::cast(obj)); |
+ set_map(new_map); |
map()->set_instance_descriptors(Heap::empty_descriptor_array()); |
- map()->set_unused_property_fields(0); |
set_properties(dictionary); |
Counters::props_to_dictionary.Increment(); |
@@ -1982,7 +2018,7 @@ |
if (!result.IsValid()) return Heap::true_value(); |
// Normalize object if needed. |
- Object* obj = NormalizeProperties(); |
+ Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES); |
if (obj->IsFailure()) return obj; |
ASSERT(!HasFastProperties()); |
@@ -2145,7 +2181,7 @@ |
return JSObject::cast(this)->DeleteLazyProperty(&result, name); |
} |
// Normalize object if needed. |
- Object* obj = NormalizeProperties(); |
+ Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES); |
if (obj->IsFailure()) return obj; |
// Make sure the properties are normalized before removing the entry. |
Dictionary* dictionary = property_dictionary(); |
@@ -2411,7 +2447,7 @@ |
} |
// Normalize object to make this operation simple. |
- Object* ok = NormalizeProperties(); |
+ Object* ok = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES); |
if (ok->IsFailure()) return ok; |
// Allocate the fixed array to hold getter and setter. |
@@ -6664,7 +6700,9 @@ |
if (descriptors_unchecked->IsFailure()) return descriptors_unchecked; |
DescriptorArray* descriptors = DescriptorArray::cast(descriptors_unchecked); |
- int number_of_allocated_fields = number_of_fields + unused_property_fields; |
+ int inobject_props = obj->map()->inobject_properties(); |
+ int number_of_allocated_fields = |
+ number_of_fields + unused_property_fields - inobject_props; |
// Allocate the fixed array for the fields. |
Object* fields = Heap::AllocateFixedArray(number_of_allocated_fields); |
@@ -6682,6 +6720,7 @@ |
if (key->IsFailure()) return key; |
PropertyDetails details = DetailsAt(i); |
PropertyType type = details.type(); |
+ |
if (value->IsJSFunction()) { |
ConstantFunctionDescriptor d(String::cast(key), |
JSFunction::cast(value), |
@@ -6689,7 +6728,14 @@ |
details.index()); |
w.Write(&d); |
} else if (type == NORMAL) { |
- FixedArray::cast(fields)->set(current_offset, value); |
+ if (current_offset < inobject_props) { |
+ obj->InObjectPropertyAtPut(current_offset, |
+ value, |
+ UPDATE_WRITE_BARRIER); |
+ } else { |
+ int offset = current_offset - inobject_props; |
+ FixedArray::cast(fields)->set(offset, value); |
+ } |
FieldDescriptor d(String::cast(key), |
current_offset++, |
details.attributes(), |
@@ -6722,8 +6768,9 @@ |
ASSERT(obj->IsJSObject()); |
descriptors->SetNextEnumerationIndex(NextEnumerationIndex()); |
- // Check it really works. |
+ // Check that it really works. |
ASSERT(obj->HasFastProperties()); |
+ |
return obj; |
} |