Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(120)

Side by Side Diff: src/objects.cc

Issue 7341: Allocate room for expected number of properties based on the... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 12 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/objects.h ('k') | src/objects-debug.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after
359 } 359 }
360 Object* value; 360 Object* value;
361 JSObject* holder = result->holder(); 361 JSObject* holder = result->holder();
362 switch (result->type()) { 362 switch (result->type()) {
363 case NORMAL: 363 case NORMAL:
364 value = 364 value =
365 holder->property_dictionary()->ValueAt(result->GetDictionaryEntry()); 365 holder->property_dictionary()->ValueAt(result->GetDictionaryEntry());
366 ASSERT(!value->IsTheHole() || result->IsReadOnly()); 366 ASSERT(!value->IsTheHole() || result->IsReadOnly());
367 return value->IsTheHole() ? Heap::undefined_value() : value; 367 return value->IsTheHole() ? Heap::undefined_value() : value;
368 case FIELD: 368 case FIELD:
369 value = holder->properties()->get(result->GetFieldIndex()); 369 value = holder->FastPropertyAt(result->GetFieldIndex());
370 ASSERT(!value->IsTheHole() || result->IsReadOnly()); 370 ASSERT(!value->IsTheHole() || result->IsReadOnly());
371 return value->IsTheHole() ? Heap::undefined_value() : value; 371 return value->IsTheHole() ? Heap::undefined_value() : value;
372 case CONSTANT_FUNCTION: 372 case CONSTANT_FUNCTION:
373 return result->GetConstantFunction(); 373 return result->GetConstantFunction();
374 case CALLBACKS: 374 case CALLBACKS:
375 return GetPropertyWithCallback(receiver, 375 return GetPropertyWithCallback(receiver,
376 result->GetCallbackObject(), 376 result->GetCallbackObject(),
377 name, 377 name,
378 holder); 378 holder);
379 case INTERCEPTOR: { 379 case INTERCEPTOR: {
(...skipping 549 matching lines...) Expand 10 before | Expand all | Expand 10 after
929 929
930 // Return the new clone. 930 // Return the new clone.
931 return clone; 931 return clone;
932 } 932 }
933 933
934 934
935 Object* JSObject::AddFastPropertyUsingMap(Map* new_map, 935 Object* JSObject::AddFastPropertyUsingMap(Map* new_map,
936 String* name, 936 String* name,
937 Object* value) { 937 Object* value) {
938 int index = new_map->PropertyIndexFor(name); 938 int index = new_map->PropertyIndexFor(name);
939 if (map()->unused_property_fields() > 0) { 939 if (map()->unused_property_fields() == 0) {
940 ASSERT(index < properties()->length());
941 properties()->set(index, value);
942 } else {
943 ASSERT(map()->unused_property_fields() == 0); 940 ASSERT(map()->unused_property_fields() == 0);
944 int new_unused = new_map->unused_property_fields(); 941 int new_unused = new_map->unused_property_fields();
945 Object* values = 942 Object* values =
946 properties()->CopySize(properties()->length() + new_unused + 1); 943 properties()->CopySize(properties()->length() + new_unused + 1);
947 if (values->IsFailure()) return values; 944 if (values->IsFailure()) return values;
948 FixedArray::cast(values)->set(index, value);
949 set_properties(FixedArray::cast(values)); 945 set_properties(FixedArray::cast(values));
950 } 946 }
951 set_map(new_map); 947 set_map(new_map);
952 return value; 948 return FastPropertyAtPut(index, value);
953 } 949 }
954 950
955 951
956 Object* JSObject::AddFastProperty(String* name, 952 Object* JSObject::AddFastProperty(String* name,
957 Object* value, 953 Object* value,
958 PropertyAttributes attributes) { 954 PropertyAttributes attributes) {
959 // Normalize the object if the name is not a real identifier. 955 // Normalize the object if the name is not a real identifier.
960 StringInputBuffer buffer(name); 956 StringInputBuffer buffer(name);
961 if (!Scanner::IsIdentifier(&buffer)) { 957 if (!Scanner::IsIdentifier(&buffer)) {
962 Object* obj = NormalizeProperties(); 958 Object* obj = NormalizeProperties();
(...skipping 10 matching lines...) Expand all
973 Object* new_descriptors = 969 Object* new_descriptors =
974 old_descriptors->CopyInsert(&new_field, REMOVE_TRANSITIONS); 970 old_descriptors->CopyInsert(&new_field, REMOVE_TRANSITIONS);
975 if (new_descriptors->IsFailure()) return new_descriptors; 971 if (new_descriptors->IsFailure()) return new_descriptors;
976 972
977 // Only allow map transition if the object's map is NOT equal to the 973 // Only allow map transition if the object's map is NOT equal to the
978 // global object_function's map and there is not a transition for name. 974 // global object_function's map and there is not a transition for name.
979 bool allow_map_transition = 975 bool allow_map_transition =
980 !old_descriptors->Contains(name) && 976 !old_descriptors->Contains(name) &&
981 (Top::context()->global_context()->object_function()->map() != map()); 977 (Top::context()->global_context()->object_function()->map() != map());
982 978
983 ASSERT(index < properties()->length() || 979 ASSERT(index < map()->inobject_properties() ||
980 (index - map()->inobject_properties()) < properties()->length() ||
984 map()->unused_property_fields() == 0); 981 map()->unused_property_fields() == 0);
985 // Allocate a new map for the object. 982 // Allocate a new map for the object.
986 Object* r = map()->Copy(); 983 Object* r = map()->Copy();
987 if (r->IsFailure()) return r; 984 if (r->IsFailure()) return r;
988 Map* new_map = Map::cast(r); 985 Map* new_map = Map::cast(r);
989 if (allow_map_transition) { 986 if (allow_map_transition) {
990 // Allocate new instance descriptors for the old map with map transition. 987 // Allocate new instance descriptors for the old map with map transition.
991 MapTransitionDescriptor d(name, Map::cast(new_map), attributes); 988 MapTransitionDescriptor d(name, Map::cast(new_map), attributes);
992 Object* r = old_descriptors->CopyInsert(&d, KEEP_TRANSITIONS); 989 Object* r = old_descriptors->CopyInsert(&d, KEEP_TRANSITIONS);
993 if (r->IsFailure()) return r; 990 if (r->IsFailure()) return r;
994 old_descriptors = DescriptorArray::cast(r); 991 old_descriptors = DescriptorArray::cast(r);
995 } 992 }
996 993
997
998 if (map()->unused_property_fields() == 0) { 994 if (map()->unused_property_fields() == 0) {
999 if (properties()->length() > kMaxFastProperties) { 995 if (properties()->length() > kMaxFastProperties) {
1000 Object* obj = NormalizeProperties(); 996 Object* obj = NormalizeProperties();
1001 if (obj->IsFailure()) return obj; 997 if (obj->IsFailure()) return obj;
1002 return AddSlowProperty(name, value, attributes); 998 return AddSlowProperty(name, value, attributes);
1003 } 999 }
1004 // Make room for the new value 1000 // Make room for the new value
1005 Object* values = 1001 Object* values =
1006 properties()->CopySize(properties()->length() + kFieldsAdded); 1002 properties()->CopySize(properties()->length() + kFieldsAdded);
1007 if (values->IsFailure()) return values; 1003 if (values->IsFailure()) return values;
1008 set_properties(FixedArray::cast(values)); 1004 set_properties(FixedArray::cast(values));
1009 new_map->set_unused_property_fields(kFieldsAdded - 1); 1005 new_map->set_unused_property_fields(kFieldsAdded - 1);
1010 } else { 1006 } else {
1011 new_map->set_unused_property_fields(map()->unused_property_fields() - 1); 1007 new_map->set_unused_property_fields(map()->unused_property_fields() - 1);
1012 } 1008 }
1013 // We have now allocated all the necessary objects. 1009 // We have now allocated all the necessary objects.
1014 // All the changes can be applied at once, so they are atomic. 1010 // All the changes can be applied at once, so they are atomic.
1015 map()->set_instance_descriptors(old_descriptors); 1011 map()->set_instance_descriptors(old_descriptors);
1016 new_map->set_instance_descriptors(DescriptorArray::cast(new_descriptors)); 1012 new_map->set_instance_descriptors(DescriptorArray::cast(new_descriptors));
1017 set_map(new_map); 1013 set_map(new_map);
1018 properties()->set(index, value); 1014 return FastPropertyAtPut(index, value);
1019
1020 return value;
1021 } 1015 }
1022 1016
1023 1017
1024 Object* JSObject::AddConstantFunctionProperty(String* name, 1018 Object* JSObject::AddConstantFunctionProperty(String* name,
1025 JSFunction* function, 1019 JSFunction* function,
1026 PropertyAttributes attributes) { 1020 PropertyAttributes attributes) {
1027 // Allocate new instance descriptors with (name, function) added 1021 // Allocate new instance descriptors with (name, function) added
1028 ConstantFunctionDescriptor d(name, function, attributes); 1022 ConstantFunctionDescriptor d(name, function, attributes);
1029 Object* new_descriptors = 1023 Object* new_descriptors =
1030 map()->instance_descriptors()->CopyInsert(&d, REMOVE_TRANSITIONS); 1024 map()->instance_descriptors()->CopyInsert(&d, REMOVE_TRANSITIONS);
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
1204 new_properties = FixedArray::cast(new_properties_unchecked); 1198 new_properties = FixedArray::cast(new_properties_unchecked);
1205 } 1199 }
1206 1200
1207 // Update pointers to commit changes. 1201 // Update pointers to commit changes.
1208 // Object points to the new map. 1202 // Object points to the new map.
1209 new_map->set_unused_property_fields(new_unused_property_fields); 1203 new_map->set_unused_property_fields(new_unused_property_fields);
1210 set_map(new_map); 1204 set_map(new_map);
1211 if (new_properties) { 1205 if (new_properties) {
1212 set_properties(FixedArray::cast(new_properties)); 1206 set_properties(FixedArray::cast(new_properties));
1213 } 1207 }
1214 properties()->set(index, new_value); 1208 return FastPropertyAtPut(index, new_value);
1215 return new_value;
1216 } 1209 }
1217 1210
1218 1211
1219 1212
1220 Object* JSObject::SetPropertyWithInterceptor(String* name, 1213 Object* JSObject::SetPropertyWithInterceptor(String* name,
1221 Object* value, 1214 Object* value,
1222 PropertyAttributes attributes) { 1215 PropertyAttributes attributes) {
1223 HandleScope scope; 1216 HandleScope scope;
1224 Handle<JSObject> this_handle(this); 1217 Handle<JSObject> this_handle(this);
1225 Handle<String> name_handle(name); 1218 Handle<String> name_handle(name);
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
1370 1363
1371 void JSObject::LocalLookupRealNamedProperty(String* name, 1364 void JSObject::LocalLookupRealNamedProperty(String* name,
1372 LookupResult* result) { 1365 LookupResult* result) {
1373 if (HasFastProperties()) { 1366 if (HasFastProperties()) {
1374 LookupInDescriptor(name, result); 1367 LookupInDescriptor(name, result);
1375 if (result->IsValid()) { 1368 if (result->IsValid()) {
1376 ASSERT(result->holder() == this && result->type() != NORMAL); 1369 ASSERT(result->holder() == this && result->type() != NORMAL);
1377 // Disallow caching for uninitialized constants. These can only 1370 // Disallow caching for uninitialized constants. These can only
1378 // occur as fields. 1371 // occur as fields.
1379 if (result->IsReadOnly() && result->type() == FIELD && 1372 if (result->IsReadOnly() && result->type() == FIELD &&
1380 properties()->get(result->GetFieldIndex())->IsTheHole()) { 1373 FastPropertyAt(result->GetFieldIndex())->IsTheHole()) {
1381 result->DisallowCaching(); 1374 result->DisallowCaching();
1382 } 1375 }
1383 return; 1376 return;
1384 } 1377 }
1385 } else { 1378 } else {
1386 int entry = property_dictionary()->FindStringEntry(name); 1379 int entry = property_dictionary()->FindStringEntry(name);
1387 if (entry != DescriptorArray::kNotFound) { 1380 if (entry != DescriptorArray::kNotFound) {
1388 // Make sure to disallow caching for uninitialized constants 1381 // Make sure to disallow caching for uninitialized constants
1389 // found in the dictionary-mode objects. 1382 // found in the dictionary-mode objects.
1390 if (property_dictionary()->ValueAt(entry)->IsTheHole()) { 1383 if (property_dictionary()->ValueAt(entry)->IsTheHole()) {
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
1507 return SetLazyProperty(result, name, value, attributes); 1500 return SetLazyProperty(result, name, value, attributes);
1508 } 1501 }
1509 if (result->IsReadOnly() && result->IsProperty()) return value; 1502 if (result->IsReadOnly() && result->IsProperty()) return value;
1510 // This is a real property that is not read-only, or it is a 1503 // This is a real property that is not read-only, or it is a
1511 // transition or null descriptor and there are no setters in the prototypes. 1504 // transition or null descriptor and there are no setters in the prototypes.
1512 switch (result->type()) { 1505 switch (result->type()) {
1513 case NORMAL: 1506 case NORMAL:
1514 property_dictionary()->ValueAtPut(result->GetDictionaryEntry(), value); 1507 property_dictionary()->ValueAtPut(result->GetDictionaryEntry(), value);
1515 return value; 1508 return value;
1516 case FIELD: 1509 case FIELD:
1517 properties()->set(result->GetFieldIndex(), value); 1510 return FastPropertyAtPut(result->GetFieldIndex(), value);
1518 return value;
1519 case MAP_TRANSITION: 1511 case MAP_TRANSITION:
1520 if (attributes == result->GetAttributes()) { 1512 if (attributes == result->GetAttributes()) {
1521 // Only use map transition if the attributes match. 1513 // Only use map transition if the attributes match.
1522 return AddFastPropertyUsingMap(result->GetTransitionMap(), 1514 return AddFastPropertyUsingMap(result->GetTransitionMap(),
1523 name, 1515 name,
1524 value); 1516 value);
1525 } 1517 }
1526 return ConvertDescriptorToField(name, value, attributes); 1518 return ConvertDescriptorToField(name, value, attributes);
1527 case CONSTANT_FUNCTION: 1519 case CONSTANT_FUNCTION:
1528 if (value == result->GetConstantFunction()) return value; 1520 if (value == result->GetConstantFunction()) return value;
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
1578 } 1570 }
1579 if (!result->IsLoaded()) { 1571 if (!result->IsLoaded()) {
1580 return SetLazyProperty(result, name, value, attributes); 1572 return SetLazyProperty(result, name, value, attributes);
1581 } 1573 }
1582 // Check of IsReadOnly removed from here in clone. 1574 // Check of IsReadOnly removed from here in clone.
1583 switch (result->type()) { 1575 switch (result->type()) {
1584 case NORMAL: 1576 case NORMAL:
1585 property_dictionary()->ValueAtPut(result->GetDictionaryEntry(), value); 1577 property_dictionary()->ValueAtPut(result->GetDictionaryEntry(), value);
1586 return value; 1578 return value;
1587 case FIELD: 1579 case FIELD:
1588 properties()->set(result->GetFieldIndex(), value); 1580 return FastPropertyAtPut(result->GetFieldIndex(), value);
1589 return value;
1590 case MAP_TRANSITION: 1581 case MAP_TRANSITION:
1591 if (attributes == result->GetAttributes()) { 1582 if (attributes == result->GetAttributes()) {
1592 // Only use map transition if the attributes match. 1583 // Only use map transition if the attributes match.
1593 return AddFastPropertyUsingMap(result->GetTransitionMap(), 1584 return AddFastPropertyUsingMap(result->GetTransitionMap(),
1594 name, 1585 name,
1595 value); 1586 value);
1596 } else { 1587 } else {
1597 return ConvertDescriptorToField(name, value, attributes); 1588 return ConvertDescriptorToField(name, value, attributes);
1598 } 1589 }
1599 case CONSTANT_FUNCTION: 1590 case CONSTANT_FUNCTION:
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
1773 PropertyDetails(details.attributes(), NORMAL, details.index()); 1764 PropertyDetails(details.attributes(), NORMAL, details.index());
1774 Object* value = r.GetConstantFunction(); 1765 Object* value = r.GetConstantFunction();
1775 Object* result = dictionary->AddStringEntry(r.GetKey(), value, d); 1766 Object* result = dictionary->AddStringEntry(r.GetKey(), value, d);
1776 if (result->IsFailure()) return result; 1767 if (result->IsFailure()) return result;
1777 dictionary = Dictionary::cast(result); 1768 dictionary = Dictionary::cast(result);
1778 break; 1769 break;
1779 } 1770 }
1780 case FIELD: { 1771 case FIELD: {
1781 PropertyDetails d = 1772 PropertyDetails d =
1782 PropertyDetails(details.attributes(), NORMAL, details.index()); 1773 PropertyDetails(details.attributes(), NORMAL, details.index());
1783 Object* value = properties()->get(r.GetFieldIndex()); 1774 Object* value = FastPropertyAt(r.GetFieldIndex());
1784 Object* result = dictionary->AddStringEntry(r.GetKey(), value, d); 1775 Object* result = dictionary->AddStringEntry(r.GetKey(), value, d);
1785 if (result->IsFailure()) return result; 1776 if (result->IsFailure()) return result;
1786 dictionary = Dictionary::cast(result); 1777 dictionary = Dictionary::cast(result);
1787 break; 1778 break;
1788 } 1779 }
1789 case CALLBACKS: { 1780 case CALLBACKS: {
1790 PropertyDetails d = 1781 PropertyDetails d =
1791 PropertyDetails(details.attributes(), CALLBACKS, details.index()); 1782 PropertyDetails(details.attributes(), CALLBACKS, details.index());
1792 Object* value = r.GetCallbacksObject(); 1783 Object* value = r.GetCallbacksObject();
1793 Object* result = dictionary->AddStringEntry(r.GetKey(), value, d); 1784 Object* result = dictionary->AddStringEntry(r.GetKey(), value, d);
(...skipping 534 matching lines...) Expand 10 before | Expand all | Expand 10 after
2328 return Heap::undefined_value(); 2319 return Heap::undefined_value();
2329 } 2320 }
2330 2321
2331 2322
2332 Object* JSObject::SlowReverseLookup(Object* value) { 2323 Object* JSObject::SlowReverseLookup(Object* value) {
2333 if (HasFastProperties()) { 2324 if (HasFastProperties()) {
2334 for (DescriptorReader r(map()->instance_descriptors()); 2325 for (DescriptorReader r(map()->instance_descriptors());
2335 !r.eos(); 2326 !r.eos();
2336 r.advance()) { 2327 r.advance()) {
2337 if (r.type() == FIELD) { 2328 if (r.type() == FIELD) {
2338 if (properties()->get(r.GetFieldIndex()) == value) { 2329 if (FastPropertyAt(r.GetFieldIndex()) == value) {
2339 return r.GetKey(); 2330 return r.GetKey();
2340 } 2331 }
2341 } else if (r.type() == CONSTANT_FUNCTION) { 2332 } else if (r.type() == CONSTANT_FUNCTION) {
2342 if (r.GetConstantFunction() == value) { 2333 if (r.GetConstantFunction() == value) {
2343 return r.GetKey(); 2334 return r.GetKey();
2344 } 2335 }
2345 } 2336 }
2346 } 2337 }
2347 return Heap::undefined_value(); 2338 return Heap::undefined_value();
2348 } else { 2339 } else {
2349 return property_dictionary()->SlowReverseLookup(value); 2340 return property_dictionary()->SlowReverseLookup(value);
2350 } 2341 }
2351 } 2342 }
2352 2343
2353 2344
2354 Object* Map::Copy() { 2345 Object* Map::Copy() {
2355 Object* result = Heap::AllocateMap(instance_type(), instance_size()); 2346 Object* result = Heap::AllocateMap(instance_type(), instance_size());
2356 if (result->IsFailure()) return result; 2347 if (result->IsFailure()) return result;
2357 Map::cast(result)->set_prototype(prototype()); 2348 Map::cast(result)->set_prototype(prototype());
2358 Map::cast(result)->set_constructor(constructor()); 2349 Map::cast(result)->set_constructor(constructor());
2359 // Don't copy descriptors, so map transitions always remain a forest. 2350 // Don't copy descriptors, so map transitions always remain a forest.
2360 Map::cast(result)->set_instance_descriptors(Heap::empty_descriptor_array()); 2351 Map::cast(result)->set_instance_descriptors(Heap::empty_descriptor_array());
2361 // Please note instance_type and instance_size are set when allocated. 2352 // Please note instance_type and instance_size are set when allocated.
2353 Map::cast(result)->set_inobject_properties(inobject_properties());
2362 Map::cast(result)->set_unused_property_fields(unused_property_fields()); 2354 Map::cast(result)->set_unused_property_fields(unused_property_fields());
2363 Map::cast(result)->set_bit_field(bit_field()); 2355 Map::cast(result)->set_bit_field(bit_field());
2364 Map::cast(result)->ClearCodeCache(); 2356 Map::cast(result)->ClearCodeCache();
2365 return result; 2357 return result;
2366 } 2358 }
2367 2359
2368 2360
2369 Object* Map::CopyDropTransitions() { 2361 Object* Map::CopyDropTransitions() {
2370 Object *new_map = Copy(); 2362 Object *new_map = Copy();
2371 if (new_map->IsFailure()) return new_map; 2363 if (new_map->IsFailure()) return new_map;
(...skipping 4064 matching lines...) Expand 10 before | Expand all | Expand 10 after
6436 // No break point. 6428 // No break point.
6437 if (break_point_objects()->IsUndefined()) return 0; 6429 if (break_point_objects()->IsUndefined()) return 0;
6438 // Single beak point. 6430 // Single beak point.
6439 if (!break_point_objects()->IsFixedArray()) return 1; 6431 if (!break_point_objects()->IsFixedArray()) return 1;
6440 // Multiple break points. 6432 // Multiple break points.
6441 return FixedArray::cast(break_point_objects())->length(); 6433 return FixedArray::cast(break_point_objects())->length();
6442 } 6434 }
6443 6435
6444 6436
6445 } } // namespace v8::internal 6437 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/objects-debug.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698