Commit 12854e6c authored by ager@chromium.org's avatar ager@chromium.org

Allocate as many object-literal properties as possible inobject.

This can lead to large objects which wastes a lot of space if we normalize properties.  We therfore clear the inobject properties when normalizing properties.  This is done by adjusting the instance size in the new map and overwriting the inobject properties with a filler.
Review URL: http://codereview.chromium.org/17308

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@1051 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 4a16e492
...@@ -195,6 +195,29 @@ Handle<Map> Factory::CopyMap(Handle<Map> src) { ...@@ -195,6 +195,29 @@ Handle<Map> Factory::CopyMap(Handle<Map> src) {
} }
Handle<Map> Factory::CopyMap(Handle<Map> src,
int extra_inobject_properties) {
Handle<Map> copy = CopyMap(src);
// Check that we do not overflow the instance size when adding the
// extra inobject properties.
int instance_size_delta = extra_inobject_properties * kPointerSize;
int max_instance_size_delta =
JSObject::kMaxInstanceSize - copy->instance_size();
if (instance_size_delta > max_instance_size_delta) {
// If the instance size overflows, we allocate as many properties
// as we can as inobject properties.
instance_size_delta = max_instance_size_delta;
extra_inobject_properties = max_instance_size_delta >> kPointerSizeLog2;
}
// Adjust the map with the extra inobject properties.
int inobject_properties =
copy->inobject_properties() + extra_inobject_properties;
copy->set_inobject_properties(inobject_properties);
copy->set_unused_property_fields(inobject_properties);
copy->set_instance_size(copy->instance_size() + instance_size_delta);
return copy;
}
Handle<Map> Factory::CopyMapDropTransitions(Handle<Map> src) { Handle<Map> Factory::CopyMapDropTransitions(Handle<Map> src) {
CALL_HEAP_FUNCTION(src->CopyDropTransitions(), Map); CALL_HEAP_FUNCTION(src->CopyDropTransitions(), Map);
} }
...@@ -577,16 +600,6 @@ Handle<JSObject> Factory::NewJSObjectFromMap(Handle<Map> map) { ...@@ -577,16 +600,6 @@ Handle<JSObject> Factory::NewJSObjectFromMap(Handle<Map> map) {
} }
Handle<JSObject> Factory::NewObjectLiteral(int expected_number_of_properties) {
Handle<Map> map = Handle<Map>(Top::object_function()->initial_map());
map = Factory::CopyMap(map);
map->set_instance_descriptors(Heap::empty_descriptor_array());
map->set_unused_property_fields(expected_number_of_properties);
CALL_HEAP_FUNCTION(Heap::AllocateJSObjectFromMap(*map, TENURED),
JSObject);
}
Handle<JSArray> Factory::NewArrayLiteral(int length) { Handle<JSArray> Factory::NewArrayLiteral(int length) {
return NewJSArrayWithElements(NewFixedArray(length), TENURED); return NewJSArrayWithElements(NewFixedArray(length), TENURED);
} }
...@@ -816,7 +829,8 @@ Handle<Map> Factory::ObjectLiteralMapFromCache(Handle<Context> context, ...@@ -816,7 +829,8 @@ Handle<Map> Factory::ObjectLiteralMapFromCache(Handle<Context> context,
if (result->IsMap()) return Handle<Map>::cast(result); if (result->IsMap()) return Handle<Map>::cast(result);
// Create a new map and add it to the cache. // Create a new map and add it to the cache.
Handle<Map> map = Handle<Map> map =
CopyMap(Handle<Map>(context->object_function()->initial_map())); CopyMap(Handle<Map>(context->object_function()->initial_map()),
keys->length());
AddToMapCache(context, keys, map); AddToMapCache(context, keys, map);
return Handle<Map>(map); return Handle<Map>(map);
} }
......
...@@ -157,6 +157,10 @@ class Factory : public AllStatic { ...@@ -157,6 +157,10 @@ class Factory : public AllStatic {
static Handle<Map> CopyMap(Handle<Map> map); static Handle<Map> CopyMap(Handle<Map> map);
// Copy the map adding more inobject properties if possible without
// overflowing the instance size.
static Handle<Map> CopyMap(Handle<Map> map, int extra_inobject_props);
static Handle<Map> CopyMapDropTransitions(Handle<Map> map); static Handle<Map> CopyMapDropTransitions(Handle<Map> map);
static Handle<FixedArray> CopyFixedArray(Handle<FixedArray> array); static Handle<FixedArray> CopyFixedArray(Handle<FixedArray> array);
...@@ -182,10 +186,6 @@ class Factory : public AllStatic { ...@@ -182,10 +186,6 @@ class Factory : public AllStatic {
// runtime. // runtime.
static Handle<JSObject> NewJSObjectFromMap(Handle<Map> map); static Handle<JSObject> NewJSObjectFromMap(Handle<Map> map);
// Allocate a JS object representing an object literal. The object is
// pretenured (allocated directly in the old generation).
static Handle<JSObject> NewObjectLiteral(int expected_number_of_properties);
// Allocate a JS array representing an array literal. The array is // Allocate a JS array representing an array literal. The array is
// pretenured (allocated directly in the old generation). // pretenured (allocated directly in the old generation).
static Handle<JSArray> NewArrayLiteral(int length); static Handle<JSArray> NewArrayLiteral(int length);
......
...@@ -99,8 +99,9 @@ void SetExpectedNofPropertiesFromEstimate(Handle<JSFunction> func, ...@@ -99,8 +99,9 @@ void SetExpectedNofPropertiesFromEstimate(Handle<JSFunction> func,
} }
void NormalizeProperties(Handle<JSObject> object) { void NormalizeProperties(Handle<JSObject> object,
CALL_HEAP_FUNCTION_VOID(object->NormalizeProperties()); PropertyNormalizationMode mode) {
CALL_HEAP_FUNCTION_VOID(object->NormalizeProperties(mode));
} }
...@@ -454,7 +455,7 @@ OptimizedObjectForAddingMultipleProperties(Handle<JSObject> object, ...@@ -454,7 +455,7 @@ OptimizedObjectForAddingMultipleProperties(Handle<JSObject> object,
// Normalize the properties of object to avoid n^2 behavior // Normalize the properties of object to avoid n^2 behavior
// when extending the object multiple properties. // when extending the object multiple properties.
unused_property_fields_ = object->map()->unused_property_fields(); unused_property_fields_ = object->map()->unused_property_fields();
NormalizeProperties(object_); NormalizeProperties(object_, KEEP_INOBJECT_PROPERTIES);
has_been_transformed_ = true; has_been_transformed_ = true;
} else { } else {
......
...@@ -96,7 +96,8 @@ class Handle { ...@@ -96,7 +96,8 @@ class Handle {
// an object of expected type, or the handle is an error if running out // an object of expected type, or the handle is an error if running out
// of space or encounting an internal error. // of space or encounting an internal error.
void NormalizeProperties(Handle<JSObject> object); void NormalizeProperties(Handle<JSObject> object,
PropertyNormalizationMode mode);
void NormalizeElements(Handle<JSObject> object); void NormalizeElements(Handle<JSObject> object);
void TransformToFastProperties(Handle<JSObject> object, void TransformToFastProperties(Handle<JSObject> object,
int unused_property_fields); int unused_property_fields);
......
...@@ -2293,6 +2293,7 @@ Object* Heap::CopyFixedArray(FixedArray* src) { ...@@ -2293,6 +2293,7 @@ Object* Heap::CopyFixedArray(FixedArray* src) {
Object* Heap::AllocateFixedArray(int length) { Object* Heap::AllocateFixedArray(int length) {
if (length == 0) return empty_fixed_array();
Object* result = AllocateRawFixedArray(length); Object* result = AllocateRawFixedArray(length);
if (!result->IsFailure()) { if (!result->IsFailure()) {
// Initialize header. // Initialize header.
......
...@@ -43,6 +43,22 @@ ...@@ -43,6 +43,22 @@
namespace v8 { namespace internal { 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 // Getters and setters are stored in a fixed array property. These are
// constants for their indices. // constants for their indices.
const int kGetterIndex = 0; const int kGetterIndex = 0;
...@@ -1040,7 +1056,7 @@ Object* JSObject::AddFastProperty(String* name, ...@@ -1040,7 +1056,7 @@ Object* JSObject::AddFastProperty(String* name,
// Normalize the object if the name is not a real identifier. // Normalize the object if the name is not a real identifier.
StringInputBuffer buffer(name); StringInputBuffer buffer(name);
if (!Scanner::IsIdentifier(&buffer)) { if (!Scanner::IsIdentifier(&buffer)) {
Object* obj = NormalizeProperties(); Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES);
if (obj->IsFailure()) return obj; if (obj->IsFailure()) return obj;
return AddSlowProperty(name, value, attributes); return AddSlowProperty(name, value, attributes);
} }
...@@ -1078,7 +1094,7 @@ Object* JSObject::AddFastProperty(String* name, ...@@ -1078,7 +1094,7 @@ Object* JSObject::AddFastProperty(String* name,
if (map()->unused_property_fields() == 0) { if (map()->unused_property_fields() == 0) {
if (properties()->length() > kMaxFastProperties) { if (properties()->length() > kMaxFastProperties) {
Object* obj = NormalizeProperties(); Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES);
if (obj->IsFailure()) return obj; if (obj->IsFailure()) return obj;
return AddSlowProperty(name, value, attributes); return AddSlowProperty(name, value, attributes);
} }
...@@ -1180,7 +1196,7 @@ Object* JSObject::AddProperty(String* name, ...@@ -1180,7 +1196,7 @@ Object* JSObject::AddProperty(String* name,
} else { } else {
// Normalize the object to prevent very large instance descriptors. // Normalize the object to prevent very large instance descriptors.
// This eliminates unwanted N^2 allocation and lookup behavior. // This eliminates unwanted N^2 allocation and lookup behavior.
Object* obj = NormalizeProperties(); Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES);
if (obj->IsFailure()) return obj; if (obj->IsFailure()) return obj;
} }
} }
...@@ -1253,7 +1269,7 @@ Object* JSObject::ConvertDescriptorToField(String* name, ...@@ -1253,7 +1269,7 @@ Object* JSObject::ConvertDescriptorToField(String* name,
PropertyAttributes attributes) { PropertyAttributes attributes) {
if (map()->unused_property_fields() == 0 && if (map()->unused_property_fields() == 0 &&
properties()->length() > kMaxFastProperties) { properties()->length() > kMaxFastProperties) {
Object* obj = NormalizeProperties(); Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES);
if (obj->IsFailure()) return obj; if (obj->IsFailure()) return obj;
return ReplaceSlowProperty(name, new_value, attributes); return ReplaceSlowProperty(name, new_value, attributes);
} }
...@@ -1848,7 +1864,7 @@ PropertyAttributes JSObject::GetLocalPropertyAttribute(String* name) { ...@@ -1848,7 +1864,7 @@ PropertyAttributes JSObject::GetLocalPropertyAttribute(String* name) {
} }
Object* JSObject::NormalizeProperties() { Object* JSObject::NormalizeProperties(PropertyNormalizationMode mode) {
if (!HasFastProperties()) return this; if (!HasFastProperties()) return this;
// Allocate new content // Allocate new content
...@@ -1908,13 +1924,33 @@ Object* JSObject::NormalizeProperties() { ...@@ -1908,13 +1924,33 @@ Object* JSObject::NormalizeProperties() {
// Allocate new map. // Allocate new map.
obj = map()->Copy(); obj = map()->Copy();
if (obj->IsFailure()) return obj; 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. // We have now sucessfully allocated all the necessary objects.
// Changes can now be made with the guarantee that all of them take effect. // 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_instance_descriptors(Heap::empty_descriptor_array());
map()->set_unused_property_fields(0);
set_properties(dictionary); set_properties(dictionary);
Counters::props_to_dictionary.Increment(); Counters::props_to_dictionary.Increment();
...@@ -1982,7 +2018,7 @@ Object* JSObject::DeletePropertyPostInterceptor(String* name) { ...@@ -1982,7 +2018,7 @@ Object* JSObject::DeletePropertyPostInterceptor(String* name) {
if (!result.IsValid()) return Heap::true_value(); if (!result.IsValid()) return Heap::true_value();
// Normalize object if needed. // Normalize object if needed.
Object* obj = NormalizeProperties(); Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES);
if (obj->IsFailure()) return obj; if (obj->IsFailure()) return obj;
ASSERT(!HasFastProperties()); ASSERT(!HasFastProperties());
...@@ -2145,7 +2181,7 @@ Object* JSObject::DeleteProperty(String* name) { ...@@ -2145,7 +2181,7 @@ Object* JSObject::DeleteProperty(String* name) {
return JSObject::cast(this)->DeleteLazyProperty(&result, name); return JSObject::cast(this)->DeleteLazyProperty(&result, name);
} }
// Normalize object if needed. // Normalize object if needed.
Object* obj = NormalizeProperties(); Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES);
if (obj->IsFailure()) return obj; if (obj->IsFailure()) return obj;
// Make sure the properties are normalized before removing the entry. // Make sure the properties are normalized before removing the entry.
Dictionary* dictionary = property_dictionary(); Dictionary* dictionary = property_dictionary();
...@@ -2411,7 +2447,7 @@ Object* JSObject::DefineGetterSetter(String* name, ...@@ -2411,7 +2447,7 @@ Object* JSObject::DefineGetterSetter(String* name,
} }
// Normalize object to make this operation simple. // Normalize object to make this operation simple.
Object* ok = NormalizeProperties(); Object* ok = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES);
if (ok->IsFailure()) return ok; if (ok->IsFailure()) return ok;
// Allocate the fixed array to hold getter and setter. // Allocate the fixed array to hold getter and setter.
...@@ -6664,7 +6700,9 @@ Object* Dictionary::TransformPropertiesToFastFor(JSObject* obj, ...@@ -6664,7 +6700,9 @@ Object* Dictionary::TransformPropertiesToFastFor(JSObject* obj,
if (descriptors_unchecked->IsFailure()) return descriptors_unchecked; if (descriptors_unchecked->IsFailure()) return descriptors_unchecked;
DescriptorArray* descriptors = DescriptorArray::cast(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. // Allocate the fixed array for the fields.
Object* fields = Heap::AllocateFixedArray(number_of_allocated_fields); Object* fields = Heap::AllocateFixedArray(number_of_allocated_fields);
...@@ -6682,6 +6720,7 @@ Object* Dictionary::TransformPropertiesToFastFor(JSObject* obj, ...@@ -6682,6 +6720,7 @@ Object* Dictionary::TransformPropertiesToFastFor(JSObject* obj,
if (key->IsFailure()) return key; if (key->IsFailure()) return key;
PropertyDetails details = DetailsAt(i); PropertyDetails details = DetailsAt(i);
PropertyType type = details.type(); PropertyType type = details.type();
if (value->IsJSFunction()) { if (value->IsJSFunction()) {
ConstantFunctionDescriptor d(String::cast(key), ConstantFunctionDescriptor d(String::cast(key),
JSFunction::cast(value), JSFunction::cast(value),
...@@ -6689,7 +6728,14 @@ Object* Dictionary::TransformPropertiesToFastFor(JSObject* obj, ...@@ -6689,7 +6728,14 @@ Object* Dictionary::TransformPropertiesToFastFor(JSObject* obj,
details.index()); details.index());
w.Write(&d); w.Write(&d);
} else if (type == NORMAL) { } 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), FieldDescriptor d(String::cast(key),
current_offset++, current_offset++,
details.attributes(), details.attributes(),
...@@ -6722,8 +6768,9 @@ Object* Dictionary::TransformPropertiesToFastFor(JSObject* obj, ...@@ -6722,8 +6768,9 @@ Object* Dictionary::TransformPropertiesToFastFor(JSObject* obj,
ASSERT(obj->IsJSObject()); ASSERT(obj->IsJSObject());
descriptors->SetNextEnumerationIndex(NextEnumerationIndex()); descriptors->SetNextEnumerationIndex(NextEnumerationIndex());
// Check it really works. // Check that it really works.
ASSERT(obj->HasFastProperties()); ASSERT(obj->HasFastProperties());
return obj; return obj;
} }
......
...@@ -166,9 +166,20 @@ class PropertyDetails BASE_EMBEDDED { ...@@ -166,9 +166,20 @@ class PropertyDetails BASE_EMBEDDED {
uint32_t value_; uint32_t value_;
}; };
// Setter that skips the write barrier if mode is SKIP_WRITE_BARRIER. // Setter that skips the write barrier if mode is SKIP_WRITE_BARRIER.
enum WriteBarrierMode { SKIP_WRITE_BARRIER, UPDATE_WRITE_BARRIER }; enum WriteBarrierMode { SKIP_WRITE_BARRIER, UPDATE_WRITE_BARRIER };
// PropertyNormalizationMode is used to specify wheter or not to
// keep inobject properties when normalizing properties of a
// JSObject.
enum PropertyNormalizationMode {
CLEAR_INOBJECT_PROPERTIES,
KEEP_INOBJECT_PROPERTIES
};
// All Maps have a field instance_type containing a InstanceType. // All Maps have a field instance_type containing a InstanceType.
// It describes the type of the instances. // It describes the type of the instances.
// //
...@@ -560,9 +571,9 @@ enum CompareResult { ...@@ -560,9 +571,9 @@ enum CompareResult {
inline void set_##name(bool value); \ inline void set_##name(bool value); \
#define DECL_ACCESSORS(name, type) \ #define DECL_ACCESSORS(name, type) \
inline type* name(); \ inline type* name(); \
inline void set_##name(type* value, \ inline void set_##name(type* value, \
WriteBarrierMode mode = UPDATE_WRITE_BARRIER); \ WriteBarrierMode mode = UPDATE_WRITE_BARRIER); \
...@@ -1357,7 +1368,7 @@ class JSObject: public HeapObject { ...@@ -1357,7 +1368,7 @@ class JSObject: public HeapObject {
// Convert the object to use the canonical dictionary // Convert the object to use the canonical dictionary
// representation. // representation.
Object* NormalizeProperties(); Object* NormalizeProperties(PropertyNormalizationMode mode);
Object* NormalizeElements(); Object* NormalizeElements();
// Transform slow named properties to fast variants. // Transform slow named properties to fast variants.
...@@ -2293,7 +2304,7 @@ class Code: public HeapObject { ...@@ -2293,7 +2304,7 @@ class Code: public HeapObject {
// - How to iterate over an object (for garbage collection) // - How to iterate over an object (for garbage collection)
class Map: public HeapObject { class Map: public HeapObject {
public: public:
// instance size. // Instance size.
inline int instance_size(); inline int instance_size();
inline void set_instance_size(int value); inline void set_instance_size(int value);
...@@ -2301,16 +2312,16 @@ class Map: public HeapObject { ...@@ -2301,16 +2312,16 @@ class Map: public HeapObject {
inline int inobject_properties(); inline int inobject_properties();
inline void set_inobject_properties(int value); inline void set_inobject_properties(int value);
// instance type. // Instance type.
inline InstanceType instance_type(); inline InstanceType instance_type();
inline void set_instance_type(InstanceType value); inline void set_instance_type(InstanceType value);
// tells how many unused property fields are available in the instance. // Tells how many unused property fields are available in the
// (only used for JSObject in fast mode). // instance (only used for JSObject in fast mode).
inline int unused_property_fields(); inline int unused_property_fields();
inline void set_unused_property_fields(int value); inline void set_unused_property_fields(int value);
// bit field. // Bit field.
inline byte bit_field(); inline byte bit_field();
inline void set_bit_field(byte value); inline void set_bit_field(byte value);
...@@ -2463,7 +2474,6 @@ class Map: public HeapObject { ...@@ -2463,7 +2474,6 @@ class Map: public HeapObject {
static const int kInObjectPropertiesOffset = kInstanceSizesOffset + 1; static const int kInObjectPropertiesOffset = kInstanceSizesOffset + 1;
// The bytes at positions 2 and 3 are not in use at the moment. // The bytes at positions 2 and 3 are not in use at the moment.
// Byte offsets within kInstanceAttributesOffset attributes. // Byte offsets within kInstanceAttributesOffset attributes.
static const int kInstanceTypeOffset = kInstanceAttributesOffset + 0; static const int kInstanceTypeOffset = kInstanceAttributesOffset + 0;
static const int kUnusedPropertyFieldsOffset = kInstanceAttributesOffset + 1; static const int kUnusedPropertyFieldsOffset = kInstanceAttributesOffset + 1;
......
...@@ -102,9 +102,9 @@ static Handle<Map> ComputeObjectLiteralMap( ...@@ -102,9 +102,9 @@ static Handle<Map> ComputeObjectLiteralMap(
Handle<Context> context, Handle<Context> context,
Handle<FixedArray> constant_properties, Handle<FixedArray> constant_properties,
bool* is_result_from_cache) { bool* is_result_from_cache) {
int number_of_properties = constant_properties->length() / 2;
if (FLAG_canonicalize_object_literal_maps) { if (FLAG_canonicalize_object_literal_maps) {
// First find prefix of consecutive symbol keys. // First find prefix of consecutive symbol keys.
int number_of_properties = constant_properties->length()/2;
int number_of_symbol_keys = 0; int number_of_symbol_keys = 0;
while ((number_of_symbol_keys < number_of_properties) && while ((number_of_symbol_keys < number_of_properties) &&
(constant_properties->get(number_of_symbol_keys*2)->IsSymbol())) { (constant_properties->get(number_of_symbol_keys*2)->IsSymbol())) {
...@@ -125,7 +125,9 @@ static Handle<Map> ComputeObjectLiteralMap( ...@@ -125,7 +125,9 @@ static Handle<Map> ComputeObjectLiteralMap(
} }
} }
*is_result_from_cache = false; *is_result_from_cache = false;
return Handle<Map>(context->object_function()->initial_map()); return Factory::CopyMap(
Handle<Map>(context->object_function()->initial_map()),
number_of_properties);
} }
......
...@@ -25,25 +25,32 @@ ...@@ -25,25 +25,32 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Make sure that we can create large object literals. // Test that we can create object literals of various sizes.
var nofProperties = 150; function testLiteral(size) {
// Build large object literal string. // Build object-literal string.
var literal = "var o = { "; var literal = "var o = { ";
for (var i = 0; i < nofProperties; i++) {
if (i > 0) literal += ",";
literal += ("a" + i + ":" + i);
}
literal += "}";
for (var i = 0; i < size; i++) {
if (i > 0) literal += ",";
literal += ("a" + i + ":" + i);
}
literal += "}";
// Create the large object literal // Create the object literal.
eval(literal); eval(literal);
// Check that the properties have the expected values. // Check that the properties have the expected values.
for (var i = 0; i < nofProperties; i++) { for (var i = 0; i < size; i++) {
assertEquals(o["a"+i], i); assertEquals(i, o["a"+i]);
}
} }
// The sizes to test.
var sizes = [0, 1, 2, 100, 200, 400, 1000];
// Run the test.
for (var i = 0; i < sizes.length; i++) {
testLiteral(sizes[i]);
}
// Copyright 2009 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --expose-gc
// Test that the clearing of object literal when normalizing objects
// works. In particular, test that the garbage collector handles the
// normalized object literals correctly.
function testLiteral(size) {
// Build object-literal string.
var literal = "var o = { ";
for (var i = 0; i < size; i++) {
if (i > 0) literal += ",";
literal += ("a" + i + ":" + i);
}
literal += "}";
// Create the object literal.
eval(literal);
// Force normalization of the properties.
delete o["a" + (size - 1)];
// Perform GC.
gc();
// Check that the properties have the expected values.
for (var i = 0; i < size - 1; i++) {
assertEquals(i, o["a"+i]);
}
}
// The sizes to test.
var sizes = [0, 1, 2, 100, 200, 400, 1000];
// Run the test.
for (var i = 0; i < sizes.length; i++) {
testLiteral(sizes[i]);
}
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