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

Side by Side Diff: src/objects.cc

Issue 14146005: Track representations of fields (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Make double support consistent. Now DOUBLE always contains smi or heapnumber Created 7 years, 8 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-inl.h » ('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 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 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 1697 matching lines...) Expand 10 before | Expand all | Expand 10 after
1708 } 1708 }
1709 1709
1710 1710
1711 MaybeObject* JSObject::AddFastPropertyUsingMap(Map* new_map, 1711 MaybeObject* JSObject::AddFastPropertyUsingMap(Map* new_map,
1712 Name* name, 1712 Name* name,
1713 Object* value, 1713 Object* value,
1714 int field_index) { 1714 int field_index) {
1715 if (map()->unused_property_fields() == 0) { 1715 if (map()->unused_property_fields() == 0) {
1716 int new_unused = new_map->unused_property_fields(); 1716 int new_unused = new_map->unused_property_fields();
1717 FixedArray* values; 1717 FixedArray* values;
1718 { MaybeObject* maybe_values = 1718 MaybeObject* maybe_values =
1719 properties()->CopySize(properties()->length() + new_unused + 1); 1719 properties()->CopySize(properties()->length() + new_unused + 1);
1720 if (!maybe_values->To(&values)) return maybe_values; 1720 if (!maybe_values->To(&values)) return maybe_values;
1721 } 1721
1722 set_properties(values); 1722 set_properties(values);
1723 } 1723 }
1724 set_map(new_map); 1724 set_map(new_map);
1725 return FastPropertyAtPut(field_index, value); 1725 return FastPropertyAtPut(field_index, value);
1726 } 1726 }
1727 1727
1728 1728
1729 static bool IsIdentifier(UnicodeCache* cache, Name* name) { 1729 static bool IsIdentifier(UnicodeCache* cache, Name* name) {
1730 // Checks whether the buffer contains an identifier (no escape). 1730 // Checks whether the buffer contains an identifier (no escape).
1731 if (!name->IsString()) return false; 1731 if (!name->IsString()) return false;
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1768 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 1768 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
1769 1769
1770 return AddSlowProperty(name, value, attributes); 1770 return AddSlowProperty(name, value, attributes);
1771 } 1771 }
1772 1772
1773 // Compute the new index for new field. 1773 // Compute the new index for new field.
1774 int index = map()->NextFreePropertyIndex(); 1774 int index = map()->NextFreePropertyIndex();
1775 1775
1776 // Allocate new instance descriptors with (name, index) added 1776 // Allocate new instance descriptors with (name, index) added
1777 FieldDescriptor new_field(name, index, attributes, 0); 1777 FieldDescriptor new_field(name, index, attributes, 0);
1778 new_field.SetStorageType(value->RequiredStorage());
1778 1779
1779 ASSERT(index < map()->inobject_properties() || 1780 ASSERT(index < map()->inobject_properties() ||
1780 (index - map()->inobject_properties()) < properties()->length() || 1781 (index - map()->inobject_properties()) < properties()->length() ||
1781 map()->unused_property_fields() == 0); 1782 map()->unused_property_fields() == 0);
1782 1783
1783 FixedArray* values = NULL; 1784 FixedArray* values = NULL;
1784 1785
1785 if (map()->unused_property_fields() == 0) { 1786 if (map()->unused_property_fields() == 0) {
1786 // Make room for the new value 1787 // Make room for the new value
1787 MaybeObject* maybe_values = 1788 MaybeObject* maybe_values =
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after
2021 if (!maybe_result->To(&result)) return maybe_result; 2022 if (!maybe_result->To(&result)) return maybe_result;
2022 2023
2023 if (!HasFastProperties()) return result; 2024 if (!HasFastProperties()) return result;
2024 2025
2025 // This method should only be used to convert existing transitions. 2026 // This method should only be used to convert existing transitions.
2026 Map* new_map = map(); 2027 Map* new_map = map();
2027 2028
2028 // TODO(verwaest): From here on we lose existing map transitions, causing 2029 // TODO(verwaest): From here on we lose existing map transitions, causing
2029 // invalid back pointers. This will change once we can store multiple 2030 // invalid back pointers. This will change once we can store multiple
2030 // transitions with the same key. 2031 // transitions with the same key.
2031
2032 bool owned_descriptors = old_map->owns_descriptors(); 2032 bool owned_descriptors = old_map->owns_descriptors();
2033 if (owned_descriptors || 2033 if (owned_descriptors ||
2034 old_target->instance_descriptors() == old_map->instance_descriptors()) { 2034 old_target->instance_descriptors() == old_map->instance_descriptors()) {
2035 // Since the conversion above generated a new fast map with an additional 2035 // Since the conversion above generated a new fast map with an additional
2036 // property which can be shared as well, install this descriptor pointer 2036 // property which can be shared as well, install this descriptor pointer
2037 // along the entire chain of smaller maps. 2037 // along the entire chain of smaller maps.
2038 Map* map; 2038 Map* map;
2039 DescriptorArray* new_descriptors = new_map->instance_descriptors(); 2039 DescriptorArray* new_descriptors = new_map->instance_descriptors();
2040 DescriptorArray* old_descriptors = old_map->instance_descriptors(); 2040 DescriptorArray* old_descriptors = old_map->instance_descriptors();
2041 for (Object* current = old_map; 2041 for (Object* current = old_map;
2042 !current->IsUndefined(); 2042 !current->IsUndefined();
2043 current = map->GetBackPointer()) { 2043 current = map->GetBackPointer()) {
2044 map = Map::cast(current); 2044 map = Map::cast(current);
2045 if (map->instance_descriptors() != old_descriptors) break; 2045 if (map->instance_descriptors() != old_descriptors) break;
2046 map->SetEnumLength(Map::kInvalidEnumCache); 2046 map->SetEnumLength(Map::kInvalidEnumCache);
2047 map->set_instance_descriptors(new_descriptors); 2047 map->set_instance_descriptors(new_descriptors);
2048 } 2048 }
2049 old_map->set_owns_descriptors(false); 2049 old_map->set_owns_descriptors(false);
2050 } 2050 }
2051 2051
2052 old_target->InvalidateTransitionTree();
danno 2013/04/24 15:23:00 nit: How about InvalidateMapTransitionTree()?
2053
2052 old_map->SetTransition(transition_index, new_map); 2054 old_map->SetTransition(transition_index, new_map);
2053 new_map->SetBackPointer(old_map); 2055 new_map->SetBackPointer(old_map);
2054 return result; 2056 return result;
2055 } 2057 }
2056 2058
2057 2059
2058 MaybeObject* JSObject::ConvertDescriptorToField(Name* name, 2060 MaybeObject* JSObject::ConvertDescriptorToField(Name* name,
2059 Object* new_value, 2061 Object* new_value,
2060 PropertyAttributes attributes) { 2062 PropertyAttributes attributes) {
2061 if (map()->unused_property_fields() == 0 && 2063 if (map()->unused_property_fields() == 0 &&
2062 TooManyFastProperties(properties()->length(), MAY_BE_STORE_FROM_KEYED)) { 2064 TooManyFastProperties(properties()->length(), MAY_BE_STORE_FROM_KEYED)) {
2063 Object* obj; 2065 Object* obj;
2064 MaybeObject* maybe_obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); 2066 MaybeObject* maybe_obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
2065 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 2067 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
2066 return ReplaceSlowProperty(name, new_value, attributes); 2068 return ReplaceSlowProperty(name, new_value, attributes);
2067 } 2069 }
2068 2070
2069 int index = map()->NextFreePropertyIndex(); 2071 int index = map()->NextFreePropertyIndex();
2070 FieldDescriptor new_field(name, index, attributes, 0); 2072 FieldDescriptor new_field(name, index, attributes, 0);
2073 new_field.SetStorageType(new_value->RequiredStorage());
2071 2074
2072 // Make a new map for the object. 2075 // Make a new map for the object.
2073 Map* new_map; 2076 Map* new_map;
2074 MaybeObject* maybe_new_map = map()->CopyInsertDescriptor(&new_field, 2077 MaybeObject* maybe_new_map = map()->CopyInsertDescriptor(&new_field,
2075 OMIT_TRANSITION); 2078 OMIT_TRANSITION);
2076 if (!maybe_new_map->To(&new_map)) return maybe_new_map; 2079 if (!maybe_new_map->To(&new_map)) return maybe_new_map;
2077 2080
2078 // Make new properties array if necessary. 2081 // Make new properties array if necessary.
2079 FixedArray* new_properties = NULL; 2082 FixedArray* new_properties = NULL;
2080 int new_unused_property_fields = map()->unused_property_fields() - 1; 2083 int new_unused_property_fields = map()->unused_property_fields() - 1;
2081 if (map()->unused_property_fields() == 0) { 2084 if (map()->unused_property_fields() == 0) {
2082 new_unused_property_fields = kFieldsAdded - 1; 2085 new_unused_property_fields = kFieldsAdded - 1;
2083 MaybeObject* maybe_new_properties = 2086 MaybeObject* maybe_new_properties =
2084 properties()->CopySize(properties()->length() + kFieldsAdded); 2087 properties()->CopySize(properties()->length() + kFieldsAdded);
2085 if (!maybe_new_properties->To(&new_properties)) return maybe_new_properties; 2088 if (!maybe_new_properties->To(&new_properties)) return maybe_new_properties;
2086 } 2089 }
2087 2090
2088 // Update pointers to commit changes. 2091 // Update pointers to commit changes.
2089 // Object points to the new map. 2092 // Object points to the new map.
2090 new_map->set_unused_property_fields(new_unused_property_fields); 2093 new_map->set_unused_property_fields(new_unused_property_fields);
2091 set_map(new_map); 2094 set_map(new_map);
2092 if (new_properties != NULL) { 2095 if (new_properties != NULL) {
2093 set_properties(new_properties); 2096 set_properties(new_properties);
2094 } 2097 }
2095 return FastPropertyAtPut(index, new_value); 2098 return FastPropertyAtPut(index, new_value);
2096 } 2099 }
2097 2100
2098 2101
2102 enum RightTrimMode { FROM_GC, FROM_MUTATOR };
2103
2104
2105 static void ZapEndOfFixedArray(Address new_end, int to_trim) {
2106 // If we are doing a big trim in old space then we zap the space.
2107 Object** zap = reinterpret_cast<Object**>(new_end);
2108 zap++; // Header of filler must be at least one word so skip that.
2109 for (int i = 1; i < to_trim; i++) {
2110 *zap++ = Smi::FromInt(0);
2111 }
2112 }
2113
2114
2115 template<RightTrimMode trim_mode>
2116 static void RightTrimFixedArray(Heap* heap, FixedArray* elms, int to_trim) {
2117 ASSERT(elms->map() != HEAP->fixed_cow_array_map());
2118 // For now this trick is only applied to fixed arrays in new and paged space.
2119 ASSERT(!HEAP->lo_space()->Contains(elms));
2120
2121 const int len = elms->length();
2122
2123 ASSERT(to_trim < len);
2124
2125 Address new_end = elms->address() + FixedArray::SizeFor(len - to_trim);
2126
2127 if (trim_mode != FROM_GC || Heap::ShouldZapGarbage()) {
2128 ZapEndOfFixedArray(new_end, to_trim);
2129 }
2130
2131 int size_delta = to_trim * kPointerSize;
2132
2133 // Technically in new space this write might be omitted (except for
2134 // debug mode which iterates through the heap), but to play safer
2135 // we still do it.
2136 heap->CreateFillerObjectAt(new_end, size_delta);
2137
2138 elms->set_length(len - to_trim);
2139
2140 // Maintain marking consistency for IncrementalMarking.
2141 if (Marking::IsBlack(Marking::MarkBitFrom(elms))) {
2142 if (trim_mode == FROM_GC) {
2143 MemoryChunk::IncrementLiveBytesFromGC(elms->address(), -size_delta);
2144 } else {
2145 MemoryChunk::IncrementLiveBytesFromMutator(elms->address(), -size_delta);
2146 }
2147 }
2148 }
2149
2150
2151 MaybeObject* JSObject::MigrateToMap(Map* new_map) {
2152 Heap* heap = GetHeap();
2153 Map* old_map = map();
2154 int number_of_fields = new_map->NumberOfFields();
2155
2156 // Nothing to do if no functions were converted to fields.
2157 if (old_map->NumberOfFields() == number_of_fields &&
2158 (old_map->inobject_properties() == new_map->inobject_properties() ||
2159 number_of_fields < new_map->inobject_properties())) {
2160 ASSERT(map()->inobject_properties() == new_map->inobject_properties() ||
2161 new_map->NumberOfFields() <= new_map->inobject_properties());
2162 ASSERT(map()->unused_property_fields() ==
2163 (new_map->unused_property_fields() +
2164 map()->inobject_properties() -
2165 new_map->inobject_properties()));
2166 set_map(new_map);
2167 return this;
2168 }
2169
2170 int inobject = new_map->inobject_properties();
2171 int total_size = number_of_fields + new_map->unused_property_fields();
2172 int external = total_size - inobject;
2173 FixedArray* array;
2174 MaybeObject* maybe_array = heap->AllocateFixedArray(total_size);
2175 if (!maybe_array->To(&array)) return maybe_array;
2176
2177 DescriptorArray* old_descriptors = old_map->instance_descriptors();
2178 DescriptorArray* new_descriptors = new_map->instance_descriptors();
2179 int descriptors = new_map->NumberOfOwnDescriptors();
2180
2181 for (int i = 0; i < descriptors; i++) {
2182 PropertyDetails details = new_descriptors->GetDetails(i);
2183 if (details.type() != FIELD) continue;
2184 PropertyDetails old_details = old_descriptors->GetDetails(i);
2185 ASSERT(old_details.type() == CONSTANT_FUNCTION ||
2186 old_details.type() == FIELD);
2187 Object* value = old_details.type() == CONSTANT_FUNCTION
2188 ? old_descriptors->GetValue(i)
2189 : FastPropertyAt(old_descriptors->GetFieldIndex(i));
2190 int target_index = new_descriptors->GetFieldIndex(i) - inobject;
2191 if (target_index < 0) target_index += total_size;
2192 array->set(target_index, value);
2193 }
2194
2195 // From here on we cannot fail anymore.
2196
2197 // Copy (real) inobject properties.
2198 int limit = Min(inobject, number_of_fields);
2199 for (int i = 0; i < limit; i++) {
2200 FastPropertyAtPut(i, array->get(external + i));
2201 }
2202
2203 // Create filler object past the new instance size.
2204 int new_instance_size = new_map->instance_size();
2205 int instance_size_delta = old_map->instance_size() - new_instance_size;
2206 ASSERT(instance_size_delta >= 0);
2207 Address address = this->address() + new_instance_size;
2208 heap->CreateFillerObjectAt(address, instance_size_delta);
2209
2210 // If there are properties in the new backing store, trim it to the correct
2211 // size and install the backing store into the object.
2212 if (external > 0) {
2213 RightTrimFixedArray<FROM_MUTATOR>(heap, array, inobject);
2214 set_properties(array);
2215 }
2216
2217 set_map(new_map);
2218
2219 return this;
2220 }
2221
2222
2223 MaybeObject* JSObject::GeneralizeFieldStorage(int modify_index,
2224 StorageType new_storage) {
2225 Map* new_map;
2226 MaybeObject* maybe_new_map =
2227 map()->GeneralizeStorage(modify_index, new_storage);
2228 if (!maybe_new_map->To(&new_map)) return maybe_new_map;
2229 ASSERT(map() != new_map || new_map->FindRootMap()->is_invalid_transition());
2230
2231 return MigrateToMap(new_map);
2232 }
2233
2234
2235 int Map::NumberOfFields() {
2236 DescriptorArray* descriptors = instance_descriptors();
2237 int result = 0;
2238 for (int i = 0; i < NumberOfOwnDescriptors(); i++) {
2239 if (descriptors->GetDetails(i).type() == FIELD) result++;
2240 }
2241 return result;
2242 }
2243
2244
2245 MaybeObject* Map::CopyGeneralizeStorage(int modify_index,
2246 StorageType new_storage) {
2247 Map* new_map;
2248 MaybeObject* maybe_map = this->Copy();
2249 if (!maybe_map->To(&new_map)) return maybe_map;
2250
2251 new_map->instance_descriptors()->InitializeStorageTypes(TAGGED);
2252 return new_map;
2253 }
2254
2255
2256 void Map::InvalidateTransitionTree() {
2257 if (is_invalid_transition()) return;
2258 if (HasTransitionArray()) {
2259 TransitionArray* transitions = this->transitions();
2260 for (int i = 0; i < transitions->number_of_transitions(); i++) {
2261 transitions->GetTarget(i)->InvalidateTransitionTree();
2262 }
2263 }
2264 invalidate_transition();
2265 dependent_code()->DeoptimizeDependentCodeGroup(
2266 GetIsolate(), DependentCode::kFieldTransitionGroup);
2267 dependent_code()->DeoptimizeDependentCodeGroup(
2268 GetIsolate(), DependentCode::kPrototypeCheckGroup);
2269 }
2270
2271
2272 void Map::InvalidateTarget(Name* key, DescriptorArray* new_descriptors) {
2273 if (HasTransitionArray()) {
2274 TransitionArray* transitions = this->transitions();
2275 int transition = transitions->Search(key);
2276 if (transition != TransitionArray::kNotFound) {
2277 transitions->GetTarget(transition)->InvalidateTransitionTree();
2278 }
2279 }
2280
2281 // Don't overwrite the empty descriptor array.
2282 if (NumberOfOwnDescriptors() == 0) return;
2283
2284 DescriptorArray* to_replace = instance_descriptors();
2285 Map* current = this;
2286 while (current->instance_descriptors() == to_replace) {
2287 current->SetEnumLength(Map::kInvalidEnumCache);
2288 current->set_instance_descriptors(new_descriptors);
2289 Object* next = current->GetBackPointer();
2290 if (next->IsUndefined()) break;
2291 current = Map::cast(next);
2292 }
2293
2294 set_owns_descriptors(false);
2295 }
2296
2297
2298 bool Map::TransitionsTo(Map* other) {
2299 if (!HasTransitionArray()) return false;
2300
2301 int descriptor = other->LastAdded();
2302 Name* name = other->instance_descriptors()->GetKey(descriptor);
2303
2304 TransitionArray* transitions = this->transitions();
2305 int transition = transitions->Search(name);
2306 if (transition == TransitionArray::kNotFound) return false;
2307
2308 return transitions->GetTarget(transition) == other;
2309 }
2310
2311
2312 Map* Map::FindRootMap() {
2313 Map* result = this;
2314 while (true) {
2315 Object* back = result->GetBackPointer();
2316 if (back->IsUndefined()) return result;
2317 result = Map::cast(back);
2318 }
2319 }
2320
2321
2322 Map* Map::FindUpdatedMap(int length, DescriptorArray* descriptors) {
2323 // This can only be called on roots of transition trees.
2324 ASSERT(GetBackPointer()->IsUndefined());
2325
2326 Map* current = this;
2327
2328 for (int i = 0; i < length; i++) {
2329 if (!current->HasTransitionArray()) break;
2330 Name* name = descriptors->GetKey(i);
2331 TransitionArray* transitions = current->transitions();
2332 int transition = transitions->Search(name);
2333 if (transition == TransitionArray::kNotFound) break;
2334 current = transitions->GetTarget(transition);
2335 }
2336
2337 return current;
2338 }
2339
2340
2341 Map* Map::FindLastMatchMap(DescriptorArray* descriptors) {
2342 // This can only be called on roots of transition trees.
2343 ASSERT(GetBackPointer()->IsUndefined());
2344
2345 Map* current = this;
2346 int length = descriptors->number_of_descriptors();
2347
2348 for (int i = 0; i < length; i++) {
2349 if (!current->HasTransitionArray()) break;
2350 Name* name = descriptors->GetKey(i);
2351 TransitionArray* transitions = current->transitions();
2352 int transition = transitions->Search(name);
2353 if (transition == TransitionArray::kNotFound) break;
2354
2355 Map* next = transitions->GetTarget(transition);
2356 DescriptorArray* next_descriptors = next->instance_descriptors();
2357
2358 if (next_descriptors->GetValue(i) != descriptors->GetValue(i)) break;
2359
2360 PropertyDetails details = descriptors->GetDetails(i);
2361 PropertyDetails next_details = next_descriptors->GetDetails(i);
2362 if (details.type() != next_details.type()) break;
2363 if (details.attributes() != next_details.attributes()) break;
2364 if (details.storage_type() != next_details.storage_type()) break;
2365 ASSERT(!details.IsDeleted());
2366 ASSERT(!next_details.IsDeleted());
2367
2368 current = next;
2369 }
2370 return current;
2371 }
2372
2373
2374 MaybeObject* Map::GeneralizeStorage(int modify_index, StorageType new_storage) {
2375 Map* old_map = this;
2376 DescriptorArray* old_descriptors = old_map->instance_descriptors();
2377 StorageType old_storage =
2378 old_descriptors->GetDetails(modify_index).storage_type();
2379
2380 if (old_storage == ANY) {
2381 old_descriptors->SetStorageType(modify_index, new_storage);
2382 return this;
2383 }
2384
2385 int descriptors = old_map->NumberOfOwnDescriptors();
2386 Map* root_map = old_map->FindRootMap();
2387
2388 if (!old_map->EquivalentToForTransition(root_map)) {
2389 return CopyGeneralizeStorage(modify_index, new_storage);
2390 }
2391
2392 Map* updated = root_map->FindUpdatedMap(descriptors, old_descriptors);
2393 // Check the state of the root map.
2394 DescriptorArray* updated_descriptors = updated->instance_descriptors();
2395
2396 DescriptorArray* new_descriptors;
2397 MaybeObject* maybe_descriptors = updated_descriptors->Merge(
2398 root_map->NumberOfOwnDescriptors(),
2399 updated->NumberOfOwnDescriptors(),
2400 descriptors,
2401 old_descriptors);
2402 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
2403
2404 if (IsMoreGeneralStorageType(
2405 new_storage,
2406 new_descriptors->GetDetails(modify_index).storage_type())) {
2407 new_descriptors->SetStorageType(modify_index, new_storage);
2408 }
2409
2410 Map* split_map = root_map->FindLastMatchMap(new_descriptors);
2411
2412 int descriptor = split_map->NumberOfOwnDescriptors();
2413 // Check whether |split_map| matches what we were looking for. If so, return
2414 // it.
2415 if (descriptors == descriptor) return split_map;
2416
2417 split_map->InvalidateTarget(
2418 old_descriptors->GetKey(descriptor), new_descriptors);
2419
2420 Map* new_map = split_map;
2421 // Add missing transitions.
2422 for (; descriptor < descriptors; descriptor++) {
2423 MaybeObject* maybe_map = new_map->CopyInstallDescriptors(
2424 descriptor, new_descriptors);
2425 if (!maybe_map->To(&new_map)) {
2426 // Create a handle for the last created map to ensure it stays alive
2427 // during GC. Its descriptor array is too large, but it will be
2428 // overwritten during retry anyway.
2429 Handle<Map>(new_map);
2430 }
2431 }
2432
2433 new_map->set_owns_descriptors(true);
2434 return new_map;
2435 }
2436
2099 2437
2100 MaybeObject* JSObject::SetPropertyWithInterceptor( 2438 MaybeObject* JSObject::SetPropertyWithInterceptor(
2101 Name* name, 2439 Name* name,
2102 Object* value, 2440 Object* value,
2103 PropertyAttributes attributes, 2441 PropertyAttributes attributes,
2104 StrictModeFlag strict_mode) { 2442 StrictModeFlag strict_mode) {
2105 // TODO(rossberg): Support symbols in the API. 2443 // TODO(rossberg): Support symbols in the API.
2106 if (name->IsSymbol()) return value; 2444 if (name->IsSymbol()) return value;
2107 Isolate* isolate = GetIsolate(); 2445 Isolate* isolate = GetIsolate();
2108 HandleScope scope(isolate); 2446 HandleScope scope(isolate);
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after
2384 if (strict_mode == kNonStrictMode) return value; 2722 if (strict_mode == kNonStrictMode) return value;
2385 Handle<Object> args[] = { Handle<Object>(name, isolate), 2723 Handle<Object> args[] = { Handle<Object>(name, isolate),
2386 Handle<Object>(this, isolate)}; 2724 Handle<Object>(this, isolate)};
2387 return isolate->Throw(*isolate->factory()->NewTypeError( 2725 return isolate->Throw(*isolate->factory()->NewTypeError(
2388 "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args)))); 2726 "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args))));
2389 } 2727 }
2390 return heap->the_hole_value(); 2728 return heap->the_hole_value();
2391 } 2729 }
2392 2730
2393 2731
2394 enum RightTrimMode { FROM_GC, FROM_MUTATOR };
2395
2396
2397 static void ZapEndOfFixedArray(Address new_end, int to_trim) {
2398 // If we are doing a big trim in old space then we zap the space.
2399 Object** zap = reinterpret_cast<Object**>(new_end);
2400 zap++; // Header of filler must be at least one word so skip that.
2401 for (int i = 1; i < to_trim; i++) {
2402 *zap++ = Smi::FromInt(0);
2403 }
2404 }
2405
2406
2407 template<RightTrimMode trim_mode>
2408 static void RightTrimFixedArray(Heap* heap, FixedArray* elms, int to_trim) {
2409 ASSERT(elms->map() != HEAP->fixed_cow_array_map());
2410 // For now this trick is only applied to fixed arrays in new and paged space.
2411 ASSERT(!HEAP->lo_space()->Contains(elms));
2412
2413 const int len = elms->length();
2414
2415 ASSERT(to_trim < len);
2416
2417 Address new_end = elms->address() + FixedArray::SizeFor(len - to_trim);
2418
2419 if (trim_mode != FROM_GC || Heap::ShouldZapGarbage()) {
2420 ZapEndOfFixedArray(new_end, to_trim);
2421 }
2422
2423 int size_delta = to_trim * kPointerSize;
2424
2425 // Technically in new space this write might be omitted (except for
2426 // debug mode which iterates through the heap), but to play safer
2427 // we still do it.
2428 heap->CreateFillerObjectAt(new_end, size_delta);
2429
2430 elms->set_length(len - to_trim);
2431
2432 // Maintain marking consistency for IncrementalMarking.
2433 if (Marking::IsBlack(Marking::MarkBitFrom(elms))) {
2434 if (trim_mode == FROM_GC) {
2435 MemoryChunk::IncrementLiveBytesFromGC(elms->address(), -size_delta);
2436 } else {
2437 MemoryChunk::IncrementLiveBytesFromMutator(elms->address(), -size_delta);
2438 }
2439 }
2440 }
2441
2442
2443 void Map::EnsureDescriptorSlack(Handle<Map> map, int slack) { 2732 void Map::EnsureDescriptorSlack(Handle<Map> map, int slack) {
2444 Handle<DescriptorArray> descriptors(map->instance_descriptors()); 2733 Handle<DescriptorArray> descriptors(map->instance_descriptors());
2445 if (slack <= descriptors->NumberOfSlackDescriptors()) return; 2734 if (slack <= descriptors->NumberOfSlackDescriptors()) return;
2446 int number_of_descriptors = descriptors->number_of_descriptors(); 2735 int number_of_descriptors = descriptors->number_of_descriptors();
2447 Isolate* isolate = map->GetIsolate(); 2736 Isolate* isolate = map->GetIsolate();
2448 Handle<DescriptorArray> new_descriptors = 2737 Handle<DescriptorArray> new_descriptors =
2449 isolate->factory()->NewDescriptorArray(number_of_descriptors, slack); 2738 isolate->factory()->NewDescriptorArray(number_of_descriptors, slack);
2450 DescriptorArray::WhitenessWitness witness(*new_descriptors); 2739 DescriptorArray::WhitenessWitness witness(*new_descriptors);
2451 2740
2452 for (int i = 0; i < number_of_descriptors; ++i) { 2741 for (int i = 0; i < number_of_descriptors; ++i) {
(...skipping 643 matching lines...) Expand 10 before | Expand all | Expand 10 after
3096 return Handle<Object>(); 3385 return Handle<Object>();
3097 } 3386 }
3098 trap = Handle<Object>(derived); 3387 trap = Handle<Object>(derived);
3099 } 3388 }
3100 3389
3101 bool threw; 3390 bool threw;
3102 return Execution::Call(trap, handler, argc, argv, &threw); 3391 return Execution::Call(trap, handler, argc, argv, &threw);
3103 } 3392 }
3104 3393
3105 3394
3106 void JSObject::AddFastPropertyUsingMap(Handle<JSObject> object,
3107 Handle<Map> map) {
3108 CALL_HEAP_FUNCTION_VOID(
3109 object->GetIsolate(),
3110 object->AddFastPropertyUsingMap(*map));
3111 }
3112
3113
3114 void JSObject::TransitionToMap(Handle<JSObject> object, Handle<Map> map) { 3395 void JSObject::TransitionToMap(Handle<JSObject> object, Handle<Map> map) {
3115 CALL_HEAP_FUNCTION_VOID( 3396 CALL_HEAP_FUNCTION_VOID(
3116 object->GetIsolate(), 3397 object->GetIsolate(),
3117 object->TransitionToMap(*map)); 3398 object->TransitionToMap(*map));
3118 } 3399 }
3119 3400
3120 3401
3402 void JSObject::MigrateInstance(Handle<JSObject> object) {
3403 CALL_HEAP_FUNCTION_VOID(
3404 object->GetIsolate(),
3405 object->MigrateInstance());
3406 }
3407
3408
3121 MaybeObject* JSObject::SetPropertyForResult(LookupResult* lookup, 3409 MaybeObject* JSObject::SetPropertyForResult(LookupResult* lookup,
3122 Name* name_raw, 3410 Name* name_raw,
3123 Object* value_raw, 3411 Object* value_raw,
3124 PropertyAttributes attributes, 3412 PropertyAttributes attributes,
3125 StrictModeFlag strict_mode, 3413 StrictModeFlag strict_mode,
3126 StoreFromKeyed store_mode) { 3414 StoreFromKeyed store_mode) {
3127 Heap* heap = GetHeap(); 3415 Heap* heap = GetHeap();
3128 Isolate* isolate = heap->isolate(); 3416 Isolate* isolate = heap->isolate();
3129 // Make sure that the top context does not change when doing callbacks or 3417 // Make sure that the top context does not change when doing callbacks or
3130 // interceptor calls. 3418 // interceptor calls.
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
3199 old_value = Object::GetProperty(self, name); 3487 old_value = Object::GetProperty(self, name);
3200 } 3488 }
3201 3489
3202 // This is a real property that is not read-only, or it is a 3490 // This is a real property that is not read-only, or it is a
3203 // transition or null descriptor and there are no setters in the prototypes. 3491 // transition or null descriptor and there are no setters in the prototypes.
3204 MaybeObject* result = *value; 3492 MaybeObject* result = *value;
3205 switch (lookup->type()) { 3493 switch (lookup->type()) {
3206 case NORMAL: 3494 case NORMAL:
3207 result = lookup->holder()->SetNormalizedProperty(lookup, *value); 3495 result = lookup->holder()->SetNormalizedProperty(lookup, *value);
3208 break; 3496 break;
3209 case FIELD: 3497 case FIELD: {
3498 StorageType storage_type = lookup->storage_type();
3499 if (!value->FitsStorage(storage_type)) {
3500 MaybeObject* maybe_failure = GeneralizeFieldStorage(
3501 lookup->GetDescriptorIndex(), value->RequiredStorage());
3502 if (maybe_failure->IsFailure()) return maybe_failure;
3503 }
3210 result = lookup->holder()->FastPropertyAtPut( 3504 result = lookup->holder()->FastPropertyAtPut(
3211 lookup->GetFieldIndex().field_index(), *value); 3505 lookup->GetFieldIndex().field_index(), *value);
3212 break; 3506 break;
3507 }
3213 case CONSTANT_FUNCTION: 3508 case CONSTANT_FUNCTION:
3214 // Only replace the function if necessary. 3509 // Only replace the function if necessary.
3215 if (*value == lookup->GetConstantFunction()) return *value; 3510 if (*value == lookup->GetConstantFunction()) return *value;
3216 // Preserve the attributes of this existing property. 3511 // Preserve the attributes of this existing property.
3217 attributes = lookup->GetAttributes(); 3512 attributes = lookup->GetAttributes();
3218 result = 3513 result =
3219 lookup->holder()->ConvertDescriptorToField(*name, *value, attributes); 3514 lookup->holder()->ConvertDescriptorToField(*name, *value, attributes);
3220 break; 3515 break;
3221 case CALLBACKS: { 3516 case CALLBACKS: {
3222 Object* callback_object = lookup->GetCallbackObject(); 3517 Object* callback_object = lookup->GetCallbackObject();
3223 return self->SetPropertyWithCallback( 3518 return self->SetPropertyWithCallback(
3224 callback_object, *name, *value, lookup->holder(), strict_mode); 3519 callback_object, *name, *value, lookup->holder(), strict_mode);
3225 } 3520 }
3226 case INTERCEPTOR: 3521 case INTERCEPTOR:
3227 result = lookup->holder()->SetPropertyWithInterceptor( 3522 result = lookup->holder()->SetPropertyWithInterceptor(
3228 *name, *value, attributes, strict_mode); 3523 *name, *value, attributes, strict_mode);
3229 break; 3524 break;
3230 case TRANSITION: { 3525 case TRANSITION: {
3231 Map* transition_map = lookup->GetTransitionTarget(); 3526 Map* transition_map = lookup->GetTransitionTarget();
3232 int descriptor = transition_map->LastAdded(); 3527 int descriptor = transition_map->LastAdded();
3233 3528
3234 DescriptorArray* descriptors = transition_map->instance_descriptors(); 3529 DescriptorArray* descriptors = transition_map->instance_descriptors();
3235 PropertyDetails details = descriptors->GetDetails(descriptor); 3530 PropertyDetails details = descriptors->GetDetails(descriptor);
3236 3531
3237 if (details.type() == FIELD) { 3532 if (details.type() == FIELD) {
3238 if (attributes == details.attributes()) { 3533 if (attributes == details.attributes()) {
3534 if (!value->FitsStorage(details.storage_type())) {
3535 MaybeObject* maybe_map = transition_map->GeneralizeStorage(
3536 descriptor, value->RequiredStorage());
3537 if (!maybe_map->To(&transition_map)) return maybe_map;
3538 Object* back = transition_map->GetBackPointer();
3539 if (back->IsMap()) {
3540 MaybeObject* maybe_failure = MigrateToMap(Map::cast(back));
3541 if (maybe_failure->IsFailure()) return maybe_failure;
3542 }
3543 }
3239 int field_index = descriptors->GetFieldIndex(descriptor); 3544 int field_index = descriptors->GetFieldIndex(descriptor);
3240 result = lookup->holder()->AddFastPropertyUsingMap( 3545 result = lookup->holder()->AddFastPropertyUsingMap(
3241 transition_map, *name, *value, field_index); 3546 transition_map, *name, *value, field_index);
3242 } else { 3547 } else {
3243 result = lookup->holder()->ConvertDescriptorToField( 3548 result = lookup->holder()->ConvertDescriptorToField(
3244 *name, *value, attributes); 3549 *name, *value, attributes);
3245 } 3550 }
3246 } else if (details.type() == CALLBACKS) { 3551 } else if (details.type() == CALLBACKS) {
3247 result = lookup->holder()->ConvertDescriptorToField( 3552 result = lookup->holder()->ConvertDescriptorToField(
3248 *name, *value, attributes); 3553 *name, *value, attributes);
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
3363 } 3668 }
3364 3669
3365 // Check of IsReadOnly removed from here in clone. 3670 // Check of IsReadOnly removed from here in clone.
3366 MaybeObject* result = *value; 3671 MaybeObject* result = *value;
3367 switch (lookup.type()) { 3672 switch (lookup.type()) {
3368 case NORMAL: { 3673 case NORMAL: {
3369 PropertyDetails details = PropertyDetails(attributes, NORMAL); 3674 PropertyDetails details = PropertyDetails(attributes, NORMAL);
3370 result = self->SetNormalizedProperty(*name, *value, details); 3675 result = self->SetNormalizedProperty(*name, *value, details);
3371 break; 3676 break;
3372 } 3677 }
3373 case FIELD: 3678 case FIELD: {
3679 StorageType storage_type = lookup.storage_type();
3680 if (!value->FitsStorage(storage_type)) {
3681 MaybeObject* maybe_failure = GeneralizeFieldStorage(
3682 lookup.GetDescriptorIndex(), value->RequiredStorage());
3683 if (maybe_failure->IsFailure()) return maybe_failure;
3684 }
3374 result = self->FastPropertyAtPut( 3685 result = self->FastPropertyAtPut(
3375 lookup.GetFieldIndex().field_index(), *value); 3686 lookup.GetFieldIndex().field_index(), *value);
3376 break; 3687 break;
3688 }
3377 case CONSTANT_FUNCTION: 3689 case CONSTANT_FUNCTION:
3378 // Only replace the function if necessary. 3690 // Only replace the function if necessary.
3379 if (*value != lookup.GetConstantFunction()) { 3691 if (*value != lookup.GetConstantFunction()) {
3380 // Preserve the attributes of this existing property. 3692 // Preserve the attributes of this existing property.
3381 attributes = lookup.GetAttributes(); 3693 attributes = lookup.GetAttributes();
3382 result = self->ConvertDescriptorToField(*name, *value, attributes); 3694 result = self->ConvertDescriptorToField(*name, *value, attributes);
3383 } 3695 }
3384 break; 3696 break;
3385 case CALLBACKS: 3697 case CALLBACKS:
3386 case INTERCEPTOR: 3698 case INTERCEPTOR:
3387 // Override callback in clone 3699 // Override callback in clone
3388 result = self->ConvertDescriptorToField(*name, *value, attributes); 3700 result = self->ConvertDescriptorToField(*name, *value, attributes);
3389 break; 3701 break;
3390 case TRANSITION: { 3702 case TRANSITION: {
3391 Map* transition_map = lookup.GetTransitionTarget(); 3703 Map* transition_map = lookup.GetTransitionTarget();
3392 int descriptor = transition_map->LastAdded(); 3704 int descriptor = transition_map->LastAdded();
3393 3705
3394 DescriptorArray* descriptors = transition_map->instance_descriptors(); 3706 DescriptorArray* descriptors = transition_map->instance_descriptors();
3395 PropertyDetails details = descriptors->GetDetails(descriptor); 3707 PropertyDetails details = descriptors->GetDetails(descriptor);
3396 3708
3397 if (details.type() == FIELD) { 3709 if (details.type() == FIELD) {
3398 if (attributes == details.attributes()) { 3710 if (attributes == details.attributes()) {
3711 if (!value->FitsStorage(details.storage_type())) {
3712 MaybeObject* maybe_map = transition_map->GeneralizeStorage(
3713 descriptor, value->RequiredStorage());
3714 if (!maybe_map->To(&transition_map)) return maybe_map;
3715 Object* back = transition_map->GetBackPointer();
3716 if (back->IsMap()) {
3717 MaybeObject* maybe_failure = MigrateToMap(Map::cast(back));
3718 if (maybe_failure->IsFailure()) return maybe_failure;
3719 }
3720 }
3399 int field_index = descriptors->GetFieldIndex(descriptor); 3721 int field_index = descriptors->GetFieldIndex(descriptor);
3400 result = self->AddFastPropertyUsingMap( 3722 result = self->AddFastPropertyUsingMap(
3401 transition_map, *name, *value, field_index); 3723 transition_map, *name, *value, field_index);
3402 } else { 3724 } else {
3403 result = self->ConvertDescriptorToField(*name, *value, attributes); 3725 result = self->ConvertDescriptorToField(*name, *value, attributes);
3404 } 3726 }
3405 } else if (details.type() == CALLBACKS) { 3727 } else if (details.type() == CALLBACKS) {
3406 result = self->ConvertDescriptorToField(*name, *value, attributes); 3728 result = self->ConvertDescriptorToField(*name, *value, attributes);
3407 } else { 3729 } else {
3408 ASSERT(details.type() == CONSTANT_FUNCTION); 3730 ASSERT(details.type() == CONSTANT_FUNCTION);
(...skipping 1502 matching lines...) Expand 10 before | Expand all | Expand 10 after
4911 for (int i = 0; i < limit; i++) { 5233 for (int i = 0; i < limit; i++) {
4912 if ((descs->GetDetails(i).attributes() & filter) == 0 && 5234 if ((descs->GetDetails(i).attributes() & filter) == 0 &&
4913 ((filter & SYMBOLIC) == 0 || !descs->GetKey(i)->IsSymbol())) { 5235 ((filter & SYMBOLIC) == 0 || !descs->GetKey(i)->IsSymbol())) {
4914 result++; 5236 result++;
4915 } 5237 }
4916 } 5238 }
4917 return result; 5239 return result;
4918 } 5240 }
4919 5241
4920 5242
4921 int Map::PropertyIndexFor(Name* name) {
4922 DescriptorArray* descs = instance_descriptors();
4923 int limit = NumberOfOwnDescriptors();
4924 for (int i = 0; i < limit; i++) {
4925 if (name->Equals(descs->GetKey(i))) return descs->GetFieldIndex(i);
4926 }
4927 return -1;
4928 }
4929
4930
4931 int Map::NextFreePropertyIndex() { 5243 int Map::NextFreePropertyIndex() {
4932 int max_index = -1; 5244 int max_index = -1;
4933 int number_of_own_descriptors = NumberOfOwnDescriptors(); 5245 int number_of_own_descriptors = NumberOfOwnDescriptors();
4934 DescriptorArray* descs = instance_descriptors(); 5246 DescriptorArray* descs = instance_descriptors();
4935 for (int i = 0; i < number_of_own_descriptors; i++) { 5247 for (int i = 0; i < number_of_own_descriptors; i++) {
4936 if (descs->GetType(i) == FIELD) { 5248 if (descs->GetType(i) == FIELD) {
4937 int current_index = descs->GetFieldIndex(i); 5249 int current_index = descs->GetFieldIndex(i);
4938 if (current_index > max_index) max_index = current_index; 5250 if (current_index > max_index) max_index = current_index;
4939 } 5251 }
4940 } 5252 }
(...skipping 830 matching lines...) Expand 10 before | Expand all | Expand 10 after
5771 if (!maybe_result->To(&result)) return maybe_result; 6083 if (!maybe_result->To(&result)) return maybe_result;
5772 6084
5773 result->InitializeDescriptors(descriptors); 6085 result->InitializeDescriptors(descriptors);
5774 6086
5775 if (flag == INSERT_TRANSITION && CanHaveMoreTransitions()) { 6087 if (flag == INSERT_TRANSITION && CanHaveMoreTransitions()) {
5776 TransitionArray* transitions; 6088 TransitionArray* transitions;
5777 SimpleTransitionFlag simple_flag = 6089 SimpleTransitionFlag simple_flag =
5778 (descriptor_index == descriptors->number_of_descriptors() - 1) 6090 (descriptor_index == descriptors->number_of_descriptors() - 1)
5779 ? SIMPLE_TRANSITION 6091 ? SIMPLE_TRANSITION
5780 : FULL_TRANSITION; 6092 : FULL_TRANSITION;
6093 ASSERT(name == descriptors->GetKey(descriptor_index));
5781 MaybeObject* maybe_transitions = AddTransition(name, result, simple_flag); 6094 MaybeObject* maybe_transitions = AddTransition(name, result, simple_flag);
5782 if (!maybe_transitions->To(&transitions)) return maybe_transitions; 6095 if (!maybe_transitions->To(&transitions)) return maybe_transitions;
5783 6096
5784 set_transitions(transitions); 6097 set_transitions(transitions);
5785 result->SetBackPointer(this); 6098 result->SetBackPointer(this);
5786 } 6099 }
5787 6100
5788 return result; 6101 return result;
5789 } 6102 }
5790 6103
5791 6104
6105 MaybeObject* Map::CopyInstallDescriptors(int new_descriptor,
6106 DescriptorArray* descriptors) {
6107 ASSERT(descriptors->IsSortedNoDuplicates());
6108
6109 Map* result;
6110 MaybeObject* maybe_result = CopyDropDescriptors();
6111 if (!maybe_result->To(&result)) return maybe_result;
6112
6113 result->InitializeDescriptors(descriptors);
6114 result->SetNumberOfOwnDescriptors(new_descriptor + 1);
6115
6116 int unused_property_fields = this->unused_property_fields();
6117 if (descriptors->GetDetails(new_descriptor).type() == FIELD) {
6118 unused_property_fields = this->unused_property_fields() - 1;
6119 if (unused_property_fields < 0) {
6120 unused_property_fields += JSObject::kFieldsAdded;
6121 }
6122 }
6123
6124 result->set_unused_property_fields(unused_property_fields);
6125 result->set_owns_descriptors(false);
6126
6127 if (CanHaveMoreTransitions()) {
6128 Name* name = descriptors->GetKey(new_descriptor);
6129 TransitionArray* transitions;
6130 MaybeObject* maybe_transitions =
6131 AddTransition(name, result, SIMPLE_TRANSITION);
6132 if (!maybe_transitions->To(&transitions)) return maybe_transitions;
6133
6134 set_transitions(transitions);
6135 result->SetBackPointer(this);
6136 }
6137
6138 return result;
6139 }
6140
6141
5792 MaybeObject* Map::CopyAsElementsKind(ElementsKind kind, TransitionFlag flag) { 6142 MaybeObject* Map::CopyAsElementsKind(ElementsKind kind, TransitionFlag flag) {
5793 if (flag == INSERT_TRANSITION) { 6143 if (flag == INSERT_TRANSITION) {
5794 ASSERT(!HasElementsTransition() || 6144 ASSERT(!HasElementsTransition() ||
5795 ((elements_transition_map()->elements_kind() == DICTIONARY_ELEMENTS || 6145 ((elements_transition_map()->elements_kind() == DICTIONARY_ELEMENTS ||
5796 IsExternalArrayElementsKind( 6146 IsExternalArrayElementsKind(
5797 elements_transition_map()->elements_kind())) && 6147 elements_transition_map()->elements_kind())) &&
5798 (kind == DICTIONARY_ELEMENTS || 6148 (kind == DICTIONARY_ELEMENTS ||
5799 IsExternalArrayElementsKind(kind)))); 6149 IsExternalArrayElementsKind(kind))));
5800 ASSERT(!IsFastElementsKind(kind) || 6150 ASSERT(!IsFastElementsKind(kind) ||
5801 IsMoreGeneralElementsKindTransition(elements_kind(), kind)); 6151 IsMoreGeneralElementsKindTransition(elements_kind(), kind));
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
5850 JSFunction* ctor = JSFunction::cast(constructor()); 6200 JSFunction* ctor = JSFunction::cast(constructor());
5851 Map* map = ctor->initial_map(); 6201 Map* map = ctor->initial_map();
5852 DescriptorArray* descriptors = map->instance_descriptors(); 6202 DescriptorArray* descriptors = map->instance_descriptors();
5853 6203
5854 int number_of_own_descriptors = map->NumberOfOwnDescriptors(); 6204 int number_of_own_descriptors = map->NumberOfOwnDescriptors();
5855 DescriptorArray* new_descriptors; 6205 DescriptorArray* new_descriptors;
5856 MaybeObject* maybe_descriptors = 6206 MaybeObject* maybe_descriptors =
5857 descriptors->CopyUpTo(number_of_own_descriptors); 6207 descriptors->CopyUpTo(number_of_own_descriptors);
5858 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; 6208 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
5859 6209
6210 new_descriptors->InitializeStorageTypes(TAGGED);
6211
5860 return CopyReplaceDescriptors(new_descriptors, NULL, OMIT_TRANSITION, 0); 6212 return CopyReplaceDescriptors(new_descriptors, NULL, OMIT_TRANSITION, 0);
5861 } 6213 }
5862 6214
5863 6215
5864 MaybeObject* Map::Copy() { 6216 MaybeObject* Map::Copy() {
5865 DescriptorArray* descriptors = instance_descriptors(); 6217 DescriptorArray* descriptors = instance_descriptors();
5866 DescriptorArray* new_descriptors; 6218 DescriptorArray* new_descriptors;
5867 int number_of_own_descriptors = NumberOfOwnDescriptors(); 6219 int number_of_own_descriptors = NumberOfOwnDescriptors();
5868 MaybeObject* maybe_descriptors = 6220 MaybeObject* maybe_descriptors =
5869 descriptors->CopyUpTo(number_of_own_descriptors); 6221 descriptors->CopyUpTo(number_of_own_descriptors);
(...skipping 935 matching lines...) Expand 10 before | Expand all | Expand 10 after
6805 DescriptorArray* src, 7157 DescriptorArray* src,
6806 int src_index, 7158 int src_index,
6807 const WhitenessWitness& witness) { 7159 const WhitenessWitness& witness) {
6808 Object* value = src->GetValue(src_index); 7160 Object* value = src->GetValue(src_index);
6809 PropertyDetails details = src->GetDetails(src_index); 7161 PropertyDetails details = src->GetDetails(src_index);
6810 Descriptor desc(src->GetKey(src_index), value, details); 7162 Descriptor desc(src->GetKey(src_index), value, details);
6811 Set(dst_index, &desc, witness); 7163 Set(dst_index, &desc, witness);
6812 } 7164 }
6813 7165
6814 7166
7167 MaybeObject* DescriptorArray::Merge(int verbatim,
7168 int valid,
7169 int new_size,
7170 DescriptorArray* other) {
7171 ASSERT(verbatim <= valid);
7172 ASSERT(valid <= new_size);
7173
7174 DescriptorArray* result;
7175 // Allocate a new descriptor array large enough to hold the required
7176 // descriptors, with minimally the exact same size as this descriptor array.
7177 MaybeObject* maybe_descriptors = DescriptorArray::Allocate(
7178 new_size, Max(new_size, number_of_descriptors()) - new_size);
7179 if (!maybe_descriptors->To(&result)) return maybe_descriptors;
7180 ASSERT(result->length() > length() ||
7181 result->NumberOfSlackDescriptors() > 0 ||
7182 result->number_of_descriptors() == other->number_of_descriptors());
7183 ASSERT(result->number_of_descriptors() == new_size);
7184
7185 DescriptorArray::WhitenessWitness witness(result);
7186
7187 int descriptor;
7188
7189 int current_offset = 0;
7190 for (descriptor = 0; descriptor < verbatim; descriptor++) {
7191 if (GetDetails(descriptor).type() == FIELD) current_offset++;
7192 result->CopyFrom(descriptor, this, descriptor, witness);
7193 }
7194
7195 for (; descriptor < valid; descriptor++) {
7196 Name* key = GetKey(descriptor);
7197 PropertyDetails details = GetDetails(descriptor);
7198 PropertyDetails other_details = other->GetDetails(descriptor);
7199 ASSERT(details.attributes() == other_details.attributes());
7200
7201 if (details.type() == FIELD) {
7202 ASSERT(other_details.type() != CALLBACKS);
7203 FieldDescriptor d(key,
7204 current_offset++,
7205 details.attributes(),
7206 descriptor + 1);
7207 StorageType storage =
7208 IsMoreGeneralStorageType(
7209 other_details.storage_type(), details.storage_type())
7210 ? other_details.storage_type() : details.storage_type();
7211 d.SetStorageType(storage);
7212 result->Set(descriptor, &d, witness);
7213 } else if (other_details.type() == FIELD) {
7214 FieldDescriptor d(key,
7215 current_offset++,
7216 details.attributes(),
7217 descriptor + 1);
7218 StorageType storage =
7219 IsMoreGeneralStorageType(
7220 other_details.storage_type(), details.storage_type())
7221 ? other_details.storage_type() : details.storage_type();
7222 d.SetStorageType(storage);
7223 result->Set(descriptor, &d, witness);
7224 } else if (other_details.type() == CONSTANT_FUNCTION) {
7225 Object* value = GetValue(descriptor);
7226 Object* other_value = other->GetValue(descriptor);
7227 if (details.type() == CONSTANT_FUNCTION && value != other_value) {
7228 FieldDescriptor d(key,
7229 current_offset++,
7230 details.attributes(),
7231 descriptor + 1);
7232 d.SetStorageType(TAGGED);
7233 result->Set(descriptor, &d, witness);
7234 } else {
7235 ConstantFunctionDescriptor d(key,
7236 JSFunction::cast(other_value),
7237 details.attributes(),
7238 descriptor + 1);
7239 result->Set(descriptor, &d, witness);
7240 }
7241 } else {
7242 ASSERT(other_details.type() != FIELD);
7243 result->CopyFrom(descriptor, other, descriptor, witness);
7244 }
7245 }
7246
7247 for (; descriptor < new_size; descriptor++) {
7248 PropertyDetails details = other->GetDetails(descriptor);
7249 if (details.type() == FIELD) {
7250 Name* key = other->GetKey(descriptor);
7251 FieldDescriptor d(key,
7252 current_offset++,
7253 details.attributes(),
7254 descriptor + 1);
7255 result->Set(descriptor, &d, witness);
7256 } else {
7257 result->CopyFrom(descriptor, other, descriptor, witness);
7258 }
7259 }
7260
7261 result->Sort();
7262 return result;
7263 }
7264
7265
6815 // We need the whiteness witness since sort will reshuffle the entries in the 7266 // We need the whiteness witness since sort will reshuffle the entries in the
6816 // descriptor array. If the descriptor array were to be black, the shuffling 7267 // descriptor array. If the descriptor array were to be black, the shuffling
6817 // would move a slot that was already recorded as pointing into an evacuation 7268 // would move a slot that was already recorded as pointing into an evacuation
6818 // candidate. This would result in missing updates upon evacuation. 7269 // candidate. This would result in missing updates upon evacuation.
6819 void DescriptorArray::Sort() { 7270 void DescriptorArray::Sort() {
6820 // In-place heap sort. 7271 // In-place heap sort.
6821 int len = number_of_descriptors(); 7272 int len = number_of_descriptors();
6822 // Reset sorting since the descriptor array might contain invalid pointers. 7273 // Reset sorting since the descriptor array might contain invalid pointers.
6823 for (int i = 0; i < len; ++i) SetSortedKey(i, i); 7274 for (int i = 0; i < len; ++i) SetSortedKey(i, i);
6824 // Bottom-up max-heap construction. 7275 // Bottom-up max-heap construction.
(...skipping 1341 matching lines...) Expand 10 before | Expand all | Expand 10 after
8166 // XOR-ing the prototype and constructor directly yields too many zero bits 8617 // XOR-ing the prototype and constructor directly yields too many zero bits
8167 // when the two pointers are close (which is fairly common). 8618 // when the two pointers are close (which is fairly common).
8168 // To avoid this we shift the prototype 4 bits relatively to the constructor. 8619 // To avoid this we shift the prototype 4 bits relatively to the constructor.
8169 hash ^= (static_cast<uint32_t>( 8620 hash ^= (static_cast<uint32_t>(
8170 reinterpret_cast<uintptr_t>(prototype())) << 2); 8621 reinterpret_cast<uintptr_t>(prototype())) << 2);
8171 8622
8172 return hash ^ (hash >> 16) ^ bit_field2(); 8623 return hash ^ (hash >> 16) ^ bit_field2();
8173 } 8624 }
8174 8625
8175 8626
8627 static bool CheckEquivalent(Map* first, Map* second) {
8628 return
8629 first->constructor() == second->constructor() &&
8630 first->prototype() == second->prototype() &&
8631 first->instance_type() == second->instance_type() &&
8632 first->bit_field() == second->bit_field() &&
8633 first->bit_field2() == second->bit_field2() &&
8634 first->is_observed() == second->is_observed() &&
8635 first->function_with_prototype() == second->function_with_prototype();
8636 }
8637
8638
8639 bool Map::EquivalentToForTransition(Map* other) {
8640 return CheckEquivalent(this, other);
8641 }
8642
8643
8176 bool Map::EquivalentToForNormalization(Map* other, 8644 bool Map::EquivalentToForNormalization(Map* other,
8177 PropertyNormalizationMode mode) { 8645 PropertyNormalizationMode mode) {
8178 return 8646 int properties = mode == CLEAR_INOBJECT_PROPERTIES
8179 constructor() == other->constructor() && 8647 ? 0 : other->inobject_properties();
8180 prototype() == other->prototype() && 8648 return CheckEquivalent(this, other) && inobject_properties() == properties;
8181 inobject_properties() == ((mode == CLEAR_INOBJECT_PROPERTIES) ?
8182 0 :
8183 other->inobject_properties()) &&
8184 instance_type() == other->instance_type() &&
8185 bit_field() == other->bit_field() &&
8186 bit_field2() == other->bit_field2() &&
8187 is_observed() == other->is_observed() &&
8188 function_with_prototype() == other->function_with_prototype();
8189 } 8649 }
8190 8650
8191 8651
8192 void JSFunction::JSFunctionIterateBody(int object_size, ObjectVisitor* v) { 8652 void JSFunction::JSFunctionIterateBody(int object_size, ObjectVisitor* v) {
8193 // Iterate over all fields in the body but take care in dealing with 8653 // Iterate over all fields in the body but take care in dealing with
8194 // the code entry. 8654 // the code entry.
8195 IteratePointers(v, kPropertiesOffset, kCodeEntryOffset); 8655 IteratePointers(v, kPropertiesOffset, kCodeEntryOffset);
8196 v->VisitCodeEntry(this->address() + kCodeEntryOffset); 8656 v->VisitCodeEntry(this->address() + kCodeEntryOffset);
8197 IteratePointers(v, kCodeEntryOffset + kPointerSize, object_size); 8657 IteratePointers(v, kCodeEntryOffset + kPointerSize, object_size);
8198 } 8658 }
(...skipping 5716 matching lines...) Expand 10 before | Expand all | Expand 10 after
13915 value, 14375 value,
13916 UPDATE_WRITE_BARRIER); 14376 UPDATE_WRITE_BARRIER);
13917 } else { 14377 } else {
13918 int offset = current_offset - inobject_props; 14378 int offset = current_offset - inobject_props;
13919 fields->set(offset, value); 14379 fields->set(offset, value);
13920 } 14380 }
13921 FieldDescriptor d(key, 14381 FieldDescriptor d(key,
13922 current_offset++, 14382 current_offset++,
13923 details.attributes(), 14383 details.attributes(),
13924 enumeration_index); 14384 enumeration_index);
14385 // TODO(verwaest): Support storage types in the boilerplate.
14386 // d.SetStorageType(value->RequiredStorage());
14387 d.SetStorageType(TAGGED);
13925 descriptors->Set(enumeration_index - 1, &d, witness); 14388 descriptors->Set(enumeration_index - 1, &d, witness);
13926 } else if (type == CALLBACKS) { 14389 } else if (type == CALLBACKS) {
13927 CallbacksDescriptor d(key, 14390 CallbacksDescriptor d(key,
13928 value, 14391 value,
13929 details.attributes(), 14392 details.attributes(),
13930 enumeration_index); 14393 enumeration_index);
13931 descriptors->Set(enumeration_index - 1, &d, witness); 14394 descriptors->Set(enumeration_index - 1, &d, witness);
13932 } else { 14395 } else {
13933 UNREACHABLE(); 14396 UNREACHABLE();
13934 } 14397 }
(...skipping 570 matching lines...) Expand 10 before | Expand all | Expand 10 after
14505 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); 14968 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER);
14506 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); 14969 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER);
14507 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); 14970 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER);
14508 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); 14971 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER);
14509 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); 14972 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER);
14510 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); 14973 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER);
14511 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); 14974 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER);
14512 } 14975 }
14513 14976
14514 } } // namespace v8::internal 14977 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698